[Tarantool-patches] [PATCH v2 2/4] sql: allow to bind uuid values

imeevma at tarantool.org imeevma at tarantool.org
Sat Jul 10 17:33:38 MSK 2021


Thank you for the review! My answers, diff and new patch below. However, this
diff not exactly right, since the patch also changed due to dropping of previous
patch of patch-set.

On 08.07.2021 00:44, Vladislav Shpilevoy wrote:
> Thanks for the patch!
>
> See 4 comments below.
>
> On 05.07.2021 17:06, Mergen Imeev via Tarantool-patches wrote:
>> After this patch, uuid values can be binded like any other supported by
>
> 1. binded -> bound.
>
Fixed.

>> diff --git a/src/box/bind.h b/src/box/bind.h
>> index 568c558f3..20f3e7942 100644
>> --- a/src/box/bind.h
>> +++ b/src/box/bind.h
>> @@ -40,6 +40,8 @@ extern "C" {
>>  #include <stdlib.h>
>>  
>>  #include "msgpuck.h"
>> +#include "uuid/tt_uuid.h"
>> +#include "lib/core/mp_extension_types.h"
>
> 2. lib/core is already in the paths. You can omit it.
>
Fixed.

>> diff --git a/src/box/sql/vdbeapi.c b/src/box/sql/vdbeapi.c
>> index aaae12e41..a9700350d 100644
>> --- a/src/box/sql/vdbeapi.c
>> +++ b/src/box/sql/vdbeapi.c
>> @@ -840,6 +840,17 @@ sql_bind_zeroblob64(sql_stmt * pStmt, int i, sql_uint64 n)
>>      return sql_bind_zeroblob(pStmt, i, n);
>>  }
>>  
>> +int
>> +sql_bind_uuid(struct sql_stmt *stmt, int i, const struct tt_uuid *uuid)
>> +{
>> +    struct Vdbe *p = (struct Vdbe *)stmt;
>> +    if (vdbeUnbind(p, i) != 0)
>> +            return -1;
>> +    int rc = sql_bind_type(p, i, "uuid");
>> +    mem_set_uuid(&p->aVar[i - 1], uuid);
>
> 3. Why do you set UUID even if bind_type() failed?
>
It happened because I used sql_bind_uint64() as prototype and did not noticed
that there were an error. Fixed.

>> diff --git a/test/sql-tap/gh-6164-uuid-follow-ups.test.lua b/test/sql-tap/gh-6164-uuid-follow-ups.test.lua
>> index 8872f9f23..426717972 100755
>> --- a/test/sql-tap/gh-6164-uuid-follow-ups.test.lua
>> +++ b/test/sql-tap/gh-6164-uuid-follow-ups.test.lua
>> @@ -32,4 +32,18 @@ test:do_execsql_test(
>>          true
>>      })
>>  
>> +-- Make sure that uuid value can be binded.
>> +box.execute('CREATE TABLE t(i INT PRIMARY KEY, a UUID);')
>> +box.execute('INSERT INTO t VALUES(1, ?);', {uuid});
>
> 4. Do you need a table for that? Can you just make 'SELECT ?' with
> the uuid argument?
>
True, fixed.

>> +
>> +test:do_execsql_test(
>> +    "gh-6164-4",
>> +    [[
>> +        SELECT * FROM t;
>> +    ]], {
>> +        1, uuid
>> +    })
>> +
>> +box.execute([[DROP TABLE t;]])
>> +
>>  test:finish_test()
>>


Diff:

commit daf89852f18bc3dbb3255dfd785182da5ef81e93
Author: Mergen Imeev <imeevma at gmail.com>
Date:   Sat Jul 10 14:50:53 2021 +0300

    Review fix

diff --git a/src/box/bind.h b/src/box/bind.h
index 20f3e7942..143f010ce 100644
--- a/src/box/bind.h
+++ b/src/box/bind.h
@@ -41,7 +41,7 @@ extern "C" {
 
 #include "msgpuck.h"
 #include "uuid/tt_uuid.h"
-#include "lib/core/mp_extension_types.h"
+#include "mp_extension_types.h"
 
 struct sql_stmt;
 
diff --git a/src/box/sql/vdbeapi.c b/src/box/sql/vdbeapi.c
index a9700350d..8031ee0dc 100644
--- a/src/box/sql/vdbeapi.c
+++ b/src/box/sql/vdbeapi.c
@@ -844,11 +844,10 @@ int
 sql_bind_uuid(struct sql_stmt *stmt, int i, const struct tt_uuid *uuid)
 {
        struct Vdbe *p = (struct Vdbe *)stmt;
-       if (vdbeUnbind(p, i) != 0)
+       if (vdbeUnbind(p, i) != 0 || sql_bind_type(p, i, "uuid") != 0)
                return -1;
-       int rc = sql_bind_type(p, i, "uuid");
        mem_set_uuid(&p->aVar[i - 1], uuid);
-       return rc;
+       return 0;
 }
 
 int
diff --git a/test/sql-tap/gh-6164-uuid-follow-ups.test.lua b/test/sql-tap/gh-6164-uuid-follow-ups.test.lua
index 822311237..4fc5052d8 100755
--- a/test/sql-tap/gh-6164-uuid-follow-ups.test.lua
+++ b/test/sql-tap/gh-6164-uuid-follow-ups.test.lua
@@ -1,8 +1,6 @@
 #!/usr/bin/env tarantool
 local test = require("sqltester")
-test:plan(2)
-
-local uuid = require('uuid').fromstr('11111111-1111-1111-1111-111111111111')
+test:plan(4)
 
 -- Make sure that function quote() can work with uuid.
 test:do_execsql_test(
@@ -14,17 +12,27 @@ test:do_execsql_test(
     })
 
 -- Make sure that uuid value can be binded.
-box.execute('CREATE TABLE t(i INT PRIMARY KEY, a UUID);')
-box.execute('INSERT INTO t VALUES(1, ?);', {uuid});
+local uuid1 = require('uuid').fromstr('11111111-1111-1111-1111-111111111111')
+local uuid2 = require('uuid').fromstr('11111111-2222-1111-1111-111111111111')
+local uuid3 = require('uuid').fromstr('11111111-1111-3333-1111-111111111111')
+test:do_test(
+    "gh-6164-2",
+    function()
+        return box.execute([[SELECT ?;]], {uuid1}).rows[1][1]
+    end,
+    uuid1)
+test:do_test(
+    "gh-6164-3",
+    function()
+        return box.execute([[SELECT $2;]], {123, uuid2}).rows[1][1]
+    end,
+    uuid2)
 
-test:do_execsql_test(
+test:do_test(
     "gh-6164-4",
-    [[
-        SELECT * FROM t;
-    ]], {
-        1, uuid
-    })
-
-box.execute([[DROP TABLE t;]])
+    function()
+        return box.execute([[SELECT :two;]], {{[":two"] = uuid3}}).rows[1][1]
+    end,
+    uuid3)
 
 test:finish_test()



New patch:

commit 8faa40c89f027dbb9aa8c8d7551b6b1aa214ed88
Author: Mergen Imeev <imeevma at gmail.com>
Date:   Mon Jul 5 11:57:35 2021 +0300

    sql: allow to bind uuid values
    
    After this patch, uuid values can be bound like any other supported by
    SQL values.
    
    Part of #6164

diff --git a/src/box/bind.c b/src/box/bind.c
index d45a0f9a7..734f65186 100644
--- a/src/box/bind.c
+++ b/src/box/bind.c
@@ -191,6 +191,9 @@ sql_bind_column(struct sql_stmt *stmt, const struct sql_bind *p,
        case MP_BIN:
                return sql_bind_blob64(stmt, pos, (const void *) p->s, p->bytes,
                                       SQL_STATIC);
+       case MP_EXT:
+               assert(p->ext_type == MP_UUID);
+               return sql_bind_uuid(stmt, pos, &p->uuid);
        default:
                unreachable();
        }
diff --git a/src/box/bind.h b/src/box/bind.h
index 568c558f3..143f010ce 100644
--- a/src/box/bind.h
+++ b/src/box/bind.h
@@ -40,6 +40,8 @@ extern "C" {
 #include <stdlib.h>
 
 #include "msgpuck.h"
+#include "uuid/tt_uuid.h"
+#include "mp_extension_types.h"
 
 struct sql_stmt;
 
@@ -59,6 +61,8 @@ struct sql_bind {
        uint32_t bytes;
        /** MessagePack type of the value. */
        enum mp_type type;
+       /** Subtype of MP_EXT type. */
+       enum mp_extension_type ext_type;
        /** Bind value. */
        union {
                bool b;
@@ -67,6 +71,7 @@ struct sql_bind {
                uint64_t u64;
                /** For string or blob. */
                const char *s;
+               struct tt_uuid uuid;
        };
 };
 
diff --git a/src/box/lua/execute.c b/src/box/lua/execute.c
index 1b59b2e4a..62ccaf3f1 100644
--- a/src/box/lua/execute.c
+++ b/src/box/lua/execute.c
@@ -371,6 +371,10 @@ lua_sql_bind_decode(struct lua_State *L, struct sql_bind *bind, int idx, int i)
                bind->s = mp_decode_bin(&field.sval.data, &bind->bytes);
                break;
        case MP_EXT:
+               if (field.ext_type == MP_UUID) {
+                       bind->uuid = *field.uuidval;
+                       break;
+               }
                diag_set(ClientError, ER_SQL_BIND_TYPE, "USERDATA",
                         sql_bind_name(bind));
                return -1;
@@ -386,6 +390,7 @@ lua_sql_bind_decode(struct lua_State *L, struct sql_bind *bind, int idx, int i)
                unreachable();
        }
        bind->type = field.type;
+       bind->ext_type = field.ext_type;
        lua_pop(L, lua_gettop(L) - idx);
        return 0;
 }
diff --git a/src/box/sql/sqlInt.h b/src/box/sql/sqlInt.h
index ef8dcd693..115c52f96 100644
--- a/src/box/sql/sqlInt.h
+++ b/src/box/sql/sqlInt.h
@@ -326,6 +326,8 @@ struct sql_vfs {
 #define SQL_LIMIT_LIKE_PATTERN_LENGTH       8
 #define SQL_LIMIT_TRIGGER_DEPTH             9
 
+struct tt_uuid;
+
 enum sql_ret_code {
        /** sql_step() has another row ready. */
        SQL_ROW = 1,
@@ -634,6 +636,9 @@ int
 sql_bind_zeroblob64(sql_stmt *, int,
                        sql_uint64);
 
+int
+sql_bind_uuid(struct sql_stmt *stmt, int i, const struct tt_uuid *uuid);
+
 /**
  * Return the number of wildcards that should be bound to.
  */
diff --git a/src/box/sql/vdbeapi.c b/src/box/sql/vdbeapi.c
index aaae12e41..8031ee0dc 100644
--- a/src/box/sql/vdbeapi.c
+++ b/src/box/sql/vdbeapi.c
@@ -840,6 +840,16 @@ sql_bind_zeroblob64(sql_stmt * pStmt, int i, sql_uint64 n)
        return sql_bind_zeroblob(pStmt, i, n);
 }
 
+int
+sql_bind_uuid(struct sql_stmt *stmt, int i, const struct tt_uuid *uuid)
+{
+       struct Vdbe *p = (struct Vdbe *)stmt;
+       if (vdbeUnbind(p, i) != 0 || sql_bind_type(p, i, "uuid") != 0)
+               return -1;
+       mem_set_uuid(&p->aVar[i - 1], uuid);
+       return 0;
+}
+
 int
 sql_bind_parameter_count(const struct sql_stmt *stmt)
 {
diff --git a/test/sql-tap/gh-6164-uuid-follow-ups.test.lua b/test/sql-tap/gh-6164-uuid-follow-ups.test.lua
index a8f662f77..4fc5052d8 100755
--- a/test/sql-tap/gh-6164-uuid-follow-ups.test.lua
+++ b/test/sql-tap/gh-6164-uuid-follow-ups.test.lua
@@ -1,6 +1,6 @@
 #!/usr/bin/env tarantool
 local test = require("sqltester")
-test:plan(1)
+test:plan(4)
 
 -- Make sure that function quote() can work with uuid.
 test:do_execsql_test(
@@ -11,4 +11,28 @@ test:do_execsql_test(
         '11111111-1111-1111-1111-111111111111'
     })
 
+-- Make sure that uuid value can be binded.
+local uuid1 = require('uuid').fromstr('11111111-1111-1111-1111-111111111111')
+local uuid2 = require('uuid').fromstr('11111111-2222-1111-1111-111111111111')
+local uuid3 = require('uuid').fromstr('11111111-1111-3333-1111-111111111111')
+test:do_test(
+    "gh-6164-2",
+    function()
+        return box.execute([[SELECT ?;]], {uuid1}).rows[1][1]
+    end,
+    uuid1)
+test:do_test(
+    "gh-6164-3",
+    function()
+        return box.execute([[SELECT $2;]], {123, uuid2}).rows[1][1]
+    end,
+    uuid2)
+
+test:do_test(
+    "gh-6164-4",
+    function()
+        return box.execute([[SELECT :two;]], {{[":two"] = uuid3}}).rows[1][1]
+    end,
+    uuid3)
+
 test:finish_test()


More information about the Tarantool-patches mailing list