From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from localhost (localhost [127.0.0.1]) by turing.freelists.org (Avenir Technologies Mail Multiplex) with ESMTP id 0ACEB310FB for ; Fri, 7 Jun 2019 11:37:52 -0400 (EDT) Received: from turing.freelists.org ([127.0.0.1]) by localhost (turing.freelists.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id UxjJZsVc09PX for ; Fri, 7 Jun 2019 11:37:51 -0400 (EDT) Received: from smtpng2.m.smailru.net (smtpng2.m.smailru.net [94.100.179.3]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by turing.freelists.org (Avenir Technologies Mail Multiplex) with ESMTPS id 81DF231074 for ; Fri, 7 Jun 2019 11:37:51 -0400 (EDT) From: Nikita Pettik Subject: [tarantool-patches] [PATCH 4/6] sql: make built-in functions operate on unsigned values Date: Fri, 7 Jun 2019 18:37:44 +0300 Message-Id: <4acf9fab112e7ca119f1b2bf5efea53b3831ea4f.1559919361.git.korablev@tarantool.org> In-Reply-To: References: In-Reply-To: References: Sender: tarantool-patches-bounce@freelists.org Errors-to: tarantool-patches-bounce@freelists.org Reply-To: tarantool-patches@freelists.org List-Help: List-Unsubscribe: List-software: Ecartis version 1.0.0 List-Id: tarantool-patches List-Subscribe: List-Owner: List-post: List-Archive: To: tarantool-patches@freelists.org Cc: v.shpilevoy@tarantool.org, Nikita Pettik As a part of introduction unsigned type in SQL, let's patch all built-in function to make them accept and operate on unsigned value, i.e. values which come with MEM_UInt VDBE memory type. Part of #3810 Part of #4015 --- src/box/sql/func.c | 70 ++++++++++++++++++------------------------- src/box/sql/main.c | 3 +- src/box/sql/sqlInt.h | 9 ++++-- src/box/sql/vdbeInt.h | 2 +- src/box/sql/vdbeapi.c | 22 ++++++++++---- test/sql-tap/cast.test.lua | 8 ++--- test/sql-tap/check.test.lua | 2 +- test/sql-tap/cse.test.lua | 6 ++-- test/sql-tap/default.test.lua | 2 +- test/sql-tap/fkey2.test.lua | 4 +-- test/sql-tap/func.test.lua | 18 ++++++++--- test/sql-tap/table.test.lua | 2 +- test/sql-tap/tkt3493.test.lua | 4 +-- 13 files changed, 82 insertions(+), 70 deletions(-) diff --git a/src/box/sql/func.c b/src/box/sql/func.c index 457c9b92b..365f8f9d2 100644 --- a/src/box/sql/func.c +++ b/src/box/sql/func.c @@ -111,9 +111,11 @@ typeofFunc(sql_context * context, int NotUsed, sql_value ** argv) UNUSED_PARAMETER(NotUsed); switch (sql_value_type(argv[0])) { case MP_INT: - case MP_UINT: z = "integer"; break; + case MP_UINT: + z = "unsigned"; + break; case MP_STR: z = "string"; break; @@ -148,8 +150,7 @@ lengthFunc(sql_context * context, int argc, sql_value ** argv) case MP_INT: case MP_UINT: case MP_DOUBLE:{ - sql_result_int(context, - sql_value_bytes(argv[0])); + sql_result_uint(context, sql_value_bytes(argv[0])); break; } case MP_STR:{ @@ -157,7 +158,7 @@ lengthFunc(sql_context * context, int argc, sql_value ** argv) if (z == 0) return; len = sql_utf8_char_count(z, sql_value_bytes(argv[0])); - sql_result_int(context, len); + sql_result_uint(context, len); break; } default:{ @@ -179,24 +180,15 @@ absFunc(sql_context * context, int argc, sql_value ** argv) assert(argc == 1); UNUSED_PARAMETER(argc); switch (sql_value_type(argv[0])) { - case MP_UINT: + case MP_UINT: { + sql_result_uint(context, sql_value_uint64(argv[0])); + break; + } case MP_INT:{ - i64 iVal = sql_value_int64(argv[0]); - if (iVal < 0) { - if (iVal == SMALLEST_INT64) { - /* IMP: R-31676-45509 If X is the integer -9223372036854775808 - * then abs(X) throws an integer overflow error since there is no - * equivalent positive 64-bit two complement value. - */ - sql_result_error(context, - "integer overflow", - -1); - return; - } - iVal = -iVal; - } - sql_result_int64(context, iVal); - break; + i64 iVal = sql_value_int64(argv[0]); + assert(iVal < 0); + sql_result_uint(context, -iVal); + break; } case MP_NIL:{ /* IMP: R-37434-19929 Abs(X) returns NULL if X is NULL. */ @@ -358,7 +350,8 @@ position_func(struct sql_context *context, int argc, struct Mem **argv) } } finish: - sql_result_int(context, position); + assert(position >= 0); + sql_result_uint(context, position); } /* @@ -645,21 +638,13 @@ ICU_CASE_CONVERT(Upper); static void randomFunc(sql_context * context, int NotUsed, sql_value ** NotUsed2) { - sql_int64 r; + int64_t r; UNUSED_PARAMETER2(NotUsed, NotUsed2); sql_randomness(sizeof(r), &r); - if (r < 0) { - /* We need to prevent a random number of 0x8000000000000000 - * (or -9223372036854775808) since when you do abs() of that - * number of you get the same value back again. To do this - * in a way that is testable, mask the sign bit off of negative - * values, resulting in a positive value. Then take the - * 2s complement of that positive value. The end result can - * therefore be no less than -9223372036854775807. - */ - r = -(r & LARGEST_INT64); - } - sql_result_int64(context, r); + if (r < 0) + sql_result_int(context, r); + else + sql_result_uint(context, r); } /* @@ -1126,7 +1111,7 @@ unicodeFunc(sql_context * context, int argc, sql_value ** argv) const unsigned char *z = sql_value_text(argv[0]); (void)argc; if (z && z[0]) - sql_result_int(context, sqlUtf8Read(&z)); + sql_result_uint(context, sqlUtf8Read(&z)); } /* @@ -1145,10 +1130,13 @@ charFunc(sql_context * context, int argc, sql_value ** argv) return; } for (i = 0; i < argc; i++) { - sql_int64 x; + uint64_t x; unsigned c; - x = sql_value_int64(argv[i]); - if (x < 0 || x > 0x10ffff) + if (sql_value_type(argv[i]) == MP_INT) + x = 0xfffd; + else + x = sql_value_uint64(argv[i]); + if (x > 0x10ffff) x = 0xfffd; c = (unsigned)(x & 0x1fffff); if (c < 0x00080) { @@ -1627,7 +1615,7 @@ sum_step(struct sql_context *context, int argc, sql_value **argv) else p->rSum += (uint64_t) v; if ((p->approx | p->overflow) == 0 && - sql_add_int(p->iSum, p->is_neg, v, v < 0, &p->iSum, + sql_add_int(p->iSum, p->is_neg, v, type == MP_INT, &p->iSum, &p->is_neg) != 0) { p->overflow = 1; } @@ -1698,7 +1686,7 @@ countFinalize(sql_context * context) { CountCtx *p; p = sql_aggregate_context(context, 0); - sql_result_int64(context, p ? p->n : 0); + sql_result_uint(context, p ? p->n : 0); } /* diff --git a/src/box/sql/main.c b/src/box/sql/main.c index fe1135a71..6a08a9302 100644 --- a/src/box/sql/main.c +++ b/src/box/sql/main.c @@ -250,7 +250,8 @@ sql_row_count(struct sql_context *context, MAYBE_UNUSED int unused1, MAYBE_UNUSED sql_value **unused2) { sql *db = sql_context_db_handle(context); - sql_result_int(context, db->nChange); + assert(db->nChange >= 0); + sql_result_uint(context, db->nChange); } /* diff --git a/src/box/sql/sqlInt.h b/src/box/sql/sqlInt.h index c0e2ab699..4697e3003 100644 --- a/src/box/sql/sqlInt.h +++ b/src/box/sql/sqlInt.h @@ -455,6 +455,9 @@ sql_column_subtype(struct sql_stmt *stmt, int i); sql_int64 sql_value_int64(sql_value *); +uint64_t +sql_value_uint64(sql_value *val); + const unsigned char * sql_value_text(sql_value *); @@ -496,13 +499,13 @@ void sql_result_error_code(sql_context *, int); void -sql_result_int(sql_context *, int); +sql_result_int(sql_context *, int64_t); void -sql_result_bool(struct sql_context *ctx, bool value); +sql_result_uint(sql_context *ctx, int64_t u_val); void -sql_result_int64(sql_context *, sql_int64); +sql_result_bool(struct sql_context *ctx, bool value); void sql_result_null(sql_context *); diff --git a/src/box/sql/vdbeInt.h b/src/box/sql/vdbeInt.h index abed46486..0c86ed0f3 100644 --- a/src/box/sql/vdbeInt.h +++ b/src/box/sql/vdbeInt.h @@ -501,7 +501,7 @@ void sqlVdbeMemShallowCopy(Mem *, const Mem *, int); void sqlVdbeMemMove(Mem *, Mem *); int sqlVdbeMemNulTerminate(Mem *); int sqlVdbeMemSetStr(Mem *, const char *, int, u8, void (*)(void *)); -void sqlVdbeMemSetInt64(Mem *, i64); +void sqlVdbeMemSetInt64(Mem *, i64, bool is_neg); void mem_set_bool(struct Mem *mem, bool value); diff --git a/src/box/sql/vdbeapi.c b/src/box/sql/vdbeapi.c index 393782c23..752efeecb 100644 --- a/src/box/sql/vdbeapi.c +++ b/src/box/sql/vdbeapi.c @@ -239,6 +239,16 @@ sql_value_int64(sql_value * pVal) return i; } +uint64_t +sql_value_uint64(sql_value *val) +{ + int64_t i = 0; + bool is_neg; + sqlVdbeIntValue((struct Mem *) val, &i, &is_neg); + assert(!is_neg); + return i; +} + enum sql_subtype sql_value_subtype(sql_value * pVal) { @@ -386,21 +396,21 @@ sql_result_error(sql_context * pCtx, const char *z, int n) } void -sql_result_int(sql_context * pCtx, int iVal) +sql_result_int(sql_context * pCtx, int64_t iVal) { - mem_set_int(pCtx->pOut, (i64) iVal, iVal < 0); + mem_set_int(pCtx->pOut, (i64) iVal, true); } void -sql_result_bool(struct sql_context *ctx, bool value) +sql_result_uint(sql_context *ctx, int64_t u_val) { - mem_set_bool(ctx->pOut, value); + mem_set_int(ctx->pOut, u_val, false); } void -sql_result_int64(sql_context * pCtx, i64 iVal) +sql_result_bool(struct sql_context *ctx, bool value) { - mem_set_int(pCtx->pOut, iVal, iVal < 0); + mem_set_bool(ctx->pOut, value); } void diff --git a/test/sql-tap/cast.test.lua b/test/sql-tap/cast.test.lua index 531c310d2..315f49d08 100755 --- a/test/sql-tap/cast.test.lua +++ b/test/sql-tap/cast.test.lua @@ -220,7 +220,7 @@ test:do_execsql_test( SELECT typeof(123) ]], { -- - "integer" + "unsigned" -- }) @@ -280,7 +280,7 @@ test:do_execsql_test( SELECT typeof(CAST(123 AS SCALAR)) ]], { -- - "integer" + "unsigned" -- }) @@ -300,7 +300,7 @@ test:do_execsql_test( SELECT typeof(CAST(123 AS integer)) ]], { -- - "integer" + "unsigned" -- }) @@ -400,7 +400,7 @@ test:do_execsql_test( SELECT typeof(CAST(123.456 AS integer)) ]], { -- - "integer" + "unsigned" -- }) diff --git a/test/sql-tap/check.test.lua b/test/sql-tap/check.test.lua index b01afca7c..8fd722924 100755 --- a/test/sql-tap/check.test.lua +++ b/test/sql-tap/check.test.lua @@ -206,7 +206,7 @@ test:do_execsql_test( [[ CREATE TABLE t2( id INT primary key, - x INTEGER CONSTRAINT one CHECK( typeof(coalesce(x,0))=='integer'), + x INTEGER CONSTRAINT one CHECK( typeof(coalesce(x,0))=='unsigned'), y REAL CONSTRAINT two CHECK( typeof(coalesce(y,0.1))=='number' ), z TEXT CONSTRAINT three CHECK( typeof(coalesce(z,''))=='string' ) ); diff --git a/test/sql-tap/cse.test.lua b/test/sql-tap/cse.test.lua index 78d0d2046..f83cde9bd 100755 --- a/test/sql-tap/cse.test.lua +++ b/test/sql-tap/cse.test.lua @@ -165,7 +165,7 @@ test:do_execsql_test( SELECT CAST(b AS integer), typeof(b), CAST(b AS text), typeof(b) FROM t1 ]], { -- - 11, "integer", "11", "integer", 21, "integer", "21", "integer" + 11, "unsigned", "11", "unsigned", 21, "unsigned", "21", "unsigned" -- }) @@ -201,7 +201,7 @@ test:do_execsql_test( SELECT upper(b), typeof(b), b FROM t1 ]], { -- - "11", "integer", 11, "21", "integer", 21 + "11", "unsigned", 11, "21", "unsigned", 21 -- }) @@ -211,7 +211,7 @@ test:do_execsql_test( SELECT b, typeof(b), upper(b), typeof(b), b FROM t1 ]], { -- - 11, "integer", "11", "integer", 11, 21, "integer", "21", "integer", 21 + 11, "unsigned", "11", "unsigned", 11, 21, "unsigned", "21", "unsigned", 21 -- }) diff --git a/test/sql-tap/default.test.lua b/test/sql-tap/default.test.lua index 55d16bcd7..0353796d5 100755 --- a/test/sql-tap/default.test.lua +++ b/test/sql-tap/default.test.lua @@ -119,7 +119,7 @@ test:do_execsql_test( -- In current situation I don't know what to do, need Kirill's -- advice. -- Bulat - 1, "integer", 5, "integer", "row1", "string", 5.25, "number", 8.67, "number", "321", "string", 432, "integer" + 1, "unsigned", 5, "unsigned", "row1", "string", 5.25, "number", 8.67, "number", "321", "string", 432, "unsigned" -- }) diff --git a/test/sql-tap/fkey2.test.lua b/test/sql-tap/fkey2.test.lua index 54e5059b3..8e786edec 100755 --- a/test/sql-tap/fkey2.test.lua +++ b/test/sql-tap/fkey2.test.lua @@ -320,10 +320,10 @@ test:do_execsql_test( CREATE TABLE j(j INT PRIMARY KEY REFERENCES i); INSERT INTO i VALUES(35); INSERT INTO j VALUES(35); - SELECT j, typeof(j) FROM j; + SELECT j FROM j; ]], { -- - 35, "integer" + 35 -- }) diff --git a/test/sql-tap/func.test.lua b/test/sql-tap/func.test.lua index 314c528ab..9cf9c2f67 100755 --- a/test/sql-tap/func.test.lua +++ b/test/sql-tap/func.test.lua @@ -1,6 +1,6 @@ #!/usr/bin/env tarantool test = require("sqltester") -test:plan(14591) +test:plan(14592) --!./tcltestrunner.lua -- 2001 September 15 @@ -908,7 +908,7 @@ test:do_execsql_test( UNION ALL SELECT -9223372036854775807) ]], { -- - "integer" + "unsigned" -- }) @@ -1587,7 +1587,7 @@ test:do_execsql_test( SELECT typeof(sum(x)) FROM t6 ]], { -- - "integer" + "unsigned" -- }) @@ -1742,10 +1742,20 @@ test:do_catchsql_test( SELECT abs(-9223372036854775807-1); ]], { -- - 1, "Failed to execute SQL statement: integer overflow" + 0, {9223372036854775808LL} -- }) +test:do_catchsql_test( + "func-18.33", + [[ + SELECT abs(-9223372036854775807-1); + ]], { + -- + 0, {9223372036854775808LL} + -- +}) + -- The MATCH function exists but is only a stub and always throws an error. -- test:do_execsql_test( diff --git a/test/sql-tap/table.test.lua b/test/sql-tap/table.test.lua index 5b793c0fc..5ed4a83fa 100755 --- a/test/sql-tap/table.test.lua +++ b/test/sql-tap/table.test.lua @@ -906,7 +906,7 @@ test:do_execsql_test( FROM t7 LIMIT 1; ]], { -- - "integer", "null", "null", "null", "null", "null", "null", "null" + "unsigned", "null", "null", "null", "null", "null", "null", "null" -- }) diff --git a/test/sql-tap/tkt3493.test.lua b/test/sql-tap/tkt3493.test.lua index 67e79da72..df6bb4d36 100755 --- a/test/sql-tap/tkt3493.test.lua +++ b/test/sql-tap/tkt3493.test.lua @@ -229,7 +229,7 @@ test:do_execsql_test( SELECT typeof(b), b FROM t1 GROUP BY a HAVING b='456' ]], { -- - "integer", 456 + "unsigned", 456 -- }) @@ -239,7 +239,7 @@ test:do_execsql_test( SELECT typeof(b), b FROM t1 GROUP BY b HAVING b='456' ]], { -- - "integer", 456 + "unsigned", 456 -- }) -- 2.15.1