在join子句中解析SQL Select语句(包括BNF语法)

时间:2016-11-06 11:18:01

标签: sql parsing bnf

我正在努力理解这个SQL语法如何用于从解析器中解析下面提供的SQL语句。我被困在'表引用'和'加入'构造之后找到WHERE标记。

BNF:http://www.contrib.andrew.cmu.edu/~shadow/sql/sql2bnf.aug92.txt

<table reference> ::=
         <table name> [ <correlation specification> ]
     | <derived table> <correlation specification>
     | <joined table>

 <joined table>    ::=
         <cross join>
     | <qualified join>
     | <left paren> <joined table> <right paren>

<cross join>    ::=
         <table reference> CROSS JOIN <table reference>

<qualified join>    ::=
         <table reference> [ NATURAL ] [ <join type> ] JOIN <table reference> [ <join specification> ]

<join type>    ::=
         INNER
     | <outer join type> [ OUTER ]
     | UNION

<outer join type>    ::=   LEFT | RIGHT | FULL

<join specification>    ::=   <join condition> | <named columns join>

<join condition>    ::=   ON <search condition>

<named columns join>    ::=   USING <left paren> <join column list> <right paren>

SQL:

SELECT p.Name, v.Name
FROM Production.Product p
JOIN Purchasing.ProductVendor pv
ON p.ProductID = pv.ProductID
JOIN Purchasing.Vendor v
ON pv.BusinessEntityID = v.BusinessEntityID
WHERE ProductSubcategoryID = 15
ORDER BY v.Name; 

跳转到FROM caluse。这里有一个TableName,后跟两个JOIN。

如果您查看“表格引用”,那么您会看到它包含“表格名称”。这是我能理解的。

<table reference>    ::=
         **<table name> [ <correlation specification> ]**
     | <derived table> <correlation specification>
     | <joined table>

但是为了获得连接,解析器必须到达它不能的'Joined table',因为它已经准备好读取'table name'。

要达到加入,解析器必须达到“合格加入”,但不能,因为BNF中没有重复。如果它以某种方式到达'Join table'元素,那么如果会非常失望,因为下一次读取将再次是'Table reference'然后它将再次达到'Qualifed join',然后......然后你得到一个堆栈溢出。

  <joined table>    ::=
         <cross join>
     | <**qualified join>**
     | <left paren> <joined table> <right paren>

**<qualified join>**    ::=
         <table reference> [ NATURAL ] [ <join type> ] JOIN <table reference> [ <join specification> ]

我没有到这里来的?我确信它有一个技巧,但我只是没有看到它。

我希望你的一些才华横溢的家伙可以向我解释这对我的impossibel语法有什么影响。

如何构建一个让我们说一个递归的正确解析器来解决这个语法?

解析器需要遵循哪些步骤和/或规则?

祝你好运, 布莱恩安德森

2 个答案:

答案 0 :(得分:1)

该语法不是LL(1),这是构建递归下降解析器所需的。我怀疑SQL是否有LL(1)语法,特别是如果有一个可以生成正确的解析树的语法。幸运的是,这并不重要,因为有更强大的解析技术。

很可能您可以使用该语法来构建LALR(1)解析器,使用像bison / yacc这样的工具。或者查看sqlite source code,其中包括LALR(1)语法和名为&#34; lemon&#34;的LALR(1)解析器生成器。

答案 1 :(得分:0)

问这个问题已经有一段时间了,但是由于ANTLR的性能/内存问题,我正在考虑将ANTLR4 SQL解析器重写为RDP。

因此,我(在思想上)解决JOIN问题的方式是,我将它们像运算符一样对待,因为这就是它们的本质(至少这是我的印象)。

基本表达语法既适合常用表达又适合于联接:

ex
    : '(' ex ')'
    | ex OPERATOR ex
    | TERMINAL
    ;

在JOIN情况下,您的OPERATOR变为JOIN,而TERMINAL成为表引用。

现在,这种左递归语法不是LL语法,但可以将其转换为ANTLR4自动执行的语法。