Tarantool development patches archive
 help / color / mirror / Atom feed
From: Nikita Pettik <korablev@tarantool.org>
To: tarantool-patches@freelists.org
Cc: v.shpilevoy@tarantool.org, kostja@tarantool.org,
	Nikita Pettik <korablev@tarantool.org>
Subject: [tarantool-patches] [PATCH 2/9] sql: disallow text values participate in sum() aggregate
Date: Sun, 14 Apr 2019 18:04:00 +0300	[thread overview]
Message-ID: <cf6661047c5e04da60569bd4118cafc1452401b8.1555252410.git.korablev@tarantool.org> (raw)
In-Reply-To: <cover.1555252410.git.korablev@tarantool.org>
In-Reply-To: <cover.1555252410.git.korablev@tarantool.org>

It is obvious that we can't add string with number except the case when
string is a number literal in quotes (aka '123' or '0.5'). Before this
patch values which can't be converted to numbers were just skipped.
Now error is raised. Another one misbehavior was in using
sql_value_numeric_type() function, which set flag indicating number
value in memory cell, but didn't clear MEM_Str flag. As a result, we
couldn't determine type of value in such memory cell without
ambigiousness.
---
 src/box/sql/func.c            | 38 ++++++++++++++++++++++++--------------
 src/box/sql/sqlInt.h          |  3 ---
 src/box/sql/vdbe.c            | 19 ++-----------------
 src/box/sql/vdbeInt.h         |  3 +--
 test/sql-tap/select1.test.lua |  4 ++--
 test/sql-tap/select5.test.lua |  3 ++-
 6 files changed, 31 insertions(+), 39 deletions(-)

diff --git a/src/box/sql/func.c b/src/box/sql/func.c
index b86a95d9a..9adfeec67 100644
--- a/src/box/sql/func.c
+++ b/src/box/sql/func.c
@@ -1495,24 +1495,34 @@ static void
 sumStep(sql_context * context, int argc, sql_value ** argv)
 {
 	SumCtx *p;
-	int type;
 	assert(argc == 1);
 	UNUSED_PARAMETER(argc);
 	p = sql_aggregate_context(context, sizeof(*p));
-	type = sql_value_numeric_type(argv[0]);
-	if (p && type != SQL_NULL) {
-		p->cnt++;
-		if (type == SQL_INTEGER) {
-			i64 v = sql_value_int64(argv[0]);
-			p->rSum += v;
-			if ((p->approx | p->overflow) == 0
-			    && sqlAddInt64(&p->iSum, v)) {
-				p->overflow = 1;
-			}
-		} else {
-			p->rSum += sql_value_double(argv[0]);
-			p->approx = 1;
+	assert(p != NULL);
+	int type = sql_value_type(argv[0]);
+	if (type == SQL_NULL)
+		return;
+	if (type != SQL_FLOAT && type != SQL_INTEGER) {
+		if (mem_apply_numeric_type(argv[0]) != 0) {
+			diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
+				 sql_value_text(argv[0]), "number");
+			context->fErrorOrAux = 1;
+			context->isError = SQL_TARANTOOL_ERROR;
+			return;
 		}
+		type = sql_value_type(argv[0]);
+	}
+	p->cnt++;
+	if (type == SQL_INTEGER) {
+		i64 v = sql_value_int64(argv[0]);
+		p->rSum += v;
+		if ((p->approx | p->overflow) == 0 &&
+		    sqlAddInt64(&p->iSum, v)) {
+			p->overflow = 1;
+		}
+	} else {
+		p->rSum += sql_value_double(argv[0]);
+		p->approx = 1;
 	}
 }
 
diff --git a/src/box/sql/sqlInt.h b/src/box/sql/sqlInt.h
index d8dc03284..b5c596d2f 100644
--- a/src/box/sql/sqlInt.h
+++ b/src/box/sql/sqlInt.h
@@ -458,9 +458,6 @@ sql_value_text(sql_value *);
 int
 sql_value_type(sql_value *);
 
-int
-sql_value_numeric_type(sql_value *);
-
 sql *
 sql_context_db_handle(sql_context *);
 
diff --git a/src/box/sql/vdbe.c b/src/box/sql/vdbe.c
index 1b3e2a59d..c689aaf1d 100644
--- a/src/box/sql/vdbe.c
+++ b/src/box/sql/vdbe.c
@@ -276,7 +276,8 @@ allocateCursor(
 int
 mem_apply_numeric_type(struct Mem *record)
 {
-	assert((record->flags & (MEM_Str | MEM_Int | MEM_Real)) == MEM_Str);
+	if ((record->flags & (MEM_Str | MEM_Int | MEM_Real)) != MEM_Str)
+		return -1;
 	int64_t integer_value;
 	if (sql_atoi64(record->z, &integer_value, record->n) == 0) {
 		record->u.i = integer_value;
@@ -355,22 +356,6 @@ mem_apply_type(struct Mem *record, enum field_type type)
 	}
 }
 
-/*
- * Try to convert the type of a function argument or a result column
- * into a numeric representation.  Use either INTEGER or REAL whichever
- * is appropriate.  But only do the conversion if it is possible without
- * loss of information and return the revised type of the argument.
- */
-int sql_value_numeric_type(sql_value *pVal) {
-	int eType = sql_value_type(pVal);
-	if (eType==SQL_TEXT) {
-		Mem *pMem = (Mem*)pVal;
-		mem_apply_numeric_type(pMem);
-		eType = sql_value_type(pVal);
-	}
-	return eType;
-}
-
 /*
  * Exported version of mem_apply_type(). This one works on sql_value*,
  * not the internal Mem* type.
diff --git a/src/box/sql/vdbeInt.h b/src/box/sql/vdbeInt.h
index 8cd00d43a..ec9123a66 100644
--- a/src/box/sql/vdbeInt.h
+++ b/src/box/sql/vdbeInt.h
@@ -274,8 +274,7 @@ mem_type_to_str(const struct Mem *p);
  * if we can do so without loss of information. Firstly, value
  * is attempted to be converted to integer, and in case of fail -
  * to floating point number. Note that function is assumed to be
- * called only on memory cell containing string,
- * i.e. memory->type == MEM_Str.
+ * called on memory cell containing string, i.e. mem->type == MEM_Str.
  *
  * @param record Memory cell containing value to be converted.
  * @retval 0 If value can be converted to integer or number.
diff --git a/test/sql-tap/select1.test.lua b/test/sql-tap/select1.test.lua
index be63e815d..1bad7679f 100755
--- a/test/sql-tap/select1.test.lua
+++ b/test/sql-tap/select1.test.lua
@@ -503,13 +503,13 @@ test:do_catchsql_test(
         -- </select1-2.17>
     })
 
-test:do_execsql_test(
+test:do_catchsql_test(
     "select1-2.17.1",
     [[
         SELECT sum(a) FROM t3
     ]], {
         -- <select1-2.17.1>
-        44.0
+        1, "Type mismatch: can not convert abc to number"
         -- </select1-2.17.1>
     })
 
diff --git a/test/sql-tap/select5.test.lua b/test/sql-tap/select5.test.lua
index 507448d00..1353b39fc 100755
--- a/test/sql-tap/select5.test.lua
+++ b/test/sql-tap/select5.test.lua
@@ -550,7 +550,7 @@ test:do_execsql_test(
     -- </select5-9.13>
 })
 
-test:do_execsql_test(
+test:do_catchsql_test(
     "select5-9.13.2",
     [[
             CREATE TABLE jj (s1 INT, s2 VARCHAR(1), PRIMARY KEY(s1));
@@ -558,6 +558,7 @@ test:do_execsql_test(
             SELECT 1 FROM jj HAVING avg(s2) = 1 AND avg(s2) = 0;
     ]], {
     -- <select5-9.13.2>
+    1, "Type mismatch: can not convert A to number"
     -- </select5-9.13.2>
 })
 
-- 
2.15.1

  parent reply	other threads:[~2019-04-14 15:04 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 ` Nikita Pettik [this message]
2019-04-16 14:12   ` [tarantool-patches] Re: [PATCH 2/9] sql: disallow text values participate in sum() aggregate 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   ` [tarantool-patches] " Vladislav Shpilevoy
2019-04-18 17:55     ` 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=cf6661047c5e04da60569bd4118cafc1452401b8.1555252410.git.korablev@tarantool.org \
    --to=korablev@tarantool.org \
    --cc=kostja@tarantool.org \
    --cc=tarantool-patches@freelists.org \
    --cc=v.shpilevoy@tarantool.org \
    --subject='Re: [tarantool-patches] [PATCH 2/9] sql: disallow text values participate in sum() aggregate' \
    /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