为简化的SQL " where "子句执行BNF



我有以下SQL语句,其中应用了基本的BNF:

SELECT
from_expression [, from_expression] ...
FROM
from_source
WHERE
condition

from_source:
table_name
from_expression:
literal              # 'abc', 1, 
column               # Table.Field1, Table.Profit
function             # ABS(...)
operator invocation  # NOT field1, 2+3, Genres[0], Genres[1:2], Address.name
condition:
???

目前WHERE条件与from_expression条件相同,但计算为布尔值。怎样才合适呢?

语法不关心语义。

在语法上,表达式就是表达式,仅此而已。如果稍后进行某种语义分析,这时就需要处理这种差异。您可能会在conditionfrom_expression的还原操作中这样做,但在解析时构建AST并稍后在树上进行语义分析会更干净。

其中一个选项如下,其中的示例为:

expression:
literal                                       # 'abc', 1, 
column                                        # Table.Field1, Table.Profit
function call                                 # ABS(...)
operator invocation                           # NOT field1, 2+3, Genres[0], Genres[1:2], Address.name
condition:
expression { = | != | < | <= | > | >= | IN } expression  # Revenue > 0
expression IS [NOT] NULL                       # Revenue IS NOT NULL
condition { AND | OR } condition               # Revenue > 0 AND Profit < 100

这个注释不适合放在注释区

我很犹豫是否要提供指向LiveSQL实现的链接,因为它是专门针对Java语言的,它是开源的,但我们从来没有添加任何文档。阅读风险自负。

主类是LiveSQL.java:在第113行中,您可以看到select子句的主要变体。它有许多变体,但这个变体允许开发人员根据需要包含尽可能多的结果集列(表达式):

public SelectColumnsPhase<Map<String, Object>> select(
final ResultSetColumn... resultSetColumns) {
return new SelectColumnsPhase<Map<String, Object>>(this.sqlDialect,
this.sqlSession, this.liveSQLMapper, false,
resultSetColumns);
}

当然,SELECT子句还有许多其他变体,如果您稍微研究一下,就可以在同一个类中找到它们。我想当我研究了所有的变体时,我已经非常详尽了。它应该是[大部分]完整的,除了我没有考虑到的非标准SQL方言的变化。

如果您沿着QueryBuilder一直到WHERE阶段,您可以看到谓词是如何在SelectFrom.java类的方法where(final Predicate predicate)(第101行)中组装的,如下所示:

public SelectWherePhase<R> where(final Predicate predicate) {
return new SelectWherePhase<R>(this.select, predicate);
}

可以看到WHERE子句不接受任何类型的表达式。首先,它只接受单个表达式,而不是一个列表。其次,这个表达式必须是一个谓词(布尔表达式)。当然,这个谓词可以非常复杂,可以混合各种表达式和布尔逻辑。您可以查看Predicate.java类来探索可以构建的所有表达式。

让我们以上面描述的Predicate类为例。如果pq是布尔表达式,而abc[几乎]是任意类型,则可以将条件表示为:

condition:
<predicate>
predicate:
p and q,
p or q,
not p,
( p ),
a == b,
a <> b,
a > b,
a < b,
a >= b,
a <= b,
a between b and c,
a not between b and c,
a in (b, c, ... )
a not in (b, c, ... )

当然还有更多的操作符,但这给了你它的要点。

最新更新