Tarantool development patches archive
 help / color / mirror / Atom feed
From: Vladislav Shpilevoy <v.shpilevoy@tarantool.org>
To: tarantool-patches@freelists.org, Nikita Pettik <korablev@tarantool.org>
Cc: kostja@tarantool.org
Subject: [tarantool-patches] Re: [PATCH 7/9] sql: make predicates accept and return boolean
Date: Tue, 16 Apr 2019 17:12:50 +0300	[thread overview]
Message-ID: <29403d26-5619-32ec-d2a6-474cc5256994@tarantool.org> (raw)
In-Reply-To: <8a92ae4cb6030c442fc540fa0ea07d9e6daa4e98.1555252410.git.korablev@tarantool.org>

Thanks for the patch! See 5 comments below.

On 14/04/2019 18:04, Nikita Pettik wrote:
> This patch make following predicates accept and return only values
> of type boolean: IN, EXISTS, OR, AND, NOT, BETWEEN, IS (NULL).
> In terms of approach, it is enough to patch opcodes implementing these
> predicates.
> 
> Part of #3723
> ---
>  src/box/sql/expr.c              | 26 ++++++++++++--------------
>  src/box/sql/parse.y             |  4 +++-
>  src/box/sql/parse_def.c         |  5 +++++
>  src/box/sql/select.c            |  2 +-
>  src/box/sql/sqlInt.h            |  1 +
>  src/box/sql/vdbe.c              | 37 ++++++++++++++-----------------------
>  test/sql-tap/cse.test.lua       |  6 +++---
>  test/sql-tap/e_select1.test.lua |  2 +-
>  test/sql-tap/in1.test.lua       |  6 +++---
>  test/sql-tap/misc3.test.lua     |  2 +-
>  test/sql-tap/select4.test.lua   |  2 +-
>  test/sql-tap/tkt3541.test.lua   |  2 +-
>  test/sql/types.result           | 22 +++++++++++++---------
>  13 files changed, 59 insertions(+), 58 deletions(-)
> 
> diff --git a/src/box/sql/expr.c b/src/box/sql/expr.c
> index e4de472a8..c5ec55de2 100644
> --- a/src/box/sql/expr.c
> +++ b/src/box/sql/expr.c
> @@ -1134,7 +1130,10 @@ sql_and_expr_new(struct sql *db, struct Expr *left_expr,
>  	} else if (exprAlwaysFalse(left_expr) || exprAlwaysFalse(right_expr)) {
>  		sql_expr_delete(db, left_expr, false);
>  		sql_expr_delete(db, right_expr, false);
> -		return sql_expr_new(db, TK_INTEGER, &sqlIntTokens[0]);
> +		struct Expr *f = sql_expr_new(db, TK_FALSE,
> +					      &sql_boolean_tokens[0]);
> +		f->type = FIELD_TYPE_BOOLEAN;

1. No check for f == NULL.

2. Why do you need f->type at all, if anyway you use sql_expr_type()
to get the type? Why isn't this field dropped still?

> +		return f;
>  	} else {
>  		struct Expr *new_expr = sql_expr_new_anon(db, TK_AND);
>  		sqlExprAttachSubtrees(db, new_expr, left_expr, right_expr);
> diff --git a/src/box/sql/parse.y b/src/box/sql/parse.y
> index f64a84948..b520b23d5 100644
> --- a/src/box/sql/parse.y
> +++ b/src/box/sql/parse.y
> @@ -1237,11 +1237,13 @@ expr(A) ::= expr(A) in_op(N) LP exprlist(Y) RP(E). [IN] {
>      ** regardless of the value of expr1.
>      */
>      sql_expr_delete(pParse->db, A.pExpr, false);
> -    A.pExpr = sql_expr_new_dequoted(pParse->db, TK_INTEGER, &sqlIntTokens[N]);
> +    int tk = N == 0 ? TK_FALSE : TK_TRUE;
> +    A.pExpr = sql_expr_new_dequoted(pParse->db, tk, &sql_boolean_tokens[N]);

3. Why do you use 'dequoted'? Do you store not normalized names in
sql_boolean_tokens? If you do, then why not to store already
normalized names and use sql_expr_new() here so as to avoid ICU calls?

A normalized name is always uppercased, but sql_boolean_tokens stores
lowercase strings. I tried to do this:

    -    A.pExpr = sql_expr_new_dequoted(pParse->db, tk, &sql_boolean_tokens[N]);
    +    A.pExpr = sql_expr_new(pParse->db, tk, &sql_boolean_tokens[N]);

And the tests passed. Why?

Another question - why boolean constant needs zToken at all? As I understand,
the only reason is that sqlExprCodeTarget parses zToken again even having ready
at hand TK_FALSE and TK_TRUE values. If I am right, you can drop boolean_tokens
array once you've fixed my comment 5 from the main patch (4/9).

The same question could be asked for integer constants stored in struct Expr
and having zToken. The only reason for that is the delayed parsing of the tokens,
as I understand. First they all are stored in Expr.zToken, and then parsed in
CodeTarget. But it would not be necessary if we parsed them right after reading and
storing actual value into Expr.u.iValue. In such a case zToken would be used for
identifiers and strings only, not for constants which I think appear quite often.
The reasoning behind my proposal is that parsing of an integer is likely to be
faster itself than calling ICU normalization functions.

The same can be said about float/double values, but I do not see such a type in
Expr.u.

Of course, all these integer/float-related thoughts are not about this patchset.
Probably, it is worth opening a separate issue.

>      if (A.pExpr == NULL) {
>        pParse->is_aborted = true;
>        return;
>      }
> +    A.pExpr->type = FIELD_TYPE_BOOLEAN;
>    }else if( Y->nExpr==1 ){
>      /* Expressions of the form:
>      **
> diff --git a/test/sql-tap/cse.test.lua b/test/sql-tap/cse.test.lua
> index 4b25f936d..39c1cc4ca 100755
> --- a/test/sql-tap/cse.test.lua
> +++ b/test/sql-tap/cse.test.lua
> @@ -132,7 +132,7 @@ test:do_execsql_test(
>  test:do_execsql_test(
>      "cse-1.7",
>      [[
> -        SELECT a, -a, ~a, NOT a, NOT NOT a, a-a, a+a, a*a, a/a, a FROM t1
> +        SELECT a, -a, ~a, NOT CAST(a AS BOOLEAN), NOT NOT CAST(a AS BOOLEAN), a-a, a+a, a*a, a/a, a FROM t1
>      ]], {
>          -- <cse-1.7>
>          1, -1, -2, 0, 1, 0, 2, 1, 1, 1, 2, -2, -3, 0, 1, 0, 4, 4, 1, 2

4. Above the fourth selected column is 'NOT CAST(a AS BOOLEAN)'. It is either true or
false, but in the result set it is 0. Why? First I thought, that probably 0 == false
in Lua, but it is not as a test showed:

tarantool> 0 == false
---
- false
...

tarantool> 1 == true
---
- false
...

> diff --git a/test/sql-tap/tkt3541.test.lua b/test/sql-tap/tkt3541.test.lua
> index 08a9be557..05247728d 100755
> --- a/test/sql-tap/tkt3541.test.lua
> +++ b/test/sql-tap/tkt3541.test.lua
> @@ -39,7 +39,7 @@ test:do_test(
>      "tkt3541-1.2",
>      function()
>          return test:execsql [[
> -            SELECT CASE NOT max(x) WHEN min(x) THEN 1 ELSE max(x) END FROM t1;
> +            SELECT CASE max(x) = 0 WHEN min(x) > 0 THEN 1 ELSE max(x) END FROM t1;

5. If negative numbers are not treated as FALSE, then I
guess you meant 'min(x) <> 0'.

>          ]]
>      end, {
>          -- <tkt3541-1.2>

My total diff which I am not sure why does not break tests:

==============================================================================
diff --git a/src/box/sql/expr.c b/src/box/sql/expr.c
index c5ec55de2..42b60babd 100644
--- a/src/box/sql/expr.c
+++ b/src/box/sql/expr.c
@@ -1130,10 +1130,7 @@ sql_and_expr_new(struct sql *db, struct Expr *left_expr,
 	} else if (exprAlwaysFalse(left_expr) || exprAlwaysFalse(right_expr)) {
 		sql_expr_delete(db, left_expr, false);
 		sql_expr_delete(db, right_expr, false);
-		struct Expr *f = sql_expr_new(db, TK_FALSE,
-					      &sql_boolean_tokens[0]);
-		f->type = FIELD_TYPE_BOOLEAN;
-		return f;
+		return sql_expr_new_anon(db, TK_FALSE);
 	} else {
 		struct Expr *new_expr = sql_expr_new_anon(db, TK_AND);
 		sqlExprAttachSubtrees(db, new_expr, left_expr, right_expr);
diff --git a/src/box/sql/parse.y b/src/box/sql/parse.y
index b520b23d5..f75999c35 100644
--- a/src/box/sql/parse.y
+++ b/src/box/sql/parse.y
@@ -1238,12 +1238,11 @@ expr(A) ::= expr(A) in_op(N) LP exprlist(Y) RP(E). [IN] {
     */
     sql_expr_delete(pParse->db, A.pExpr, false);
     int tk = N == 0 ? TK_FALSE : TK_TRUE;
-    A.pExpr = sql_expr_new_dequoted(pParse->db, tk, &sql_boolean_tokens[N]);
+    A.pExpr = sql_expr_new(pParse->db, tk, &sql_boolean_tokens[N]);
     if (A.pExpr == NULL) {
       pParse->is_aborted = true;
       return;
     }
-    A.pExpr->type = FIELD_TYPE_BOOLEAN;
   }else if( Y->nExpr==1 ){
     /* Expressions of the form:
     **

==============================================================================

  reply	other threads:[~2019-04-16 14:12 UTC|newest]

Thread overview: 42+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-04-14 15:03 [tarantool-patches] [PATCH 0/9] Introduce type BOOLEAN in SQL Nikita Pettik
2019-04-14 15:03 ` [tarantool-patches] [PATCH 1/9] sql: refactor mem_apply_numeric_type() Nikita Pettik
2019-04-14 15:04 ` [tarantool-patches] [PATCH 2/9] sql: disallow text values participate in sum() aggregate Nikita Pettik
2019-04-16 14:12   ` [tarantool-patches] " Vladislav Shpilevoy
2019-04-18 17:54     ` n.pettik
2019-04-22 18:02       ` Vladislav Shpilevoy
2019-04-23 19:58         ` n.pettik
2019-04-14 15:04 ` [tarantool-patches] [PATCH 3/9] sql: use msgpack types instead of custom ones Nikita Pettik
2019-04-16 14:12   ` [tarantool-patches] " Vladislav Shpilevoy
2019-04-18 17:54     ` n.pettik
2019-04-22 18:02       ` Vladislav Shpilevoy
2019-04-23 19:58         ` n.pettik
2019-04-14 15:04 ` [tarantool-patches] [PATCH 4/9] sql: introduce type boolean Nikita Pettik
2019-04-16 14:12   ` [tarantool-patches] " Vladislav Shpilevoy
2019-04-18 17:54     ` n.pettik
2019-04-22 18:02       ` Vladislav Shpilevoy
2019-04-23 19:58         ` n.pettik
2019-04-23 21:06           ` Vladislav Shpilevoy
2019-04-14 15:04 ` [tarantool-patches] [PATCH 5/9] sql: improve type determination for column meta Nikita Pettik
2019-04-16 14:12   ` [tarantool-patches] " Vladislav Shpilevoy
2019-04-18 17:54     ` n.pettik
2019-04-22 18:02       ` Vladislav Shpilevoy
2019-04-23 19:58         ` n.pettik
2019-04-14 15:04 ` [tarantool-patches] [PATCH 6/9] sql: make comparison predicate return boolean Nikita Pettik
2019-04-16 14:12   ` [tarantool-patches] " Vladislav Shpilevoy
2019-04-18 17:54     ` n.pettik
2019-04-14 15:04 ` [tarantool-patches] [PATCH 7/9] sql: make predicates accept and " Nikita Pettik
2019-04-16 14:12   ` Vladislav Shpilevoy [this message]
2019-04-18 17:55     ` [tarantool-patches] " n.pettik
2019-04-14 15:04 ` [tarantool-patches] [PATCH 9/9] sql: make <search condition> accept only boolean Nikita Pettik
2019-04-16 14:12   ` [tarantool-patches] " Vladislav Shpilevoy
2019-04-18 17:55     ` n.pettik
2019-04-22 18:02       ` Vladislav Shpilevoy
2019-04-23 19:59         ` n.pettik
2019-04-23 21:06           ` Vladislav Shpilevoy
2019-04-23 22:01             ` n.pettik
     [not found] ` <b2a84f129c2343d3da3311469cbb7b20488a21c2.1555252410.git.korablev@tarantool.org>
2019-04-16 14:12   ` [tarantool-patches] Re: [PATCH 8/9] sql: make LIKE predicate return boolean result Vladislav Shpilevoy
2019-04-18 17:55     ` n.pettik
2019-04-22 18:02       ` Vladislav Shpilevoy
2019-04-23 19:58         ` n.pettik
2019-04-24 10:28 ` [tarantool-patches] Re: [PATCH 0/9] Introduce type BOOLEAN in SQL Vladislav Shpilevoy
2019-04-25  8:46 ` Kirill Yukhin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=29403d26-5619-32ec-d2a6-474cc5256994@tarantool.org \
    --to=v.shpilevoy@tarantool.org \
    --cc=korablev@tarantool.org \
    --cc=kostja@tarantool.org \
    --cc=tarantool-patches@freelists.org \
    --subject='[tarantool-patches] Re: [PATCH 7/9] sql: make predicates accept and return boolean' \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox