[tarantool-patches] [PATCH 4/6] sql: make built-in functions operate on unsigned values
Nikita Pettik
korablev at tarantool.org
Fri Jun 7 18:37:44 MSK 2019
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)
]], {
-- <cast-1.22>
- "integer"
+ "unsigned"
-- </cast-1.22>
})
@@ -280,7 +280,7 @@ test:do_execsql_test(
SELECT typeof(CAST(123 AS SCALAR))
]], {
-- <cast-1.28>
- "integer"
+ "unsigned"
-- </cast-1.28>
})
@@ -300,7 +300,7 @@ test:do_execsql_test(
SELECT typeof(CAST(123 AS integer))
]], {
-- <cast-1.30>
- "integer"
+ "unsigned"
-- </cast-1.30>
})
@@ -400,7 +400,7 @@ test:do_execsql_test(
SELECT typeof(CAST(123.456 AS integer))
]], {
-- <cast-1.38>
- "integer"
+ "unsigned"
-- </cast-1.38>
})
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
]], {
-- <cse-1.10>
- 11, "integer", "11", "integer", 21, "integer", "21", "integer"
+ 11, "unsigned", "11", "unsigned", 21, "unsigned", "21", "unsigned"
-- </cse-1.10>
})
@@ -201,7 +201,7 @@ test:do_execsql_test(
SELECT upper(b), typeof(b), b FROM t1
]], {
-- <cse-1.13>
- "11", "integer", 11, "21", "integer", 21
+ "11", "unsigned", 11, "21", "unsigned", 21
-- </cse-1.13>
})
@@ -211,7 +211,7 @@ test:do_execsql_test(
SELECT b, typeof(b), upper(b), typeof(b), b FROM t1
]], {
-- <cse-1.14>
- 11, "integer", "11", "integer", 11, 21, "integer", "21", "integer", 21
+ 11, "unsigned", "11", "unsigned", 11, 21, "unsigned", "21", "unsigned", 21
-- </cse-1.14>
})
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"
-- </default-3.1>
})
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;
]], {
-- <fkey2-2.1>
- 35, "integer"
+ 35
-- </fkey2-2.1>
})
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)
]], {
-- <func-8.6>
- "integer"
+ "unsigned"
-- </func-8.6>
})
@@ -1587,7 +1587,7 @@ test:do_execsql_test(
SELECT typeof(sum(x)) FROM t6
]], {
-- <func-18.11>
- "integer"
+ "unsigned"
-- </func-18.11>
})
@@ -1742,10 +1742,20 @@ test:do_catchsql_test(
SELECT abs(-9223372036854775807-1);
]], {
-- <func-18.32>
- 1, "Failed to execute SQL statement: integer overflow"
+ 0, {9223372036854775808LL}
-- </func-18.32>
})
+test:do_catchsql_test(
+ "func-18.33",
+ [[
+ SELECT abs(-9223372036854775807-1);
+ ]], {
+ -- <func-18.32>
+ 0, {9223372036854775808LL}
+ -- </func-18.32>
+})
+
-- 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;
]], {
-- <table-11.1>
- "integer", "null", "null", "null", "null", "null", "null", "null"
+ "unsigned", "null", "null", "null", "null", "null", "null", "null"
-- </table-11.1>
})
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'
]], {
-- <tkt3493-2.5.1>
- "integer", 456
+ "unsigned", 456
-- </tkt3493-2.5.1>
})
@@ -239,7 +239,7 @@ test:do_execsql_test(
SELECT typeof(b), b FROM t1 GROUP BY b HAVING b='456'
]], {
-- <tkt3493-2.5.2>
- "integer", 456
+ "unsigned", 456
-- </tkt3493-2.5.2>
})
--
2.15.1
More information about the Tarantool-patches
mailing list