为简化的 SQL “where” 子句做 BNF
Doing BNF for a simplified SQL “where” clause
我有以下 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
相同,但评估为布尔值。显示这一点的正确方法是什么?
语法不关心语义。
从句法上讲,表达式就是表达式,仅此而已。如果您稍后进行某种语义分析,那就是您需要处理差异的时候。您可以在 condition
和 from_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 实现提供 link,因为它专门针对 Java 语言,它是开源的,但我们从未添加任何文档。阅读风险自负。
主要的 class 是 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 子句还有许多其他变体,如果您稍微探索一下,您可以在同一个 class 中找到它们。当我研究所有变体时,我认为我已经非常详尽了。它应该 [大部分] 完整,除了我没有考虑的非标准 SQL 方言变体。
如果您在 WHERE 阶段跟随 QueryBuilder,您可以看到谓词是如何在 SelectFrom.java class 的方法 where(final Predicate predicate)
(第 101 行)中组装的,如下所示:
public SelectWherePhase<R> where(final Predicate predicate) {
return new SelectWherePhase<R>(this.select, predicate);
}
如您所见,WHERE 子句不接受任何类型的表达式。首先,它只接受一个表达式,而不是一个列表。其次,这个表达式必须是谓词(布尔表达式)。当然,这个谓词可以很复杂,混合各种表达式和布尔逻辑。您可以查看 Predicate.java class 以探索所有可以构建的表达式。
条件
我们以上面描述的谓词class为例。如果 p
和 q
是布尔表达式,并且 a
、b
、c
是 [大部分] 任何类型,您可以将条件表示为:
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, ... )
当然还有更多的运算符,但这让您了解了它的要点。
我有以下 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
相同,但评估为布尔值。显示这一点的正确方法是什么?
语法不关心语义。
从句法上讲,表达式就是表达式,仅此而已。如果您稍后进行某种语义分析,那就是您需要处理差异的时候。您可以在 condition
和 from_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 实现提供 link,因为它专门针对 Java 语言,它是开源的,但我们从未添加任何文档。阅读风险自负。
主要的 class 是 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 子句还有许多其他变体,如果您稍微探索一下,您可以在同一个 class 中找到它们。当我研究所有变体时,我认为我已经非常详尽了。它应该 [大部分] 完整,除了我没有考虑的非标准 SQL 方言变体。
如果您在 WHERE 阶段跟随 QueryBuilder,您可以看到谓词是如何在 SelectFrom.java class 的方法 where(final Predicate predicate)
(第 101 行)中组装的,如下所示:
public SelectWherePhase<R> where(final Predicate predicate) {
return new SelectWherePhase<R>(this.select, predicate);
}
如您所见,WHERE 子句不接受任何类型的表达式。首先,它只接受一个表达式,而不是一个列表。其次,这个表达式必须是谓词(布尔表达式)。当然,这个谓词可以很复杂,混合各种表达式和布尔逻辑。您可以查看 Predicate.java class 以探索所有可以构建的表达式。
条件
我们以上面描述的谓词class为例。如果 p
和 q
是布尔表达式,并且 a
、b
、c
是 [大部分] 任何类型,您可以将条件表示为:
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, ... )
当然还有更多的运算符,但这让您了解了它的要点。