Cassandra CQL出现“no viable alternative at input 'None'”错误的原因是什么?

16

我试图使用一个新的键将修改后的文档插入回Cassandra数据库。我很难确定错误信息指向的问题所在。当寻找其他遇到类似问题的人时,答案似乎与键有关,在我的情况下,None只是几个键的值。我该如何解决这个问题?

keys = ','.join(current.keys())
params = [':' + x for x in current.keys()]
values = ','.join(params)

query = "INSERT INTO wiki.pages (%s) Values (%s)" % (keys, values)
query = query.encode('utf-8')
cursor.execute(query, current)

这是查询和当前数据:

INSERT INTO wiki.pages (changed,content,meta,attachment,revision,page,editor) 
VALUES (:changed,:content,:meta,:attachment,:revision,:page,:editor)

{
    u'changed': '2013-02-15 16:31:49', 
    u'content': 'Testing', 
    u'meta': None, 
    u'attachment': None,    
    u'revision': 2, 
    u'page': u'FrontPage', 
    u'editor': 'Anonymous'
}

这个操作失败,出现了以下错误:

cql.apivalues.ProgrammingError: 
Bad Request: line 1:123 no viable alternative at input 'None'
1个回答

16

"无可行的替代方案"意味着某些关键数据类型与该列族列的模式不匹配,遗憾的是错误消息中没有明确说明。

在我的情况下,meta的数据类型为:

map<text,text> 

因此,在插入时将None视为坏值。我通过在插入前将None替换为空字典来解决了这个问题:

if current['meta'] is None:
    current['meta'] = dict()

CQL驱动程序可以接受空字典作为空映射类型的新值,而None是不允许的,即使查询映射列返回None是空的。由于返回None并不直观,因此我决定创建自定义包装器来替换cursor.fetchone(),它返回列的映射而不是列的列表,还检查MapType,ListType或SetType是否返回None。如果存在None值,则用空的dict(),list()或set()替换它们以避免将修改后的数据插入回Cassandra时出现问题。这似乎很好地解决了问题。


4
“FWIW,“no viable alternative” 技术上是一个解析错误,而不是类型错误。” 的意思是“就我所知,“无可行的替代方案”在技术层面上是一个语法分析错误,而不是类型错误。” - jbellis
3
补充一下@jbellis所说的,当我在多行连接字符串常量(用于预处理语句)时,如果我忘记确保标识符/关键字两侧有空格,就会出现这种情况。例如,SELECT * FROM tablenameWHERE foo = ?会导致 no viable alternative at: foo 错误,因为它期望的是WHERE关键字而不是标识符。(如果它提示期望什么就更好了。) - William Price
1
顺便说一句,“no viable alternative”来自ANTLR,所以如果你需要深入了解,请获取ANTLR语法。 - Jus12

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接