[Tarantool-patches] [PATCH v6 06/22] sql: check args of length()

imeevma at tarantool.org imeevma at tarantool.org
Thu Jul 16 17:45:52 MSK 2020


After this patch, the argument types of the length(), char_length() and
character_length() functions will be checked properly.

Part of #4159
---
 src/box/sql/func.c             |  48 ++++-------
 test/sql-tap/func.test.lua     |   2 +-
 test/sql-tap/func5.test.lua    | 149 ++++++++++++++++++++++++++++++++-
 test/sql-tap/orderby1.test.lua |   2 +-
 test/sql/boolean.result        |  10 +--
 5 files changed, 170 insertions(+), 41 deletions(-)

diff --git a/src/box/sql/func.c b/src/box/sql/func.c
index 2d0aea801..a22ba38e2 100644
--- a/src/box/sql/func.c
+++ b/src/box/sql/func.c
@@ -467,30 +467,18 @@ lengthFunc(sql_context * context, int argc, sql_value ** argv)
 
 	assert(argc == 1);
 	UNUSED_PARAMETER(argc);
-	switch (sql_value_type(argv[0])) {
-	case MP_BIN:
-	case MP_ARRAY:
-	case MP_MAP:
-	case MP_INT:
-	case MP_UINT:
-	case MP_BOOL:
-	case MP_DOUBLE:{
-			sql_result_uint(context, sql_value_bytes(argv[0]));
-			break;
-		}
-	case MP_STR:{
-			const unsigned char *z = sql_value_text(argv[0]);
-			if (z == 0)
-				return;
-			len = sql_utf8_char_count(z, sql_value_bytes(argv[0]));
-			sql_result_uint(context, len);
-			break;
-		}
-	default:{
-			sql_result_null(context);
-			break;
-		}
-	}
+	enum mp_type mp_type = sql_value_type(argv[0]);
+	if (mp_type == MP_NIL)
+		return sql_result_null(context);
+	if (mp_type == MP_BIN)
+		return sql_result_uint(context, sql_value_bytes(argv[0]));
+	assert(mp_type == MP_STR);
+	const unsigned char *z = sql_value_text(argv[0]);
+	if (z == NULL)
+		return;
+	len = sql_utf8_char_count(z, sql_value_bytes(argv[0]));
+	sql_result_uint(context, len);
+	return;
 }
 
 /*
@@ -2278,9 +2266,9 @@ static struct {
 	 }, {
 	 .name = "CHARACTER_LENGTH",
 	 .param_count = 1,
-	 .first_arg = FIELD_TYPE_ANY,
+	 .first_arg = FIELD_TYPE_STRING,
 	 .args = FIELD_TYPE_ANY,
-	 .is_blob_like_str = false,
+	 .is_blob_like_str = true,
 	 .returns = FIELD_TYPE_INTEGER,
 	 .aggregate = FUNC_AGGREGATE_NONE,
 	 .is_deterministic = true,
@@ -2291,9 +2279,9 @@ static struct {
 	}, {
 	 .name = "CHAR_LENGTH",
 	 .param_count = 1,
-	 .first_arg = FIELD_TYPE_ANY,
+	 .first_arg = FIELD_TYPE_STRING,
 	 .args = FIELD_TYPE_ANY,
-	 .is_blob_like_str = false,
+	 .is_blob_like_str = true,
 	 .returns = FIELD_TYPE_INTEGER,
 	 .aggregate = FUNC_AGGREGATE_NONE,
 	 .is_deterministic = true,
@@ -2551,9 +2539,9 @@ static struct {
 	}, {
 	 .name = "LENGTH",
 	 .param_count = 1,
-	 .first_arg = FIELD_TYPE_ANY,
+	 .first_arg = FIELD_TYPE_STRING,
 	 .args = FIELD_TYPE_ANY,
-	 .is_blob_like_str = false,
+	 .is_blob_like_str = true,
 	 .returns = FIELD_TYPE_INTEGER,
 	 .aggregate = FUNC_AGGREGATE_NONE,
 	 .is_deterministic = true,
diff --git a/test/sql-tap/func.test.lua b/test/sql-tap/func.test.lua
index ffee8f1c5..69d175e16 100755
--- a/test/sql-tap/func.test.lua
+++ b/test/sql-tap/func.test.lua
@@ -95,7 +95,7 @@ test:do_execsql_test(
 test:do_execsql_test(
     "func-1.4",
     [[
-        SELECT coalesce(length(a),-1) FROM t2
+        SELECT coalesce(length(CAST(a AS STRING)),-1) FROM t2
     ]], {
         -- <func-1.4>
         1, -1, 3, -1, 5
diff --git a/test/sql-tap/func5.test.lua b/test/sql-tap/func5.test.lua
index 6e65b98ac..0398d8a9d 100755
--- a/test/sql-tap/func5.test.lua
+++ b/test/sql-tap/func5.test.lua
@@ -1,6 +1,6 @@
 #!/usr/bin/env tarantool
 test = require("sqltester")
-test:plan(57)
+test:plan(78)
 
 --!./tcltestrunner.lua
 -- 2010 August 27
@@ -542,4 +542,151 @@ test:do_catchsql_test(
         1, "Type mismatch: can not convert varbinary to unsigned"
     })
 
+test:do_execsql_test(
+    "func-5-6.6.1", [[
+        SELECT length(NULL);
+    ]],{
+        ""
+    })
+
+test:do_catchsql_test(
+    "func-5-6.6.2", [[
+        SELECT length(123);
+    ]], {
+        1, "Type mismatch: can not convert 123 to string"
+    })
+
+test:do_catchsql_test(
+    "func-5-6.6.3", [[
+        SELECT length(-123);
+    ]], {
+        1, "Type mismatch: can not convert -123 to string"
+    })
+
+test:do_catchsql_test(
+    "func-5-6.6.4", [[
+        SELECT length(-5.5);
+    ]], {
+        1, "Type mismatch: can not convert -5.5 to string"
+    })
+
+test:do_execsql_test(
+    "func-5-6.6.5", [[
+        SELECT length('-123');
+    ]], {
+        4
+    })
+
+test:do_catchsql_test(
+    "func-5-6.6.6", [[
+        SELECT length(false);
+    ]], {
+        1, "Type mismatch: can not convert FALSE to string"
+    })
+
+test:do_execsql_test(
+    "func-5-6.6.7", [[
+        SELECT length(X'3334');
+    ]], {
+        2
+    })
+
+test:do_execsql_test(
+    "func-5-6.7.1", [[
+        SELECT char_length(NULL);
+    ]],{
+        ""
+    })
+
+test:do_catchsql_test(
+    "func-5-6.7.2", [[
+        SELECT char_length(123);
+    ]], {
+        1, "Type mismatch: can not convert 123 to string"
+    })
+
+test:do_catchsql_test(
+    "func-5-6.7.3", [[
+        SELECT char_length(-123);
+    ]], {
+        1, "Type mismatch: can not convert -123 to string"
+    })
+
+test:do_catchsql_test(
+    "func-5-6.7.4", [[
+        SELECT char_length(-5.5);
+    ]], {
+        1, "Type mismatch: can not convert -5.5 to string"
+    })
+
+test:do_execsql_test(
+    "func-5-6.7.5", [[
+        SELECT char_length('-123');
+    ]], {
+        4
+    })
+
+test:do_catchsql_test(
+    "func-5-6.7.6", [[
+        SELECT char_length(false);
+    ]], {
+        1, "Type mismatch: can not convert FALSE to string"
+    })
+
+test:do_execsql_test(
+    "func-5-6.7.7", [[
+        SELECT char_length(X'3334');
+    ]], {
+        2
+    })
+
+test:do_execsql_test(
+    "func-5-6.8.1", [[
+        SELECT character_length(NULL);
+    ]],{
+        ""
+    })
+
+test:do_catchsql_test(
+    "func-5-6.8.2", [[
+        SELECT character_length(123);
+    ]], {
+        1, "Type mismatch: can not convert 123 to string"
+    })
+
+test:do_catchsql_test(
+    "func-5-6.8.3", [[
+        SELECT character_length(-123);
+    ]], {
+        1, "Type mismatch: can not convert -123 to string"
+    })
+
+test:do_catchsql_test(
+    "func-5-6.8.4", [[
+        SELECT character_length(-5.5);
+    ]], {
+        1, "Type mismatch: can not convert -5.5 to string"
+    })
+
+test:do_execsql_test(
+    "func-5-6.8.5", [[
+        SELECT character_length('-123');
+    ]], {
+        4
+    })
+
+test:do_catchsql_test(
+    "func-5-6.8.6", [[
+        SELECT character_length(false);
+    ]], {
+        1, "Type mismatch: can not convert FALSE to string"
+    })
+
+test:do_execsql_test(
+    "func-5-6.8.7", [[
+        SELECT character_length(X'3334');
+    ]], {
+        2
+    })
+
 test:finish_test()
diff --git a/test/sql-tap/orderby1.test.lua b/test/sql-tap/orderby1.test.lua
index 51e8d301f..95a8de487 100755
--- a/test/sql-tap/orderby1.test.lua
+++ b/test/sql-tap/orderby1.test.lua
@@ -735,7 +735,7 @@ test:do_execsql_test(
         SELECT (
           SELECT 'hardware' FROM ( 
             SELECT 'software' ORDER BY 'firmware' ASC, 'sportswear' DESC
-          ) GROUP BY 1 HAVING length(b) <> 0
+          ) GROUP BY 1 HAVING length(CAST(b AS STRING)) <> 0
         )
         FROM abc;
     ]], {
diff --git a/test/sql/boolean.result b/test/sql/boolean.result
index c470ebd40..39098b1f4 100644
--- a/test/sql/boolean.result
+++ b/test/sql/boolean.result
@@ -314,14 +314,8 @@ SELECT quote(a) FROM t0;
 -- gh-4462: LENGTH didn't take BOOLEAN arguments.
 SELECT length(a) FROM t0;
  | ---
- | - metadata:
- |   - name: length(a)
- |     type: integer
- |   rows:
- |   - [5]
- |   - [4]
- |   - [null]
- |   - [null]
+ | - null
+ | - 'Type mismatch: can not convert FALSE to string'
  | ...
 SELECT typeof(a) FROM t0;
  | ---
-- 
2.25.1



More information about the Tarantool-patches mailing list