2

我现在正在研究mysql的SQL解析器。

这是我注意到但无法解释的有趣的事情:

(在sql_yacc.yy

predicate:
        ...
        | bit_expr BETWEEN_SYM bit_expr AND_SYM predicate
          {
            $$= new (YYTHD->mem_root) Item_func_between($1,$3,$5);
            if ($$ == NULL)
              MYSQL_YYABORT;
          }

表达式语法页面也是如此:

predicate:
  ...
  | bit_expr [NOT] BETWEEN bit_expr AND predicate

这意味着

foo BETWEEN 1 AND bar BETWEEN 1 AND 2

查询语法正确,但根本没有意义。

我的问题:这可以用来做什么?如果使用我们会错过什么

bit_expr [NOT] BETWEEN bit_expr AND bit_expr

反而?

LOL(实际上不再是 LOL)

此查询执行没有错误:

select * from users where id between 1 and id between 1 and 10;
// returns row with id = 1

select * from users where id between 2 and id between 2 and 10;
Empty set (0.00 sec)

(这里添加了更新)......实际上它预期的。

大概它将第二个表达式直接转换为01并将其用作操作数。

更新

我提交了一个错误 - http://bugs.mysql.com/bug.php?id=69208

这绝对不是预期的语法

UPD 2:所以看起来它只是一个小错字,根本不会改变解析器的行为(好吧,要清楚,它会使普通BETWEEN表达式的速度变慢而难以察觉)。

4

1 回答 1

2

Your analysis is basically correct:

foo BETWEEN 1 AND bar BETWEEN 1 AND 2

is parsed as:

foo BETWEEN 1 AND (bar BETWEEN 1 AND 2)

and the second (parenthesized) predicate will presumably evaluate to either 0 or 1 (for false or true). Therefore, if bar is not between 1 and 2, the set of selected values from foo will be empty (because foo BETWEEN 1 AND 0 is a shorthand for foo >= 1 AND f <= 0 and there are no values for which that is true, even allowing for NULLs). Contrariwise, if bar is between 1 and 2, then the set of selected values from foo will be the set where `foo1 equals 1.

And alternative question to your "what would you lose if you replaced the 'predicate' term with 'bit_expr'?" might be "would you gain anything if you replaced the 'bit_expr' with 'predicate'?"

Without a careful scrutiny of the complete grammar (or, at least, scrutiny of the parts referenced by bit_expr and predicate, and possibly a review of places where bit_expr and predicate are used), it is hard to know the answer to either question.

于 2013-05-13T05:19:33.277 回答