Antlr4 sqlite3.g4语法无法正确处理左连接

Antlr4 sqlite3.g4语法无法正确处理左连接,antlr4,Antlr4,github sqlite3语法github.com/antlr/grammars-v4/blob/master/sqlite/sqlite.g4存在左连接问题 对于此sql select * from t1 left join t2 on t1.owner = t2.email 单词“left”被解析为表别名。从那以后,情况迅速恶化 我想我可以通过说table\u alias是any\u name除了K\u LEFT、K\u RIGHT、K\u INNER之外的任何名称来解决这个问题,但我不

github sqlite3语法github.com/antlr/grammars-v4/blob/master/sqlite/sqlite.g4存在左连接问题

对于此sql

select * from t1 left join t2 on t1.owner = t2.email
单词“left”被解析为表别名。从那以后,情况迅速恶化

我想我可以通过说
table\u alias
any\u name
除了K\u LEFT、K\u RIGHT、K\u INNER之外的任何名称来解决这个问题,但我不知道如何用语法来表达它

或者也许有更好的方法来解决这个问题

更新。只是为了澄清sqlite的行为。(不是谈论antlr,而是谈论sqlite理解的内容)

这个

工作

这个

表示列user.id不存在失败

显然,单词“left”被识别为关键字,而不是表别名

select username from user alias join device on device.owner = alias.id limit 2
工作,并进行内部连接

select username from user alias left join device on device.owner = user.id limit 2
工作并进行左连接

@Mike Lischke的进一步更新

select username from user left where device.owner = left.id limit 2

失败了<代码>“查询失败:靠近“where”:语法错误。

行为正确
LEFT
包含在
关键字
规则中,该规则依次用于
任何名称
,这是
表别名
的有效输入(这称为关键字作为标识符问题)。根据语法句号,您的查询是错误的。表名后面的任何单词都是表别名,而不管它通常是否为关键字


一种解决方法是添加一个验证谓词,该谓词检查以下标记,并在当前标记应按其原始含义使用时使
table_alias
规则失败。通过从
关键字
规则中删除
LEFT
关键字,可以获得相同的结果。但是,如果您希望
LEFT
关键字成为标识符的有效输入,则这可能会产生其他副作用。

您是从头开始编写语法的吗?你看了吗?这就是我指的语法-更新了问题愚蠢的问题,但是当你对所有保留关键字使用大写字母时,这种情况也会发生吗?sqlite接受查询并执行它,就像它是一个左连接,而不是表别名一样(我不能通过名称“left”引用该表,在单词“left”之前添加“as”使其成为别名)。我假设它知道一个表名后面允许有几个关键字:as、left、right、internal,并且它会检查它触发表alais规则的b4。在表名后面是否单独有
left
(即,不使用
JOIN
)?我认为SQLite解析器要么根据某些条件更改某些关键字的含义(非上下文无关解析器),要么在诸如表别名之类的上下文中不允许使用这些关键字(并且您使用的语法是错误的)。您没有提到我要求的案例,例如,
从用户左侧选择用户名,其中device.owner=left.id limit 2
。如果允许
left
作为正常标识符,这仍然有效,使
left
成为
用户的别名。如果失败,则可能是因为
left join
短语不完整,而导致的ANTLR4语法是错误的。请参阅更新的问题。TL;博士,SQL失败,语法错误,这是我所期望的。<代码>左< /COD>单独是不允许的(如果这个关键字真的被允许作为标识符的话)。这意味着g4语法是错误的。您必须更改它。只需从
关键字
规则中删除少数
JOIN
关键字即可。您可能需要创建另一个类似的规则,其中包括用于其他规则的关键字。
select username from user alias left join device on device.owner = user.id limit 2
select username from user left where device.owner = left.id limit 2