Tarantool development patches archive
 help / color / mirror / Atom feed
* [Tarantool-patches] [PATCH v2 0/7] Remove implicit cast
@ 2020-06-11 12:54 imeevma
  2020-06-11 12:54 ` [Tarantool-patches] [PATCH v2 1/7] sql: remove implicit cast for assignment imeevma
                   ` (6 more replies)
  0 siblings, 7 replies; 14+ messages in thread
From: imeevma @ 2020-06-11 12:54 UTC (permalink / raw)
  To: v.shpilevoy, tsafin, tarantool-patches

This patch-set removes implicit cast between string and numbers
for assignment and for comparison.

https://github.com/tarantool/tarantool/issues/3809
https://github.com/tarantool/tarantool/issues/4230
https://github.com/tarantool/tarantool/tree/imeevma/gh-3809-disallow-imlicit-cast-from-string-to-nums

@ChangeLog
 - [Breaking change] Removed implicit cast from string to numbers
   and vice versa for assignment and comparison.

v2:
 - Added a commit that changes the type mismatch error
   description.

Mergen Imeev (7):
  sql: remove implicit cast for assignment
  sql: remove mem_apply_type() from OP_MakeRecord
  sql: replace ApplyType by CheckType for IN operator
  sql: remove mem_apply_type() from OP_MustBeInt
  sql: remove implicit cast from string for comparison
  sql: remove OP_ApplyType
  sql: use type instead of value in type mismatch error

 src/box/sql/analyze.c                         |    7 +-
 src/box/sql/delete.c                          |    8 +-
 src/box/sql/expr.c                            |   53 +-
 src/box/sql/fk_constraint.c                   |    9 +-
 src/box/sql/insert.c                          |   16 +-
 src/box/sql/select.c                          |   25 +-
 src/box/sql/sqlInt.h                          |   25 -
 src/box/sql/update.c                          |   14 +-
 src/box/sql/vdbe.c                            |  273 +++--
 src/box/sql/vdbeInt.h                         |    5 +
 src/box/sql/vdbemem.c                         |    7 +
 src/box/sql/wherecode.c                       |  211 +---
 test/sql-tap/autoinc.test.lua                 |    6 +-
 test/sql-tap/cast.test.lua                    |   16 +-
 test/sql-tap/default.test.lua                 |    6 +-
 test/sql-tap/e_select1.test.lua               |   27 +-
 .../gh-3809-implicit-cast-assignment.test.lua |  649 +++++++++++
 .../gh-4230-del-impl-cast-str-to-num.test.lua |  281 +++++
 ...-4766-wrong-cast-from-blob-to-int.test.lua |    9 +-
 test/sql-tap/identifier_case.test.lua         |    6 +-
 test/sql-tap/in1.test.lua                     |    4 +-
 test/sql-tap/in3.test.lua                     |   18 +-
 test/sql-tap/in4.test.lua                     |  100 +-
 test/sql-tap/index1.test.lua                  |   28 +-
 test/sql-tap/insert3.test.lua                 |   12 +-
 test/sql-tap/intpkey.test.lua                 |   37 +-
 test/sql-tap/join.test.lua                    |    8 +-
 test/sql-tap/limit.test.lua                   |    2 +-
 test/sql-tap/minmax2.test.lua                 |    6 +-
 test/sql-tap/misc1.test.lua                   |   66 +-
 test/sql-tap/numcast.test.lua                 |    6 +-
 test/sql-tap/select1.test.lua                 |   16 +-
 test/sql-tap/select4.test.lua                 |   12 +-
 test/sql-tap/select7.test.lua                 |    4 +-
 test/sql-tap/sort.test.lua                    |    8 +-
 test/sql-tap/subquery.test.lua                |   73 +-
 test/sql-tap/tkt-3998683a16.test.lua          |   26 +-
 test/sql-tap/tkt-54844eea3f.test.lua          |    8 +-
 test/sql-tap/tkt-7bbfb7d442.test.lua          |    4 +-
 test/sql-tap/tkt-80e031a00f.test.lua          |    4 +-
 test/sql-tap/tkt-9a8b09f8e6.test.lua          |  528 ---------
 test/sql-tap/tkt-f973c7ac31.test.lua          |   18 +-
 test/sql-tap/tkt-fc7bd6358f.test.lua          |  111 --
 test/sql-tap/tkt1444.test.lua                 |    4 +-
 test/sql-tap/tkt3493.test.lua                 |   46 +-
 test/sql-tap/tkt3841.test.lua                 |   12 +-
 test/sql-tap/transitive1.test.lua             |   16 +-
 test/sql-tap/triggerA.test.lua                |    4 +-
 test/sql-tap/unique.test.lua                  |    8 +-
 test/sql-tap/view.test.lua                    |    2 +-
 test/sql-tap/where2.test.lua                  |  183 +--
 test/sql-tap/where5.test.lua                  |   22 +-
 test/sql-tap/whereB.test.lua                  |  908 ---------------
 test/sql-tap/whereC.test.lua                  |    8 +-
 test/sql/boolean.result                       | 1026 ++++++++---------
 test/sql/integer-overflow.result              |    4 +-
 test/sql/persistency.result                   |    2 +-
 test/sql/types.result                         |   57 +-
 test/sql/types.test.lua                       |    1 -
 59 files changed, 1906 insertions(+), 3149 deletions(-)
 create mode 100755 test/sql-tap/gh-3809-implicit-cast-assignment.test.lua
 create mode 100755 test/sql-tap/gh-4230-del-impl-cast-str-to-num.test.lua
 delete mode 100755 test/sql-tap/tkt-9a8b09f8e6.test.lua
 delete mode 100755 test/sql-tap/tkt-fc7bd6358f.test.lua
 delete mode 100755 test/sql-tap/whereB.test.lua

-- 
2.25.1

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [Tarantool-patches] [PATCH v2 1/7] sql: remove implicit cast for assignment
  2020-06-11 12:54 [Tarantool-patches] [PATCH v2 0/7] Remove implicit cast imeevma
@ 2020-06-11 12:54 ` imeevma
  2020-06-11 12:54 ` [Tarantool-patches] [PATCH v2 2/7] sql: remove mem_apply_type() from OP_MakeRecord imeevma
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 14+ messages in thread
From: imeevma @ 2020-06-11 12:54 UTC (permalink / raw)
  To: v.shpilevoy, tsafin, tarantool-patches

Hi! Thanks for the review! My answer and patch are below. The
patch is the same.


On 10.06.2020 01:28, Vladislav Shpilevoy wrote:
> Hi! Thanks for the patch!
>
>>>> +    ]], {
>>>> +        0
>>>> +    })
>>>> +
>>>> diff --git a/test/sql-tap/numcast.test.lua b/test/sql-tap/numcast.test.lua
>>>> index eeac5353a..9bbae5ca4 100755
>>>> --- a/test/sql-tap/numcast.test.lua
>>>> +++ b/test/sql-tap/numcast.test.lua
>>>> @@ -135,7 +135,7 @@ test:do_catchsql_test(
>>>>           INSERT INTO t VALUES(20000000000000000000.01);
>>>>           SELECT * FROM t;
>>>>       ]], {
>>>> -        1,"Tuple field 1 type does not match one required by operation: expected integer"
>>>> +        1,"Type mismatch: can not convert real to integer"
>>> 8. Is it correct, that we can remove all the checks from OP_CheckType
>>> except numeric conversions, and everything will work fine, because
>>> box makes the type checks anyway? It seems OP_CheckType duplicates
>>> box's work.
>> This is correct in most cases. We will lose the implicit cast
>> between numeric values, but this can be done, for example, during
>> MakeRecord. In addition, all type mismatch errors will look the
>> same as in Lua.
>
> I didn't meant to remove number casts. Only non-numeric checks.
> For example, if mem_check_type is called on a string, and target
> is number, we can ignore that, and let box raise an error.
>
> This should become even simpler, when MEM_<type> flags are
> replaced with enum field_type.
>
> Please, do it here, if it is easy, or file a new ticket (I mean
> error fallthrough down to box, not MEM_<type> removal).

It is not very easy to do since this function used in some other
places. I filled a new ticked (#5074).



Patch:

From be6254fb656d0b688ff0c85a092d30703903a20f Mon Sep 17 00:00:00 2001
From: Mergen Imeev <imeevma@gmail.com>
Date: Wed, 27 May 2020 13:49:11 +0300
Subject: [PATCH] sql: remove implicit cast for assignment

This patch removes implicit cast for assignment, however,
it is allowed to implicitly cast DOUBLE to INTEGER and
vice versa.

Closes #3809

diff --git a/src/box/sql/insert.c b/src/box/sql/insert.c
index 588e142d2..253304ba3 100644
--- a/src/box/sql/insert.c
+++ b/src/box/sql/insert.c
@@ -69,7 +69,7 @@ sql_emit_table_types(struct Vdbe *v, struct space_def *def, int reg)
    for (uint32_t i = 0; i < field_count; ++i)
        colls_type[i] = def->fields[i].type;
    colls_type[field_count] = field_type_MAX;
-   sqlVdbeAddOp4(v, OP_ApplyType, reg, field_count, 0,
+   sqlVdbeAddOp4(v, OP_CheckType, reg, field_count, 0,
              (char *)colls_type, P4_DYNAMIC);
 }
 
diff --git a/src/box/sql/vdbe.c b/src/box/sql/vdbe.c
index 6b769805c..ae2622c9e 100644
--- a/src/box/sql/vdbe.c
+++ b/src/box/sql/vdbe.c
@@ -418,6 +418,113 @@ sql_value_apply_type(
    mem_apply_type((Mem *) pVal, type);
 }
 
+/**
+ * Check that mem_type of the mem is compatible with given type.
+ * In the case of numeric values, this function tries to convert
+ * the mem to the specified type and returns -1 if this is not
+ * possible.
+ *
+ * @param mem The value to check.
+ * @param type The type to check.
+ */
+static int
+mem_check_types(struct Mem *mem, enum field_type type)
+{
+   if ((mem->flags & MEM_Null) != 0)
+       return 0;
+   assert(type < field_type_MAX);
+   uint32_t flags = mem->flags;
+   switch (type) {
+   case FIELD_TYPE_UNSIGNED:
+       if ((flags & MEM_Int) != 0)
+           return -1;
+       if ((flags & MEM_Real) != 0 && mem->u.r < 0)
+           return -1;
+       FALLTHROUGH;
+   case FIELD_TYPE_INTEGER:
+       if ((flags & (MEM_Int | MEM_UInt)) != 0)
+           return 0;
+       if ((flags & MEM_Real) == 0)
+           return -1;
+       double d = mem->u.r;
+       if (d >= (double)UINT64_MAX || d < (double)INT64_MIN)
+           return -1;
+       if (d < (double)INT64_MAX) {
+           int64_t i = (int64_t) d;
+           if (i == d) {
+               mem_set_int(mem, i, i <= -1);
+               return 0;
+           }
+           return -1;
+       }
+       uint64_t u = (uint64_t) d;
+       if (u == d) {
+           mem_set_u64(mem, u);
+           return 0;
+       }
+       return -1;
+   case FIELD_TYPE_BOOLEAN:
+       if ((flags & MEM_Bool) != 0)
+           return 0;
+       return -1;
+   case FIELD_TYPE_NUMBER:
+       if ((flags & (MEM_Real | MEM_Int | MEM_UInt)) != 0)
+           return 0;
+       return -1;
+   case FIELD_TYPE_DOUBLE:
+       if ((flags & MEM_Real) != 0)
+           return 0;
+       if ((flags & (MEM_Int | MEM_UInt)) == 0)
+           return -1;
+       if ((flags & MEM_Int) != 0) {
+           double d = mem->u.i;
+           if (mem->u.i == (int64_t)d) {
+               mem_set_double(mem, d);
+               return 0;
+           }
+       } else {
+           double d = mem->u.u;
+           if (mem->u.u == (uint64_t)d) {
+               mem_set_double(mem, d);
+               return 0;
+           }
+       }
+       return -1;
+   case FIELD_TYPE_STRING:
+       if ((flags & MEM_Str) != 0)
+           return 0;
+       return -1;
+   case FIELD_TYPE_VARBINARY:
+       if ((flags & MEM_Blob) != 0)
+           return 0;
+       return -1;
+   case FIELD_TYPE_SCALAR:
+       /* Can't cast MAP and ARRAY to scalar types. */
+       if ((flags & MEM_Subtype) == 0 ||
+           mem->subtype != SQL_SUBTYPE_MSGPACK)
+           return 0;
+       assert(mp_typeof(*mem->z) == MP_MAP ||
+              mp_typeof(*mem->z) == MP_ARRAY);
+       return -1;
+   case FIELD_TYPE_MAP:
+       if ((flags & MEM_Subtype) != 0 &&
+           mem->subtype == SQL_SUBTYPE_MSGPACK &&
+           mp_typeof(*mem->z) == MP_MAP)
+           return 0;
+       return -1;
+   case FIELD_TYPE_ARRAY:
+       if ((flags & MEM_Subtype) != 0 &&
+           mem->subtype == SQL_SUBTYPE_MSGPACK &&
+           mp_typeof(*mem->z) == MP_ARRAY)
+           return 0;
+       return -1;
+   case FIELD_TYPE_ANY:
+       return 0;
+   default:
+       return -1;
+   }
+}
+
 /*
  * pMem currently only holds a string type (or maybe a BLOB that we can
  * interpret as a string if we want to).  Compute its corresponding
@@ -2776,6 +2883,31 @@ case OP_ApplyType: {
    break;
 }
 
+/* Opcode: CheckType P1 P2 * P4 *
+ * Synopsis: type(r[P1@P2])
+ *
+ * Check that types of P2 registers starting from register
+ * P1 are compatible with given with given field types in P4.
+ */
+case OP_CheckType: {
+   enum field_type *types = pOp->p4.types;
+   assert(types != NULL);
+   assert(types[pOp->p2] == field_type_MAX);
+   pIn1 = &aMem[pOp->p1];
+   enum field_type type;
+   while((type = *(types++)) != field_type_MAX) {
+       assert(pIn1 <= &p->aMem[(p->nMem+1 - p->nCursor)]);
+       assert(memIsValid(pIn1));
+       if (mem_check_types(pIn1, type) != 0) {
+           diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
+                mem_type_to_str(pIn1), field_type_strs[type]);
+           goto abort_due_to_error;
+       }
+       pIn1++;
+   }
+   break;
+}
+
 /* Opcode: MakeRecord P1 P2 P3 P4 P5
  * Synopsis: r[P3]=mkrec(r[P1@P2])
  *
diff --git a/src/box/sql/vdbeInt.h b/src/box/sql/vdbeInt.h
index 2c50b6768..edb216a8a 100644
--- a/src/box/sql/vdbeInt.h
+++ b/src/box/sql/vdbeInt.h
@@ -517,6 +517,11 @@ mem_set_u64(struct Mem *mem, uint64_t value);
 void
 mem_set_int(struct Mem *mem, int64_t value, bool is_neg);
 
+/** Set double value and MEM_Real flag. */
+void
+mem_set_double(struct Mem *mem, double value);
+
+
 void sqlVdbeMemSetDouble(Mem *, double);
 void sqlVdbeMemInit(Mem *, sql *, u32);
 void sqlVdbeMemSetNull(Mem *);
diff --git a/src/box/sql/vdbemem.c b/src/box/sql/vdbemem.c
index 8dad2db9a..9e8586ffc 100644
--- a/src/box/sql/vdbemem.c
+++ b/src/box/sql/vdbemem.c
@@ -839,6 +839,13 @@ mem_set_int(struct Mem *mem, int64_t value, bool is_neg)
    }
 }
 
+void
+mem_set_double(struct Mem *mem, double value)
+{
+   mem->u.r = value;
+   MemSetTypeFlag(mem, MEM_Real);
+}
+
 /*
  * Delete any previous value and set the value stored in *pMem to val,
  * manifest type REAL.
diff --git a/test/sql-tap/autoinc.test.lua b/test/sql-tap/autoinc.test.lua
index 37e65e541..ec8dfeab1 100755
--- a/test/sql-tap/autoinc.test.lua
+++ b/test/sql-tap/autoinc.test.lua
@@ -618,7 +618,7 @@ test:do_catchsql_test(
             INSERT INTO t2 VALUES('asd'); 
     ]], {
         -- <autoinc-10.2>
-        1, "Type mismatch: can not convert asd to integer"
+        1, "Type mismatch: can not convert text to integer"
         -- </autoinc-10.2>
     })
 
@@ -694,7 +694,7 @@ test:do_test(
                  INSERT INTO t3928(b) VALUES('after-int-' || CAST(new.b AS TEXT));
             END;
             DELETE FROM t3928 WHERE a!=1;
-            UPDATE t3928 SET b=456 WHERE a=1;
+            UPDATE t3928 SET b='456' WHERE a=1;
             SELECT * FROM t3928 ORDER BY a;
         ]])
     end, {
diff --git a/test/sql-tap/default.test.lua b/test/sql-tap/default.test.lua
index d3e35c71c..f1def2b10 100755
--- a/test/sql-tap/default.test.lua
+++ b/test/sql-tap/default.test.lua
@@ -109,16 +109,12 @@ test:do_execsql_test(
    f VARCHAR(15), --COLLATE RTRIM,
    g INTEGER DEFAULT( 3600*12 )
    );
-   INSERT INTO t3 VALUES(null, 5, 'row1', 5.25, 8.67, 321, 432);
+   INSERT INTO t3 VALUES(null, 5, 'row1', 5.25, 8.67, '321', 432);
    SELECT a, typeof(a), b, typeof(b), c, typeof(c), 
    d, typeof(d), e, typeof(e), f, typeof(f),
    g, typeof(g) FROM t3;
    ]], {
    -- <default-3.1>
-   -- TODO: In original test "321" is not a string, its a value.
-   -- 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"
    -- </default-3.1>
 })
diff --git a/test/sql-tap/e_select1.test.lua b/test/sql-tap/e_select1.test.lua
index 1d3b964b9..7673426f4 100755
--- a/test/sql-tap/e_select1.test.lua
+++ b/test/sql-tap/e_select1.test.lua
@@ -753,11 +753,11 @@ test:do_execsql_test(
         CREATE TABLE z3(id  INT primary key, a NUMBER, b NUMBER);
 
         INSERT INTO z1 VALUES(1, 51.65, -59.58, 'belfries');
-        INSERT INTO z1 VALUES(2, -5, NULL, 75);
+        INSERT INTO z1 VALUES(2, -5, NULL, '75');
         INSERT INTO z1 VALUES(3, -2.2, -23.18, 'suiters');
         INSERT INTO z1 VALUES(4, NULL, 67, 'quartets');
         INSERT INTO z1 VALUES(5, -1.04, -32.3, 'aspen');
-        INSERT INTO z1 VALUES(6, 63, '0', -26);
+        INSERT INTO z1 VALUES(6, 63, 0, '-26');
 
         INSERT INTO z2 VALUES(1, NULL, 21);
         INSERT INTO z2 VALUES(2, 36.0, 6.0);
@@ -1457,13 +1457,13 @@ test:do_execsql_test(
         CREATE TABLE q2(id  INT primary key, d TEXT, e NUMBER);
         CREATE TABLE q3(id  INT primary key, f TEXT, g INT);
 
-        INSERT INTO q1 VALUES(1, 16, -87.66, NULL);
+        INSERT INTO q1 VALUES(1, '16', -87.66, NULL);
         INSERT INTO q1 VALUES(2, 'legible', 94, -42.47);
         INSERT INTO q1 VALUES(3, 'beauty', 36, NULL);
 
         INSERT INTO q2 VALUES(1, 'legible', 1);
         INSERT INTO q2 VALUES(2, 'beauty', 2);
-        INSERT INTO q2 VALUES(3, -65, 4);
+        INSERT INTO q2 VALUES(3, '-65', 4);
         INSERT INTO q2 VALUES(4, 'emanating', -16.56);
 
         INSERT INTO q3 VALUES(1, 'beauty', 2);
@@ -1603,7 +1603,7 @@ test:do_execsql_test(
         CREATE TABLE w2(a  INT PRIMARY KEY, b TEXT);
 
         INSERT INTO w1 VALUES('1', 4.1);
-        INSERT INTO w2 VALUES(1, 4.1);
+        INSERT INTO w2 VALUES(1, '4.1');
     ]], {
         -- <e_select-7.10.0>
 
diff --git a/test/sql-tap/gh-3809-implicit-cast-assignment.test.lua b/test/sql-tap/gh-3809-implicit-cast-assignment.test.lua
new file mode 100755
index 000000000..de72cf3a4
--- /dev/null
+++ b/test/sql-tap/gh-3809-implicit-cast-assignment.test.lua
@@ -0,0 +1,649 @@
+#!/usr/bin/env tarantool
+test = require("sqltester")
+test:plan(77)
+
+--
+-- Make sure there are no implicit casts during assignment,
+-- except for the implicit cast between numeric values.
+--
+test:execsql([[
+    CREATE TABLE ti (a INT PRIMARY KEY AUTOINCREMENT, i INTEGER);
+    CREATE TABLE td (a INT PRIMARY KEY AUTOINCREMENT, d DOUBLE);
+    CREATE TABLE tb (a INT PRIMARY KEY AUTOINCREMENT, b BOOLEAN);
+    CREATE TABLE tt (a INT PRIMARY KEY AUTOINCREMENT, t TEXT);
+    CREATE TABLE tv (a INT PRIMARY KEY AUTOINCREMENT, v VARBINARY);
+    CREATE TABLE ts (a INT PRIMARY KEY AUTOINCREMENT, s SCALAR);
+]])
+
+test:do_catchsql_test(
+    "gh-3809-1",
+    [[
+        INSERT INTO ti(i) VALUES (11)
+    ]], {
+        0
+    })
+
+test:do_catchsql_test(
+    "gh-3809-2",
+    [[
+        INSERT INTO ti(i) VALUES (22.2)
+    ]], {
+        1, "Type mismatch: can not convert real to integer"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-3",
+    [[
+        INSERT INTO ti(i) VALUES (33.0)
+    ]], {
+        0
+    })
+
+test:do_catchsql_test(
+    "gh-3809-4",
+    [[
+        INSERT INTO ti(i) VALUES (true)
+    ]], {
+        1, "Type mismatch: can not convert boolean to integer"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-5",
+    [[
+        INSERT INTO ti(i) VALUES ('33')
+    ]], {
+        1, "Type mismatch: can not convert text to integer"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-6",
+    [[
+        INSERT INTO ti(i) VALUES (X'3434')
+    ]], {
+        1, "Type mismatch: can not convert varbinary to integer"
+    })
+
+test:do_execsql_test(
+    "gh-3809-7",
+    [[
+        SELECT * FROM ti;
+    ]], {
+        1, 11, 2, 33
+    })
+
+test:do_catchsql_test(
+    "gh-3809-8",
+    [[
+        INSERT INTO td(d) VALUES (11)
+    ]], {
+        0
+    })
+
+test:do_catchsql_test(
+    "gh-3809-9",
+    [[
+        INSERT INTO td(d) VALUES (100000000000000001);
+    ]], {
+        1, "Type mismatch: can not convert unsigned to double"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-10",
+    [[
+        INSERT INTO td(d) VALUES (22.2)
+    ]], {
+        0
+    })
+
+test:do_catchsql_test(
+    "gh-3809-11",
+    [[
+        INSERT INTO td(d) VALUES (true)
+    ]], {
+        1, "Type mismatch: can not convert boolean to double"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-12",
+    [[
+        INSERT INTO td(d) VALUES ('33')
+    ]], {
+        1, "Type mismatch: can not convert text to double"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-13",
+    [[
+        INSERT INTO td(d) VALUES (X'3434')
+    ]], {
+        1, "Type mismatch: can not convert varbinary to double"
+    })
+
+test:do_execsql_test(
+    "gh-3809-14",
+    [[
+        SELECT * FROM td;
+    ]], {
+        1, 11, 2, 22.2
+    })
+
+test:do_catchsql_test(
+    "gh-3809-15",
+    [[
+        INSERT INTO tb(b) VALUES (11)
+    ]], {
+        1, "Type mismatch: can not convert unsigned to boolean"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-16",
+    [[
+        INSERT INTO tb(b) VALUES (22.2)
+    ]], {
+        1, "Type mismatch: can not convert real to boolean"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-17",
+    [[
+        INSERT INTO tb(b) VALUES (true)
+    ]], {
+        0
+    })
+
+test:do_catchsql_test(
+    "gh-3809-18",
+    [[
+        INSERT INTO tb(b) VALUES ('33')
+    ]], {
+        1, "Type mismatch: can not convert text to boolean"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-19",
+    [[
+        INSERT INTO tb(b) VALUES (X'3434')
+    ]], {
+        1, "Type mismatch: can not convert varbinary to boolean"
+    })
+
+test:do_execsql_test(
+    "gh-3809-20",
+    [[
+        SELECT * FROM tb;
+    ]], {
+        1, true
+    })
+
+test:do_catchsql_test(
+    "gh-3809-21",
+    [[
+        INSERT INTO tt(t) VALUES (11)
+    ]], {
+        1, "Type mismatch: can not convert unsigned to string"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-22",
+    [[
+        INSERT INTO tt(t) VALUES (22.2)
+    ]], {
+        1, "Type mismatch: can not convert real to string"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-23",
+    [[
+        INSERT INTO tt(t) VALUES (true)
+    ]], {
+        1, "Type mismatch: can not convert boolean to string"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-24",
+    [[
+        INSERT INTO tt(t) VALUES ('33')
+    ]], {
+        0
+    })
+
+test:do_catchsql_test(
+    "gh-3809-25",
+    [[
+        INSERT INTO tt(t) VALUES (X'3434')
+    ]], {
+        1, "Type mismatch: can not convert varbinary to string"
+    })
+
+test:do_execsql_test(
+    "gh-3809-26",
+    [[
+        SELECT * FROM tt;
+    ]], {
+        1, "33"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-27",
+    [[
+        INSERT INTO tv(v) VALUES (11)
+    ]], {
+        1, "Type mismatch: can not convert unsigned to varbinary"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-28",
+    [[
+        INSERT INTO tv(v) VALUES (22.2)
+    ]], {
+        1, "Type mismatch: can not convert real to varbinary"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-29",
+    [[
+        INSERT INTO tv(v) VALUES (true)
+    ]], {
+        1, "Type mismatch: can not convert boolean to varbinary"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-30",
+    [[
+        INSERT INTO tv(v) VALUES ('33')
+    ]], {
+        1, "Type mismatch: can not convert text to varbinary"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-31",
+    [[
+        INSERT INTO tv(v) VALUES (X'3434')
+    ]], {
+        0
+    })
+
+test:do_execsql_test(
+    "gh-3809-32",
+    [[
+        SELECT * FROM tv;
+    ]], {
+        1, "44"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-33",
+    [[
+        INSERT INTO ts(s) VALUES (11)
+    ]], {
+        0
+    })
+
+test:do_catchsql_test(
+    "gh-3809-34",
+    [[
+        INSERT INTO ts(s) VALUES (22.2)
+    ]], {
+        0
+    })
+
+test:do_catchsql_test(
+    "gh-3809-35",
+    [[
+        INSERT INTO ts(s) VALUES (true)
+    ]], {
+        0
+    })
+
+test:do_catchsql_test(
+    "gh-3809-36",
+    [[
+        INSERT INTO ts(s) VALUES ('33')
+    ]], {
+        0
+    })
+
+test:do_catchsql_test(
+    "gh-3809-37",
+    [[
+        INSERT INTO ts(s) VALUES (X'3434')
+    ]], {
+        0
+    })
+
+test:do_execsql_test(
+    "gh-3809-38",
+    [[
+        SELECT * FROM ts;
+    ]], {
+        1, 11, 2, 22.2, 3, true, 4, "33", 5, "44"
+    })
+
+test:execsql([[
+    DELETE FROM ti;
+    DELETE FROM td;
+    DELETE FROM tb;
+    DELETE FROM tt;
+    DELETE FROM tv;
+    DELETE FROM ts;
+    INSERT INTO ti(a) VALUES(1);
+    INSERT INTO td(a) VALUES(1);
+    INSERT INTO tb(a) VALUES(1);
+    INSERT INTO tt(a) VALUES(1);
+    INSERT INTO tv(a) VALUES(1);
+    INSERT INTO ts(a) VALUES(1);
+]])
+
+test:do_execsql_test(
+    "gh-3809-39",
+    [[
+        SELECT * FROM ti, td, tb, tt, tv, ts;
+    ]], {
+        1, "", 1, "", 1, "", 1, "", 1, "", 1, ""
+    })
+
+test:do_catchsql_test(
+    "gh-3809-40",
+    [[
+        UPDATE ti SET i = 11 WHERE a = 1;
+    ]], {
+        0
+    })
+
+test:do_catchsql_test(
+    "gh-3809-41",
+    [[
+        UPDATE ti SET i = 22.2 WHERE a = 1;
+    ]], {
+        1, "Type mismatch: can not convert real to integer"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-42",
+    [[
+        UPDATE ti SET i = 33.0 WHERE a = 1;
+    ]], {
+        0
+    })
+
+test:do_catchsql_test(
+    "gh-3809-43",
+    [[
+        UPDATE ti SET i = true WHERE a = 1;
+    ]], {
+        1, "Type mismatch: can not convert boolean to integer"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-44",
+    [[
+        UPDATE ti SET i = '33' WHERE a = 1;
+    ]], {
+        1, "Type mismatch: can not convert text to integer"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-45",
+    [[
+        UPDATE ti SET i = X'3434' WHERE a = 1;
+    ]], {
+        1, "Type mismatch: can not convert varbinary to integer"
+    })
+
+test:do_execsql_test(
+    "gh-3809-46",
+    [[
+        SELECT * FROM ti;
+    ]], {
+        1, 33
+    })
+
+test:do_catchsql_test(
+    "gh-3809-47",
+    [[
+        UPDATE td SET d = 11 WHERE a = 1;
+    ]], {
+        0
+    })
+
+test:do_catchsql_test(
+    "gh-3809-48",
+    [[
+        UPDATE td SET d = 100000000000000001 WHERE a = 1;
+    ]], {
+        1, "Type mismatch: can not convert unsigned to double"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-49",
+    [[
+        UPDATE td SET d = 22.2 WHERE a = 1;
+    ]], {
+        0
+    })
+
+test:do_catchsql_test(
+    "gh-3809-50",
+    [[
+        UPDATE td SET d = true WHERE a = 1;
+    ]], {
+        1, "Type mismatch: can not convert boolean to double"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-51",
+    [[
+        UPDATE td SET d = '33' WHERE a = 1;
+    ]], {
+        1, "Type mismatch: can not convert text to double"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-52",
+    [[
+        UPDATE td SET d = X'3434' WHERE a = 1;
+    ]], {
+        1, "Type mismatch: can not convert varbinary to double"
+    })
+
+test:do_execsql_test(
+    "gh-3809-53",
+    [[
+        SELECT * FROM td;
+    ]], {
+        1, 22.2
+    })
+
+test:do_catchsql_test(
+    "gh-3809-54",
+    [[
+        UPDATE tb SET b = 11 WHERE a = 1;
+    ]], {
+        1, "Type mismatch: can not convert unsigned to boolean"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-55",
+    [[
+        UPDATE tb SET b = 22.2 WHERE a = 1;
+    ]], {
+        1, "Type mismatch: can not convert real to boolean"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-56",
+    [[
+        UPDATE tb SET b = true WHERE a = 1;
+    ]], {
+        0
+    })
+
+test:do_catchsql_test(
+    "gh-3809-57",
+    [[
+        UPDATE tb SET b = '33' WHERE a = 1;
+    ]], {
+        1, "Type mismatch: can not convert text to boolean"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-58",
+    [[
+        UPDATE tb SET b = X'3434' WHERE a = 1;
+    ]], {
+        1, "Type mismatch: can not convert varbinary to boolean"
+    })
+
+test:do_execsql_test(
+    "gh-3809-59",
+    [[
+        SELECT * FROM tb;
+    ]], {
+        1, true
+    })
+
+test:do_catchsql_test(
+    "gh-3809-60",
+    [[
+        UPDATE tt SET t = 11 WHERE a = 1;
+    ]], {
+        1, "Type mismatch: can not convert unsigned to string"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-61",
+    [[
+        UPDATE tt SET t = 22.2 WHERE a = 1;
+    ]], {
+        1, "Type mismatch: can not convert real to string"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-62",
+    [[
+        UPDATE tt SET t = true WHERE a = 1;
+    ]], {
+        1, "Type mismatch: can not convert boolean to string"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-63",
+    [[
+        UPDATE tt SET t = '33' WHERE a = 1;
+    ]], {
+        0
+    })
+
+test:do_catchsql_test(
+    "gh-3809-64",
+    [[
+        UPDATE tt SET t = X'3434' WHERE a = 1;
+    ]], {
+        1, "Type mismatch: can not convert varbinary to string"
+    })
+
+test:do_execsql_test(
+    "gh-3809-65",
+    [[
+        SELECT * FROM tt;
+    ]], {
+        1, "33"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-66",
+    [[
+        UPDATE tv SET v = 11 WHERE a = 1;
+    ]], {
+        1, "Type mismatch: can not convert unsigned to varbinary"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-67",
+    [[
+        UPDATE tv SET v = 22.2 WHERE a = 1;
+    ]], {
+        1, "Type mismatch: can not convert real to varbinary"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-68",
+    [[
+        UPDATE tv SET v = true WHERE a = 1;
+    ]], {
+        1, "Type mismatch: can not convert boolean to varbinary"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-69",
+    [[
+        UPDATE tv SET v = '33' WHERE a = 1;
+    ]], {
+        1, "Type mismatch: can not convert text to varbinary"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-70",
+    [[
+        UPDATE tv SET v = X'3434' WHERE a = 1;
+    ]], {
+        0
+    })
+
+test:do_execsql_test(
+    "gh-3809-71",
+    [[
+        SELECT * FROM tv;
+    ]], {
+        1, "44"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-72",
+    [[
+        UPDATE ts SET s = 11 WHERE a = 1;
+    ]], {
+        0
+    })
+
+test:do_catchsql_test(
+    "gh-3809-73",
+    [[
+        UPDATE ts SET s = 22.2 WHERE a = 1;
+    ]], {
+        0
+    })
+
+test:do_catchsql_test(
+    "gh-3809-74",
+    [[
+        UPDATE ts SET s = true WHERE a = 1;
+    ]], {
+        0
+    })
+
+test:do_catchsql_test(
+    "gh-3809-75",
+    [[
+        UPDATE ts SET s = '33' WHERE a = 1;
+    ]], {
+        0
+    })
+
+test:do_catchsql_test(
+    "gh-3809-76",
+    [[
+        UPDATE ts SET s = X'3434' WHERE a = 1;
+    ]], {
+        0
+    })
+
+test:do_execsql_test(
+    "gh-3809-77",
+    [[
+        SELECT * FROM ts;
+    ]], {
+        1, "44"
+    })
+
+test:finish_test()
diff --git a/test/sql-tap/index1.test.lua b/test/sql-tap/index1.test.lua
index e173e685c..ce66b7c1e 100755
--- a/test/sql-tap/index1.test.lua
+++ b/test/sql-tap/index1.test.lua
@@ -593,25 +593,17 @@ test:do_test(
         -- </index-11.1>
     })
 end
--- integrity_check index-11.2
--- Numeric strings should compare as if they were numbers.  So even if the
--- strings are not character-by-character the same, if they represent the
--- same number they should compare equal to one another.  Verify that this
--- is true in indices.
---
--- Updated for sql v3: sql will now store these values as numbers
--- (because the affinity of column a is NUMERIC) so the quirky
--- representations are not retained. i.e. '+1.0' becomes '1'.
+
 test:do_execsql_test(
     "index-12.1",
     [[
         CREATE TABLE t4(id  INT primary key, a NUMBER,b INT );
-        INSERT INTO t4 VALUES(1, '0.0',1);
-        INSERT INTO t4 VALUES(2, '0.00',2);
-        INSERT INTO t4 VALUES(4, '-1.0',4);
-        INSERT INTO t4 VALUES(5, '+1.0',5);
-        INSERT INTO t4 VALUES(6, '0',6);
-        INSERT INTO t4 VALUES(7, '00000',7);
+        INSERT INTO t4 VALUES(1, 0.0, 1);
+        INSERT INTO t4 VALUES(2, 0.00, 2);
+        INSERT INTO t4 VALUES(4, -1.0, 4);
+        INSERT INTO t4 VALUES(5, +1.0, 5);
+        INSERT INTO t4 VALUES(6, 0, 6);
+        INSERT INTO t4 VALUES(7, 00000, 7);
         SELECT a FROM t4 ORDER BY b;
     ]], {
         -- <index-12.1>
@@ -692,7 +684,7 @@ test:do_execsql_test(
            c  TEXT,
            UNIQUE(a,c)
         );
-        INSERT INTO t5 VALUES(1,2,3);
+        INSERT INTO t5 VALUES(1,2,'3');
         SELECT * FROM t5;
     ]], {
         -- <index-13.1>
diff --git a/test/sql-tap/insert3.test.lua b/test/sql-tap/insert3.test.lua
index 43bb06630..b92bc508e 100755
--- a/test/sql-tap/insert3.test.lua
+++ b/test/sql-tap/insert3.test.lua
@@ -60,7 +60,7 @@ test:do_execsql_test(
             CREATE TABLE log2(rowid INTEGER PRIMARY KEY AUTOINCREMENT, x TEXT UNIQUE,y INT );
             CREATE TRIGGER r2 BEFORE INSERT ON t1 FOR EACH ROW BEGIN
               UPDATE log2 SET y=y+1 WHERE x=new.b;
-              INSERT OR IGNORE INTO log2(x, y) VALUES(new.b,1);
+              INSERT OR IGNORE INTO log2(x, y) VALUES(CAST(new.b AS STRING),1);
             END;
             INSERT INTO t1(a, b) VALUES('hi', 453);
             SELECT x,y FROM log ORDER BY x;
@@ -129,8 +129,8 @@ test:do_execsql_test(
               INSERT INTO t2dup(a,b,c) VALUES(new.a,new.b,new.c);
             END;
             INSERT INTO t2(a) VALUES(123);
-            INSERT INTO t2(b) VALUES(234);
-            INSERT INTO t2(c) VALUES(345);
+            INSERT INTO t2(b) VALUES('234');
+            INSERT INTO t2(c) VALUES('345');
             SELECT * FROM t2dup;
     ]], {
         -- <insert3-2.1>
@@ -143,8 +143,8 @@ test:do_execsql_test(
     [[
             DELETE FROM t2dup;
             INSERT INTO t2(a) SELECT 1 FROM t1 LIMIT 1;
-            INSERT INTO t2(b) SELECT 987 FROM t1 LIMIT 1;
-            INSERT INTO t2(c) SELECT 876 FROM t1 LIMIT 1;
+            INSERT INTO t2(b) SELECT '987' FROM t1 LIMIT 1;
+            INSERT INTO t2(c) SELECT '876' FROM t1 LIMIT 1;
             SELECT * FROM t2dup;
     ]], {
         -- <insert3-2.2>
diff --git a/test/sql-tap/intpkey.test.lua b/test/sql-tap/intpkey.test.lua
index b6b186632..0db18ba91 100755
--- a/test/sql-tap/intpkey.test.lua
+++ b/test/sql-tap/intpkey.test.lua
@@ -770,11 +770,6 @@ test:do_execsql_test(
         -- </intpkey-11.1>
     })
 
--- integrity_check intpkey-12.1
--- Try to use a string that looks like a floating point number as
--- an integer primary key.  This should actually work when the floating
--- point value can be rounded to an integer without loss of data.
---
 test:do_execsql_test(
     "intpkey-13.1",
     [[
@@ -788,7 +783,7 @@ test:do_execsql_test(
 test:do_execsql_test(
     "intpkey-13.2",
     [[
-        INSERT INTO t1 VALUES('1',2,3);
+        INSERT INTO t1 VALUES(1,'2','3');
         SELECT * FROM t1 WHERE a=1;
     ]], {
         -- <intpkey-13.2>
@@ -825,7 +820,7 @@ end
 test:do_catchsql_test(
     "intpkey-13.5",
     [[
-        INSERT INTO t1 VALUES('+1234567890',3,4);
+        INSERT INTO t1 VALUES(1234567890,'3','4');
     ]], {
         -- <intpkey-13.5>
         0
@@ -842,7 +837,7 @@ test:do_execsql_test(
         CREATE TABLE t3(a INTEGER PRIMARY KEY, b INTEGER, c TEXT);
         INSERT INTO t3 VALUES(1, 1, 'one');
         INSERT INTO t3 VALUES(2, 2, '2');
-        INSERT INTO t3 VALUES(3, 3, 3);
+        INSERT INTO t3 VALUES(3, 3, '3');
     ]], {
         -- <intpkey-14.1>
         
@@ -905,7 +900,7 @@ test:do_execsql_test(
 test:do_execsql_test(
     "intpkey-15.1",
     [[
-        INSERT INTO t1 VALUES(2147483647, 'big-1', 123);
+        INSERT INTO t1 VALUES(2147483647, 'big-1', '123');
         SELECT * FROM t1 WHERE a>2147483648;
     ]], {
         -- <intpkey-15.1>
diff --git a/test/sql-tap/minmax2.test.lua b/test/sql-tap/minmax2.test.lua
index 0e0f0d08e..707d1c4da 100755
--- a/test/sql-tap/minmax2.test.lua
+++ b/test/sql-tap/minmax2.test.lua
@@ -441,9 +441,9 @@ test:do_execsql_test(
     "minmax2-8.2",
     [[
         CREATE TABLE t5(a INTEGER PRIMARY KEY);
-        INSERT INTO t5 VALUES('1234');
-        INSERT INTO t5 VALUES('234');
-        INSERT INTO t5 VALUES('34');
+        INSERT INTO t5 VALUES(1234);
+        INSERT INTO t5 VALUES(234);
+        INSERT INTO t5 VALUES(34);
         SELECT min(a), max(a) FROM t5;
     ]], {
         -- <minmax2-8.2>
diff --git a/test/sql-tap/misc1.test.lua b/test/sql-tap/misc1.test.lua
index 32f38cc97..e0fe50bbe 100755
--- a/test/sql-tap/misc1.test.lua
+++ b/test/sql-tap/misc1.test.lua
@@ -34,9 +34,9 @@ test:do_test(
         end
         cmd = cmd .. ")"
         test:execsql(cmd)
-        cmd = "INSERT INTO manycol VALUES(1, 0"
+        cmd = "INSERT INTO manycol VALUES(1, '0'"
         for i = 1, 99, 1 do
-            cmd = cmd .. ","..i..""
+            cmd = cmd .. ",'"..i.."'"
         end
         cmd = cmd .. ")"
         test:execsql(cmd)
@@ -61,9 +61,9 @@ test:do_test(
     "misc1-1.3.1",
     function()
         for j = 100, 1000, 100 do
-            local cmd = string.format("INSERT INTO manycol VALUES(%s, %s", j, j)
+            local cmd = string.format("INSERT INTO manycol VALUES(%s, '%s'", j, j)
             for i = 1, 99, 1 do
-                cmd = cmd .. ","..(i + j)..""
+                cmd = cmd .. ",'"..(i + j).."'"
             end
             cmd = cmd .. ")"
             test:execsql(cmd)
@@ -178,12 +178,12 @@ test:do_test(
         test:execsql([[
             CREATE TABLE agger(one text primary key, two text, three text, four text);
             START TRANSACTION;
-            INSERT INTO agger VALUES(1, 'one', 'hello', 'yes');
-            INSERT INTO agger VALUES(2, 'two', 'howdy', 'no');
-            INSERT INTO agger VALUES(3, 'thr', 'howareya', 'yes');
-            INSERT INTO agger VALUES(4, 'two', 'lothere', 'yes');
-            INSERT INTO agger VALUES(5, 'one', 'atcha', 'yes');
-            INSERT INTO agger VALUES(6, 'two', 'hello', 'no');
+            INSERT INTO agger VALUES('1', 'one', 'hello', 'yes');
+            INSERT INTO agger VALUES('2', 'two', 'howdy', 'no');
+            INSERT INTO agger VALUES('3', 'thr', 'howareya', 'yes');
+            INSERT INTO agger VALUES('4', 'two', 'lothere', 'yes');
+            INSERT INTO agger VALUES('5', 'one', 'atcha', 'yes');
+            INSERT INTO agger VALUES('6', 'two', 'hello', 'no');
             COMMIT
         ]])
         return test:execsql("SELECT count(*) FROM agger")
@@ -531,7 +531,7 @@ test:do_test(
     "misc1-10.7",
     function()
         where = string.gsub(where, "x0=0", "x0=100")
-        return test:catchsql("UPDATE manycol SET x1=x1+1 "..where.."")
+        return test:catchsql("UPDATE manycol SET x1=CAST(x1+1 AS STRING) "..where.."")
     end, {
         -- <misc1-10.7>
         0
@@ -553,7 +553,7 @@ test:do_execsql_test(
 -- } {0 {}}
 test:do_execsql_test(
     "misc1-10.9",
-    "UPDATE manycol SET x1=x1+1 "..where
+    "UPDATE manycol SET x1=CAST(x1+1 AS STRING) "..where
         --"UPDATE manycol SET x1=x1+1 $::where AND rowid>0"
     , {})
 
@@ -665,7 +665,7 @@ test:do_execsql_test(
 test:do_execsql_test(
     "misc1-12.6",
     [[
-        INSERT OR IGNORE INTO t6 VALUES('y',0);
+        INSERT OR IGNORE INTO t6 VALUES('y','0');
         SELECT * FROM t6;
     ]], {
         -- <misc1-12.6>
@@ -679,10 +679,10 @@ test:do_execsql_test(
     "misc1-12.7",
     [[
         CREATE TABLE t7(x INTEGER, y TEXT, z  INT primary key);
-        INSERT INTO t7 VALUES(0,0,1);
-        INSERT INTO t7 VALUES(0.0,0,2);
-        INSERT INTO t7 VALUES(0,0.0,3);
-        INSERT INTO t7 VALUES(0.0,0.0,4);
+        INSERT INTO t7 VALUES(0,'0',1);
+        INSERT INTO t7 VALUES(0.0,'0',2);
+        INSERT INTO t7 VALUES(0,'0.0',3);
+        INSERT INTO t7 VALUES(0.0,'0.0',4);
         SELECT DISTINCT x, y FROM t7 ORDER BY z;
     ]], {
         -- <misc1-12.7>
diff --git a/test/sql-tap/numcast.test.lua b/test/sql-tap/numcast.test.lua
index eeac5353a..9bbae5ca4 100755
--- a/test/sql-tap/numcast.test.lua
+++ b/test/sql-tap/numcast.test.lua
@@ -135,7 +135,7 @@ test:do_catchsql_test(
         INSERT INTO t VALUES(20000000000000000000.01);
         SELECT * FROM t;
     ]], {
-        1,"Tuple field 1 type does not match one required by operation: expected integer"
+        1,"Type mismatch: can not convert real to integer"
     })
 
 test:do_catchsql_test(
@@ -144,7 +144,7 @@ test:do_catchsql_test(
         INSERT INTO t VALUES(2.1);
         SELECT * FROM t;
     ]], {
-        1,"Tuple field 1 type does not match one required by operation: expected integer"
+        1,"Type mismatch: can not convert real to integer"
     })
 
 --
diff --git a/test/sql-tap/select1.test.lua b/test/sql-tap/select1.test.lua
index fbebfab37..9a969bf3c 100755
--- a/test/sql-tap/select1.test.lua
+++ b/test/sql-tap/select1.test.lua
@@ -231,7 +231,7 @@ string.format([[
         CREATE TABLE t3(id INT, a TEXT, b TEXT, PRIMARY KEY(id));
         INSERT INTO t3 VALUES(1, 'abc',NULL);
         INSERT INTO t3 VALUES(2, NULL,'xyz');
-        INSERT INTO t3 SELECT f1, * FROM test1;
+        INSERT INTO t3 SELECT f1, CAST(f1 AS STRING), CAST(f2 AS STRING) FROM test1;
         DROP TABLE IF EXISTS t4;
         CREATE TABLE t4(id INT, a INT , b TEXT , PRIMARY KEY(id));
         INSERT INTO t4 VALUES(1, NULL,'%s');
@@ -1671,8 +1671,8 @@ test:do_execsql_test(
     [[
         DELETE FROM t3;
         DELETE FROM t4;
-        INSERT INTO t3 VALUES(0,1,2);
-        INSERT INTO t4 VALUES(0,3,4);
+        INSERT INTO t3 VALUES(0,'1','2');
+        INSERT INTO t4 VALUES(0,3,'4');
         SELECT * FROM t3, t4;
     ]], {
         -- <select1-11.1>
@@ -1878,7 +1878,7 @@ test:do_execsql_test(
     "select1-12.4",
     [[
         DELETE FROM t3;
-        INSERT INTO t3 VALUES(0,1,2);
+        INSERT INTO t3 VALUES(0,'1','2');
     ]], {
         -- <select1-12.4>
         
diff --git a/test/sql-tap/select4.test.lua b/test/sql-tap/select4.test.lua
index 23cf1bf1b..f7a320438 100755
--- a/test/sql-tap/select4.test.lua
+++ b/test/sql-tap/select4.test.lua
@@ -761,12 +761,12 @@ test:do_test(
         test:execsql [[
             CREATE TABLE t3(a text primary key, b NUMBER, c text);
             START TRANSACTION;
-            INSERT INTO t3 VALUES(1, 1.1, '1.1');
-            INSERT INTO t3 VALUES(2, 1.10, '1.10');
-            INSERT INTO t3 VALUES(3, 1.10, '1.1');
-            INSERT INTO t3 VALUES(4, 1.1, '1.10');
-            INSERT INTO t3 VALUES(5, 1.2, '1.2');
-            INSERT INTO t3 VALUES(6, 1.3, '1.3');
+            INSERT INTO t3 VALUES('1', 1.1, '1.1');
+            INSERT INTO t3 VALUES('2', 1.10, '1.10');
+            INSERT INTO t3 VALUES('3', 1.10, '1.1');
+            INSERT INTO t3 VALUES('4', 1.1, '1.10');
+            INSERT INTO t3 VALUES('5', 1.2, '1.2');
+            INSERT INTO t3 VALUES('6', 1.3, '1.3');
             COMMIT;
         ]]
         return test:execsql [[
diff --git a/test/sql-tap/select7.test.lua b/test/sql-tap/select7.test.lua
index fec5d7a41..e1e43c557 100755
--- a/test/sql-tap/select7.test.lua
+++ b/test/sql-tap/select7.test.lua
@@ -255,7 +255,7 @@ test:do_execsql_test(
     [[
         DROP TABLE IF EXISTS t5;
         CREATE TABLE t5(a TEXT primary key, b INT);
-        INSERT INTO t5 VALUES(123, 456);
+        INSERT INTO t5 VALUES('123', 456);
         SELECT typeof(a), a FROM t5 GROUP BY a HAVING a<b;
     ]], {
         -- <select7-7.7>
diff --git a/test/sql-tap/sort.test.lua b/test/sql-tap/sort.test.lua
index 36074d6ef..18bfd443d 100755
--- a/test/sql-tap/sort.test.lua
+++ b/test/sql-tap/sort.test.lua
@@ -505,10 +505,10 @@ test:do_execsql_test(
           a INTEGER PRIMARY KEY,
           b VARCHAR(30)
         );
-        INSERT INTO t4 VALUES(1,1);
-        INSERT INTO t4 VALUES(2,2);
-        INSERT INTO t4 VALUES(11,11);
-        INSERT INTO t4 VALUES(12,12);
+        INSERT INTO t4 VALUES(1,'1');
+        INSERT INTO t4 VALUES(2,'2');
+        INSERT INTO t4 VALUES(11,'11');
+        INSERT INTO t4 VALUES(12,'12');
         SELECT a FROM t4 ORDER BY 1;
     ]], {
         -- <sort-7.1>
diff --git a/test/sql-tap/tkt-3998683a16.test.lua b/test/sql-tap/tkt-3998683a16.test.lua
index 885dcf5cd..9bc310358 100755
--- a/test/sql-tap/tkt-3998683a16.test.lua
+++ b/test/sql-tap/tkt-3998683a16.test.lua
@@ -26,29 +26,17 @@ test:do_test(
     function()
         return test:execsql [[
             CREATE TABLE t1(x  INT primary key, y NUMBER);
-            INSERT INTO t1 VALUES(1, '1.0');
-            INSERT INTO t1 VALUES(2, '.125');
-            INSERT INTO t1 VALUES(3, '123.');
-            INSERT INTO t1 VALUES(4, '123.e+2');
-            INSERT INTO t1 VALUES(5, '.125e+3');
-            INSERT INTO t1 VALUES(6, '123e4');
-            INSERT INTO t1 VALUES(11, '  1.0');
-            INSERT INTO t1 VALUES(12, '  .125');
-            INSERT INTO t1 VALUES(13, '  123.');
-            INSERT INTO t1 VALUES(14, '  123.e+2');
-            INSERT INTO t1 VALUES(15, '  .125e+3');
-            INSERT INTO t1 VALUES(16, '  123e4');
-            INSERT INTO t1 VALUES(21, '1.0  ');
-            INSERT INTO t1 VALUES(22, '.125  ');
-            INSERT INTO t1 VALUES(23, '123.  ');
-            INSERT INTO t1 VALUES(24, '123.e+2  ');
-            INSERT INTO t1 VALUES(25, '.125e+3  ');
-            INSERT INTO t1 VALUES(26, '123e4  ');
+            INSERT INTO t1 VALUES(1, 1.0);
+            INSERT INTO t1 VALUES(2, .125);
+            INSERT INTO t1 VALUES(3, 123.);
+            INSERT INTO t1 VALUES(4, 123.e+2);
+            INSERT INTO t1 VALUES(5, .125e+3);
+            INSERT INTO t1 VALUES(6, 123e4);
             SELECT x FROM t1 WHERE typeof(y)=='number' ORDER BY x;
         ]]
     end, {
         -- <tkt-3998683a16.1>
-        1, 2, 3, 4, 5, 6, 11, 12, 13, 14, 15, 16, 21, 22, 23, 24, 25, 26
+        1, 2, 3, 4, 5, 6
         -- </tkt-3998683a16.1>
     })
 
diff --git a/test/sql-tap/tkt-54844eea3f.test.lua b/test/sql-tap/tkt-54844eea3f.test.lua
index d6cd56e52..89d0d1218 100755
--- a/test/sql-tap/tkt-54844eea3f.test.lua
+++ b/test/sql-tap/tkt-54844eea3f.test.lua
@@ -62,10 +62,10 @@ test:do_execsql_test(
     "1.2",
     [[
         CREATE TABLE t4(id INT primary key, a TEXT, b TEXT, c TEXT);
-        INSERT INTO t4 VALUES(1, 'a', 1, 'one');
-        INSERT INTO t4 VALUES(2, 'a', 2, 'two');
-        INSERT INTO t4 VALUES(3, 'b', 1, 'three');
-        INSERT INTO t4 VALUES(4, 'b', 2, 'four');
+        INSERT INTO t4 VALUES(1, 'a', '1', 'one');
+        INSERT INTO t4 VALUES(2, 'a', '2', 'two');
+        INSERT INTO t4 VALUES(3, 'b', '1', 'three');
+        INSERT INTO t4 VALUES(4, 'b', '2', 'four');
         SELECT ( 
           SELECT c FROM (
             SELECT a,b,c FROM t4 WHERE a=output.a ORDER BY b LIMIT 10 OFFSET 1
diff --git a/test/sql-tap/tkt-7bbfb7d442.test.lua b/test/sql-tap/tkt-7bbfb7d442.test.lua
index 535303771..bfddcd920 100755
--- a/test/sql-tap/tkt-7bbfb7d442.test.lua
+++ b/test/sql-tap/tkt-7bbfb7d442.test.lua
@@ -109,13 +109,13 @@ if (1 > 0)
                     T1.Variant AS Variant,
                     T1.ControlDate AS ControlDate,
                     1 AS ControlState,
-                    COALESCE(T2.DeliveredQty,0) AS DeliveredQty
+                    CAST(COALESCE(T2.DeliveredQty,0) AS STRING) AS DeliveredQty
                 FROM (
                     SELECT
                         NEW.InventoryControlId AS InventoryControlId,
                         II.SKU AS SKU,
                         II.Variant AS Variant,
-                        COALESCE(LastClosedIC.ControlDate,NEW.ControlDate) AS ControlDate
+                        CAST(COALESCE(LastClosedIC.ControlDate,NEW.ControlDate) AS STRING) AS ControlDate
                     FROM
                         InventoryItem II
                     LEFT JOIN
diff --git a/test/sql-tap/tkt1444.test.lua b/test/sql-tap/tkt1444.test.lua
index 82a5ded25..fb148bc5f 100755
--- a/test/sql-tap/tkt1444.test.lua
+++ b/test/sql-tap/tkt1444.test.lua
@@ -30,8 +30,8 @@ test:do_execsql_test(
     [[
         CREATE TABLE DemoTable (id  INT primary key, x INTEGER, TextKey TEXT, DKey NUMBER);
         CREATE INDEX DemoTableIdx ON DemoTable (TextKey);
-        INSERT INTO DemoTable VALUES(1, 9,8,7);
-        INSERT INTO DemoTable VALUES(2, 1,2,3);
+        INSERT INTO DemoTable VALUES(1, 9,'8',7);
+        INSERT INTO DemoTable VALUES(2, 1,'2',3);
         CREATE VIEW DemoView AS SELECT x, TextKey, DKey FROM DemoTable ORDER BY TextKey;
         SELECT x,TextKey,DKey FROM DemoTable UNION ALL SELECT * FROM DemoView ORDER BY 1;
     ]], {
diff --git a/test/sql-tap/tkt3493.test.lua b/test/sql-tap/tkt3493.test.lua
index 7ceec4702..de77e61e9 100755
--- a/test/sql-tap/tkt3493.test.lua
+++ b/test/sql-tap/tkt3493.test.lua
@@ -29,8 +29,8 @@ test:do_execsql_test(
         START TRANSACTION;
         INSERT INTO A VALUES(1,'123');
         INSERT INTO A VALUES(2,'456');
-        INSERT INTO B VALUES(1,1);
-        INSERT INTO B VALUES(2,2);
+        INSERT INTO B VALUES(1,'1');
+        INSERT INTO B VALUES(2,'2');
         INSERT INTO A_B VALUES(1,1);
         INSERT INTO A_B VALUES(2,2);
         COMMIT;
@@ -116,7 +116,7 @@ test:do_execsql_test(
     "tkt3493-2.1",
     [[
         CREATE TABLE t1(a TEXT PRIMARY KEY, b INT);
-        INSERT INTO t1 VALUES(123, 456);
+        INSERT INTO t1 VALUES('123', 456);
     ]], {
         -- <tkt3493-2.1>
         
diff --git a/test/sql-tap/tkt3841.test.lua b/test/sql-tap/tkt3841.test.lua
index 5203d0cd4..56668f6a3 100755
--- a/test/sql-tap/tkt3841.test.lua
+++ b/test/sql-tap/tkt3841.test.lua
@@ -31,12 +31,12 @@ test:do_execsql_test(
 
         INSERT INTO table2 VALUES ('a', 'alist');
         INSERT INTO table2 VALUES ('b', 'blist');
-        INSERT INTO list VALUES ('a', 1);
-        INSERT INTO list VALUES ('a', 2);
-        INSERT INTO list VALUES ('a', 3);
-        INSERT INTO list VALUES ('b', 4);
-        INSERT INTO list VALUES ('b', 5);
-        INSERT INTO list VALUES ('b', 6);
+        INSERT INTO list VALUES ('a', '1');
+        INSERT INTO list VALUES ('a', '2');
+        INSERT INTO list VALUES ('a', '3');
+        INSERT INTO list VALUES ('b', '4');
+        INSERT INTO list VALUES ('b', '5');
+        INSERT INTO list VALUES ('b', '6');
 
         SELECT
           table2.x,
diff --git a/test/sql-tap/triggerA.test.lua b/test/sql-tap/triggerA.test.lua
index fac51ca14..fc8ecfe17 100755
--- a/test/sql-tap/triggerA.test.lua
+++ b/test/sql-tap/triggerA.test.lua
@@ -283,7 +283,7 @@ test:do_test(
             CREATE TABLE result2(id INTEGER PRIMARY KEY, a TEXT,b INT);
             CREATE TRIGGER r5d INSTEAD OF DELETE ON v5 FOR EACH ROW BEGIN
               INSERT INTO result2(id, a,b) VALUES((SELECT coalesce(max(id),0) + 1 FROM result2),
-                                                  old.x, old.b);
+                                                  CAST(old.x AS STRING), old.b);
             END;
             DELETE FROM v5 WHERE x=5;
             SELECT a, b FROM result2;
@@ -301,7 +301,7 @@ test:do_test(
             DELETE FROM result4;
             CREATE TRIGGER r5u INSTEAD OF UPDATE ON v5 FOR EACH ROW BEGIN
               INSERT INTO result4(id, a,b,c,d) VALUES((SELECT coalesce(max(id),0) + 1 FROM result4),
-                                                      old.x, old.b, new.x, new.b);
+                                                      CAST(old.x AS STRING), old.b, CAST(new.x AS STRING), new.b);
             END;
             UPDATE v5 SET b = b+9900000 WHERE x BETWEEN 3 AND 5;
             SELECT a,b,c,d FROM result4 ORDER BY a;
diff --git a/test/sql-tap/unique.test.lua b/test/sql-tap/unique.test.lua
index 9818f90a8..6b0a7e20d 100755
--- a/test/sql-tap/unique.test.lua
+++ b/test/sql-tap/unique.test.lua
@@ -52,7 +52,7 @@ test:do_catchsql_test(
 test:do_catchsql_test(
     "unique-1.2",
     [[
-        INSERT INTO t1(a,b,c) VALUES(1,2,3)
+        INSERT INTO t1(a,b,c) VALUES(1,2,'3')
     ]], {
         -- <unique-1.2>
         0
@@ -62,7 +62,7 @@ test:do_catchsql_test(
 test:do_catchsql_test(
     "unique-1.3",
     [[
-        INSERT INTO t1(a,b,c) VALUES(1,3,4)
+        INSERT INTO t1(a,b,c) VALUES(1,3,'4')
     ]], {
         -- <unique-1.3>
         1, "Duplicate key exists in unique index 'pk_unnamed_T1_1' in space 'T1'"
@@ -83,7 +83,7 @@ test:do_execsql_test(
 test:do_catchsql_test(
     "unique-1.5",
     [[
-        INSERT INTO t1(a,b,c) VALUES(3,2,4)
+        INSERT INTO t1(a,b,c) VALUES(3,2,'4')
     ]], {
         -- <unique-1.5>
         1, "Duplicate key exists in unique index 'unique_unnamed_T1_2' in space 'T1'"
@@ -104,7 +104,7 @@ test:do_execsql_test(
 test:do_catchsql_test(
     "unique-1.7",
     [[
-        INSERT INTO t1(a,b,c) VALUES(3,4,5)
+        INSERT INTO t1(a,b,c) VALUES(3,4,'5')
     ]], {
         -- <unique-1.7>
         0
diff --git a/test/sql-tap/view.test.lua b/test/sql-tap/view.test.lua
index e553b91c7..ab14c5edb 100755
--- a/test/sql-tap/view.test.lua
+++ b/test/sql-tap/view.test.lua
@@ -757,7 +757,7 @@ test:do_execsql_test(
     "view-10.1",
     [=[
         CREATE TABLE t3("9" integer primary key, "4" text);
-        INSERT INTO t3 VALUES(1,2);
+        INSERT INTO t3 VALUES(1,'2');
         CREATE VIEW v_t3_a AS SELECT a."9" FROM t3 AS a;
         CREATE VIEW v_t3_b AS SELECT "4" FROM t3;
         SELECT * FROM v_t3_a;
diff --git a/test/sql-tap/where5.test.lua b/test/sql-tap/where5.test.lua
index 749201564..3aefcaca5 100755
--- a/test/sql-tap/where5.test.lua
+++ b/test/sql-tap/where5.test.lua
@@ -27,11 +27,11 @@ test:do_test("where5-1.0", function()
         CREATE TABLE t1(x TEXT primary key);
         CREATE TABLE t2(x integer primary key);
         CREATE TABLE t3(x integer PRIMARY KEY);
-        INSERT INTO t1 VALUES(-1);
-        INSERT INTO t1 VALUES(0);
-        INSERT INTO t1 VALUES(1);
-        INSERT INTO t2 SELECT * FROM t1;
-        INSERT INTO t3 SELECT * FROM t1;
+        INSERT INTO t1 VALUES('-1');
+        INSERT INTO t1 VALUES('0');
+        INSERT INTO t1 VALUES('1');
+        INSERT INTO t2 SELECT CAST(x AS INTEGER) FROM t1;
+        INSERT INTO t3 SELECT CAST(x AS INTEGER) FROM t1;
     ]]
     return test:execsql [[
         SELECT * FROM t1 WHERE x<0
diff --git a/test/sql-tap/whereB.test.lua b/test/sql-tap/whereB.test.lua
index d98645fdc..fe5e28c70 100755
--- a/test/sql-tap/whereB.test.lua
+++ b/test/sql-tap/whereB.test.lua
@@ -112,24 +112,16 @@ test:do_execsql_test(
     -- </whereB-1.102>
     })
 
--- For this set of tests:
---
---  *   t1.y holds a text value with affinity TEXT
---  *   t2.b holds an integer value with affinity NONE
---
--- These values are not equal and because neither affinity is NUMERIC
--- no type conversion occurs.
---
 test:do_execsql_test(
     "whereB-2.1",
     [[
         DROP TABLE t1;
         DROP TABLE t2;
 
-        CREATE TABLE t1(x  INT primary key, y TEXT);    -- affinity of t1.y is TEXT
-        INSERT INTO t1 VALUES(1,99);
+        CREATE TABLE t1(x  INT primary key, y TEXT);
+        INSERT INTO t1 VALUES(1,'99');
 
-        CREATE TABLE t2(a  INT primary key, b SCALAR);  -- affinity of t2.b is NONE
+        CREATE TABLE t2(a  INT primary key, b SCALAR);
         CREATE INDEX t2b ON t2(b);
         INSERT INTO t2 VALUES(2, 99);
 
diff --git a/test/sql/boolean.result b/test/sql/boolean.result
index 112e41a12..e88183854 100644
--- a/test/sql/boolean.result
+++ b/test/sql/boolean.result
@@ -161,7 +161,7 @@ SELECT s FROM ts WHERE s IN (true, 1, 'abcd');
 INSERT INTO ts VALUES (true, 12345);
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 
 -- Check that we can create index on field of type BOOLEAN.
diff --git a/test/sql/persistency.result b/test/sql/persistency.result
index 6d14d4c4e..6ec2f06fc 100644
--- a/test/sql/persistency.result
+++ b/test/sql/persistency.result
@@ -370,7 +370,7 @@ box.execute("SELECT \"name\", \"opts\" FROM \"_trigger\"");
 box.execute("INSERT INTO foobar VALUES ('foobar trigger test', 8888)")
 ---
 - null
-- 'Type mismatch: can not convert foobar trigger test to integer'
+- 'Type mismatch: can not convert text to integer'
 ...
 box.execute("SELECT * FROM barfoo WHERE foo = 9999");
 ---
diff --git a/test/sql/types.result b/test/sql/types.result
index 54aff460e..6b0f7a651 100644
--- a/test/sql/types.result
+++ b/test/sql/types.result
@@ -1062,7 +1062,7 @@ box.execute("INSERT INTO t1 VALUES (0), (1), (2);")
 box.execute("INSERT INTO t1 VALUES (-3);")
 ---
 - null
-- 'Type mismatch: can not convert -3 to unsigned'
+- 'Type mismatch: can not convert integer to unsigned'
 ...
 box.execute("SELECT id FROM t1;")
 ---
@@ -1220,22 +1220,22 @@ box.execute("CREATE TABLE t (id INT PRIMARY KEY, v VARBINARY);")
 box.execute("INSERT INTO t VALUES(1, 1);")
 ---
 - null
-- 'Type mismatch: can not convert 1 to varbinary'
+- 'Type mismatch: can not convert unsigned to varbinary'
 ...
 box.execute("INSERT INTO t VALUES(1, 1.123);")
 ---
 - null
-- 'Type mismatch: can not convert 1.123 to varbinary'
+- 'Type mismatch: can not convert real to varbinary'
 ...
 box.execute("INSERT INTO t VALUES(1, true);")
 ---
 - null
-- 'Type mismatch: can not convert TRUE to varbinary'
+- 'Type mismatch: can not convert boolean to varbinary'
 ...
 box.execute("INSERT INTO t VALUES(1, 'asd');")
 ---
 - null
-- 'Type mismatch: can not convert asd to varbinary'
+- 'Type mismatch: can not convert text to varbinary'
 ...
 box.execute("INSERT INTO t VALUES(1, x'616263');")
 ---
@@ -1617,7 +1617,7 @@ s:insert({1, {1,2,3}})
 box.execute('INSERT INTO t1(a) SELECT a FROM t2;')
 ---
 - null
-- 'Type mismatch: can not convert [1, 2, 3] to scalar'
+- 'Type mismatch: can not convert varbinary to scalar'
 ...
 s:replace({1, {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30}})
 ---
@@ -1627,8 +1627,7 @@ s:replace({1, {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25
 box.execute('INSERT INTO t1(a) SELECT a FROM t2;')
 ---
 - null
-- 'Type mismatch: can not convert [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
-  15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30] to scalar'
+- 'Type mismatch: can not convert varbinary to scalar'
 ...
 --
 -- Make sure that the error will be displayed correctly even if
@@ -1653,13 +1652,7 @@ s:replace({1, long_array})
 box.execute('INSERT INTO t1(a) SELECT a FROM t2;')
 ---
 - null
-- 'Type mismatch: can not convert [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
-  15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
-  35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
-  55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74,
-  75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94,
-  95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
-  112, 113, 114, 115, 116, 117, 11'
+- 'Type mismatch: can not convert varbinary to scalar'
 ...
 s:drop()
 ---
@@ -1680,7 +1673,7 @@ s:insert({1, {b = 1}})
 box.execute('INSERT INTO t1(a) SELECT a FROM t2;')
 ---
 - null
-- 'Type mismatch: can not convert {"b": 1} to scalar'
+- 'Type mismatch: can not convert varbinary to scalar'
 ...
 s:drop()
 ---

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [Tarantool-patches] [PATCH v2 2/7] sql: remove mem_apply_type() from OP_MakeRecord
  2020-06-11 12:54 [Tarantool-patches] [PATCH v2 0/7] Remove implicit cast imeevma
  2020-06-11 12:54 ` [Tarantool-patches] [PATCH v2 1/7] sql: remove implicit cast for assignment imeevma
@ 2020-06-11 12:54 ` imeevma
  2020-06-11 12:54 ` [Tarantool-patches] [PATCH v2 3/7] sql: replace ApplyType by CheckType for IN operator imeevma
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 14+ messages in thread
From: imeevma @ 2020-06-11 12:54 UTC (permalink / raw)
  To: v.shpilevoy, tsafin, tarantool-patches

This patch removes type changing from OP_MakeRecord.

Part of #4230
---
 src/box/sql/analyze.c       |  7 +------
 src/box/sql/delete.c        |  8 ++------
 src/box/sql/expr.c          |  8 +-------
 src/box/sql/fk_constraint.c |  9 ++-------
 src/box/sql/select.c        | 25 ++++++-------------------
 src/box/sql/update.c        | 14 +++-----------
 src/box/sql/vdbe.c          | 19 +------------------
 test/sql-tap/in3.test.lua   |  4 ++--
 8 files changed, 18 insertions(+), 76 deletions(-)

diff --git a/src/box/sql/analyze.c b/src/box/sql/analyze.c
index f74f9b358..23fbb15de 100644
--- a/src/box/sql/analyze.c
+++ b/src/box/sql/analyze.c
@@ -965,12 +965,7 @@ vdbe_emit_analyze_space(struct Parse *parse, struct space *space)
 		sqlVdbeAddOp2(v, OP_Next, idx_cursor, next_row_addr);
 		/* Add the entry to the stat1 table. */
 		callStatGet(v, stat4_reg, STAT_GET_STAT1, stat1_reg);
-		enum field_type types[4] = { FIELD_TYPE_STRING,
-					     FIELD_TYPE_STRING,
-					     FIELD_TYPE_STRING,
-					     field_type_MAX };
-		sqlVdbeAddOp4(v, OP_MakeRecord, tab_name_reg, 4, tmp_reg,
-				  (char *)types, sizeof(types));
+		sqlVdbeAddOp3(v, OP_MakeRecord, tab_name_reg, 4, tmp_reg);
 		sqlVdbeAddOp4(v, OP_IdxInsert, tmp_reg, 0, 0,
 				  (char *)stat1, P4_SPACEPTR);
 		/* Add the entries to the stat4 table. */
diff --git a/src/box/sql/delete.c b/src/box/sql/delete.c
index 68abd1f58..0b6f0bd62 100644
--- a/src/box/sql/delete.c
+++ b/src/box/sql/delete.c
@@ -328,12 +328,8 @@ sql_table_delete_from(struct Parse *parse, struct SrcList *tab_list,
 			 * key.
 			 */
 			key_len = 0;
-			struct index *pk = space_index(space, 0);
-			enum field_type *types = is_view ? NULL :
-						 sql_index_type_str(parse->db,
-								    pk->def);
-			sqlVdbeAddOp4(v, OP_MakeRecord, reg_pk, pk_len,
-					  reg_key, (char *)types, P4_DYNAMIC);
+			sqlVdbeAddOp3(v, OP_MakeRecord, reg_pk, pk_len,
+				      reg_key);
 			/* Set flag to save memory allocating one
 			 * by malloc.
 			 */
diff --git a/src/box/sql/expr.c b/src/box/sql/expr.c
index bc2182446..019628a26 100644
--- a/src/box/sql/expr.c
+++ b/src/box/sql/expr.c
@@ -2859,8 +2859,6 @@ sqlCodeSubselect(Parse * pParse,	/* Parsing context */
 				struct ExprList_item *pItem;
 				int r1, r2, r3;
 
-				enum field_type lhs_type =
-					sql_expr_type(pLeft);
 				bool unused;
 				struct coll *unused_coll;
 				if (sql_expr_coll(pParse, pExpr->pLeft, &unused,
@@ -2886,11 +2884,7 @@ sqlCodeSubselect(Parse * pParse,	/* Parsing context */
 						jmpIfDynamic = -1;
 					}
 					r3 = sqlExprCodeTarget(pParse, pE2, r1);
-					enum field_type types[2] =
-						{ lhs_type, field_type_MAX };
-	 				sqlVdbeAddOp4(v, OP_MakeRecord, r3,
-							  1, r2, (char *)types,
-							  sizeof(types));
+					sqlVdbeAddOp3(v, OP_MakeRecord, r3, 1, r2);
 					sql_expr_type_cache_change(pParse,
 								   r3, 1);
 					sqlVdbeAddOp2(v, OP_IdxInsert, r2,
diff --git a/src/box/sql/fk_constraint.c b/src/box/sql/fk_constraint.c
index 482220a95..43471d51a 100644
--- a/src/box/sql/fk_constraint.c
+++ b/src/box/sql/fk_constraint.c
@@ -262,13 +262,8 @@ fk_constraint_lookup_parent(struct Parse *parse_context, struct space *parent,
 					  link->child_field + 1 + reg_data,
 					  temp_regs + i);
 		}
-		struct index *idx = space_index(parent, referenced_idx);
-		assert(idx != NULL);
-		sqlVdbeAddOp4(v, OP_MakeRecord, temp_regs, field_count,
-				  rec_reg,
-				  (char *) sql_index_type_str(parse_context->db,
-							      idx->def),
-				  P4_DYNAMIC);
+		sqlVdbeAddOp3(v, OP_MakeRecord, temp_regs, field_count,
+			      rec_reg);
 		sqlVdbeAddOp4Int(v, OP_Found, cursor, ok_label, rec_reg, 0);
 		sqlReleaseTempReg(parse_context, rec_reg);
 		sqlReleaseTempRange(parse_context, temp_regs, field_count);
diff --git a/src/box/sql/select.c b/src/box/sql/select.c
index 0b7358af4..f3f5dad76 100644
--- a/src/box/sql/select.c
+++ b/src/box/sql/select.c
@@ -1270,13 +1270,8 @@ selectInnerLoop(Parse * pParse,		/* The parser context */
 					       regOrig, nResultCol, nPrefixReg);
 			} else {
 				int r1 = sqlGetTempReg(pParse);
-				enum field_type *types =
-					field_type_sequence_dup(pParse,
-								pDest->dest_type,
-								nResultCol);
-				sqlVdbeAddOp4(v, OP_MakeRecord, regResult,
-						  nResultCol, r1, (char *)types,
-						  P4_DYNAMIC);
+				sqlVdbeAddOp3(v, OP_MakeRecord, regResult,
+					      nResultCol, r1);
 				sql_expr_type_cache_change(pParse,
 							   regResult,
 							   nResultCol);
@@ -1693,12 +1688,8 @@ generateSortTail(Parse * pParse,	/* Parsing context */
 			break;
 		}
 	case SRT_Set:{
-			enum field_type *types =
-				field_type_sequence_dup(pParse, pDest->dest_type,
-							nColumn);
-			sqlVdbeAddOp4(v, OP_MakeRecord, regRow, nColumn,
-					  regTupleid, (char *)types,
-					  P4_DYNAMIC);
+			sqlVdbeAddOp3(v, OP_MakeRecord, regRow, nColumn,
+				      regTupleid);
 			sql_expr_type_cache_change(pParse, regRow, nColumn);
 			sqlVdbeAddOp2(v, OP_IdxInsert, regTupleid, pDest->reg_eph);
 			break;
@@ -3136,12 +3127,8 @@ generateOutputSubroutine(struct Parse *parse, struct Select *p,
 			int r1;
 			testcase(in->nSdst > 1);
 			r1 = sqlGetTempReg(parse);
-			enum field_type *types =
-				field_type_sequence_dup(parse, dest->dest_type,
-							in->nSdst);
-			sqlVdbeAddOp4(v, OP_MakeRecord, in->iSdst,
-					  in->nSdst, r1, (char *)types,
-					  P4_DYNAMIC);
+			sqlVdbeAddOp3(v, OP_MakeRecord, in->iSdst, in->nSdst,
+				      r1);
 			sql_expr_type_cache_change(parse, in->iSdst,
 						   in->nSdst);
 			sqlVdbeAddOp2(v, OP_IdxInsert, r1, dest->reg_eph);
diff --git a/src/box/sql/update.c b/src/box/sql/update.c
index 24c7cfa27..22f82390c 100644
--- a/src/box/sql/update.c
+++ b/src/box/sql/update.c
@@ -251,11 +251,7 @@ sqlUpdate(Parse * pParse,		/* The parser context */
 		nKey = pk_part_count;
 		regKey = iPk;
 	} else {
-		enum field_type *types = is_view ? NULL :
-					 sql_index_type_str(pParse->db,
-							    pPk->def);
-		sqlVdbeAddOp4(v, OP_MakeRecord, iPk, pk_part_count,
-				  regKey, (char *) types, P4_DYNAMIC);
+		sqlVdbeAddOp3(v, OP_MakeRecord, iPk, pk_part_count, regKey);
 		/*
 		 * Set flag to save memory allocating one by
 		 * malloc.
@@ -420,12 +416,8 @@ sqlUpdate(Parse * pParse,		/* The parser context */
 			int key_reg;
 			if (okOnePass) {
 				key_reg = sqlGetTempReg(pParse);
-				enum field_type *types =
-					sql_index_type_str(pParse->db,
-							   pPk->def);
-				sqlVdbeAddOp4(v, OP_MakeRecord, iPk,
-						  pk_part_count, key_reg,
-						  (char *) types, P4_DYNAMIC);
+				sqlVdbeAddOp3(v, OP_MakeRecord, iPk,
+					      pk_part_count, key_reg);
 			} else {
 				assert(nKey == 0);
 				key_reg = regKey;
diff --git a/src/box/sql/vdbe.c b/src/box/sql/vdbe.c
index ae2622c9e..eb5c89e9d 100644
--- a/src/box/sql/vdbe.c
+++ b/src/box/sql/vdbe.c
@@ -2908,24 +2908,17 @@ case OP_CheckType: {
 	break;
 }
 
-/* Opcode: MakeRecord P1 P2 P3 P4 P5
+/* Opcode: MakeRecord P1 P2 P3 * P5
  * Synopsis: r[P3]=mkrec(r[P1@P2])
  *
  * Convert P2 registers beginning with P1 into the [record format]
  * use as a data record in a database table or as a key
  * in an index.  The OP_Column opcode can decode the record later.
  *
- * P4 may be a string that is P2 characters long.  The nth character of the
- * string indicates the column type that should be used for the nth
- * field of the index key.
- *
- * If P4 is NULL then all index fields have type SCALAR.
- *
  * If P5 is not NULL then record under construction is intended to be inserted
  * into ephemeral space. Thus, sort of memory optimization can be performed.
  */
 case OP_MakeRecord: {
-	Mem *pRec;             /* The new record */
 	Mem *pData0;           /* First field to be combined into the record */
 	Mem MAYBE_UNUSED *pLast;  /* Last field of the record */
 	int nField;            /* Number of fields in the record */
@@ -2947,7 +2940,6 @@ case OP_MakeRecord: {
 	 * of the record to data0.
 	 */
 	nField = pOp->p1;
-	enum field_type *types = pOp->p4.types;
 	bIsEphemeral = pOp->p5;
 	assert(nField>0 && pOp->p2>0 && pOp->p2+nField<=(p->nMem+1 - p->nCursor)+1);
 	pData0 = &aMem[nField];
@@ -2958,15 +2950,6 @@ case OP_MakeRecord: {
 	assert(pOp->p3<pOp->p1 || pOp->p3>=pOp->p1+pOp->p2);
 	pOut = vdbe_prepare_null_out(p, pOp->p3);
 
-	/* Apply the requested types to all inputs */
-	assert(pData0<=pLast);
-	if (types != NULL) {
-		pRec = pData0;
-		do {
-			mem_apply_type(pRec++, *(types++));
-		} while(types[0] != field_type_MAX);
-	}
-
 	struct region *region = &fiber()->gc;
 	size_t used = region_used(region);
 	uint32_t tuple_size;
diff --git a/test/sql-tap/in3.test.lua b/test/sql-tap/in3.test.lua
index e29db9d93..f7681640e 100755
--- a/test/sql-tap/in3.test.lua
+++ b/test/sql-tap/in3.test.lua
@@ -354,7 +354,7 @@ test:do_test(
         return exec_neph(" SELECT y IN (SELECT a FROM t1) FROM t2 ")
     end, {
         -- <in3-3.5>
-        1, true
+        1, false
         -- </in3-3.5>
     })
 
@@ -378,7 +378,7 @@ test:do_test(
         return exec_neph(" SELECT y IN (SELECT c FROM t1) FROM t2 ")
     end, {
         -- <in3-3.7>
-        1, true
+        1, false
         -- </in3-3.7>
     })
 
-- 
2.25.1

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [Tarantool-patches] [PATCH v2 3/7] sql: replace ApplyType by CheckType for IN operator
  2020-06-11 12:54 [Tarantool-patches] [PATCH v2 0/7] Remove implicit cast imeevma
  2020-06-11 12:54 ` [Tarantool-patches] [PATCH v2 1/7] sql: remove implicit cast for assignment imeevma
  2020-06-11 12:54 ` [Tarantool-patches] [PATCH v2 2/7] sql: remove mem_apply_type() from OP_MakeRecord imeevma
@ 2020-06-11 12:54 ` imeevma
  2020-06-11 12:54 ` [Tarantool-patches] [PATCH v2 4/7] sql: remove mem_apply_type() from OP_MustBeInt imeevma
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 14+ messages in thread
From: imeevma @ 2020-06-11 12:54 UTC (permalink / raw)
  To: v.shpilevoy, tsafin, tarantool-patches

This patch removes implicit cast from STRING to numeric
and vice versa of left operand of IN operator.

Part of #4230
Part of #4692
---
 src/box/sql/expr.c                   |  2 +-
 test/sql-tap/in3.test.lua            | 14 +-----
 test/sql-tap/subquery.test.lua       | 69 +---------------------------
 test/sql-tap/tkt-80e031a00f.test.lua |  4 +-
 test/sql/boolean.result              | 12 ++---
 5 files changed, 11 insertions(+), 90 deletions(-)

diff --git a/src/box/sql/expr.c b/src/box/sql/expr.c
index 019628a26..8ec685cd9 100644
--- a/src/box/sql/expr.c
+++ b/src/box/sql/expr.c
@@ -3179,7 +3179,7 @@ sqlExprCodeIN(Parse * pParse,	/* Parsing and code generating context */
 	 * true.
 	 */
 	zAff[nVector] = field_type_MAX;
-	sqlVdbeAddOp4(v, OP_ApplyType, rLhs, nVector, 0, (char*)zAff,
+	sqlVdbeAddOp4(v, OP_CheckType, rLhs, nVector, 0, (char*)zAff,
 			  P4_DYNAMIC);
 	/*
 	 * zAff will be freed at the end of VDBE execution, since
diff --git a/test/sql-tap/in3.test.lua b/test/sql-tap/in3.test.lua
index f7681640e..a2147b0e8 100755
--- a/test/sql-tap/in3.test.lua
+++ b/test/sql-tap/in3.test.lua
@@ -1,6 +1,6 @@
 #!/usr/bin/env tarantool
 test = require("sqltester")
-test:plan(29)
+test:plan(28)
 
 --!./tcltestrunner.lua
 -- 2007 November 29
@@ -322,18 +322,6 @@ test:do_test(
         -- </in3-3.2>
     })
 
-test:do_test(
-    "in3-3.3",
-    function()
-        -- Logically, numeric affinity is applied to both sides before
-        -- the comparison, but index can't be used.
-        return exec_neph(" SELECT x IN (SELECT b FROM t1) FROM t2 ")
-    end, {
-        -- <in3-3.3>
-        1, true
-        -- </in3-3.3>
-    })
-
 test:do_test(
     "in3-3.4",
     function()
diff --git a/test/sql-tap/subquery.test.lua b/test/sql-tap/subquery.test.lua
index 15c4c8276..e0771825e 100755
--- a/test/sql-tap/subquery.test.lua
+++ b/test/sql-tap/subquery.test.lua
@@ -1,6 +1,6 @@
 #!/usr/bin/env tarantool
 test = require("sqltester")
-test:plan(73)
+test:plan(69)
 
 --!./tcltestrunner.lua
 -- 2005 January 19
@@ -335,73 +335,6 @@ test:do_execsql_test(
         -- </subquery-2.4.3>
     })
 
-test:do_execsql_test(
-    "subquery-2.5.1",
-    [[
-        CREATE TABLE t3(a INTEGER PRIMARY KEY);
-        INSERT INTO t3 VALUES(10);
-
-        CREATE TABLE t4(x TEXT PRIMARY KEY);
-        INSERT INTO t4 VALUES('10');
-    ]], {
-        -- <subquery-2.5.1>
-        
-        -- </subquery-2.5.1>
-    })
-
-test:do_test(
-    "subquery-2.5.2",
-    function()
-        -- In the expr "x IN (SELECT a FROM t3)" the RHS of the IN operator
-        -- has text affinity and the LHS has integer affinity.  The rule is
-        -- that we try to convert both sides to an integer before doing the
-        -- comparision. Hence, the integer value 10 in t3 will compare equal
-        -- to the string value '10.0' in t4 because the t4 value will be
-        -- converted into an integer.
-        return test:execsql [[
-            SELECT * FROM t4 WHERE x IN (SELECT a FROM t3);
-        ]]
-    end, {
-        -- <subquery-2.5.2>
-        "10"
-        -- </subquery-2.5.2>
-    })
-
-test:do_test(
-    "subquery-2.5.3.1",
-    function()
-        -- The t4i index cannot be used to resolve the "x IN (...)" constraint
-        -- because the constraint has integer affinity but t4i has text affinity.
-        return test:execsql [[
-            CREATE INDEX t4i ON t4(x);
-            SELECT * FROM t4 WHERE x IN (SELECT a FROM t3);
-        ]]
-    end, {
-        -- <subquery-2.5.3.1>
-        "10"
-        -- </subquery-2.5.3.1>
-    })
-
--- Tarantool: no-rowid is implied for the table, so query plan contains
--- scan over t4i. Verified w/ vanilla sql. Comment this case
---do_test subquery-2.5.3.2 {
--- Verify that the t4i index was not used in the previous query
---  execsql {
---    EXPLAIN QUERY PLAN
---    SELECT * FROM t4 WHERE x IN (SELECT a FROM t3);
---  }
---} {~/t4i/}
-test:do_execsql_test(
-    "subquery-2.5.4",
-    [[
-        DROP TABLE t3;
-        DROP TABLE t4;
-    ]], {
-        -- <subquery-2.5.4>
-        
-        -- </subquery-2.5.4>
-    })
-
 --------------------------------------------------------------------
 -- The following test cases - subquery-3.* - test tickets that
 -- were raised during development of correlated subqueries.
diff --git a/test/sql-tap/tkt-80e031a00f.test.lua b/test/sql-tap/tkt-80e031a00f.test.lua
index a0e6539e0..c883937ca 100755
--- a/test/sql-tap/tkt-80e031a00f.test.lua
+++ b/test/sql-tap/tkt-80e031a00f.test.lua
@@ -346,7 +346,7 @@ test:do_catchsql_test(
         SELECT 'hello' IN t1
     ]], {
         -- <tkt-80e031a00f.27>
-        1, 'Type mismatch: can not convert hello to integer'
+        1, 'Type mismatch: can not convert text to integer'
         -- </tkt-80e031a00f.27>
     })
 
@@ -356,7 +356,7 @@ test:do_catchsql_test(
         SELECT 'hello' NOT IN t1
     ]], {
         -- <tkt-80e031a00f.28>
-        1, 'Type mismatch: can not convert hello to integer'
+        1, 'Type mismatch: can not convert text to integer'
         -- </tkt-80e031a00f.28>
     })
 
diff --git a/test/sql/boolean.result b/test/sql/boolean.result
index e88183854..c74713c34 100644
--- a/test/sql/boolean.result
+++ b/test/sql/boolean.result
@@ -3877,12 +3877,12 @@ SELECT false IN (0, 1, 2, 3);
 SELECT true IN (SELECT b FROM t7);
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT false IN (SELECT b FROM t7);
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT a1, a1 IN (0, 1, 2, 3) FROM t6
  | ---
@@ -5038,22 +5038,22 @@ SELECT a2 IN (0.1, 1.2, 2.3, 3.4) FROM t6 LIMIT 1;
 SELECT true IN (SELECT c FROM t8);
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to number'
+ | - 'Type mismatch: can not convert boolean to number'
  | ...
 SELECT false IN (SELECT c FROM t8);
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to number'
+ | - 'Type mismatch: can not convert boolean to number'
  | ...
 SELECT a1 IN (SELECT c FROM t8) FROM t6 LIMIT 1;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to number'
+ | - 'Type mismatch: can not convert boolean to number'
  | ...
 SELECT a2 IN (SELECT c FROM t8) FROM t6 LIMIT 1;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to number'
+ | - 'Type mismatch: can not convert boolean to number'
  | ...
 
 SELECT true BETWEEN 0.1 and 9.9;
-- 
2.25.1

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [Tarantool-patches] [PATCH v2 4/7] sql: remove mem_apply_type() from OP_MustBeInt
  2020-06-11 12:54 [Tarantool-patches] [PATCH v2 0/7] Remove implicit cast imeevma
                   ` (2 preceding siblings ...)
  2020-06-11 12:54 ` [Tarantool-patches] [PATCH v2 3/7] sql: replace ApplyType by CheckType for IN operator imeevma
@ 2020-06-11 12:54 ` imeevma
  2020-06-11 12:54 ` [Tarantool-patches] [PATCH v2 5/7] sql: remove implicit cast from string for comparison imeevma
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 14+ messages in thread
From: imeevma @ 2020-06-11 12:54 UTC (permalink / raw)
  To: v.shpilevoy, tsafin, tarantool-patches

Thank you for the review! My answers, diff and new patch below.

On 10.06.2020 01:28, Vladislav Shpilevoy wrote:
> Thanks for the patch!
>
> See 2 comments below.
>
>> diff --git a/test/sql-tap/join.test.lua b/test/sql-tap/join.test.lua
>> index 840b780a3..51e0ecb79 100755
>> --- a/test/sql-tap/join.test.lua
>> +++ b/test/sql-tap/join.test.lua
>> @@ -1034,7 +1034,6 @@ test:do_execsql_test(
>>          SELECT * FROM t1 NATURAL JOIN t2
>>      ]], {
>>          -- <join-11.9>
>> -        "one", "1", "two", "2"
>>          -- </join-11.9>
>>      })
>
> 1. Why does "join-11.10" still work? I see it started failing
> in the next commits, but why not here?
Because in the MustBeInt opcode, the result of executing the
sql_check_types() function is not checked. The main functionality
of the function there is to convert mem if necessary and possible.

>
>> diff --git a/test/sql-tap/tkt-9a8b09f8e6.test.lua b/test/sql-tap/tkt-9a8b09f8e6.test.lua
>> index cb5348ab4..854ed774f 100755
>> --- a/test/sql-tap/tkt-9a8b09f8e6.test.lua
>> +++ b/test/sql-tap/tkt-9a8b09f8e6.test.lua
>> @@ -189,7 +189,6 @@ test:do_execsql_test(
>>          SELECT x FROM t2 WHERE x IN ('1');
>>      ]], {
>>          -- <3.3>
>> -        1
>>          -- </3.3>
>>      })
>>
>> @@ -199,7 +198,6 @@ test:do_execsql_test(
>>          SELECT x FROM t2 WHERE x IN ('1');
>>      ]], {
>>          -- <3.4>
>> -        1
>>          -- </3.4>
>>      })
>>
>> @@ -229,7 +227,6 @@ test:do_execsql_test(
>>          SELECT x FROM t2 WHERE '1' IN (x);
>>      ]], {
>>          -- <3.7>
>> -        1
>>          -- </3.7>
>>      })
>>
>> @@ -239,7 +236,6 @@ test:do_execsql_test(
>>          SELECT x FROM t2 WHERE '1' IN (x);
>>      ]], {
>>          -- <3.8>
>> -        1
>>          -- </3.8>
>
> 2. 3.7 and 3.8 are absolutely the same. Maybe better to drop
> one of them. The same about 3.4 <-> 3.3.
Removed two of them. However, in the next patch, I deleted the
entire test file after I transferred several tests to another
file.



Diff:

diff --git a/test/sql-tap/tkt-9a8b09f8e6.test.lua b/test/sql-tap/tkt-9a8b09f8e6.test.lua
index 854ed774f..ac89c7df2 100755
--- a/test/sql-tap/tkt-9a8b09f8e6.test.lua
+++ b/test/sql-tap/tkt-9a8b09f8e6.test.lua
@@ -1,6 +1,6 @@
 #!/usr/bin/env tarantool
 test = require("sqltester")
-test:plan(49)
+test:plan(47)
 
 --!./tcltestrunner.lua
 -- 2014 June 26
@@ -192,15 +192,6 @@ test:do_execsql_test(
         -- </3.3>
     })
 
-test:do_execsql_test(
-    3.4,
-    [[
-        SELECT x FROM t2 WHERE x IN ('1');
-    ]], {
-        -- <3.4>
-        -- </3.4>
-    })
-
 test:do_execsql_test(
     3.5,
     [[
@@ -230,15 +221,6 @@ test:do_execsql_test(
         -- </3.7>
     })
 
-test:do_execsql_test(
-    3.8,
-    [[
-        SELECT x FROM t2 WHERE '1' IN (x);
-    ]], {
-        -- <3.8>
-        -- </3.8>
-    })
-
 test:do_execsql_test(
     4.1,
     [[


New patch:

From 58ce0e0e58759fcd66786c7010cae687431771c4 Mon Sep 17 00:00:00 2001
From: Mergen Imeev <imeevma@gmail.com>
Date: Thu, 28 May 2020 13:10:35 +0300
Subject: [PATCH] sql: remove mem_apply_type() from OP_MustBeInt

This patch replaces mem_apply_type() with mem_check_types() in
OP_MustBeInt, which allows to remove implicit cast in some places,
for example, in the IN statement.

Part of #4230

diff --git a/src/box/sql/vdbe.c b/src/box/sql/vdbe.c
index eb5c89e9d..77b758833 100644
--- a/src/box/sql/vdbe.c
+++ b/src/box/sql/vdbe.c
@@ -2096,7 +2096,7 @@ case OP_AddImm: {            /* in1 */
 case OP_MustBeInt: {            /* jump, in1 */
    pIn1 = &aMem[pOp->p1];
    if ((pIn1->flags & (MEM_Int | MEM_UInt)) == 0) {
-       mem_apply_type(pIn1, FIELD_TYPE_INTEGER);
+       mem_check_types(pIn1, FIELD_TYPE_INTEGER);
        if ((pIn1->flags & (MEM_Int | MEM_UInt)) == 0) {
            if (pOp->p2==0) {
                diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
diff --git a/test/sql-tap/e_select1.test.lua b/test/sql-tap/e_select1.test.lua
index 7673426f4..578620fca 100755
--- a/test/sql-tap/e_select1.test.lua
+++ b/test/sql-tap/e_select1.test.lua
@@ -1,6 +1,6 @@
 #!/usr/bin/env tarantool
 test = require("sqltester")
-test:plan(510)
+test:plan(509)
 
 --!./tcltestrunner.lua
 -- 2010 July 16
@@ -2150,7 +2150,6 @@ test:do_select_tests(
         {"2", "SELECT b FROM f1 ORDER BY a LIMIT 2+3 ", {"a",  "b", "c", "d", "e"}},
         {"3", "SELECT b FROM f1 ORDER BY a LIMIT (SELECT a FROM f1 WHERE b = 'e') ", {"a",  "b", "c", "d", "e"}},
         {"4", "SELECT b FROM f1 ORDER BY a LIMIT 5.0 ", {"a",  "b", "c", "d", "e"}},
-        {"5", "SELECT b FROM f1 ORDER BY a LIMIT '5' ", {"a",  "b", "c", "d", "e"}},
     })
 
 -- EVIDENCE-OF: R-46155-47219 If the expression evaluates to a NULL value
@@ -2195,7 +2194,7 @@ test:do_select_tests(
         {"1", "SELECT b FROM f1 ORDER BY a LIMIT 0 ", {}},
         {"2", "SELECT b FROM f1 ORDER BY a DESC LIMIT 4 ", {"z", "y", "x", "w"}},
         {"3", "SELECT b FROM f1 ORDER BY a DESC LIMIT 8 ", {"z", "y", "x", "w", "v", "u", "t", "s"}},
-        {"4", "SELECT b FROM f1 ORDER BY a DESC LIMIT '12' ", {"z", y, "x", "w", "v", "u", "t", "s", "r", "q", "p", "o"}},
+        {"4", "SELECT b FROM f1 ORDER BY a DESC LIMIT 12 ", {"z", y, "x", "w", "v", "u", "t", "s", "r", "q", "p", "o"}},
     })
 
 -- EVIDENCE-OF: R-54935-19057 Or, if the SELECT statement would return
@@ -2240,10 +2239,10 @@ test:do_select_tests(
         {"1", "SELECT b FROM f1 ORDER BY a LIMIT 10 OFFSET 5", {"f", "g", "h", "i", "j", "k", "l", "m", "n", "o"}},
         {"2", "SELECT b FROM f1 ORDER BY a LIMIT 2+3 OFFSET 10", {"k", "l", "m", "n", "o"}},
         {"3", "SELECT b FROM f1 ORDER BY a LIMIT  (SELECT a FROM f1 WHERE b='j') OFFSET (SELECT a FROM f1 WHERE b='b') ", {"c", "d", "e", "f", "g", "h", "i", "j", "k", "l"}},
-        {"4", "SELECT b FROM f1 ORDER BY a LIMIT '5' OFFSET 3.0 ", {"d", "e", "f", "g", "h"}},
-        {"5", "SELECT b FROM f1 ORDER BY a LIMIT '5' OFFSET 0 ", {"a", "b", "c", "d", "e"}},
+        {"4", "SELECT b FROM f1 ORDER BY a LIMIT 5 OFFSET 3.0 ", {"d", "e", "f", "g", "h"}},
+        {"5", "SELECT b FROM f1 ORDER BY a LIMIT 5 OFFSET 0 ", {"a", "b", "c", "d", "e"}},
         {"6", "SELECT b FROM f1 ORDER BY a LIMIT 0 OFFSET 10 ", {}},
-        {"7", "SELECT b FROM f1 ORDER BY a LIMIT 3 OFFSET '1'||'5' ", {"p", "q", "r"}},
+        {"7", "SELECT b FROM f1 ORDER BY a LIMIT 3 OFFSET CAST('1'||'5' AS INTEGER) ", {"p", "q", "r"}},
     })
 
 -- EVIDENCE-OF: R-34648-44875 Or, if the SELECT would return less than
@@ -2279,10 +2278,10 @@ test:do_select_tests(
         {"1", "SELECT b FROM f1 ORDER BY a LIMIT 5, 10 ", {"f", "g", "h", "i", "j", "k", "l", "m", "n", "o"}},
         {"2", "SELECT b FROM f1 ORDER BY a LIMIT 10, 2+3 ", {"k", "l", "m", "n", "o"}},
         {"3", "SELECT b FROM f1 ORDER BY a LIMIT (SELECT a FROM f1 WHERE b='b'), (SELECT a FROM f1 WHERE b='j')", {"c", "d", "e", "f", "g", "h", "i", "j", "k", "l"}},
-        {"4", "SELECT b FROM f1 ORDER BY a LIMIT 3.0, '5' ", {"d", "e", "f", "g", "h"}},
-        {"5", "SELECT b FROM f1 ORDER BY a LIMIT 0, '5' ", {"a", "b", "c", "d", "e"}},
+        {"4", "SELECT b FROM f1 ORDER BY a LIMIT 3.0, 5 ", {"d", "e", "f", "g", "h"}},
+        {"5", "SELECT b FROM f1 ORDER BY a LIMIT 0, 5 ", {"a", "b", "c", "d", "e"}},
         {"6", "SELECT b FROM f1 ORDER BY a LIMIT 10, 0 ", {}},
-        {"7", "SELECT b FROM f1 ORDER BY a LIMIT '1'||'5', 3 ", {"p", "q", "r"}},
+        {"7", "SELECT b FROM f1 ORDER BY a LIMIT CAST('1'||'5' AS INTEGER), 3 ", {"p", "q", "r"}},
         {"8", "SELECT b FROM f1 ORDER BY a LIMIT 20, 10 ", {"u", "v", "w", "x", "y", "z"}},
         {"9", "SELECT a FROM f1 ORDER BY a DESC LIMIT 18+4, 100 ", {4, 3, 2, 1}},
         {"10", "SELECT b FROM f1 ORDER BY a LIMIT 0, 5 ", {"a", "b", "c", "d", "e"}},
diff --git a/test/sql-tap/in4.test.lua b/test/sql-tap/in4.test.lua
index 8c6917379..33947d0ab 100755
--- a/test/sql-tap/in4.test.lua
+++ b/test/sql-tap/in4.test.lua
@@ -1,6 +1,6 @@
 #!/usr/bin/env tarantool
 test = require("sqltester")
-test:plan(61)
+test:plan(52)
 
 --!./tcltestrunner.lua
 -- 2008 September 1
@@ -140,7 +140,7 @@ test:do_execsql_test(
 test:do_execsql_test(
     "in4-2.7",
     [[
-        SELECT b FROM t2 WHERE a IN ('1', '2') 
+        SELECT b FROM t2 WHERE a IN (1, 2)
     ]], {
         -- <in4-2.7>
         "one", "two"
@@ -153,7 +153,6 @@ test:do_execsql_test(
         SELECT b FROM t2 WHERE a IN ('', '0.0.0', '2') 
     ]], {
         -- <in4-2.8>
-        "two"
         -- </in4-2.8>
     })
 
@@ -585,98 +584,6 @@ test:do_execsql_test(
         -- </in4-4.6>
     })
 
-test:do_execsql_test(
-    "in4-4.11",
-    [[
-        CREATE TABLE t4b(a TEXT, b NUMBER, c  INT PRIMARY KEY);
-        INSERT INTO t4b VALUES('1.0',1,4);
-        SELECT c FROM t4b WHERE a=b;
-    ]], {
-        -- <in4-4.11>
-        4
-        -- </in4-4.11>
-    })
-
-test:do_execsql_test(
-    "in4-4.12",
-    [[
-        SELECT c FROM t4b WHERE b=a;
-    ]], {
-        -- <in4-4.12>
-        4
-        -- </in4-4.12>
-    })
-
-test:do_execsql_test(
-    "in4-4.13",
-    [[
-        SELECT c FROM t4b WHERE +a=b;
-    ]], {
-        -- <in4-4.13>
-        4
-        -- </in4-4.13>
-    })
-
-test:do_execsql_test(
-    "in4-4.14",
-    [[
-        SELECT c FROM t4b WHERE a=+b;
-    ]], {
-        -- <in4-4.14>
-        4
-        -- </in4-4.14>
-    })
-
-test:do_execsql_test(
-    "in4-4.15",
-    [[
-        SELECT c FROM t4b WHERE +b=a;
-    ]], {
-        -- <in4-4.15>
-        4
-        -- </in4-4.15>
-    })
-
-test:do_execsql_test(
-    "in4-4.16",
-    [[
-        SELECT c FROM t4b WHERE b=+a;
-    ]], {
-        -- <in4-4.16>
-        4
-        -- </in4-4.16>
-    })
-
-test:do_execsql_test(
-    "in4-4.17",
-    [[
-        SELECT c FROM t4b WHERE a IN (b);
-    ]], {
-        -- <in4-4.17>
-        4
-        -- </in4-4.17>
-    })
-
-test:do_execsql_test(
-    "in4-4.18",
-    [[
-        SELECT c FROM t4b WHERE b IN (a);
-    ]], {
-        -- <in4-4.18>
-        4
-        -- </in4-4.18>
-    })
-
-test:do_execsql_test(
-    "in4-4.19",
-    [[
-        SELECT c FROM t4b WHERE +b IN (a);
-    ]], {
-        -- <in4-4.19>
-        4
-        -- </in4-4.19>
-    })
-
 -- MUST_WORK_TEST
 -- Tarantool: TBI: Need to support collations. Depends on #2121
 -- test:do_execsql_test(
diff --git a/test/sql-tap/join.test.lua b/test/sql-tap/join.test.lua
index 840b780a3..51e0ecb79 100755
--- a/test/sql-tap/join.test.lua
+++ b/test/sql-tap/join.test.lua
@@ -1034,7 +1034,6 @@ test:do_execsql_test(
         SELECT * FROM t1 NATURAL JOIN t2 
     ]], {
         -- <join-11.9>
-        "one", "1", "two", "2"
         -- </join-11.9>
     })
 
diff --git a/test/sql-tap/limit.test.lua b/test/sql-tap/limit.test.lua
index 870233942..a7d1451f7 100755
--- a/test/sql-tap/limit.test.lua
+++ b/test/sql-tap/limit.test.lua
@@ -441,7 +441,7 @@ test:do_catchsql_test(
 test:do_execsql_test(
     "limit-6.5.2",
     [[
-        SELECT * FROM t6 LIMIT '12'
+        SELECT * FROM t6 LIMIT 12
     ]], {
     -- <limit-6.5>
     1, 2, 3, 4
diff --git a/test/sql-tap/tkt-9a8b09f8e6.test.lua b/test/sql-tap/tkt-9a8b09f8e6.test.lua
index cb5348ab4..ac89c7df2 100755
--- a/test/sql-tap/tkt-9a8b09f8e6.test.lua
+++ b/test/sql-tap/tkt-9a8b09f8e6.test.lua
@@ -1,6 +1,6 @@
 #!/usr/bin/env tarantool
 test = require("sqltester")
-test:plan(49)
+test:plan(47)
 
 --!./tcltestrunner.lua
 -- 2014 June 26
@@ -189,20 +189,9 @@ test:do_execsql_test(
         SELECT x FROM t2 WHERE x IN ('1');
     ]], {
         -- <3.3>
-        1
         -- </3.3>
     })
 
-test:do_execsql_test(
-    3.4,
-    [[
-        SELECT x FROM t2 WHERE x IN ('1');
-    ]], {
-        -- <3.4>
-        1
-        -- </3.4>
-    })
-
 test:do_execsql_test(
     3.5,
     [[
@@ -229,20 +218,9 @@ test:do_execsql_test(
         SELECT x FROM t2 WHERE '1' IN (x);
     ]], {
         -- <3.7>
-        1
         -- </3.7>
     })
 
-test:do_execsql_test(
-    3.8,
-    [[
-        SELECT x FROM t2 WHERE '1' IN (x);
-    ]], {
-        -- <3.8>
-        1
-        -- </3.8>
-    })
-
 test:do_execsql_test(
     4.1,
     [[
diff --git a/test/sql-tap/tkt-fc7bd6358f.test.lua b/test/sql-tap/tkt-fc7bd6358f.test.lua
deleted file mode 100755
index fe5d6200f..000000000
--- a/test/sql-tap/tkt-fc7bd6358f.test.lua
+++ /dev/null
@@ -1,111 +0,0 @@
-#!/usr/bin/env tarantool
-test = require("sqltester")
-test:plan(50)
-
---!./tcltestrunner.lua
--- 2013 March 05
---
--- The author disclaims copyright to this source code.  In place of
--- a legal notice, here is a blessing:
---
---    May you do good and not evil.
---    May you find forgiveness for yourself and forgive others.
---    May you share freely, never taking more than you give.
---
--------------------------------------------------------------------------
--- This file implements regression tests for sql library. Specifically,
--- it tests that ticket [fc7bd6358f]:
---
--- The following SQL yields an incorrect result (zero rows) in all
--- versions of sql between 3.6.14 and 3.7.15.2:
---
---    CREATE TABLE t(textid TEXT);
---    INSERT INTO t VALUES('12');
---    INSERT INTO t VALUES('34');
---    CREATE TABLE i(intid INTEGER PRIMARY KEY);
---    INSERT INTO i VALUES(12);
---    INSERT INTO i VALUES(34);
---
---    SELECT t1.textid AS a, i.intid AS b, t2.textid AS c
---      FROM t t1, i, t t2
---     WHERE t1.textid = i.intid
---       AND t1.textid = t2.textid;
---
--- The correct result should be two rows, one with 12|12|12 and the other
--- with 34|34|34. With this bug, no rows are returned. Bisecting shows that
--- this bug was introduced with check-in [dd4d67a67454] on 2009-04-23. 
---
--- ["set","testdir",[["file","dirname",["argv0"]]]]
--- ["source",[["testdir"],"\/tester.tcl"]]
-test:do_test(
-    "tkt-fc7bd6358f.100",
-    function()
-        return test:execsql [[
-            CREATE TABLE t(textid TEXT PRIMARY KEY);
-            INSERT INTO t VALUES('12');
-            INSERT INTO t VALUES('34');
-            CREATE TABLE i(intid INTEGER PRIMARY KEY);
-            INSERT INTO i VALUES(12);
-            INSERT INTO i VALUES(34);
-        ]]
-    end, {
-        -- <tkt-fc7bd6358f.100>
-        
-        -- </tkt-fc7bd6358f.100>
-    })
-
--- ["unset","-nocomplain","from"]
--- ["unset","-nocomplain","where"]
--- ["unset","-nocomplain","a"]
--- ["unset","-nocomplain","b"]
-local froms = {
-    "FROM t t1, i, t t2",
-    "FROM i, t t1, t t2",
-    "FROM t t1, t t2, i",
-}
-local wheres = {
-    "WHERE t1.textid=i.intid AND t1.textid=t2.textid",
-    "WHERE i.intid=t1.textid AND t1.textid=t2.textid",
-    "WHERE t1.textid=i.intid AND i.intid=t2.textid",
-    "WHERE t1.textid=i.intid AND t2.textid=i.intid",
-    "WHERE i.intid=t1.textid AND i.intid=t2.textid",
-    "WHERE i.intid=t1.textid AND t2.textid=i.intid",
-    "WHERE t1.textid=t2.textid AND i.intid=t2.textid",
-    "WHERE t1.textid=t2.textid AND t2.textid=i.intid",
-}
-for a, from in ipairs(froms) do
-    for b, where in ipairs(wheres) do
-        test:do_test(
-            string.format("tkt-fc7bd6358f.110.%s.%s.1", a, b),
-            function()
-                return test:execsql(string.format("SELECT t1.textid, i.intid, t2.textid %s %s", from, where))
-            end, {
-                "12", 12, "12", "34", 34, "34"
-            })
-
-        test:do_test(
-            string.format("tkt-fc7bd6358f.110.%s.%s.2", a, b),
-            function()
-                return test:execsql(string.format("SELECT t1.textid, i.intid, t2.textid %s %s", from, where))
-            end, {
-                "12", 12, "12", "34", 34, "34"
-            })
-
-    end
-end
-
-test:do_test(
-    "tkt-fc7bd6358f.200",
-    function()
-        return test:execsql [[
-            DROP TABLE t;
-            DROP TABLE i;
-        ]]
-    end, {
-        -- <tkt-fc7bd6358f.100>
-        
-        -- </tkt-fc7bd6358f.100>
-    })
-
-test:finish_test()
-
diff --git a/test/sql-tap/transitive1.test.lua b/test/sql-tap/transitive1.test.lua
index e96056580..96895b4a7 100755
--- a/test/sql-tap/transitive1.test.lua
+++ b/test/sql-tap/transitive1.test.lua
@@ -338,7 +338,7 @@ test:do_execsql_test(
                    ON tvshow.idshow = episode.idshow
                  LEFT JOIN seasons
                         ON seasons.idshow = episode.idshow
-                           AND seasons.season = episode.c12
+                           AND seasons.season = CAST(episode.c12 AS INTEGER)
                  JOIN path
                    ON files.idpath = path.idpath
                  LEFT JOIN bookmark
@@ -378,7 +378,7 @@ test:do_execsql_test(
         FROM episodeview
             JOIN tvshowview ON tvshowview.idShow = episodeview.idShow
             JOIN seasons ON (seasons.idShow = tvshowview.idShow
-                             AND seasons.season = episodeview.c12)
+                             AND seasons.season = CAST(episodeview.c12 AS INTEGER))
             JOIN files ON files.idFile = episodeview.idFile
             JOIN tvshowlinkpath ON tvshowlinkpath.idShow = tvshowview.idShow
             JOIN path ON path.idPath = tvshowlinkpath.idPath
diff --git a/test/sql-tap/whereB.test.lua b/test/sql-tap/whereB.test.lua
deleted file mode 100755
index fe5e28c70..000000000
--- a/test/sql-tap/whereB.test.lua
+++ /dev/null
@@ -1,900 +0,0 @@
-#!/usr/bin/env tarantool
-test = require("sqltester")
-test:plan(63)
-
---!./tcltestrunner.lua
--- 2009 August 13
---
--- The author disclaims copyright to this source code.  In place of
--- a legal notice, here is a blessing:
---
---    May you do good and not evil.
---    May you find forgiveness for yourself and forgive others.
---    May you share freely, never taking more than you give.
---
--------------------------------------------------------------------------
--- This file implements regression tests for sql library. The
--- focus of this file is testing WHERE clause conditions with
--- subtle affinity issues.
---
--- ["set","testdir",[["file","dirname",["argv0"]]]]
--- ["source",[["testdir"],"\/tester.tcl"]]
--- For this set of tests:
---
---  *   t1.y holds an integer value with affinity NONE
---  *   t2.b holds a text value with affinity TEXT
---
--- These values are not equal and because neither affinity is NUMERIC
--- no type conversion occurs.
---
-test:do_execsql_test(
-    "whereB-1.1",
-    [[
-        CREATE TABLE t1(x  INT primary key,y INT );    -- affinity of t1.y is NONE
-        INSERT INTO t1 VALUES(1,99);
-
-        CREATE TABLE t2(a  INT primary key, b TEXT);  -- affinity of t2.b is TEXT
-        CREATE INDEX t2b ON t2(b);
-        INSERT INTO t2 VALUES(2,'99');
-
-        SELECT x, a, y=b FROM t1, t2 ORDER BY +x, +a;
-    ]],
-    {
-    -- <whereB-1.1>
-    1, 2, true
-    -- </whereB-1.1>
-    })
-
-test:do_execsql_test(
-    "whereB-1.2",
-    [[
-        SELECT x, a, y=b FROM t1, t2 WHERE y=b;
-    ]],
-    {
-    -- <whereB-1.2>
-    1, 2, true
-    -- </whereB-1.2>
-    })
-
-test:do_execsql_test(
-    "whereB-1.3",
-    [[
-        SELECT x, a, y=b FROM t1, t2 WHERE b=y;
-    ]],
-    {
-    -- <whereB-1.3>
-    1, 2, true
-    -- </whereB-1.3>
-    })
-
-test:do_execsql_test(
-    "whereB-1.4",
-    [[
-        SELECT x, a, y=b FROM t1, t2 WHERE +y=+b;
-    ]],
-    {
-    -- <whereB-1.4>
-    1, 2, true
-    -- </whereB-1.4>
-    })
-
-test:do_execsql_test(
-    "whereB-1.100",
-    [[
-        DROP INDEX t2b ON t2;
-        SELECT x, a, y=b FROM t1, t2 WHERE y=b;
-    ]],
-    {
-    -- <whereB-1.100>
-    1, 2, true
-    -- </whereB-1.100>
-    })
-
-test:do_execsql_test(
-    "whereB-1.101",
-    [[
-        SELECT x, a, y=b FROM t1, t2 WHERE b=y;
-    ]],
-    {
-    -- <whereB-1.101>
-    1, 2, true
-    -- </whereB-1.101>
-    })
-
-test:do_execsql_test(
-    "whereB-1.102",
-    [[
-        SELECT x, a, y=b FROM t1, t2 WHERE +y=+b;
-    ]],
-    {
-    -- <whereB-1.102>
-    1, 2, true
-    -- </whereB-1.102>
-    })
-
-test:do_execsql_test(
-    "whereB-2.1",
-    [[
-        DROP TABLE t1;
-        DROP TABLE t2;
-
-        CREATE TABLE t1(x  INT primary key, y TEXT);
-        INSERT INTO t1 VALUES(1,'99');
-
-        CREATE TABLE t2(a  INT primary key, b SCALAR);
-        CREATE INDEX t2b ON t2(b);
-        INSERT INTO t2 VALUES(2, 99);
-
-        SELECT x, a, y=b FROM t1, t2 ORDER BY +x, +a;
-    ]],
-    {
-    -- <whereB-2.1>
-    1, 2, false
-    -- </whereB-2.1>
-    })
-
-test:do_execsql_test(
-    "whereB-2.2",
-    [[
-        SELECT x, a, y=b FROM t1, t2 WHERE y=b;
-    ]],
-    {
-    -- <whereB-2.2>
-    
-    -- </whereB-2.2>
-    })
-
-test:do_execsql_test(
-    "whereB-2.3",
-    [[
-        SELECT x, a, y=b FROM t1, t2 WHERE b=y;
-    ]],
-    {
-    -- <whereB-2.3>
-    
-    -- </whereB-2.3>
-    })
-
-test:do_execsql_test(
-    "whereB-2.4",
-    [[
-        SELECT x, a, y=b FROM t1, t2 WHERE +y=+b;
-    ]],
-    {
-    -- <whereB-2.4>
-    
-    -- </whereB-2.4>
-    })
-
-test:do_execsql_test(
-    "whereB-2.100",
-    [[
-        DROP INDEX t2b ON t2;
-        SELECT x, a, y=b FROM t1, t2 WHERE y=b;
-    ]],
-    {
-    -- <whereB-2.100>
-    
-    -- </whereB-2.100>
-    })
-
-test:do_execsql_test(
-    "whereB-2.101",
-    [[
-        SELECT x, a, y=b FROM t1, t2 WHERE b=y;
-    ]],
-    {
-    -- <whereB-2.101>
-    
-    -- </whereB-2.101>
-    })
-
-test:do_execsql_test(
-    "whereB-2.102",
-    [[
-        SELECT x, a, y=b FROM t1, t2 WHERE +y=+b;
-    ]],
-    {
-    -- <whereB-2.102>
-    
-    -- </whereB-2.102>
-    })
-
--- For this set of tests:
---
---  *   t1.y holds a text value with affinity NONE
---  *   t2.b holds an integer value with affinity NONE
---
--- These values are not equal and because neither affinity is NUMERIC
--- no type conversion occurs.
---
-test:do_execsql_test(
-    "whereB-3.1",
-    [[
-        DROP TABLE t1;
-        DROP TABLE t2;
-
-        CREATE TABLE t1(x  INT primary key, y SCALAR);    -- affinity of t1.y is NONE
-        INSERT INTO t1 VALUES(1,99);
-
-        CREATE TABLE t2(a  INT primary key, b SCALAR);  -- affinity of t2.b is NONE
-        CREATE INDEX t2b ON t2(b);
-        INSERT INTO t2 VALUES(2,'99');
-
-        SELECT x, a, y=b FROM t1, t2;
-    ]],
-    {
-    -- <whereB-3.1>
-    1, 2, false
-    -- </whereB-3.1>
-    })
-
-test:do_execsql_test(
-    "whereB-3.2",
-    [[
-        SELECT x, a, y=b FROM t1, t2 WHERE y=b;
-    ]],
-    {
-    -- <whereB-3.2>
-    
-    -- </whereB-3.2>
-    })
-
-test:do_execsql_test(
-    "whereB-3.3",
-    [[
-        SELECT x, a, y=b FROM t1, t2 WHERE b=y;
-    ]],
-    {
-    -- <whereB-3.3>
-    
-    -- </whereB-3.3>
-    })
-
-test:do_execsql_test(
-    "whereB-3.4",
-    [[
-        SELECT x, a, y=b FROM t1, t2 WHERE +y=+b;
-    ]],
-    {
-    -- <whereB-3.4>
-    
-    -- </whereB-3.4>
-    })
-
-test:do_execsql_test(
-    "whereB-3.100",
-    [[
-        DROP INDEX t2b ON t2;
-        SELECT x, a, y=b FROM t1, t2 WHERE y=b;
-    ]],
-    {
-    -- <whereB-3.100>
-    
-    -- </whereB-3.100>
-    })
-
-test:do_execsql_test(
-    "whereB-3.101",
-    [[
-        SELECT x, a, y=b FROM t1, t2 WHERE b=y;
-    ]],
-    {
-    -- <whereB-3.101>
-    
-    -- </whereB-3.101>
-    })
-
-test:do_execsql_test(
-    "whereB-3.102",
-    [[
-        SELECT x, a, y=b FROM t1, t2 WHERE +y=+b;
-    ]],
-    {
-    -- <whereB-3.102>
-    
-    -- </whereB-3.102>
-    })
-
--- For this set of tests:
---
---  *   t1.y holds a text value with affinity NONE
---  *   t2.b holds an integer value with affinity NUMERIC
---
--- Because t2.b has a numeric affinity, type conversion should occur
--- and the two fields should be equal.
---
-test:do_execsql_test(
-    "whereB-4.1",
-    [[
-        DROP TABLE IF EXISTS t1;
-        DROP TABLE IF EXISTS t2;
-
-        CREATE TABLE t1(x  INT primary key, y SCALAR);    -- affinity of t1.y is NONE
-        INSERT INTO t1 VALUES(1,'99');
-
-        CREATE TABLE t2(a  INT primary key, b NUMBER);  -- affinity of t2.b is NUMERIC
-        CREATE INDEX t2b ON t2(b);
-        INSERT INTO t2 VALUES(2,99);
-
-        SELECT x, a, y=b FROM t1, t2;
-    ]],
-    {
-    -- <whereB-4.1>
-    1, 2, true
-    -- </whereB-4.1>
-    })
-
-test:do_execsql_test(
-    "whereB-4.2",
-    [[
-        SELECT x, a, y=b FROM t1, t2 WHERE y=b;
-    ]],
-    {
-    -- <whereB-4.2>
-    1, 2, true
-    -- </whereB-4.2>
-    })
-
-test:do_execsql_test(
-    "whereB-4.3",
-    [[
-        SELECT x, a, y=b FROM t1, t2 WHERE b=y;
-    ]],
-    {
-    -- <whereB-4.3>
-    1, 2, true
-    -- </whereB-4.3>
-    })
-
-test:do_execsql_test(
-    "whereB-4.4",
-    -- In this case the unary "+" operator shouldn't
-    -- affect result set of query.
-    [[
-        SELECT x, a, y=b FROM t1, t2 WHERE +y=+b;
-    ]],
-    {
-    -- <whereB-4.4>
-    1, 2, true
-    -- </whereB-4.4>
-    })
-
-test:do_execsql_test(
-    "whereB-4.100",
-    [[
-        DROP INDEX t2b ON t2;
-        SELECT x, a, y=b FROM t1, t2 WHERE y=b;
-    ]],
-    {
-    -- <whereB-4.100>
-    1, 2, true
-    -- </whereB-4.100>
-    })
-
-test:do_execsql_test(
-    "whereB-4.101",
-    [[
-        SELECT x, a, y=b FROM t1, t2 WHERE b=y;
-    ]],
-    {
-    -- <whereB-4.101>
-    1, 2, true
-    -- </whereB-4.101>
-    })
-
-test:do_execsql_test(
-    "whereB-4.102",
-    -- In this case the unary "+" operator shouldn't
-    -- affect result set of query.
-    [[
-        SELECT x, a, y=b FROM t1, t2 WHERE +y=+b;
-    ]],
-    {
-    -- <whereB-4.102>
-    1, 2, true
-    -- </whereB-4.102>
-    })
-
--- For this set of tests:
---
---  *   t1.y holds a text value with affinity NONE
---  *   t2.b holds an integer value with affinity INTEGER
---
--- Because t2.b has a numeric affinity, type conversion should occur
--- and the two fields should be equal.
---
-test:do_execsql_test(
-    "whereB-5.1",
-    [[
-        DROP TABLE t1;
-        DROP TABLE t2;
-
-        CREATE TABLE t1(x  INT primary key, y SCALAR);    -- affinity of t1.y is NONE
-        INSERT INTO t1 VALUES(1,'99');
-
-        CREATE TABLE t2(a  INT primary key, b INT);  -- affinity of t2.b is INTEGER
-        CREATE INDEX t2b ON t2(b);
-        INSERT INTO t2 VALUES(2,99);
-
-        SELECT x, a, y=b FROM t1, t2;
-    ]],
-    {
-    -- <whereB-5.1>
-    1, 2, true
-    -- </whereB-5.1>
-    })
-
-test:do_execsql_test(
-    "whereB-5.2",
-    [[
-        SELECT x, a, y=b FROM t1, t2 WHERE y=b;
-    ]],
-    {
-    -- <whereB-5.2>
-    1, 2, true
-    -- </whereB-5.2>
-    })
-
-test:do_execsql_test(
-    "whereB-5.3",
-    [[
-        SELECT x, a, y=b FROM t1, t2 WHERE b=y;
-    ]],
-    {
-    -- <whereB-5.3>
-    1, 2, true
-    -- </whereB-5.3>
-    })
-
-test:do_execsql_test(
-    "whereB-5.4",
-    -- In this case the unary "+" operator shouldn't
-    -- affect result set of query.
-    [[
-        SELECT x, a, y=b FROM t1, t2 WHERE +y=+b;
-    ]],
-    {
-    -- <whereB-5.4>
-    1, 2, true
-    -- </whereB-5.4>
-    })
-
-test:do_execsql_test(
-    "whereB-5.100",
-    [[
-        DROP INDEX t2b ON t2;
-        SELECT x, a, y=b FROM t1, t2 WHERE y=b;
-    ]],
-    {
-    -- <whereB-5.100>
-    1, 2, true
-    -- </whereB-5.100>
-    })
-
-test:do_execsql_test(
-    "whereB-5.101",
-    [[
-        SELECT x, a, y=b FROM t1, t2 WHERE b=y;
-    ]],
-    {
-    -- <whereB-5.101>
-    1, 2, true
-    -- </whereB-5.101>
-    })
-
-test:do_execsql_test(
-    "whereB-5.102",
-    -- In this case the unary "+" operator shouldn't
-    -- affect result set of query.
-    [[
-        SELECT x, a, y=b FROM t1, t2 WHERE +y=+b;
-    ]],
-    {
-    -- <whereB-5.102>
-    1, 2, true
-    -- </whereB-5.102>
-    })
-
--- For this set of tests:
---
---  *   t1.y holds a text value with affinity NONE
---  *   t2.b holds an integer value with affinity REAL
---
--- Because t2.b has a numeric affinity, type conversion should occur
--- and the two fields should be equal.
---
-test:do_execsql_test(
-    "whereB-6.1",
-    [[
-        DROP TABLE t1;
-        DROP TABLE t2;
-
-        CREATE TABLE t1(x  INT primary key, y SCALAR);    -- affinity of t1.y is NONE
-        INSERT INTO t1 VALUES(1,'99');
-
-        CREATE TABLE t2(a  INT primary key, b NUMBER);  -- affinity of t2.b is REAL
-        CREATE INDEX t2b ON t2(b);
-        INSERT INTO t2 VALUES(2,99.0);
-
-        SELECT x, a, y=b FROM t1, t2;
-    ]],
-    {
-    -- <whereB-6.1>
-    1, 2, true
-    -- </whereB-6.1>
-    })
-
-test:do_execsql_test(
-    "whereB-6.2",
-    [[
-        SELECT x, a, y=b FROM t1, t2 WHERE y=b;
-    ]],
-    {
-    -- <whereB-6.2>
-    1, 2, true
-    -- </whereB-6.2>
-    })
-
-test:do_execsql_test(
-    "whereB-6.3",
-    [[
-        SELECT x, a, y=b FROM t1, t2 WHERE b=y;
-    ]],
-    {
-    -- <whereB-6.3>
-    1, 2, true
-    -- </whereB-6.3>
-    })
-
-test:do_execsql_test(
-    "whereB-6.4",
-    -- In this case the unary "+" operator shouldn't
-    -- affect result set of query.
-    [[
-        SELECT x, a, y=b FROM t1, t2 WHERE +y=+b;
-    ]],
-    {
-    -- <whereB-6.4>
-    1, 2, true
-    -- </whereB-6.4>
-    })
-
-test:do_execsql_test(
-    "whereB-6.100",
-    [[
-        DROP INDEX t2b ON t2;
-        SELECT x, a, y=b FROM t1, t2 WHERE y=b;
-    ]],
-    {
-    -- <whereB-6.100>
-    1, 2, true
-    -- </whereB-6.100>
-    })
-
-test:do_execsql_test(
-    "whereB-6.101",
-    [[
-        SELECT x, a, y=b FROM t1, t2 WHERE b=y;
-    ]],
-    {
-    -- <whereB-6.101>
-    1, 2, true
-    -- </whereB-6.101>
-    })
-
-test:do_execsql_test(
-    "whereB-6.102",
-    -- In this case the unary "+" operator shouldn't
-    -- affect result set of query.
-    [[
-        SELECT x, a, y=b FROM t1, t2 WHERE +y=+b;
-    ]],
-    {
-    -- <whereB-6.102>
-    1, 2, true
-    -- </whereB-6.102>
-    })
-
--- For this set of tests:
---
---  *   t1.y holds an integer value with affinity NUMERIC
---  *   t2.b holds a text value with affinity NONE
---
--- Because t1.y has a numeric affinity, type conversion should occur
--- and the two fields should be equal.
---
-test:do_execsql_test(
-    "whereB-7.1",
-    [[
-        DROP TABLE t1;
-        DROP TABLE t2;
-
-        CREATE TABLE t1(x  INT primary key, y NUMBER);  -- affinity of t1.y is NUMERIC
-        INSERT INTO t1 VALUES(1,99);
-
-        CREATE TABLE t2(a  INT primary key, b SCALAR);  -- affinity of t2.b is NONE
-        CREATE INDEX t2b ON t2(b);
-        INSERT INTO t2 VALUES(2,'99');
-
-        SELECT x, a, y=b FROM t1, t2;
-    ]],
-    {
-    -- <whereB-7.1>
-    1, 2, true
-    -- </whereB-7.1>
-    })
-
-test:do_execsql_test(
-    "whereB-7.2",
-    [[
-        SELECT x, a, y=b FROM t1, t2 WHERE y=b;
-    ]],
-    {
-    -- <whereB-7.2>
-    1, 2, true
-    -- </whereB-7.2>
-    })
-
-test:do_execsql_test(
-    "whereB-7.3",
-    [[
-        SELECT x, a, y=b FROM t1, t2 WHERE b=y;
-    ]],
-    {
-    -- <whereB-7.3>
-    1, 2, true
-    -- </whereB-7.3>
-    })
-
-test:do_execsql_test(
-    "whereB-7.4",
-    -- In this case the unary "+" operator shouldn't
-    -- affect result set of query.
-    [[
-        SELECT x, a, y=b FROM t1, t2 WHERE +y=+b;
-    ]],
-    {
-    -- <whereB-7.4>
-    1, 2, true
-    -- </whereB-7.4>
-    })
-
-test:do_execsql_test(
-    "whereB-7.100",
-    [[
-        DROP INDEX t2b ON t2;
-        SELECT x, a, y=b FROM t1, t2 WHERE y=b;
-    ]],
-    {
-    -- <whereB-7.100>
-    1, 2, true
-    -- </whereB-7.100>
-    })
-
-test:do_execsql_test(
-    "whereB-7.101",
-    [[
-        SELECT x, a, y=b FROM t1, t2 WHERE b=y;
-    ]],
-    {
-    -- <whereB-7.101>
-    1, 2, true
-    -- </whereB-7.101>
-    })
-
-test:do_execsql_test(
-    "whereB-7.102",
-    -- In this case the unary "+" operator shouldn't
-    -- affect result set of query.
-    [[
-        SELECT x, a, y=b FROM t1, t2 WHERE +y=+b;
-    ]],
-    {
-    -- <whereB-7.102>
-    1, 2, true
-    -- </whereB-7.102>
-    })
-
--- For this set of tests:
---
---  *   t1.y holds an integer value with affinity INTEGER
---  *   t2.b holds a text value with affinity NONE
---
--- Because t1.y has a numeric affinity, type conversion should occur
--- and the two fields should be equal.
---
-test:do_execsql_test(
-    "whereB-8.1",
-    [[
-        DROP TABLE t1;
-        DROP TABLE t2;
-
-        CREATE TABLE t1(x  INT primary key, y INT);  -- affinity of t1.y is INTEGER
-        INSERT INTO t1 VALUES(1,99);
-
-        CREATE TABLE t2(a  INT primary key, b SCALAR);  -- affinity of t2.b is NONE
-        CREATE INDEX t2b ON t2(b);
-        INSERT INTO t2 VALUES(2,'99');
-
-        SELECT x, a, y=b FROM t1, t2;
-    ]],
-    {
-    -- <whereB-8.1>
-    1, 2, true
-    -- </whereB-8.1>
-    })
-
-test:do_execsql_test(
-    "whereB-8.2",
-    [[
-        SELECT x, a, y=b FROM t1, t2 WHERE y=b;
-    ]],
-    {
-    -- <whereB-8.2>
-    1, 2, true
-    -- </whereB-8.2>
-    })
-
-test:do_execsql_test(
-    "whereB-8.3",
-    [[
-        SELECT x, a, y=b FROM t1, t2 WHERE b=y;
-    ]],
-    {
-    -- <whereB-8.3>
-    1, 2, true
-    -- </whereB-8.3>
-    })
-
-test:do_execsql_test(
-    "whereB-8.4",
-    -- In this case the unary "+" operator shouldn't
-    -- affect result set of query.
-    [[
-        SELECT x, a, y=b FROM t1, t2 WHERE +y=+b;
-    ]],
-    {
-    -- <whereB-8.4>
-    1, 2, true
-    -- </whereB-8.4>
-    })
-
-test:do_execsql_test(
-    "whereB-8.100",
-    [[
-        DROP INDEX t2b ON t2;
-        SELECT x, a, y=b FROM t1, t2 WHERE y=b;
-    ]],
-    {
-    -- <whereB-8.100>
-    1, 2, true
-    -- </whereB-8.100>
-    })
-
-test:do_execsql_test(
-    "whereB-8.101",
-    [[
-        SELECT x, a, y=b FROM t1, t2 WHERE b=y;
-    ]],
-    {
-    -- <whereB-8.101>
-    1, 2, true
-    -- </whereB-8.101>
-    })
-
-test:do_execsql_test(
-    "whereB-8.102",
-    -- In this case the unary "+" operator shouldn't
-    -- affect result set of query.
-    [[
-        SELECT x, a, y=b FROM t1, t2 WHERE +y=+b;
-    ]],
-    {
-    -- <whereB-8.102>
-    1, 2, true
-    -- </whereB-8.102>
-    })
-
--- For this set of tests:
---
---  *   t1.y holds an integer value with affinity REAL
---  *   t2.b holds a text value with affinity NONE
---
--- Because t1.y has a numeric affinity, type conversion should occur
--- and the two fields should be equal.
---
-test:do_execsql_test(
-    "whereB-9.1",
-    [[
-        DROP TABLE t1;
-        DROP TABLE t2;
-
-        CREATE TABLE t1(x  INT primary key, y NUMBER);  -- affinity of t1.y is REAL
-        INSERT INTO t1 VALUES(1,99.0);
-
-        CREATE TABLE t2(a  INT primary key, b SCALAR);  -- affinity of t2.b is NONE
-        CREATE INDEX t2b ON t2(b);
-        INSERT INTO t2 VALUES(2,'99');
-
-        SELECT x, a, y=b FROM t1, t2;
-    ]],
-    {
-    -- <whereB-9.1>
-    1, 2, true
-    -- </whereB-9.1>
-    })
-
-test:do_execsql_test(
-    "whereB-9.2",
-    [[
-        SELECT x, a, y=b FROM t1, t2 WHERE y=b;
-    ]],
-    {
-    -- <whereB-9.2>
-    1, 2, true
-    -- </whereB-9.2>
-    })
-
-test:do_execsql_test(
-    "whereB-9.3",
-    [[
-        SELECT x, a, y=b FROM t1, t2 WHERE b=y;
-    ]],
-    {
-    -- <whereB-9.3>
-    1, 2, true
-    -- </whereB-9.3>
-    })
-
-test:do_execsql_test(
-    "whereB-9.4",
-    -- In this case the unary "+" operator shouldn't
-    -- affect result set of query.
-    [[
-        SELECT x, a, y=b FROM t1, t2 WHERE +y=+b;
-    ]],
-    {
-    -- <whereB-9.4>
-    1, 2, true
-    -- </whereB-9.4>
-    })
-
-test:do_execsql_test(
-    "whereB-9.100",
-    [[
-        DROP INDEX t2b ON t2;
-        SELECT x, a, y=b FROM t1, t2 WHERE y=b;
-    ]],
-    {
-    -- <whereB-9.100>
-    1, 2, true
-    -- </whereB-9.100>
-    })
-
-test:do_execsql_test(
-    "whereB-9.101",
-    [[
-        SELECT x, a, y=b FROM t1, t2 WHERE b=y;
-    ]],
-    {
-    -- <whereB-9.101>
-    1, 2, true
-    -- </whereB-9.101>
-    })
-
-test:do_execsql_test(
-    "whereB-9.102",
-    -- In this case the unary "+" operator shouldn't
-    -- affect result set of query.
-    [[
-        SELECT x, a, y=b FROM t1, t2 WHERE +y=+b;
-    ]],
-    {
-    -- <whereB-9.102>
-    1, 2, true
-    -- </whereB-9.102>
-    })
-
-test:finish_test()
-
diff --git a/test/sql-tap/whereC.test.lua b/test/sql-tap/whereC.test.lua
index 89459dee3..58c049553 100755
--- a/test/sql-tap/whereC.test.lua
+++ b/test/sql-tap/whereC.test.lua
@@ -55,9 +55,9 @@ test:do_execsql_test(
 test:test("main", function()
     local data = {{"SELECT i FROM t1 WHERE a=1 AND b=2 AND i>3",         {4, 5}},
                   -- {"SELECT i FROM t1 WHERE rowid='12'",                  {12}},
-                  {"SELECT i FROM t1 WHERE a=1 AND b='2'",               {3, 4, 5}},
-                  {"SELECT i FROM t1 WHERE a=1 AND b='2' AND i>'3'",     {4, 5}},
-                  {"SELECT i FROM t1 WHERE a=1 AND b='2' AND i<5",       {3, 4}},
+                  {"SELECT i FROM t1 WHERE a=1 AND b=2",               {3, 4, 5}},
+                  {"SELECT i FROM t1 WHERE a=1 AND b=2 AND i>3",     {4, 5}},
+                  {"SELECT i FROM t1 WHERE a=1 AND b=2 AND i<5",       {3, 4}},
                   {"SELECT i FROM t1 WHERE a=2 AND b=2 AND i<12",        {10, 11}},
                   {"SELECT i FROM t1 WHERE a IN(1, 2) AND b=2 AND i<11", {3, 4, 5, 10}},
                   {"SELECT i FROM t1 WHERE a=2 AND b=2 AND i BETWEEN 10 AND 12", {10, 11, 12}},
@@ -66,7 +66,7 @@ test:test("main", function()
                   {"SELECT i FROM t1 WHERE a=2 AND b=2 AND i BETWEEN 12 AND 10", {}},
                   {"SELECT i FROM t1 WHERE a=2 AND b=2 AND i<NULL",      {}},
                   {"SELECT i FROM t1 WHERE a=2 AND b=2 AND i>=NULL",     {}},
-                  {"SELECT i FROM t1 WHERE a=1 AND b='2' AND i<4.5",     {3, 4}}}
+                  {"SELECT i FROM t1 WHERE a=1 AND b=2 AND i<4.5",     {3, 4}}}
                   -- {"SELECT i FROM t1 WHERE rowid IS '12'",               {12}}}
 
     for tn, t in ipairs(data) do

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [Tarantool-patches] [PATCH v2 5/7] sql: remove implicit cast from string for comparison
  2020-06-11 12:54 [Tarantool-patches] [PATCH v2 0/7] Remove implicit cast imeevma
                   ` (3 preceding siblings ...)
  2020-06-11 12:54 ` [Tarantool-patches] [PATCH v2 4/7] sql: remove mem_apply_type() from OP_MustBeInt imeevma
@ 2020-06-11 12:54 ` imeevma
  2020-06-11 12:54 ` [Tarantool-patches] [PATCH v2 6/7] sql: remove OP_ApplyType imeevma
  2020-06-11 12:54 ` [Tarantool-patches] [PATCH v2 7/7] sql: use type instead of value in type mismatch error imeevma
  6 siblings, 0 replies; 14+ messages in thread
From: imeevma @ 2020-06-11 12:54 UTC (permalink / raw)
  To: v.shpilevoy, tsafin, tarantool-patches

Thank yo for the patch! My answers, diff and new patch below.


On 10.06.2020 01:29, Vladislav Shpilevoy wrote:
> Thanks for the patch!
>
>>>> index 854ed774f..2a18b17be 100755
>>>> --- a/test/sql-tap/tkt-9a8b09f8e6.test.lua
>>>> +++ b/test/sql-tap/tkt-9a8b09f8e6.test.lua
>>>> @@ -83,23 +83,23 @@ test:do_execsql_test(
>>>>           -- </1.5>
>>>>       })
>>>>   -test:do_execsql_test(
>>>> +test:do_catchsql_test(
>>>>       2.1,
>>>>       [[
>>>>           SELECT x FROM t1 WHERE x IN (1);
>>>>       ]], {
>>>>           -- <2.1>
>>>> -        "1"
>>>> +        1,"Type mismatch: can not convert 1 to numeric"
>>> 3. Can tests in this file be fixed to return the same results
>>> as before?
>> I fixed this in most cases, but am not sure if this is correct.
>> I think most tests are out of date.
>
> Yeah, looks like the test file becomes mostly useless. It now
> tests rather explicit CAST than implicit cast. The previous
> version was better. At least it covered implicit cast errors.
>
> I would try to rollback to the previous version, remove obviously
> duplicated or not needed test cases, and see what is left.
> Probably the whole test file is useless.
>
I moved some tests to "gh-4230-del-impl-cast-str-to-num.test.lua"
and removed this test-file.

> See 6 comments below.
>
>> sql: remove implicit cast from string for comparison
>>
>> This patch removes implicit cast from strings to numbers for
>> comparison.
>>
>> Closes #4230
>>
>> @TarantoolBot document
>> Title: remove implicit cast between strings and numbers
>>
>> This patch-set removes implicit cast from string to number and
>> from number to string.
>>
>> Example:
>>
>> For comparison:
>>
>> tarantool> box.execute([[SELECT '1' > 0;]])
>> ---
>> - null
>> - 'Type mismatch: can not convert 1 to numeric'
>> ...
>>
>> tarantool> box.execute([[SELECT "id" FROM "_space" WHERE '1' > "id";]])
>> ---
>> - null
>> - 'Type mismatch: can not convert text to unsigned'
>> ...
>>
>> For assignment:
>>
>> tarantool> box.execute([[CREATE TABLE t1(i INT PRIMARY KEY);]])
>> tarantool> box.execute([[INSERT INTO t1 VALUES ('1');]])
>> ---
>> - null
>> - 'Type mismatch: can not convert text to integer'
>> ...
>>
>> tarantool> box.execute([[CREATE TABLE t2(t text PRIMARY KEY);]])
>> tarantool> box.execute([[INSERT INTO t2 VALUES (1);]])
>> ---
>> - null
>> - 'Type mismatch: can not convert unsigned to string'
>> ...
>
> 1. I suggest to wrap code samples into ``` to produce more
> readable github markdown in the resulting doc issue.
>
Fixed.

>> review fix
>
> 2. Hm.
>
Fixed.

>> diff --git a/src/box/sql/wherecode.c b/src/box/sql/wherecode.c
>> index 6d8768865..1d7c76670 100644
>> --- a/src/box/sql/wherecode.c
>> +++ b/src/box/sql/wherecode.c
>> @@ -335,72 +335,6 @@ disableTerm(WhereLevel * pLevel, WhereTerm * pTerm)
>>      }
>>  }
>>
>> -/**
>> - * Code an OP_ApplyType opcode to apply the column type string
>> - * @types to the n registers starting at @base.
>> - *
>> - * As an optimization, SCALAR entries (which are no-ops) at the
>> - * beginning and end of @types are ignored.  If all entries in
>> - * @types are SCALAR, then no code gets generated.
>> - *
>> - * This routine makes its own copy of @types so that the caller is
>> - * free to modify @types after this routine returns.
>> - */
>> -static void
>> -emit_apply_type(Parse *pParse, int base, int n, enum field_type *types)
>> -{
>> -    Vdbe *v = pParse->pVdbe;
>> -    if (types == NULL) {
>> -        assert(pParse->db->mallocFailed);
>> -        return;
>> -    }
>> -    assert(v != 0);
>> -
>> -    /*
>> -     * Adjust base and n to skip over SCALAR entries at the
>> -     * beginning and end of the type sequence.
>> -     */
>> -    while (n > 0 && types[0] == FIELD_TYPE_SCALAR) {
>> -        n--;
>> -        base++;
>> -        types++;
>> -    }
>> -    while (n > 1 && types[n - 1] == FIELD_TYPE_SCALAR) {
>> -        n--;
>> -    }
>> -
>> -    if (n > 0) {
>> -        enum field_type *types_dup = field_type_sequence_dup(pParse,
>> -                                     types, n);
>
> 3. This function is now unused and can be deleted.
>
Removed.

>> -        sqlVdbeAddOp4(v, OP_ApplyType, base, n, 0,
>> -                  (char *) types_dup, P4_DYNAMIC);
>> -        sql_expr_type_cache_change(pParse, base, n);
>> -    }
>> -}
>> -
>> -/**
>> - * Expression @rhs, which is the RHS of a comparison operation, is
>> - * either a vector of n elements or, if n==1, a scalar expression.
>> - * Before the comparison operation, types @types are to be applied
>> - * to the @rhs values. This function modifies entries within the
>> - * field sequence to SCALAR if either:
>> - *
>> - *   * the comparison will be performed with no type, or
>> - *   * the type change in @types is guaranteed not to change the value.
>> - */
>> -static void
>> -expr_cmp_update_rhs_type(struct Expr *rhs, int n, enum field_type *types)
>> -{
>> -    for (int i = 0; i < n; i++) {
>> -        Expr *p = sqlVectorFieldSubexpr(rhs, i);
>> -        enum field_type expr_type = sql_expr_type(p);
>> -        if (sql_type_result(expr_type, types[i]) == FIELD_TYPE_SCALAR ||
>> -            sql_expr_needs_no_type_change(p, types[i])) {
>
> 4. Ditto (removed in the next commit, up to you if want to remove
> here).
>
Removed here.

>> -            types[i] = FIELD_TYPE_SCALAR;
>> -        }
>> -    }
>> -}
>> diff --git a/test/sql-tap/gh-4230-del-impl-cast-str-to-num.test.lua b/test/sql-tap/gh-4230-del-impl-cast-str-to-num.test.lua
>> new file mode 100755
>> index 000000000..ef4127e0e
>> --- /dev/null
>> +++ b/test/sql-tap/gh-4230-del-impl-cast-str-to-num.test.lua
>> @@ -0,0 +1,78 @@
>> +#!/usr/bin/env tarantool
>> +test = require("sqltester")
>> +test:plan(8)
>> +
>> +--
>> +-- Make sure that there is no implicit cast between string and
>> +-- number.
>> +--
>> +test:do_catchsql_test(
>> +    "gh-4230-1",
>> +    [[
>> +        SELECT '1' > 0;
>> +    ]], {
>> +        1, "Type mismatch: can not convert 1 to numeric"
>> +    })
>> +
>> +test:do_catchsql_test(
>> +    "gh-4230-2",
>> +    [[
>> +        SELECT 0 > '1';
>> +    ]], {
>> +        1, "Type mismatch: can not convert 1 to numeric"
>
> 5. The error messages are really weird. We should probably wrap
> string value into quoutes. Or print it as 'text'. Without a
> value. Not necessarily here. You can create an issue for that,
> and do it later.
>
Created a new commit.

>> diff --git a/test/sql-tap/tkt-f973c7ac31.test.lua b/test/sql-tap/tkt-f973c7ac31.test.lua
>> index 82bdb52f8..604a7e6bb 100755
>> --- a/test/sql-tap/tkt-f973c7ac31.test.lua
>> +++ b/test/sql-tap/tkt-f973c7ac31.test.lua
>> @@ -39,9 +39,8 @@ for tn, sql in ipairs(sqls) do
>>      test:do_execsql_test(
>>          "tkt-f973c7ac3-1."..tn..".1",
>>          [[
>> -            SELECT c1,c2 FROM t WHERE c1 = 5 AND c2>0 AND c2<='2' ORDER BY c2 DESC
>> +            SELECT c1,c2 FROM t WHERE c1 = 5 AND c2>0 AND CAST(c2 AS STRING)<='2' ORDER BY c2 DESC
>
> 6. On the branch I see trailing whitespaces in this file.
>
Fixed.

>>          ]], {
>> -
>>          })
>>



Diff:

diff --git a/src/box/sql/expr.c b/src/box/sql/expr.c
index 8ec685cd9..f51549695 100644
--- a/src/box/sql/expr.c
+++ b/src/box/sql/expr.c
@@ -137,19 +137,6 @@ sql_expr_type(struct Expr *pExpr)
  return pExpr->type;
 }
 
-enum field_type *
-field_type_sequence_dup(struct Parse *parse, enum field_type *types,
-     uint32_t len)
-{
- uint32_t sz = (len + 1) * sizeof(enum field_type);
- enum field_type *ret_types = sqlDbMallocRaw(parse->db, sz);
- if (ret_types == NULL)
-   return NULL;
- memcpy(ret_types, types, sz);
- ret_types[len] = field_type_MAX;
- return ret_types;
-}
-
 /*
  * Set the collating sequence for expression pExpr to be the collating
  * sequence named by pToken.   Return a pointer to a new Expr node that
@@ -2246,36 +2233,6 @@ sqlExprCanBeNull(const Expr * p)
  }
 }
 
-bool
-sql_expr_needs_no_type_change(const struct Expr *p, enum field_type type)
-{
- u8 op;
- if (type == FIELD_TYPE_SCALAR)
-   return true;
- while (p->op == TK_UPLUS || p->op == TK_UMINUS) {
-   p = p->pLeft;
- }
- op = p->op;
- if (op == TK_REGISTER)
-   op = p->op2;
- switch (op) {
- case TK_INTEGER:
-   return type == FIELD_TYPE_INTEGER;
- case TK_FLOAT:
-   return type == FIELD_TYPE_DOUBLE;
- case TK_STRING:
-   return type == FIELD_TYPE_STRING;
- case TK_BLOB:
-   return type == FIELD_TYPE_VARBINARY;
- case TK_COLUMN:
-   /* p cannot be part of a CHECK constraint. */
-   assert(p->iTable >= 0);
-   return p->iColumn < 0 && sql_type_is_numeric(type);
- default:
-   return false;
- }
-}
-
 /*
  * pX is the RHS of an IN operator.  If pX is a SELECT statement
  * that can be simplified to a direct table access, then return
diff --git a/src/box/sql/sqlInt.h b/src/box/sql/sqlInt.h
index 01c32d518..b76c5eab8 100644
--- a/src/box/sql/sqlInt.h
+++ b/src/box/sql/sqlInt.h
@@ -3229,19 +3229,6 @@ int sqlExprIsTableConstant(Expr *, int);
 int sqlExprIsInteger(Expr *, int *);
 int sqlExprCanBeNull(const Expr *);
 
-/**
- * Return TRUE if the given expression is a constant which would
- * be unchanged by OP_ApplyType with the type given in the second
- * argument.
- *
- * This routine is used to determine if the OP_ApplyType operation
- * can be omitted.  When in doubt return FALSE.  A false negative
- * is harmless. A false positive, however, can result in the wrong
- * answer.
- */
-bool
-sql_expr_needs_no_type_change(const struct Expr *expr, enum field_type type);
-
 /**
  * This routine generates VDBE code that causes a single row of a
  * single table to be deleted.  Both the original table entry and
@@ -3907,14 +3894,6 @@ expr_cmp_mutual_type(struct Expr *pExpr);
 enum field_type
 sql_expr_type(struct Expr *pExpr);
 
-/**
- * This function duplicates first @len entries of types array
- * and terminates new array with field_type_MAX member.
- */
-enum field_type *
-field_type_sequence_dup(struct Parse *parse, enum field_type *types,
-     uint32_t len);
-
 /**
  * Convert z to a 64-bit signed or unsigned integer.
  * z must be decimal. This routine does *not* accept
diff --git a/test/sql-tap/gh-4230-del-impl-cast-str-to-num.test.lua b/test/sql-tap/gh-4230-del-impl-cast-str-to-num.test.lua
index ef4127e0e..b405a11b6 100755
--- a/test/sql-tap/gh-4230-del-impl-cast-str-to-num.test.lua
+++ b/test/sql-tap/gh-4230-del-impl-cast-str-to-num.test.lua
@@ -1,6 +1,6 @@
 #!/usr/bin/env tarantool
 test = require("sqltester")
-test:plan(8)
+test:plan(32)
 
 --
 -- Make sure that there is no implicit cast between string and
@@ -75,4 +75,207 @@ test:do_catchsql_test(
         1, "Type mismatch: can not convert 2 to numeric"
     })
 
+test:execsql([[
+    CREATE TABLE t1(x TEXT primary key);
+    INSERT INTO t1 VALUES('1');
+    CREATE TABLE t2(x INTEGER primary key);
+    INSERT INTO t2 VALUES(1);
+    CREATE TABLE t3(x DOUBLE primary key);
+    INSERT INTO t3 VALUES(1.0);
+]])
+
+test:do_catchsql_test(
+    "gh-4230-9",
+    [[
+        SELECT x FROM t1 WHERE x IN (1);
+    ]], {
+        1, "Type mismatch: can not convert 1 to numeric"
+    })
+
+
+test:do_catchsql_test(
+    "gh-4230-10",
+    [[
+        SELECT x FROM t1 WHERE x IN (1.0);
+    ]], {
+        1, "Type mismatch: can not convert 1 to numeric"
+    })
+
+test:do_execsql_test(
+    "gh-4230-11",
+    [[
+        SELECT x FROM t1 WHERE x IN ('1');
+    ]], {
+        "1"
+    })
+
+test:do_execsql_test(
+    "gh-4230-12",
+    [[
+        SELECT x FROM t1 WHERE x IN ('1.0');
+    ]], {
+    })
+
+test:do_catchsql_test(
+    "gh-4230-13",
+    [[
+        SELECT x FROM t1 WHERE 1 IN (x);
+    ]], {
+        1, "Type mismatch: can not convert 1 to numeric"
+    })
+
+test:do_catchsql_test(
+    "gh-4230-14",
+    [[
+        SELECT x FROM t1 WHERE 1.0 IN (x);
+    ]], {
+        1, "Type mismatch: can not convert 1 to numeric"
+    })
+
+test:do_execsql_test(
+    "gh-4230-15",
+    [[
+        SELECT x FROM t1 WHERE '1' IN (x);
+    ]], {
+        -- <2.7>
+        "1"
+        -- </2.7>
+    })
+
+test:do_execsql_test(
+    "gh-4230-16",
+    [[
+        SELECT x FROM t1 WHERE '1.0' IN (x);
+    ]], {
+    })
+
+test:do_execsql_test(
+    "gh-4230-17",
+    [[
+        SELECT x FROM t2 WHERE x IN (1);
+    ]], {
+        1
+    })
+
+
+test:do_execsql_test(
+    "gh-4230-18",
+    [[
+        SELECT x FROM t2 WHERE x IN (1.0);
+    ]], {
+        1
+    })
+
+test:do_catchsql_test(
+    "gh-4230-19",
+    [[
+        SELECT x FROM t2 WHERE x IN ('1');
+    ]], {
+        1, "Type mismatch: can not convert integer to text"
+    })
+
+test:do_catchsql_test(
+    "gh-4230-20",
+    [[
+        SELECT x FROM t2 WHERE x IN ('1.0');
+    ]], {
+        1, "Type mismatch: can not convert integer to text"
+    })
+
+test:do_execsql_test(
+    "gh-4230-21",
+    [[
+        SELECT x FROM t2 WHERE 1 IN (x);
+    ]], {
+        1
+    })
+
+test:do_execsql_test(
+    "gh-4230-22",
+    [[
+        SELECT x FROM t2 WHERE 1.0 IN (x);
+    ]], {
+        1
+    })
+
+test:do_catchsql_test(
+    "gh-4230-23",
+    [[
+        SELECT x FROM t2 WHERE '1' IN (x);
+    ]], {
+        1, "Type mismatch: can not convert integer to text"
+    })
+
+test:do_catchsql_test(
+    "gh-4230-24",
+    [[
+        SELECT x FROM t2 WHERE '1.0' IN (x);
+    ]], {
+        1, "Type mismatch: can not convert integer to text"
+    })
+
+test:do_execsql_test(
+    "gh-4230-25",
+    [[
+        SELECT x FROM t3 WHERE x IN (1);
+    ]], {
+        1
+    })
+
+test:do_execsql_test(
+    "gh-4230-26",
+    [[
+        SELECT x FROM t3 WHERE x IN (1.0);
+    ]], {
+        1
+    })
+
+test:do_catchsql_test(
+    "gh-4230-27",
+    [[
+        SELECT x FROM t3 WHERE x IN ('1');
+    ]], {
+        1, "Type mismatch: can not convert double to text"
+    })
+
+test:do_catchsql_test(
+    "gh-4230-28",
+    [[
+        SELECT x FROM t3 WHERE x IN ('1.0');
+    ]], {
+        1, "Type mismatch: can not convert double to text"
+    })
+
+test:do_execsql_test(
+    "gh-4230-29",
+    [[
+        SELECT x FROM t3 WHERE 1 IN (x);
+    ]], {
+        1
+    })
+
+test:do_execsql_test(
+    "gh-4230-30",
+    [[
+        SELECT x FROM t3 WHERE 1.0 IN (x);
+    ]], {
+        1
+    })
+
+test:do_catchsql_test(
+    "gh-4230-31",
+    [[
+        SELECT x FROM t3 WHERE '1' IN (x);
+    ]], {
+        1, "Type mismatch: can not convert double to text"
+    })
+
+test:do_catchsql_test(
+    "gh-4230-32",
+    [[
+        SELECT x FROM t3 WHERE '1.0' IN (x);
+    ]], {
+        1, "Type mismatch: can not convert double to text"
+    })
+
 test:finish_test()
diff --git a/test/sql-tap/tkt-9a8b09f8e6.test.lua b/test/sql-tap/tkt-9a8b09f8e6.test.lua
deleted file mode 100755
index 083a87b45..000000000
--- a/test/sql-tap/tkt-9a8b09f8e6.test.lua
+++ /dev/null
@@ -1,506 +0,0 @@
-#!/usr/bin/env tarantool
-test = require("sqltester")
-test:plan(47)
-
---!./tcltestrunner.lua
--- 2014 June 26
---
--- The author disclaims copyright to this source code.  In place of
--- a legal notice, here is a blessing:
---
---    May you do good and not evil.
---    May you find forgiveness for yourself and forgive others.
---    May you share freely, never taking more than you give.
---
--------------------------------------------------------------------------
--- This file implements regression tests for sql library.
---
--- This file implements tests to verify that ticket [9a8b09f8e6] has been
--- fixed.
---
--- ["set","testdir",[["file","dirname",["argv0"]]]]
--- ["source",[["testdir"],"\/tester.tcl"]]
-testprefix = "tkt-9a8b09f8e6"
--- MUST_WORK_TEST
-if (0 > 0)
- then
-end
-test:do_execsql_test(
-    1.1,
-    [[
-        CREATE TABLE t1(x TEXT primary key);
-        INSERT INTO t1 VALUES('1');
-    ]], {
-        -- <1.1>
-        
-        -- </1.1>
-    })
-
-test:do_execsql_test(
-    1.2,
-    [[
-        CREATE TABLE t2(x INTEGER primary key);
-        INSERT INTO t2 VALUES(1);
-    ]], {
-        -- <1.2>
-        
-        -- </1.2>
-    })
-
-test:do_execsql_test(
-    1.3,
-    [[
-        CREATE TABLE t3(x NUMBER primary key);
-        INSERT INTO t3 VALUES(1.0);
-    ]], {
-        -- <1.3>
-        
-        -- </1.3>
-    })
-
-test:do_execsql_test(
-    1.4,
-    [[
-        CREATE TABLE t4(x NUMBER primary key);
-        INSERT INTO t4 VALUES(1.11);
-    ]], {
-        -- <1.4>
-        
-        -- </1.4>
-    })
-
-test:do_execsql_test(
-    1.5,
-    [[
-        CREATE TABLE t5(id  INT primary key, x INT , y TEXT);
-        INSERT INTO t5 VALUES(1, 1, 'one');
-        INSERT INTO t5 VALUES(2, 1, 'two');
-        INSERT INTO t5 VALUES(3, 1.0, 'three');
-        INSERT INTO t5 VALUES(4, 1.0, 'four');
-    ]], {
-        -- <1.5>
-        
-        -- </1.5>
-    })
-
-test:do_execsql_test(
-    2.1,
-    [[
-        SELECT x FROM t1 WHERE CAST(x AS INTEGER) IN (1);
-    ]], {
-        -- <2.1>
-        "1"
-        -- </2.1>
-    })
-
-test:do_execsql_test(
-    2.2,
-    [[
-        SELECT x FROM t1 WHERE CAST(x AS DOUBLE) IN (1);
-    ]], {
-        -- <2.2>
-        "1"
-        -- </2.2>
-    })
-
-test:do_execsql_test(
-    2.3,
-    [[
-        SELECT x FROM t1 WHERE x IN ('1');
-    ]], {
-        -- <2.3>
-        "1"
-        -- </2.3>
-    })
-
-test:do_execsql_test(
-    2.4,
-    [[
-        SELECT x FROM t1 WHERE x IN ('1.0');
-    ]], {
-        -- <2.4>
-        
-        -- </2.4>
-    })
-
-test:do_execsql_test(
-    2.5,
-    [[
-        SELECT x FROM t1 WHERE CAST(1 AS STRING) IN (x);
-    ]], {
-        -- <2.5>
-        "1"
-        -- </2.5>
-    })
-
-test:do_execsql_test(
-    2.6,
-    [[
-        SELECT x FROM t1 WHERE CAST(1.0 AS STRING) IN (x);
-    ]], {
-        -- <2.6>
-        -- </2.6>
-    })
-
-test:do_execsql_test(
-    2.7,
-    [[
-        SELECT x FROM t1 WHERE '1' IN (x);
-    ]], {
-        -- <2.7>
-        "1"
-        -- </2.7>
-    })
-
-test:do_execsql_test(
-    2.8,
-    [[
-        SELECT x FROM t1 WHERE '1.0' IN (x);
-    ]], {
-        -- <2.8>
-        
-        -- </2.8>
-    })
-
-test:do_execsql_test(
-    3.1,
-    [[
-        SELECT x FROM t2 WHERE x IN (1);
-    ]], {
-        -- <3.1>
-        1
-        -- </3.1>
-    })
-
-test:do_execsql_test(
-    3.2,
-    [[
-        SELECT x FROM t2 WHERE x IN (1.0);
-    ]], {
-        -- <3.2>
-        1
-        -- </3.2>
-    })
-
-test:do_execsql_test(
-    3.3,
-    [[
-        SELECT x FROM t2 WHERE CAST(x AS STRING) IN ('1');
-    ]], {
-        -- <3.3>
-        1
-        -- </3.3>
-    })
-
-test:do_execsql_test(
-    3.5,
-    [[
-        SELECT x FROM t2 WHERE 1 IN (x);
-    ]], {
-        -- <3.5>
-        1
-        -- </3.5>
-    })
-
-test:do_execsql_test(
-    3.6,
-    [[
-        SELECT x FROM t2 WHERE 1.0 IN (x);
-    ]], {
-        -- <3.6>
-        1
-        -- </3.6>
-    })
-
-test:do_execsql_test(
-    3.7,
-    [[
-        SELECT x FROM t2 WHERE CAST('1' AS INTEGER) IN (x);
-    ]], {
-        -- <3.7>
-        1
-        -- </3.7>
-    })
-
-test:do_execsql_test(
-    4.1,
-    [[
-        SELECT x FROM t3 WHERE x IN (1);
-    ]], {
-        -- <4.1>
-        1.0
-        -- </4.1>
-    })
-
-test:do_execsql_test(
-    4.2,
-    [[
-        SELECT x FROM t3 WHERE x IN (1.0);
-    ]], {
-        -- <4.2>
-        1.0
-        -- </4.2>
-    })
-
-test:do_execsql_test(
-    4.3,
-    [[
-        SELECT x FROM t3 WHERE CAST(x AS STRING) IN ('1');
-    ]], {
-        -- <4.3>
-        -- </4.3>
-    })
-
-test:do_execsql_test(
-    4.4,
-    [[
-        SELECT x FROM t3 WHERE CAST(x AS STRING) IN ('1.0');
-    ]], {
-        -- <4.4>
-        1.0
-        -- </4.4>
-    })
-
-test:do_execsql_test(
-    4.5,
-    [[
-        SELECT x FROM t3 WHERE 1 IN (x);
-    ]], {
-        -- <4.5>
-        1.0
-        -- </4.5>
-    })
-
-test:do_execsql_test(
-    4.6,
-    [[
-        SELECT x FROM t3 WHERE 1.0 IN (x);
-    ]], {
-        -- <4.6>
-        1.0
-        -- </4.6>
-    })
-
-test:do_execsql_test(
-    4.7,
-    [[
-        SELECT x FROM t3 WHERE CAST('1' AS DOUBLE) IN (x);
-    ]], {
-        -- <4.7>
-        1.0
-        -- </4.7>
-    })
-
-test:do_execsql_test(
-    4.8,
-    [[
-        SELECT x FROM t3 WHERE CAST('1.0' AS DOUBLE) IN (x);
-    ]], {
-        -- <4.8>
-        1.0
-        -- </4.8>
-    })
-
-test:do_execsql_test(
-    5.1,
-    [[
-        SELECT x FROM t4 WHERE x IN (1);
-    ]], {
-        -- <5.1>
-        
-        -- </5.1>
-    })
-
-test:do_execsql_test(
-    5.2,
-    [[
-        SELECT x FROM t4 WHERE x IN (1.0);
-    ]], {
-        -- <5.2>
-        
-        -- </5.2>
-    })
-
-test:do_execsql_test(
-    5.3,
-    [[
-        SELECT x FROM t4 WHERE CAST(x AS STRING) IN ('1');
-    ]], {
-        -- <5.3>
-
-        -- </5.3>
-    })
-
-test:do_execsql_test(
-    5.4,
-    [[
-        SELECT x FROM t4 WHERE CAST(x AS STRING) IN ('1.0');
-    ]], {
-        -- <5.4>
-
-        -- </5.4>
-    })
-
-test:do_execsql_test(
-    5.5,
-    [[
-        SELECT x FROM t4 WHERE x IN (1.11);
-    ]], {
-        -- <5.5>
-        1.11
-        -- </5.5>
-    })
-
-test:do_execsql_test(
-    5.6,
-    [[
-        SELECT x FROM t4 WHERE CAST(x AS STRING) IN ('1.11');
-    ]], {
-        -- <5.6>
-        1.11
-        -- </5.6>
-    })
-
-test:do_execsql_test(
-    5.7,
-    [[
-        SELECT x FROM t4 WHERE 1 IN (x);
-    ]], {
-        -- <5.7>
-        
-        -- </5.7>
-    })
-
-test:do_execsql_test(
-    5.8,
-    [[
-        SELECT x FROM t4 WHERE 1.0 IN (x);
-    ]], {
-        -- <5.8>
-        
-        -- </5.8>
-    })
-
-test:do_execsql_test(
-    5.9,
-    [[
-        SELECT x FROM t4 WHERE CAST('1' AS DOUBLE) IN (x);
-    ]], {
-        -- <5.9>
-
-        -- </5.9>
-    })
-
-test:do_execsql_test(
-    5.10,
-    [[
-        SELECT x FROM t4 WHERE CAST('1.0' AS DOUBLE) IN (x);
-    ]], {
-        -- <5.10>
-
-        -- </5.10>
-    })
-
-test:do_execsql_test(
-    5.11,
-    [[
-        SELECT x FROM t4 WHERE 1.11 IN (x);
-    ]], {
-        -- <5.11>
-        1.11
-        -- </5.11>
-    })
-
-test:do_execsql_test(
-    5.12,
-    [[
-        SELECT x FROM t4 WHERE CAST('1.11' AS DOUBLE) IN (x);
-    ]], {
-        -- <5.12>
-        1.11
-        -- </5.12>
-    })
-
-test:do_execsql_test(
-    6.1,
-    [[
-        SELECT x, y FROM t5 WHERE x IN (1);
-    ]], {
-        -- <6.1>
-        1, "one", 1, "two", 1, "three", 1.0, "four"
-        -- </6.1>
-    })
-
-test:do_execsql_test(
-    6.2,
-    [[
-        SELECT x, y FROM t5 WHERE x IN (1.0);
-    ]], {
-        -- <6.2>
-        1, "one", 1, "two", 1, "three", 1.0, "four"
-        -- </6.2>
-    })
-
-test:do_execsql_test(
-    6.3,
-    [[
-        SELECT x, y FROM t5 WHERE CAST(x AS STRING) IN ('1');
-    ]], {
-        -- <6.3>
-        1, "one", 1, "two", 1, "three", 1.0, "four"
-        -- </6.3>
-    })
-
-test:do_execsql_test(
-    6.4,
-    [[
-        SELECT x, y FROM t5 WHERE CAST(x AS STRING) IN ('1.0');
-    ]], {
-        -- <6.4>
-
-        -- </6.4>
-    })
-
-test:do_execsql_test(
-    6.5,
-    [[
-        SELECT x, y FROM t5 WHERE 1 IN (x);
-    ]], {
-        -- <6.5>
-        1, "one", 1, "two", 1, "three", 1.0, "four"
-        -- </6.5>
-    })
-
-test:do_execsql_test(
-    6.6,
-    [[
-        SELECT x, y FROM t5 WHERE 1.0 IN (x);
-    ]], {
-        -- <6.6>
-        1, "one", 1, "two", 1, "three", 1.0, "four"
-        -- </6.6>
-    })
-
-test:do_execsql_test(
-    6.7,
-    [[
-        SELECT x, y FROM t5 WHERE CAST('1' AS INTEGER) IN (x);
-    ]], {
-        -- <6.7>
-        1, "one", 1, "two", 1, "three", 1.0, "four"
-        -- </6.7>
-    })
-
-test:do_execsql_test(
-    6.8,
-    [[
-        SELECT x, y FROM t5 WHERE CAST('1.0' AS DOUBLE) IN (x);
-    ]], {
-        -- <6.8>
-        1, "one", 1, "two", 1, "three", 1, "four"
-        -- </6.8>
-    })
-
-
-
-test:finish_test()
diff --git a/test/sql-tap/tkt-f973c7ac31.test.lua b/test/sql-tap/tkt-f973c7ac31.test.lua
index 604a7e6bb..9be5d3c53 100755
--- a/test/sql-tap/tkt-f973c7ac31.test.lua
+++ b/test/sql-tap/tkt-f973c7ac31.test.lua
@@ -39,7 +39,7 @@ for tn, sql in ipairs(sqls) do
     test:do_execsql_test(
         "tkt-f973c7ac3-1."..tn..".1",
         [[
-            SELECT c1,c2 FROM t WHERE c1 = 5 AND c2>0 AND CAST(c2 AS STRING)<='2' ORDER BY c2 DESC 
+            SELECT c1,c2 FROM t WHERE c1 = 5 AND c2>0 AND CAST(c2 AS STRING)<='2' ORDER BY c2 DESC
         ]], {
         })
 
@@ -54,7 +54,7 @@ for tn, sql in ipairs(sqls) do
     test:do_execsql_test(
         "tkt-f973c7ac3-1."..tn..".3",
         [[
-            SELECT c1,c2 FROM t WHERE c1 = 5 AND c2>0 AND CAST(c2 AS STRING)<='5' ORDER BY c2 DESC 
+            SELECT c1,c2 FROM t WHERE c1 = 5 AND c2>0 AND CAST(c2 AS STRING)<='5' ORDER BY c2 DESC
         ]], {
             5, 5, 5, 4
         })
@@ -62,7 +62,7 @@ for tn, sql in ipairs(sqls) do
     test:do_execsql_test(
         "tkt-f973c7ac3-1."..tn..".4",
         [[
-            SELECT c1,c2 FROM t WHERE c1 = 5 AND CAST(c2 AS STRING)>'0' AND c2<=5 ORDER BY c2 DESC 
+            SELECT c1,c2 FROM t WHERE c1 = 5 AND CAST(c2 AS STRING)>'0' AND c2<=5 ORDER BY c2 DESC
         ]], {
             5, 5, 5, 4
         })
@@ -70,7 +70,7 @@ for tn, sql in ipairs(sqls) do
     test:do_execsql_test(
         "tkt-f973c7ac3-1."..tn..".5",
         [[
-            SELECT c1,c2 FROM t WHERE c1 = 5 AND CAST(c2 AS STRING)>'0' AND CAST(c2 AS STRING)<='5' ORDER BY c2 DESC 
+            SELECT c1,c2 FROM t WHERE c1 = 5 AND CAST(c2 AS STRING)>'0' AND CAST(c2 AS STRING)<='5' ORDER BY c2 DESC
         ]], {
             5, 5, 5, 4
         })
@@ -78,7 +78,7 @@ for tn, sql in ipairs(sqls) do
     test:do_execsql_test(
         "tkt-f973c7ac3-1."..tn..".6",
         [[
-            SELECT c1,c2 FROM t WHERE c1 = 5 AND c2>0 AND CAST(c2 AS STRING)<='2' ORDER BY c2 ASC 
+            SELECT c1,c2 FROM t WHERE c1 = 5 AND c2>0 AND CAST(c2 AS STRING)<='2' ORDER BY c2 ASC
         ]], {
         })
 
@@ -93,7 +93,7 @@ for tn, sql in ipairs(sqls) do
     test:do_execsql_test(
         "tkt-f973c7ac3-1."..tn..".8",
         [[
-            SELECT c1,c2 FROM t WHERE c1 = 5 AND c2>0 AND CAST(c2 AS STRING)<='5' ORDER BY c2 ASC 
+            SELECT c1,c2 FROM t WHERE c1 = 5 AND c2>0 AND CAST(c2 AS STRING)<='5' ORDER BY c2 ASC
         ]], {
             5, 4, 5, 5
         })



New patch:

From c53921e221266ed1cea89e2c1491b3bd16e33860 Mon Sep 17 00:00:00 2001
From: Mergen Imeev <imeevma@gmail.com>
Date: Thu, 16 Apr 2020 12:52:59 +0300
Subject: [PATCH] sql: remove implicit cast from string for comparison

This patch removes implicit cast from strings to numbers for
comparison.

Closes #4230

@TarantoolBot document
Title: remove implicit cast between strings and numbers

This patch-set removes implicit cast from string to number and
from number to string.

Example:

For comparison:
```
tarantool> box.execute([[SELECT '1' > 0;]])
---
- null
- 'Type mismatch: can not convert 1 to numeric'
...

tarantool> box.execute([[SELECT "id" FROM "_space" WHERE '1' > "id";]])
---
- null
- 'Type mismatch: can not convert text to unsigned'
...
```
For assignment:
```
tarantool> box.execute([[CREATE TABLE t1(i INT PRIMARY KEY);]])
tarantool> box.execute([[INSERT INTO t1 VALUES ('1');]])
---
- null
- 'Type mismatch: can not convert text to integer'
...

tarantool> box.execute([[CREATE TABLE t2(t text PRIMARY KEY);]])
tarantool> box.execute([[INSERT INTO t2 VALUES (1);]])
---
- null
- 'Type mismatch: can not convert unsigned to string'
...
```

diff --git a/src/box/sql/expr.c b/src/box/sql/expr.c
index 8ec685cd9..f51549695 100644
--- a/src/box/sql/expr.c
+++ b/src/box/sql/expr.c
@@ -137,19 +137,6 @@ sql_expr_type(struct Expr *pExpr)
  return pExpr->type;
 }
 
-enum field_type *
-field_type_sequence_dup(struct Parse *parse, enum field_type *types,
-     uint32_t len)
-{
- uint32_t sz = (len + 1) * sizeof(enum field_type);
- enum field_type *ret_types = sqlDbMallocRaw(parse->db, sz);
- if (ret_types == NULL)
-   return NULL;
- memcpy(ret_types, types, sz);
- ret_types[len] = field_type_MAX;
- return ret_types;
-}
-
 /*
  * Set the collating sequence for expression pExpr to be the collating
  * sequence named by pToken.   Return a pointer to a new Expr node that
@@ -2246,36 +2233,6 @@ sqlExprCanBeNull(const Expr * p)
  }
 }
 
-bool
-sql_expr_needs_no_type_change(const struct Expr *p, enum field_type type)
-{
- u8 op;
- if (type == FIELD_TYPE_SCALAR)
-   return true;
- while (p->op == TK_UPLUS || p->op == TK_UMINUS) {
-   p = p->pLeft;
- }
- op = p->op;
- if (op == TK_REGISTER)
-   op = p->op2;
- switch (op) {
- case TK_INTEGER:
-   return type == FIELD_TYPE_INTEGER;
- case TK_FLOAT:
-   return type == FIELD_TYPE_DOUBLE;
- case TK_STRING:
-   return type == FIELD_TYPE_STRING;
- case TK_BLOB:
-   return type == FIELD_TYPE_VARBINARY;
- case TK_COLUMN:
-   /* p cannot be part of a CHECK constraint. */
-   assert(p->iTable >= 0);
-   return p->iColumn < 0 && sql_type_is_numeric(type);
- default:
-   return false;
- }
-}
-
 /*
  * pX is the RHS of an IN operator.  If pX is a SELECT statement
  * that can be simplified to a direct table access, then return
diff --git a/src/box/sql/insert.c b/src/box/sql/insert.c
index 253304ba3..7b9cda504 100644
--- a/src/box/sql/insert.c
+++ b/src/box/sql/insert.c
@@ -41,20 +41,6 @@
 #include "box/box.h"
 #include "box/schema.h"
 
-enum field_type *
-sql_index_type_str(struct sql *db, const struct index_def *idx_def)
-{
- uint32_t column_count = idx_def->key_def->part_count;
- uint32_t sz = (column_count + 1) * sizeof(enum field_type);
- enum field_type *types = (enum field_type *) sqlDbMallocRaw(db, sz);
- if (types == NULL)
-   return NULL;
- for (uint32_t i = 0; i < column_count; i++)
-   types[i] = idx_def->key_def->parts[i].type;
- types[column_count] = field_type_MAX;
- return types;
-}
-
 void
 sql_emit_table_types(struct Vdbe *v, struct space_def *def, int reg)
 {
diff --git a/src/box/sql/sqlInt.h b/src/box/sql/sqlInt.h
index 37283e506..b76c5eab8 100644
--- a/src/box/sql/sqlInt.h
+++ b/src/box/sql/sqlInt.h
@@ -3229,19 +3229,6 @@ int sqlExprIsTableConstant(Expr *, int);
 int sqlExprIsInteger(Expr *, int *);
 int sqlExprCanBeNull(const Expr *);
 
-/**
- * Return TRUE if the given expression is a constant which would
- * be unchanged by OP_ApplyType with the type given in the second
- * argument.
- *
- * This routine is used to determine if the OP_ApplyType operation
- * can be omitted.  When in doubt return FALSE.  A false negative
- * is harmless. A false positive, however, can result in the wrong
- * answer.
- */
-bool
-sql_expr_needs_no_type_change(const struct Expr *expr, enum field_type type);
-
 /**
  * This routine generates VDBE code that causes a single row of a
  * single table to be deleted.  Both the original table entry and
@@ -3866,10 +3853,6 @@ int sqlVarintLen(u64 v);
 #define getVarint    sqlGetVarint
 #define putVarint    sqlPutVarint
 
-/** Return string consisting of fields types of given index. */
-enum field_type *
-sql_index_type_str(struct sql *db, const struct index_def *idx_def);
-
 /**
  * Code an OP_ApplyType opcode that will force types
  * for given range of register starting from @reg.
@@ -3911,14 +3894,6 @@ expr_cmp_mutual_type(struct Expr *pExpr);
 enum field_type
 sql_expr_type(struct Expr *pExpr);
 
-/**
- * This function duplicates first @len entries of types array
- * and terminates new array with field_type_MAX member.
- */
-enum field_type *
-field_type_sequence_dup(struct Parse *parse, enum field_type *types,
-     uint32_t len);
-
 /**
  * Convert z to a 64-bit signed or unsigned integer.
  * z must be decimal. This routine does *not* accept
diff --git a/src/box/sql/vdbe.c b/src/box/sql/vdbe.c
index 77b758833..a92c9f60f 100644
--- a/src/box/sql/vdbe.c
+++ b/src/box/sql/vdbe.c
@@ -2260,8 +2260,6 @@ case OP_Ge: {             /* same as TK_GE, jump, in1, in3 */
  pIn3 = &aMem[pOp->p3];
  flags1 = pIn1->flags;
  flags3 = pIn3->flags;
- enum field_type ft_p1 = pIn1->field_type;
- enum field_type ft_p3 = pIn3->field_type;
  if ((flags1 | flags3)&MEM_Null) {
    /* One or both operands are NULL */
    if (pOp->p5 & SQL_NULLEQ) {
@@ -2320,22 +2318,17 @@ case OP_Ge: {             /* same as TK_GE, jump, in1, in3 */
  } else {
    enum field_type type = pOp->p5 & FIELD_TYPE_MASK;
    if (sql_type_is_numeric(type)) {
-     if ((flags1 | flags3)&MEM_Str) {
-       if ((flags1 & MEM_Str) == MEM_Str) {
-         mem_apply_numeric_type(pIn1);
-         testcase( flags3!=pIn3->flags); /* Possible if pIn1==pIn3 */
-         flags3 = pIn3->flags;
-       }
-       if ((flags3 & MEM_Str) == MEM_Str) {
-         if (mem_apply_numeric_type(pIn3) != 0) {
-           diag_set(ClientError,
-              ER_SQL_TYPE_MISMATCH,
-              sql_value_to_diag_str(pIn3),
-              "numeric");
-           goto abort_due_to_error;
-         }
-
-       }
+     if ((flags1 & MEM_Str) == MEM_Str) {
+       diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
+          sql_value_to_diag_str(pIn1),
+          "numeric");
+       goto abort_due_to_error;
+     }
+     if ((flags3 & MEM_Str) == MEM_Str) {
+       diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
+          sql_value_to_diag_str(pIn3),
+          "numeric");
+       goto abort_due_to_error;
      }
      /* Handle the common case of integer comparison here, as an
       * optimization, to avoid a call to sqlMemCompare()
@@ -2368,22 +2361,17 @@ case OP_Ge: {             /* same as TK_GE, jump, in1, in3 */
        goto compare_op;
      }
    } else if (type == FIELD_TYPE_STRING) {
-     if ((flags1 & MEM_Str) == 0 &&
-         (flags1 & (MEM_Int | MEM_UInt | MEM_Real)) != 0) {
-       testcase( pIn1->flags & MEM_Int);
-       testcase( pIn1->flags & MEM_Real);
-       sqlVdbeMemStringify(pIn1);
-       testcase( (flags1&MEM_Dyn) != (pIn1->flags&MEM_Dyn));
-       flags1 = (pIn1->flags & ~MEM_TypeMask) | (flags1 & MEM_TypeMask);
-       assert(pIn1!=pIn3);
+     if ((flags1 & MEM_Str) == 0) {
+       diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
+          mem_type_to_str(pIn3),
+          mem_type_to_str(pIn1));
+       goto abort_due_to_error;
      }
-     if ((flags3 & MEM_Str) == 0 &&
-         (flags3 & (MEM_Int | MEM_UInt | MEM_Real)) != 0) {
-       testcase( pIn3->flags & MEM_Int);
-       testcase( pIn3->flags & MEM_Real);
-       sqlVdbeMemStringify(pIn3);
-       testcase( (flags3&MEM_Dyn) != (pIn3->flags&MEM_Dyn));
-       flags3 = (pIn3->flags & ~MEM_TypeMask) | (flags3 & MEM_TypeMask);
+     if ((flags3 & MEM_Str) == 0) {
+       diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
+          mem_type_to_str(pIn1),
+          mem_type_to_str(pIn3));
+       goto abort_due_to_error;
      }
    }
    assert(pOp->p4type==P4_COLLSEQ || pOp->p4.pColl==0);
@@ -2399,14 +2387,6 @@ case OP_Ge: {             /* same as TK_GE, jump, in1, in3 */
  default:       res2 = res>=0;     break;
  }
 
- /* Undo any changes made by mem_apply_type() to the input registers. */
- assert((pIn1->flags & MEM_Dyn) == (flags1 & MEM_Dyn));
- pIn1->flags = flags1;
- pIn1->field_type = ft_p1;
- assert((pIn3->flags & MEM_Dyn) == (flags3 & MEM_Dyn));
- pIn3->flags = flags3;
- pIn3->field_type = ft_p3;
-
  if (pOp->p5 & SQL_STOREP2) {
    iCompare = res;
    res2 = res2!=0;  /* For this path res2 must be exactly 0 or 1 */
@@ -3496,8 +3476,6 @@ case OP_SeekGT: {       /* jump, in3 */
    pIn3 = &aMem[int_field];
    if ((pIn3->flags & MEM_Null) != 0)
      goto skip_truncate;
-   if ((pIn3->flags & MEM_Str) != 0)
-     mem_apply_numeric_type(pIn3);
    int64_t i;
    if ((pIn3->flags & MEM_Int) == MEM_Int) {
      i = pIn3->u.i;
@@ -3590,6 +3568,26 @@ skip_truncate:
  assert(oc!=OP_SeekLT || r.default_rc==+1);
 
  r.aMem = &aMem[pOp->p3];
+ for (int i = 0; i < r.nField; ++i) {
+   enum field_type type = r.key_def->parts[i].type;
+   struct Mem *mem = &r.aMem[i];
+   if ((mem->flags & MEM_Str) != 0 && sql_type_is_numeric(type)) {
+     diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
+       field_type_strs[type], mem_type_to_str(mem));
+     goto abort_due_to_error;
+   }
+   if (mem_check_types(mem, type) == 0)
+     continue;
+   if ((mem->flags & MEM_Real) != 0 &&
+       (type == FIELD_TYPE_INTEGER ||
+        type == FIELD_TYPE_UNSIGNED)) {
+     res = 1;
+     goto seek_not_found;
+   }
+   diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
+     field_type_strs[type], mem_type_to_str(mem));
+   goto abort_due_to_error;
+ }
 #ifdef SQL_DEBUG
  { int i; for(i=0; i<r.nField; i++) assert(memIsValid(&r.aMem[i])); }
 #endif
@@ -4717,6 +4715,27 @@ case OP_IdxGE:  {       /* jump */
    r.default_rc = 0;
  }
  r.aMem = &aMem[pOp->p3];
+ for (int i = 0; i < r.nField; ++i) {
+   struct Mem *mem = &r.aMem[i];
+   enum mp_type mp_type = sql_value_type(mem);
+   enum field_type field_type = r.key_def->parts[i].type;
+   if (field_type == FIELD_TYPE_SCALAR ||
+       mem->field_type == FIELD_TYPE_SCALAR)
+     continue;
+   bool is_nullable = r.key_def->parts[i].nullable_action ==
+          ON_CONFLICT_ACTION_NONE;
+   if (field_mp_plain_type_is_compatible(field_type, mp_type,
+                 is_nullable))
+     continue;
+   if (!sql_type_is_numeric(field_type) ||
+       !(mp_type == MP_INT || mp_type == MP_UINT ||
+         mp_type == MP_DOUBLE || mp_type == MP_FLOAT)) {
+     diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
+        mem_type_to_str(mem),
+        field_type_strs[field_type]);
+     goto abort_due_to_error;
+   }
+ }
 #ifdef SQL_DEBUG
  { int i; for(i=0; i<r.nField; i++) assert(memIsValid(&r.aMem[i])); }
 #endif
diff --git a/src/box/sql/wherecode.c b/src/box/sql/wherecode.c
index 6d8768865..1d7c76670 100644
--- a/src/box/sql/wherecode.c
+++ b/src/box/sql/wherecode.c
@@ -335,72 +335,6 @@ disableTerm(WhereLevel * pLevel, WhereTerm * pTerm)
  }
 }
 
-/**
- * Code an OP_ApplyType opcode to apply the column type string
- * @types to the n registers starting at @base.
- *
- * As an optimization, SCALAR entries (which are no-ops) at the
- * beginning and end of @types are ignored.  If all entries in
- * @types are SCALAR, then no code gets generated.
- *
- * This routine makes its own copy of @types so that the caller is
- * free to modify @types after this routine returns.
- */
-static void
-emit_apply_type(Parse *pParse, int base, int n, enum field_type *types)
-{
- Vdbe *v = pParse->pVdbe;
- if (types == NULL) {
-   assert(pParse->db->mallocFailed);
-   return;
- }
- assert(v != 0);
-
- /*
-  * Adjust base and n to skip over SCALAR entries at the
-  * beginning and end of the type sequence.
-  */
- while (n > 0 && types[0] == FIELD_TYPE_SCALAR) {
-   n--;
-   base++;
-   types++;
- }
- while (n > 1 && types[n - 1] == FIELD_TYPE_SCALAR) {
-   n--;
- }
-
- if (n > 0) {
-   enum field_type *types_dup = field_type_sequence_dup(pParse,
-                    types, n);
-   sqlVdbeAddOp4(v, OP_ApplyType, base, n, 0,
-         (char *) types_dup, P4_DYNAMIC);
-   sql_expr_type_cache_change(pParse, base, n);
- }
-}
-
-/**
- * Expression @rhs, which is the RHS of a comparison operation, is
- * either a vector of n elements or, if n==1, a scalar expression.
- * Before the comparison operation, types @types are to be applied
- * to the @rhs values. This function modifies entries within the
- * field sequence to SCALAR if either:
- *
- *   * the comparison will be performed with no type, or
- *   * the type change in @types is guaranteed not to change the value.
- */
-static void
-expr_cmp_update_rhs_type(struct Expr *rhs, int n, enum field_type *types)
-{
- for (int i = 0; i < n; i++) {
-   Expr *p = sqlVectorFieldSubexpr(rhs, i);
-   enum field_type expr_type = sql_expr_type(p);
-   if (sql_type_result(expr_type, types[i]) == FIELD_TYPE_SCALAR ||
-       sql_expr_needs_no_type_change(p, types[i])) {
-     types[i] = FIELD_TYPE_SCALAR;
-   }
- }
-}
-
 /*
  * Generate code for a single equality term of the WHERE clause.  An equality
  * term can be either X=expr or X IN (...).   pTerm is the term to be
@@ -644,8 +578,7 @@ static int
 codeAllEqualityTerms(Parse * pParse, /* Parsing context */
         WhereLevel * pLevel, /* Which nested loop of the FROM we are coding */
         int bRev,    /* Reverse the order of IN operators */
-        int nExtraReg, /* Number of extra registers to allocate */
-        enum field_type **res_type)
+        int nExtraReg) /* Number of extra registers to allocate */
 {
  u16 nEq;    /* The number of == or IN constraints to code */
  u16 nSkip;    /* Number of left-most columns to skip */
@@ -669,9 +602,6 @@ codeAllEqualityTerms(Parse * pParse,  /* Parsing context */
  nReg = pLoop->nEq + nExtraReg;
  pParse->nMem += nReg;
 
- enum field_type *type = sql_index_type_str(pParse->db, idx_def);
- assert(type != NULL || pParse->db->mallocFailed);
-
  if (nSkip) {
    int iIdxCur = pLevel->iIdxCur;
    sqlVdbeAddOp1(v, (bRev ? OP_Last : OP_Rewind), iIdxCur);
@@ -714,17 +644,7 @@ codeAllEqualityTerms(Parse * pParse, /* Parsing context */
        sqlVdbeAddOp2(v, OP_SCopy, r1, regBase + j);
      }
    }
-   if (pTerm->eOperator & WO_IN) {
-     if (pTerm->pExpr->flags & EP_xIsSelect) {
-       /* No type ever needs to be (or should be) applied to a value
-        * from the RHS of an "? IN (SELECT ...)" expression. The
-        * sqlFindInIndex() routine has already ensured that the
-        * type of the comparison has been applied to the value.
-        */
-       if (type != NULL)
-         type[j] = FIELD_TYPE_SCALAR;
-     }
-   } else if ((pTerm->eOperator & WO_ISNULL) == 0) {
+   if ((pTerm->eOperator & (WO_IN | WO_ISNULL)) == 0) {
      Expr *pRight = pTerm->pExpr->pRight;
      if (sqlExprCanBeNull(pRight)) {
        sqlVdbeAddOp2(v, OP_IsNull, regBase + j,
@@ -733,7 +653,6 @@ codeAllEqualityTerms(Parse * pParse,  /* Parsing context */
      }
    }
  }
- *res_type = type;
  return regBase;
 }
 
@@ -904,10 +823,6 @@ sqlWhereCodeOneLoopStart(WhereInfo * pWInfo, /* Complete information about the W
    int iIdxCur;  /* The VDBE cursor for the index */
    int nExtraReg = 0;  /* Number of extra registers needed */
    int op;   /* Instruction opcode */
-   /* Types for start of range constraint. */
-   enum field_type *start_types;
-   /* Types for end of range constraint */
-   enum field_type *end_types = NULL;
    u8 bSeekPastNull = 0; /* True to seek past initial nulls */
    u8 bStopAtNull = 0; /* Add condition to terminate at NULLs */
    int force_integer_reg = -1;  /* If non-negative: number of
@@ -994,17 +909,7 @@ sqlWhereCodeOneLoopStart(WhereInfo * pWInfo, /* Complete information about the W
     * and store the values of those terms in an array of registers
     * starting at regBase.
     */
-   regBase =
-       codeAllEqualityTerms(pParse, pLevel, bRev, nExtraReg,
-          &start_types);
-   if (start_types != NULL && nTop) {
-     uint32_t len = 0;
-     for (enum field_type *tmp = &start_types[nEq];
-          *tmp != field_type_MAX; tmp++, len++);
-     uint32_t sz = len * sizeof(enum field_type);
-     end_types = sqlDbMallocRaw(db, sz);
-     memcpy(end_types, &start_types[nEq], sz);
-   }
+   regBase = codeAllEqualityTerms(pParse, pLevel, bRev, nExtraReg);
    addrNxt = pLevel->addrNxt;
 
    testcase(pRangeStart && (pRangeStart->eOperator & WO_LE) != 0);
@@ -1029,10 +934,6 @@ sqlWhereCodeOneLoopStart(WhereInfo * pWInfo,  /* Complete information about the W
        VdbeCoverage(v);
      }
 
-     if (start_types) {
-       expr_cmp_update_rhs_type(pRight, nBtm,
-              &start_types[nEq]);
-     }
      nConstraint += nBtm;
      testcase(pRangeStart->wtFlags & TERM_VIRTUAL);
      if (sqlExprIsVector(pRight) == 0) {
@@ -1049,94 +950,6 @@ sqlWhereCodeOneLoopStart(WhereInfo * pWInfo,  /* Complete information about the W
    }
    struct index_def *idx_pk = space->index[0]->def;
    uint32_t pk_part_count = idx_pk->key_def->part_count;
-   /*
-    * Tarantool's iterator over integer fields doesn't
-    * tolerate floating point values. Hence, if term
-    * is equality comparison and value of operand is
-    * not integer, we can skip it since it always
-    * results in false: INT a == 0.5 -> false;
-    * It is done using OP_MustBeInt facilities.
-    * In case term is greater comparison (a > ?), we
-    * should notify OP_SeekGT to process truncation of
-    * floating point value: a > 0.5 -> a >= 1;
-    * It is done by setting P5 flag for OP_Seek*.
-    * It is worth mentioning that we do not need
-    * this step when it comes for less (<) comparison
-    * of nullable field. Key is NULL in this case:
-    * values are ordered as  NULL, ... NULL, min_value,
-    * so to fetch min value we pass NULL to GT iterator.
-    * The only exception is less comparison in
-    * conjunction with ORDER BY DESC clause:
-    * in such situation we use LE iterator and
-    * truncated value to compare. But then
-    * pRangeStart == NULL.
-    * This procedure is correct for compound index:
-    * only one comparison of less/greater type can be
-    * used at the same time. For instance,
-    * a < 1.5 AND b > 0.5 is handled by SeekGT using
-    * column a and fetching column b from tuple and
-    * OP_Le comparison.
-    *
-    * Note that OP_ApplyType, which is emitted before
-    * OP_Seek** doesn't truncate floating point to
-    * integer. That's why we need this routine.
-    * Also, note that terms are separated by OR
-    * predicates, so we consider term as sequence
-    * of AND'ed predicates.
-    */
-   size_t addrs_sz;
-   int *seek_addrs = region_alloc_array(&pParse->region,
-                typeof(seek_addrs[0]), nEq,
-                &addrs_sz);
-   if (seek_addrs == NULL) {
-     diag_set(OutOfMemory, addrs_sz, "region_alloc_array",
-        "seek_addrs");
-     pParse->is_aborted = true;
-     return 0;
-   }
-   memset(seek_addrs, 0, addrs_sz);
-   for (int i = 0; i < nEq; i++) {
-     enum field_type type = idx_def->key_def->parts[i].type;
-     if (type == FIELD_TYPE_INTEGER ||
-         type == FIELD_TYPE_UNSIGNED) {
-       /*
-        * OP_MustBeInt consider NULLs as
-        * non-integer values, so firstly
-        * check whether value is NULL or not.
-        */
-       seek_addrs[i] = sqlVdbeAddOp1(v, OP_IsNull,
-                   regBase);
-       sqlVdbeAddOp2(v, OP_MustBeInt, regBase + i,
-               addrNxt);
-       start_types[i] = FIELD_TYPE_SCALAR;
-       /*
-        * We need to notify column cache
-        * that type of value may change
-        * so we should fetch value from
-        * tuple again rather then copy
-        * from register.
-        */
-       sql_expr_type_cache_change(pParse, regBase + i,
-                1);
-     }
-   }
-   /* Inequality constraint comes always at the end of list. */
-   part_count = idx_def->key_def->part_count;
-   if (pRangeStart != NULL) {
-     /*
-      * nEq == 0 means that filter condition
-      * contains only inequality.
-      */
-     uint32_t ineq_idx = nEq == 0 ? 0 : nEq - 1;
-     assert(ineq_idx < part_count);
-     enum field_type ineq_type =
-       idx_def->key_def->parts[ineq_idx].type;
-     if (ineq_type == FIELD_TYPE_INTEGER ||
-         ineq_type == FIELD_TYPE_UNSIGNED)
-       force_integer_reg = regBase + nEq;
-   }
-   emit_apply_type(pParse, regBase, nConstraint - bSeekPastNull,
-       start_types);
    if (pLoop->nSkip > 0 && nConstraint == pLoop->nSkip) {
      /* The skip-scan logic inside the call to codeAllEqualityConstraints()
       * above has already left the cursor sitting on the correct row,
@@ -1146,10 +959,6 @@ sqlWhereCodeOneLoopStart(WhereInfo * pWInfo,  /* Complete information about the W
      op = aStartOp[(start_constraints << 2) +
              (startEq << 1) + bRev];
      assert(op != 0);
-     for (uint32_t i = 0; i < nEq; ++i) {
-       if (seek_addrs[i] != 0)
-         sqlVdbeJumpHere(v, seek_addrs[i]);
-     }
      sqlVdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase,
               nConstraint);
      /* If this is Seek* opcode, and IPK is detected in the
@@ -1189,13 +998,6 @@ sqlWhereCodeOneLoopStart(WhereInfo * pWInfo,  /* Complete information about the W
              addrNxt);
        VdbeCoverage(v);
      }
-     if (end_types) {
-       expr_cmp_update_rhs_type(pRight, nTop, end_types);
-       emit_apply_type(pParse, regBase + nEq, nTop,
-           end_types);
-     } else {
-       assert(pParse->db->mallocFailed);
-     }
      nConstraint += nTop;
      testcase(pRangeEnd->wtFlags & TERM_VIRTUAL);
 
@@ -1209,8 +1011,6 @@ sqlWhereCodeOneLoopStart(WhereInfo * pWInfo,  /* Complete information about the W
      endEq = 0;
      nConstraint++;
    }
-   sqlDbFree(db, start_types);
-   sqlDbFree(db, end_types);
 
    /* Top of the loop body */
    pLevel->p2 = sqlVdbeCurrentAddr(v);
diff --git a/test/sql-tap/gh-4230-del-impl-cast-str-to-num.test.lua b/test/sql-tap/gh-4230-del-impl-cast-str-to-num.test.lua
new file mode 100755
index 000000000..b405a11b6
--- /dev/null
+++ b/test/sql-tap/gh-4230-del-impl-cast-str-to-num.test.lua
@@ -0,0 +1,281 @@
+#!/usr/bin/env tarantool
+test = require("sqltester")
+test:plan(32)
+
+--
+-- Make sure that there is no implicit cast between string and
+-- number.
+--
+test:do_catchsql_test(
+    "gh-4230-1",
+    [[
+        SELECT '1' > 0;
+    ]], {
+        1, "Type mismatch: can not convert 1 to numeric"
+    })
+
+test:do_catchsql_test(
+    "gh-4230-2",
+    [[
+        SELECT 0 > '1';
+    ]], {
+        1, "Type mismatch: can not convert 1 to numeric"
+    })
+
+test:execsql([[
+        CREATE TABLE t (i INT PRIMARY KEY, d DOUBLE, n NUMBER, s STRING);
+        INSERT INTO t VALUES (1, 1.0, 1, '2'), (2, 2.0, 2.0, '2');
+    ]])
+
+test:do_catchsql_test(
+    "gh-4230-3",
+    [[
+        SELECT * from t where i > s;
+    ]], {
+        1, "Type mismatch: can not convert 2 to numeric"
+    })
+
+test:do_catchsql_test(
+    "gh-4230-4",
+    [[
+        SELECT * from t WHERE s > i;
+    ]], {
+        1, "Type mismatch: can not convert 2 to numeric"
+    })
+
+test:do_catchsql_test(
+    "gh-4230-5",
+    [[
+        SELECT * from t WHERE d > s;
+    ]], {
+        1, "Type mismatch: can not convert 2 to numeric"
+    })
+
+test:do_catchsql_test(
+    "gh-4230-6",
+    [[
+        SELECT * from t WHERE s > d;
+    ]], {
+        1, "Type mismatch: can not convert 2 to numeric"
+    })
+
+test:do_catchsql_test(
+    "gh-4230-7",
+    [[
+        SELECT * from t WHERE i = 1 and n > s;
+    ]], {
+        1, "Type mismatch: can not convert 2 to numeric"
+    })
+
+test:do_catchsql_test(
+    "gh-4230-8",
+    [[
+        SELECT * from t WHERE i = 2 and s > n;
+    ]], {
+        1, "Type mismatch: can not convert 2 to numeric"
+    })
+
+test:execsql([[
+    CREATE TABLE t1(x TEXT primary key);
+    INSERT INTO t1 VALUES('1');
+    CREATE TABLE t2(x INTEGER primary key);
+    INSERT INTO t2 VALUES(1);
+    CREATE TABLE t3(x DOUBLE primary key);
+    INSERT INTO t3 VALUES(1.0);
+]])
+
+test:do_catchsql_test(
+    "gh-4230-9",
+    [[
+        SELECT x FROM t1 WHERE x IN (1);
+    ]], {
+        1, "Type mismatch: can not convert 1 to numeric"
+    })
+
+
+test:do_catchsql_test(
+    "gh-4230-10",
+    [[
+        SELECT x FROM t1 WHERE x IN (1.0);
+    ]], {
+        1, "Type mismatch: can not convert 1 to numeric"
+    })
+
+test:do_execsql_test(
+    "gh-4230-11",
+    [[
+        SELECT x FROM t1 WHERE x IN ('1');
+    ]], {
+        "1"
+    })
+
+test:do_execsql_test(
+    "gh-4230-12",
+    [[
+        SELECT x FROM t1 WHERE x IN ('1.0');
+    ]], {
+    })
+
+test:do_catchsql_test(
+    "gh-4230-13",
+    [[
+        SELECT x FROM t1 WHERE 1 IN (x);
+    ]], {
+        1, "Type mismatch: can not convert 1 to numeric"
+    })
+
+test:do_catchsql_test(
+    "gh-4230-14",
+    [[
+        SELECT x FROM t1 WHERE 1.0 IN (x);
+    ]], {
+        1, "Type mismatch: can not convert 1 to numeric"
+    })
+
+test:do_execsql_test(
+    "gh-4230-15",
+    [[
+        SELECT x FROM t1 WHERE '1' IN (x);
+    ]], {
+        -- <2.7>
+        "1"
+        -- </2.7>
+    })
+
+test:do_execsql_test(
+    "gh-4230-16",
+    [[
+        SELECT x FROM t1 WHERE '1.0' IN (x);
+    ]], {
+    })
+
+test:do_execsql_test(
+    "gh-4230-17",
+    [[
+        SELECT x FROM t2 WHERE x IN (1);
+    ]], {
+        1
+    })
+
+
+test:do_execsql_test(
+    "gh-4230-18",
+    [[
+        SELECT x FROM t2 WHERE x IN (1.0);
+    ]], {
+        1
+    })
+
+test:do_catchsql_test(
+    "gh-4230-19",
+    [[
+        SELECT x FROM t2 WHERE x IN ('1');
+    ]], {
+        1, "Type mismatch: can not convert integer to text"
+    })
+
+test:do_catchsql_test(
+    "gh-4230-20",
+    [[
+        SELECT x FROM t2 WHERE x IN ('1.0');
+    ]], {
+        1, "Type mismatch: can not convert integer to text"
+    })
+
+test:do_execsql_test(
+    "gh-4230-21",
+    [[
+        SELECT x FROM t2 WHERE 1 IN (x);
+    ]], {
+        1
+    })
+
+test:do_execsql_test(
+    "gh-4230-22",
+    [[
+        SELECT x FROM t2 WHERE 1.0 IN (x);
+    ]], {
+        1
+    })
+
+test:do_catchsql_test(
+    "gh-4230-23",
+    [[
+        SELECT x FROM t2 WHERE '1' IN (x);
+    ]], {
+        1, "Type mismatch: can not convert integer to text"
+    })
+
+test:do_catchsql_test(
+    "gh-4230-24",
+    [[
+        SELECT x FROM t2 WHERE '1.0' IN (x);
+    ]], {
+        1, "Type mismatch: can not convert integer to text"
+    })
+
+test:do_execsql_test(
+    "gh-4230-25",
+    [[
+        SELECT x FROM t3 WHERE x IN (1);
+    ]], {
+        1
+    })
+
+test:do_execsql_test(
+    "gh-4230-26",
+    [[
+        SELECT x FROM t3 WHERE x IN (1.0);
+    ]], {
+        1
+    })
+
+test:do_catchsql_test(
+    "gh-4230-27",
+    [[
+        SELECT x FROM t3 WHERE x IN ('1');
+    ]], {
+        1, "Type mismatch: can not convert double to text"
+    })
+
+test:do_catchsql_test(
+    "gh-4230-28",
+    [[
+        SELECT x FROM t3 WHERE x IN ('1.0');
+    ]], {
+        1, "Type mismatch: can not convert double to text"
+    })
+
+test:do_execsql_test(
+    "gh-4230-29",
+    [[
+        SELECT x FROM t3 WHERE 1 IN (x);
+    ]], {
+        1
+    })
+
+test:do_execsql_test(
+    "gh-4230-30",
+    [[
+        SELECT x FROM t3 WHERE 1.0 IN (x);
+    ]], {
+        1
+    })
+
+test:do_catchsql_test(
+    "gh-4230-31",
+    [[
+        SELECT x FROM t3 WHERE '1' IN (x);
+    ]], {
+        1, "Type mismatch: can not convert double to text"
+    })
+
+test:do_catchsql_test(
+    "gh-4230-32",
+    [[
+        SELECT x FROM t3 WHERE '1.0' IN (x);
+    ]], {
+        1, "Type mismatch: can not convert double to text"
+    })
+
+test:finish_test()
diff --git a/test/sql-tap/identifier_case.test.lua b/test/sql-tap/identifier_case.test.lua
index 2a00626fc..1d56ffb44 100755
--- a/test/sql-tap/identifier_case.test.lua
+++ b/test/sql-tap/identifier_case.test.lua
@@ -242,11 +242,11 @@ data = {
     { 2,  [[ 'a' < 'b' collate "binary" ]], {0, {true}}},
     { 3,  [[ 'a' < 'b' collate 'binary' ]], {1, [[Syntax error at line 1 near ''binary'']]}},
     { 4,  [[ 'a' < 'b' collate "unicode" ]], {0, {true}}},
-    { 5,  [[ 5 < 'b' collate "unicode" ]], {0, {true}}},
+    { 5,  [[ 5 < 'b' collate "unicode" ]], {1, "Type mismatch: can not convert b to numeric"}},
     { 6,  [[ 5 < 'b' collate unicode ]], {1,"Collation 'UNICODE' does not exist"}},
-    { 7,  [[ 5 < 'b' collate "unicode_ci" ]], {0, {true}}},
+    { 7,  [[ 5 < 'b' collate "unicode_ci" ]], {1, "Type mismatch: can not convert b to numeric"}},
     { 8,  [[ 5 < 'b' collate NONE ]], {1, "Collation 'NONE' does not exist"}},
-    { 9,  [[ 5 < 'b' collate "none" ]], {0, {true}}},
+    { 9,  [[ 5 < 'b' collate "none" ]], {1, "Type mismatch: can not convert b to numeric"}},
 }
 
 for _, row in ipairs(data) do
diff --git a/test/sql-tap/in1.test.lua b/test/sql-tap/in1.test.lua
index 570cc1779..e2f498889 100755
--- a/test/sql-tap/in1.test.lua
+++ b/test/sql-tap/in1.test.lua
@@ -637,12 +637,12 @@ test:do_test(
     "in-11.2",
     function()
         -- The '2' should be coerced into 2 because t6.b is NUMERIC
-        return test:execsql [[
+        return test:catchsql [[
             SELECT * FROM t6 WHERE b IN ('2');
         ]]
     end, {
         -- <in-11.2>
-        1, 2
+        1, "Type mismatch: can not convert 2 to numeric"
         -- </in-11.2>
     })
 
diff --git a/test/sql-tap/in4.test.lua b/test/sql-tap/in4.test.lua
index 33947d0ab..a494e846f 100755
--- a/test/sql-tap/in4.test.lua
+++ b/test/sql-tap/in4.test.lua
@@ -147,12 +147,13 @@ test:do_execsql_test(
         -- </in4-2.7>
     })
 
-test:do_execsql_test(
+test:do_catchsql_test(
     "in4-2.8",
     [[
         SELECT b FROM t2 WHERE a IN ('', '0.0.0', '2') 
     ]], {
         -- <in4-2.8>
+        1, "Type mismatch: can not convert integer to text"
         -- </in4-2.8>
     })
 
diff --git a/test/sql-tap/insert3.test.lua b/test/sql-tap/insert3.test.lua
index b92bc508e..3276f0db2 100755
--- a/test/sql-tap/insert3.test.lua
+++ b/test/sql-tap/insert3.test.lua
@@ -59,7 +59,7 @@ test:do_execsql_test(
     [[
             CREATE TABLE log2(rowid INTEGER PRIMARY KEY AUTOINCREMENT, x TEXT UNIQUE,y INT );
             CREATE TRIGGER r2 BEFORE INSERT ON t1 FOR EACH ROW BEGIN
-              UPDATE log2 SET y=y+1 WHERE x=new.b;
+              UPDATE log2 SET y=y+1 WHERE x=CAST(new.b AS STRING);
               INSERT OR IGNORE INTO log2(x, y) VALUES(CAST(new.b AS STRING),1);
             END;
             INSERT INTO t1(a, b) VALUES('hi', 453);
diff --git a/test/sql-tap/intpkey.test.lua b/test/sql-tap/intpkey.test.lua
index 0db18ba91..bc3d701a7 100755
--- a/test/sql-tap/intpkey.test.lua
+++ b/test/sql-tap/intpkey.test.lua
@@ -1,6 +1,6 @@
 #!/usr/bin/env tarantool
 test = require("sqltester")
-test:plan(40)
+test:plan(39)
 
 --!./tcltestrunner.lua
 -- 2001 September 15
@@ -854,43 +854,33 @@ test:do_execsql_test(
         -- </intpkey-14.2>
     })
 
-test:do_execsql_test(
-    "intpkey-14.3",
-    [[
-        SELECT * FROM t3 WHERE a>'2';
-    ]], {
-        -- <intpkey-14.3>
-        3, 3, "3"
-        -- </intpkey-14.3>
-    })
-
-test:do_execsql_test(
+test:do_catchsql_test(
     "intpkey-14.4",
     [[
         SELECT * FROM t3 WHERE a<'2';
     ]], {
         -- <intpkey-14.4>
-        1, 1, "one"
+        1, "Type mismatch: can not convert text to integer"
         -- </intpkey-14.4>
     })
 
-test:do_execsql_test(
+test:do_catchsql_test(
     "intpkey-14.5",
     [[
         SELECT * FROM t3 WHERE a<c;
     ]], {
         -- <intpkey-14.5>
-        1, 1, "one"
+        1, "Type mismatch: can not convert one to numeric"
         -- </intpkey-14.5>
     })
 
-test:do_execsql_test(
+test:do_catchsql_test(
     "intpkey-14.6",
     [[
         SELECT * FROM t3 WHERE a=c;
     ]], {
         -- <intpkey-14.6>
-        2, 2, "2", 3, 3, "3"
+        1, "Type mismatch: can not convert one to numeric"
         -- </intpkey-14.6>
     })
 
diff --git a/test/sql-tap/join.test.lua b/test/sql-tap/join.test.lua
index 51e0ecb79..792302ab5 100755
--- a/test/sql-tap/join.test.lua
+++ b/test/sql-tap/join.test.lua
@@ -1028,22 +1028,23 @@ test:do_test(
         -- </join-11.8>
     })
 
-test:do_execsql_test(
+test:do_catchsql_test(
     "join-11.9",
     [[
         SELECT * FROM t1 NATURAL JOIN t2 
     ]], {
         -- <join-11.9>
+        1, "Type mismatch: can not convert integer to text"
         -- </join-11.9>
     })
 
-test:do_execsql_test(
+test:do_catchsql_test(
     "join-11.10",
     [[
         SELECT * FROM t2 NATURAL JOIN t1 
     ]], {
         -- <join-11.10>
-        1, "one", 2, "two"
+        1, "Type mismatch: can not convert 1 to numeric"
         -- </join-11.10>
     })
 
diff --git a/test/sql-tap/misc1.test.lua b/test/sql-tap/misc1.test.lua
index e0fe50bbe..3cef617f4 100755
--- a/test/sql-tap/misc1.test.lua
+++ b/test/sql-tap/misc1.test.lua
@@ -88,7 +88,7 @@ test:do_execsql_test(
 test:do_execsql_test(
     "misc1-1.4",
     [[
-        SELECT x75 FROM manycol WHERE x50=350
+        SELECT x75 FROM manycol WHERE x50='350'
     ]], {
         -- <misc1-1.4>
         "375"
@@ -98,7 +98,7 @@ test:do_execsql_test(
 test:do_execsql_test(
     "misc1-1.5",
     [[
-        SELECT x50 FROM manycol WHERE x99=599
+        SELECT x50 FROM manycol WHERE x99='599'
     ]], {
         -- <misc1-1.5>
         "550"
@@ -109,7 +109,7 @@ test:do_test(
     "misc1-1.6",
     function()
         test:execsql("CREATE INDEX manycol_idx1 ON manycol(x99)")
-        return test:execsql("SELECT x50 FROM manycol WHERE x99=899")
+        return test:execsql("SELECT x50 FROM manycol WHERE x99='899'")
     end, {
         -- <misc1-1.6>
         "850"
@@ -129,7 +129,7 @@ test:do_execsql_test(
 test:do_test(
     "misc1-1.8",
     function()
-        test:execsql("DELETE FROM manycol WHERE x98=1234")
+        test:execsql("DELETE FROM manycol WHERE x98='1234'")
         return test:execsql("SELECT count(*) FROM manycol")
     end, {
         -- <misc1-1.8>
@@ -140,7 +140,7 @@ test:do_test(
 test:do_test(
     "misc1-1.9",
     function()
-        test:execsql("DELETE FROM manycol WHERE x98=998")
+        test:execsql("DELETE FROM manycol WHERE x98='998'")
         return test:execsql("SELECT count(*) FROM manycol")
     end, {
         -- <misc1-1.9>
@@ -151,7 +151,7 @@ test:do_test(
 test:do_test(
     "misc1-1.10",
     function()
-        test:execsql("DELETE FROM manycol WHERE x99=500")
+        test:execsql("DELETE FROM manycol WHERE x99='500'")
         return test:execsql("SELECT count(*) FROM manycol")
     end, {
         -- <misc1-1.10>
@@ -162,7 +162,7 @@ test:do_test(
 test:do_test(
     "misc1-1.11",
     function()
-        test:execsql("DELETE FROM manycol WHERE x99=599")
+        test:execsql("DELETE FROM manycol WHERE x99='599'")
         return test:execsql("SELECT count(*) FROM manycol")
     end, {
         -- <misc1-1.11>
@@ -479,9 +479,9 @@ local where = ""
 test:do_test(
     "misc1-10.1",
     function()
-        where = "WHERE x0>=0"
+        where = "WHERE x0>='0'"
         for i = 1, 99, 1 do
-            where = where .. " AND x"..i.."<>0"
+            where = where .. " AND x"..i.."<>'0'"
         end
         return test:catchsql("SELECT count(*) FROM manycol "..where.."")
     end, {
@@ -496,7 +496,7 @@ test:do_test(
 test:do_test(
     "misc1-10.3",
     function()
-        where = string.gsub(where,"x0>=0", "x0=0")
+        where = string.gsub(where,"x0>='0'", "x0='0'")
         return test:catchsql("DELETE FROM manycol "..where.."")
     end, {
         -- <misc1-10.3>
@@ -520,7 +520,7 @@ test:do_execsql_test(
 test:do_execsql_test(
     "misc1-10.6",
     [[
-        SELECT x1 FROM manycol WHERE x0=100
+        SELECT x1 FROM manycol WHERE x0='100'
     ]], {
         -- <misc1-10.6>
         "101"
@@ -530,7 +530,7 @@ test:do_execsql_test(
 test:do_test(
     "misc1-10.7",
     function()
-        where = string.gsub(where, "x0=0", "x0=100")
+        where = string.gsub(where, "x0='0'", "x0='100'")
         return test:catchsql("UPDATE manycol SET x1=CAST(x1+1 AS STRING) "..where.."")
     end, {
         -- <misc1-10.7>
@@ -541,7 +541,7 @@ test:do_test(
 test:do_execsql_test(
     "misc1-10.8",
     [[
-        SELECT x1 FROM manycol WHERE x0=100
+        SELECT x1 FROM manycol WHERE x0='100'
     ]], {
         -- <misc1-10.8>
         "102"
@@ -563,7 +563,7 @@ test:do_execsql_test(
 test:do_execsql_test(
     "misc1-10.10",
     [[
-        SELECT x1 FROM manycol WHERE x0=100
+        SELECT x1 FROM manycol WHERE x0='100'
     ]], {
         -- <misc1-10.10>
         "103"
@@ -619,13 +619,13 @@ test:do_execsql_test(
         -- </misc1-12.1>
     })
 
-test:do_execsql_test(
+test:do_catchsql_test(
     "misc1-12.2",
     [[
         SELECT '0'==0.0
     ]], {
         -- <misc1-12.2>
-        true
+        1, "Type mismatch: can not convert 0 to numeric"
         -- </misc1-12.2>
     })
 
diff --git a/test/sql-tap/select1.test.lua b/test/sql-tap/select1.test.lua
index 9a969bf3c..f5a9b63fe 100755
--- a/test/sql-tap/select1.test.lua
+++ b/test/sql-tap/select1.test.lua
@@ -1912,7 +1912,7 @@ test:do_execsql_test(
 test:do_execsql_test(
         "select1-12.7",
         [[
-            SELECT * FROM t3 WHERE a=(SELECT 1);
+            SELECT * FROM t3 WHERE a=(SELECT '1');
         ]], {
             -- <select1-12.7>
             0, "1", "2"
@@ -1922,7 +1922,7 @@ test:do_execsql_test(
 test:do_execsql_test(
     "select1-12.8",
     [[
-        SELECT * FROM t3 WHERE a=(SELECT 2);
+        SELECT * FROM t3 WHERE a=(SELECT '2');
     ]], {
         -- <select1-12.8>
 
diff --git a/test/sql-tap/select7.test.lua b/test/sql-tap/select7.test.lua
index e1e43c557..0d1390fd6 100755
--- a/test/sql-tap/select7.test.lua
+++ b/test/sql-tap/select7.test.lua
@@ -256,7 +256,7 @@ test:do_execsql_test(
         DROP TABLE IF EXISTS t5;
         CREATE TABLE t5(a TEXT primary key, b INT);
         INSERT INTO t5 VALUES('123', 456);
-        SELECT typeof(a), a FROM t5 GROUP BY a HAVING a<b;
+        SELECT typeof(a), a FROM t5 GROUP BY a HAVING CAST(a AS INTEGER)<b;
     ]], {
         -- <select7-7.7>
         "string", "123"
diff --git a/test/sql-tap/subquery.test.lua b/test/sql-tap/subquery.test.lua
index e0771825e..bad702de9 100755
--- a/test/sql-tap/subquery.test.lua
+++ b/test/sql-tap/subquery.test.lua
@@ -284,13 +284,13 @@ test:do_execsql_test(
         -- </subquery-2.3.1>
     })
 
-test:do_execsql_test(
+test:do_catchsql_test(
     "subquery-2.3.2",
     [[
         SELECT a IN (10.0, 20) FROM t3;
     ]], {
         -- <subquery-2.3.2>
-        false
+        1, "Type mismatch: can not convert text to real"
         -- </subquery-2.3.2>
     })
 
diff --git a/test/sql-tap/tkt-9a8b09f8e6.test.lua b/test/sql-tap/tkt-9a8b09f8e6.test.lua
deleted file mode 100755
index ac89c7df2..000000000
--- a/test/sql-tap/tkt-9a8b09f8e6.test.lua
+++ /dev/null
@@ -1,506 +0,0 @@
-#!/usr/bin/env tarantool
-test = require("sqltester")
-test:plan(47)
-
---!./tcltestrunner.lua
--- 2014 June 26
---
--- The author disclaims copyright to this source code.  In place of
--- a legal notice, here is a blessing:
---
---    May you do good and not evil.
---    May you find forgiveness for yourself and forgive others.
---    May you share freely, never taking more than you give.
---
--------------------------------------------------------------------------
--- This file implements regression tests for sql library.
---
--- This file implements tests to verify that ticket [9a8b09f8e6] has been
--- fixed.
---
--- ["set","testdir",[["file","dirname",["argv0"]]]]
--- ["source",[["testdir"],"\/tester.tcl"]]
-testprefix = "tkt-9a8b09f8e6"
--- MUST_WORK_TEST
-if (0 > 0)
- then
-end
-test:do_execsql_test(
-    1.1,
-    [[
-        CREATE TABLE t1(x TEXT primary key);
-        INSERT INTO t1 VALUES('1');
-    ]], {
-        -- <1.1>
-        
-        -- </1.1>
-    })
-
-test:do_execsql_test(
-    1.2,
-    [[
-        CREATE TABLE t2(x INTEGER primary key);
-        INSERT INTO t2 VALUES(1);
-    ]], {
-        -- <1.2>
-        
-        -- </1.2>
-    })
-
-test:do_execsql_test(
-    1.3,
-    [[
-        CREATE TABLE t3(x NUMBER primary key);
-        INSERT INTO t3 VALUES(1.0);
-    ]], {
-        -- <1.3>
-        
-        -- </1.3>
-    })
-
-test:do_execsql_test(
-    1.4,
-    [[
-        CREATE TABLE t4(x NUMBER primary key);
-        INSERT INTO t4 VALUES(1.11);
-    ]], {
-        -- <1.4>
-        
-        -- </1.4>
-    })
-
-test:do_execsql_test(
-    1.5,
-    [[
-        CREATE TABLE t5(id  INT primary key, x INT , y TEXT);
-        INSERT INTO t5 VALUES(1, 1, 'one');
-        INSERT INTO t5 VALUES(2, 1, 'two');
-        INSERT INTO t5 VALUES(3, 1.0, 'three');
-        INSERT INTO t5 VALUES(4, 1.0, 'four');
-    ]], {
-        -- <1.5>
-        
-        -- </1.5>
-    })
-
-test:do_execsql_test(
-    2.1,
-    [[
-        SELECT x FROM t1 WHERE x IN (1);
-    ]], {
-        -- <2.1>
-        "1"
-        -- </2.1>
-    })
-
-test:do_execsql_test(
-    2.2,
-    [[
-        SELECT x FROM t1 WHERE x IN (1.0);
-    ]], {
-        -- <2.2>
-        "1"
-        -- </2.2>
-    })
-
-test:do_execsql_test(
-    2.3,
-    [[
-        SELECT x FROM t1 WHERE x IN ('1');
-    ]], {
-        -- <2.3>
-        "1"
-        -- </2.3>
-    })
-
-test:do_execsql_test(
-    2.4,
-    [[
-        SELECT x FROM t1 WHERE x IN ('1.0');
-    ]], {
-        -- <2.4>
-        
-        -- </2.4>
-    })
-
-test:do_execsql_test(
-    2.5,
-    [[
-        SELECT x FROM t1 WHERE 1 IN (x);
-    ]], {
-        -- <2.5>
-        "1"
-        -- </2.5>
-    })
-
-test:do_execsql_test(
-    2.6,
-    [[
-        SELECT x FROM t1 WHERE 1.0 IN (x);
-    ]], {
-        -- <2.6>
-        "1"
-        -- </2.6>
-    })
-
-test:do_execsql_test(
-    2.7,
-    [[
-        SELECT x FROM t1 WHERE '1' IN (x);
-    ]], {
-        -- <2.7>
-        "1"
-        -- </2.7>
-    })
-
-test:do_execsql_test(
-    2.8,
-    [[
-        SELECT x FROM t1 WHERE '1.0' IN (x);
-    ]], {
-        -- <2.8>
-        
-        -- </2.8>
-    })
-
-test:do_execsql_test(
-    3.1,
-    [[
-        SELECT x FROM t2 WHERE x IN (1);
-    ]], {
-        -- <3.1>
-        1
-        -- </3.1>
-    })
-
-test:do_execsql_test(
-    3.2,
-    [[
-        SELECT x FROM t2 WHERE x IN (1.0);
-    ]], {
-        -- <3.2>
-        1
-        -- </3.2>
-    })
-
-test:do_execsql_test(
-    3.3,
-    [[
-        SELECT x FROM t2 WHERE x IN ('1');
-    ]], {
-        -- <3.3>
-        -- </3.3>
-    })
-
-test:do_execsql_test(
-    3.5,
-    [[
-        SELECT x FROM t2 WHERE 1 IN (x);
-    ]], {
-        -- <3.5>
-        1
-        -- </3.5>
-    })
-
-test:do_execsql_test(
-    3.6,
-    [[
-        SELECT x FROM t2 WHERE 1.0 IN (x);
-    ]], {
-        -- <3.6>
-        1
-        -- </3.6>
-    })
-
-test:do_execsql_test(
-    3.7,
-    [[
-        SELECT x FROM t2 WHERE '1' IN (x);
-    ]], {
-        -- <3.7>
-        -- </3.7>
-    })
-
-test:do_execsql_test(
-    4.1,
-    [[
-        SELECT x FROM t3 WHERE x IN (1);
-    ]], {
-        -- <4.1>
-        1.0
-        -- </4.1>
-    })
-
-test:do_execsql_test(
-    4.2,
-    [[
-        SELECT x FROM t3 WHERE x IN (1.0);
-    ]], {
-        -- <4.2>
-        1.0
-        -- </4.2>
-    })
-
-test:do_execsql_test(
-    4.3,
-    [[
-        SELECT x FROM t3 WHERE x IN ('1');
-    ]], {
-        -- <4.3>
-        1.0
-        -- </4.3>
-    })
-
-test:do_execsql_test(
-    4.4,
-    [[
-        SELECT x FROM t3 WHERE x IN ('1.0');
-    ]], {
-        -- <4.4>
-        1.0
-        -- </4.4>
-    })
-
-test:do_execsql_test(
-    4.5,
-    [[
-        SELECT x FROM t3 WHERE 1 IN (x);
-    ]], {
-        -- <4.5>
-        1.0
-        -- </4.5>
-    })
-
-test:do_execsql_test(
-    4.6,
-    [[
-        SELECT x FROM t3 WHERE 1.0 IN (x);
-    ]], {
-        -- <4.6>
-        1.0
-        -- </4.6>
-    })
-
-test:do_execsql_test(
-    4.7,
-    [[
-        SELECT x FROM t3 WHERE '1' IN (x);
-    ]], {
-        -- <4.7>
-        1
-        -- </4.7>
-    })
-
-test:do_execsql_test(
-    4.8,
-    [[
-        SELECT x FROM t3 WHERE '1.0' IN (x);
-    ]], {
-        -- <4.8>
-        1
-        -- </4.8>
-    })
-
-test:do_execsql_test(
-    5.1,
-    [[
-        SELECT x FROM t4 WHERE x IN (1);
-    ]], {
-        -- <5.1>
-        
-        -- </5.1>
-    })
-
-test:do_execsql_test(
-    5.2,
-    [[
-        SELECT x FROM t4 WHERE x IN (1.0);
-    ]], {
-        -- <5.2>
-        
-        -- </5.2>
-    })
-
-test:do_execsql_test(
-    5.3,
-    [[
-        SELECT x FROM t4 WHERE x IN ('1');
-    ]], {
-        -- <5.3>
-        
-        -- </5.3>
-    })
-
-test:do_execsql_test(
-    5.4,
-    [[
-        SELECT x FROM t4 WHERE x IN ('1.0');
-    ]], {
-        -- <5.4>
-        
-        -- </5.4>
-    })
-
-test:do_execsql_test(
-    5.5,
-    [[
-        SELECT x FROM t4 WHERE x IN (1.11);
-    ]], {
-        -- <5.5>
-        1.11
-        -- </5.5>
-    })
-
-test:do_execsql_test(
-    5.6,
-    [[
-        SELECT x FROM t4 WHERE x IN ('1.11');
-    ]], {
-        -- <5.6>
-        1.11
-        -- </5.6>
-    })
-
-test:do_execsql_test(
-    5.7,
-    [[
-        SELECT x FROM t4 WHERE 1 IN (x);
-    ]], {
-        -- <5.7>
-        
-        -- </5.7>
-    })
-
-test:do_execsql_test(
-    5.8,
-    [[
-        SELECT x FROM t4 WHERE 1.0 IN (x);
-    ]], {
-        -- <5.8>
-        
-        -- </5.8>
-    })
-
-test:do_execsql_test(
-    5.9,
-    [[
-        SELECT x FROM t4 WHERE '1' IN (x);
-    ]], {
-        -- <5.9>
-        
-        -- </5.9>
-    })
-
-test:do_execsql_test(
-    5.10,
-    [[
-        SELECT x FROM t4 WHERE '1.0' IN (x);
-    ]], {
-        -- <5.10>
-        
-        -- </5.10>
-    })
-
-test:do_execsql_test(
-    5.11,
-    [[
-        SELECT x FROM t4 WHERE 1.11 IN (x);
-    ]], {
-        -- <5.11>
-        1.11
-        -- </5.11>
-    })
-
-test:do_execsql_test(
-    5.12,
-    [[
-        SELECT x FROM t4 WHERE '1.11' IN (x);
-    ]], {
-        -- <5.12>
-        1.11
-        -- </5.12>
-    })
-
-test:do_execsql_test(
-    6.1,
-    [[
-        SELECT x, y FROM t5 WHERE x IN (1);
-    ]], {
-        -- <6.1>
-        1, "one", 1, "two", 1, "three", 1.0, "four"
-        -- </6.1>
-    })
-
-test:do_execsql_test(
-    6.2,
-    [[
-        SELECT x, y FROM t5 WHERE x IN (1.0);
-    ]], {
-        -- <6.2>
-        1, "one", 1, "two", 1, "three", 1.0, "four"
-        -- </6.2>
-    })
-
-test:do_execsql_test(
-    6.3,
-    [[
-        SELECT x, y FROM t5 WHERE x IN ('1');
-    ]], {
-        -- <6.3>
-        1, "one", 1, "two", 1, "three", 1.0, "four"
-        -- </6.3>
-    })
-
-test:do_execsql_test(
-    6.4,
-    [[
-        SELECT x, y FROM t5 WHERE x IN ('1.0');
-    ]], {
-        -- <6.4>
-        1, "one", 1, "two", 1, "three", 1.0, "four"
-        -- </6.4>
-    })
-
-test:do_execsql_test(
-    6.5,
-    [[
-        SELECT x, y FROM t5 WHERE 1 IN (x);
-    ]], {
-        -- <6.5>
-        1, "one", 1, "two", 1, "three", 1.0, "four"
-        -- </6.5>
-    })
-
-test:do_execsql_test(
-    6.6,
-    [[
-        SELECT x, y FROM t5 WHERE 1.0 IN (x);
-    ]], {
-        -- <6.6>
-        1, "one", 1, "two", 1, "three", 1.0, "four"
-        -- </6.6>
-    })
-
-test:do_execsql_test(
-    6.7,
-    [[
-        SELECT x, y FROM t5 WHERE '1' IN (x);
-    ]], {
-        -- <6.7>
-        1, "one", 1, "two", 1, "three", 1.0, "four"
-        -- </6.7>
-    })
-
-test:do_execsql_test(
-    6.8,
-    [[
-        SELECT x, y FROM t5 WHERE '1.0' IN (x);
-    ]], {
-        -- <6.8>
-        1, "one", 1, "two", 1, "three", 1, "four"
-        -- </6.8>
-    })
-
-
-
-test:finish_test()
diff --git a/test/sql-tap/tkt-f973c7ac31.test.lua b/test/sql-tap/tkt-f973c7ac31.test.lua
index 82bdb52f8..9be5d3c53 100755
--- a/test/sql-tap/tkt-f973c7ac31.test.lua
+++ b/test/sql-tap/tkt-f973c7ac31.test.lua
@@ -39,9 +39,8 @@ for tn, sql in ipairs(sqls) do
     test:do_execsql_test(
         "tkt-f973c7ac3-1."..tn..".1",
         [[
-            SELECT c1,c2 FROM t WHERE c1 = 5 AND c2>0 AND c2<='2' ORDER BY c2 DESC 
+            SELECT c1,c2 FROM t WHERE c1 = 5 AND c2>0 AND CAST(c2 AS STRING)<='2' ORDER BY c2 DESC
         ]], {
-            
         })
 
     test:do_execsql_test(
@@ -55,7 +54,7 @@ for tn, sql in ipairs(sqls) do
     test:do_execsql_test(
         "tkt-f973c7ac3-1."..tn..".3",
         [[
-            SELECT c1,c2 FROM t WHERE c1 = 5 AND c2>0 AND c2<='5' ORDER BY c2 DESC 
+            SELECT c1,c2 FROM t WHERE c1 = 5 AND c2>0 AND CAST(c2 AS STRING)<='5' ORDER BY c2 DESC
         ]], {
             5, 5, 5, 4
         })
@@ -63,7 +62,7 @@ for tn, sql in ipairs(sqls) do
     test:do_execsql_test(
         "tkt-f973c7ac3-1."..tn..".4",
         [[
-            SELECT c1,c2 FROM t WHERE c1 = 5 AND c2>'0' AND c2<=5 ORDER BY c2 DESC 
+            SELECT c1,c2 FROM t WHERE c1 = 5 AND CAST(c2 AS STRING)>'0' AND c2<=5 ORDER BY c2 DESC
         ]], {
             5, 5, 5, 4
         })
@@ -71,7 +70,7 @@ for tn, sql in ipairs(sqls) do
     test:do_execsql_test(
         "tkt-f973c7ac3-1."..tn..".5",
         [[
-            SELECT c1,c2 FROM t WHERE c1 = 5 AND c2>'0' AND c2<='5' ORDER BY c2 DESC 
+            SELECT c1,c2 FROM t WHERE c1 = 5 AND CAST(c2 AS STRING)>'0' AND CAST(c2 AS STRING)<='5' ORDER BY c2 DESC
         ]], {
             5, 5, 5, 4
         })
@@ -79,9 +78,8 @@ for tn, sql in ipairs(sqls) do
     test:do_execsql_test(
         "tkt-f973c7ac3-1."..tn..".6",
         [[
-            SELECT c1,c2 FROM t WHERE c1 = 5 AND c2>0 AND c2<='2' ORDER BY c2 ASC 
+            SELECT c1,c2 FROM t WHERE c1 = 5 AND c2>0 AND CAST(c2 AS STRING)<='2' ORDER BY c2 ASC
         ]], {
-            
         })
 
     test:do_execsql_test(
@@ -95,7 +93,7 @@ for tn, sql in ipairs(sqls) do
     test:do_execsql_test(
         "tkt-f973c7ac3-1."..tn..".8",
         [[
-            SELECT c1,c2 FROM t WHERE c1 = 5 AND c2>0 AND c2<='5' ORDER BY c2 ASC 
+            SELECT c1,c2 FROM t WHERE c1 = 5 AND c2>0 AND CAST(c2 AS STRING)<='5' ORDER BY c2 ASC
         ]], {
             5, 4, 5, 5
         })
@@ -103,7 +101,7 @@ for tn, sql in ipairs(sqls) do
     test:do_execsql_test(
         "tkt-f973c7ac3-1."..tn..".9",
         [[
-            SELECT c1,c2 FROM t WHERE c1 = 5 AND c2>'0' AND c2<=5 ORDER BY c2 ASC 
+            SELECT c1,c2 FROM t WHERE c1 = 5 AND CAST(c2 AS STRING)>'0' AND c2<=5 ORDER BY c2 ASC 
         ]], {
             5, 4, 5, 5
         })
@@ -111,7 +109,7 @@ for tn, sql in ipairs(sqls) do
     test:do_execsql_test(
         "tkt-f973c7ac3-1."..tn..".10",
         [[
-            SELECT c1,c2 FROM t WHERE c1 = 5 AND c2>'0' AND c2<='5' ORDER BY c2 ASC 
+            SELECT c1,c2 FROM t WHERE c1 = 5 AND CAST(c2 AS STRING)>'0' AND CAST(c2 AS STRING)<='5' ORDER BY c2 ASC 
         ]], {
             5, 4, 5, 5
         })
diff --git a/test/sql-tap/tkt3493.test.lua b/test/sql-tap/tkt3493.test.lua
index de77e61e9..82ba828d0 100755
--- a/test/sql-tap/tkt3493.test.lua
+++ b/test/sql-tap/tkt3493.test.lua
@@ -1,6 +1,6 @@
 #!/usr/bin/env tarantool
 test = require("sqltester")
-test:plan(26)
+test:plan(25)
 
 --!./tcltestrunner.lua
 -- 2008 October 13
@@ -45,7 +45,7 @@ test:do_execsql_test(
     [[
         SELECT 
           CASE 
-             WHEN B.val = 1 THEN 'XYZ' 
+             WHEN B.val = '1' THEN 'XYZ'
              ELSE A.val 
           END AS Col1
         FROM B  
@@ -63,7 +63,7 @@ test:do_execsql_test(
     [[
         SELECT DISTINCT
           CASE 
-             WHEN B.val = 1 THEN 'XYZ' 
+             WHEN B.val = '1' THEN 'XYZ'
              ELSE A.val 
           END AS Col1
         FROM B  
@@ -79,7 +79,7 @@ test:do_execsql_test(
 test:do_execsql_test(
     "tkt3493-1.4",
     [[
-        SELECT b.val, CASE WHEN b.val = 1 THEN 'xyz' ELSE b.val END AS col1 FROM b;
+        SELECT b.val, CASE WHEN b.val = '1' THEN 'xyz' ELSE b.val END AS col1 FROM b;
     ]], {
         -- <tkt3493-1.4>
         "1", "xyz", "2", "2"
@@ -91,7 +91,7 @@ test:do_execsql_test(
     [[
         SELECT DISTINCT 
           b.val, 
-          CASE WHEN b.val = 1 THEN 'xyz' ELSE b.val END AS col1 
+          CASE WHEN b.val = '1' THEN 'xyz' ELSE b.val END AS col1
         FROM b;
     ]], {
         -- <tkt3493-1.5>
@@ -126,23 +126,13 @@ test:do_execsql_test(
 test:do_execsql_test(
     "tkt3493-2.2.1",
     [[
-        SELECT a=123 FROM t1 GROUP BY a 
+        SELECT a='123' FROM t1 GROUP BY a
     ]], {
         -- <tkt3493-2.2.1>
         true
         -- </tkt3493-2.2.1>
     })
 
-test:do_execsql_test(
-    "tkt3493-2.2.2",
-    [[
-        SELECT a=123 FROM t1 
-    ]], {
-        -- <tkt3493-2.2.2>
-        true
-        -- </tkt3493-2.2.2>
-    })
-
 test:do_execsql_test(
     "tkt3493-2.2.3",
     [[
@@ -156,7 +146,7 @@ test:do_execsql_test(
 test:do_execsql_test(
     "tkt3493-2.2.4",
     [[
-        SELECT count(*), a=123 FROM t1 
+        SELECT count(*), a='123' FROM t1
     ]], {
         -- <tkt3493-2.2.4>
         1, true
@@ -166,7 +156,7 @@ test:do_execsql_test(
 test:do_execsql_test(
     "tkt3493-2.2.5",
     [[
-        SELECT count(*), +a=123 FROM t1 
+        SELECT count(*), +a='123' FROM t1
     ]], {
         -- <tkt3493-2.2.5>
         1, true
@@ -176,7 +166,7 @@ test:do_execsql_test(
 test:do_execsql_test(
     "tkt3493-2.3.3",
     [[
-        SELECT b='456' FROM t1 GROUP BY a 
+        SELECT b = 456 FROM t1 GROUP BY a
     ]], {
         -- <tkt3493-2.3.3>
         true
@@ -186,7 +176,7 @@ test:do_execsql_test(
 test:do_execsql_test(
     "tkt3493-2.3.1",
     [[
-        SELECT b='456' FROM t1 GROUP BY b 
+        SELECT b = 456 FROM t1 GROUP BY b
     ]], {
         -- <tkt3493-2.3.1>
         true
@@ -196,7 +186,7 @@ test:do_execsql_test(
 test:do_execsql_test(
     "tkt3493-2.3.2",
     [[
-        SELECT b='456' FROM t1 
+        SELECT b = 456 FROM t1
     ]], {
         -- <tkt3493-2.3.2>
         true
@@ -206,7 +196,7 @@ test:do_execsql_test(
 test:do_execsql_test(
     "tkt3493-2.4.1",
     [[
-        SELECT typeof(a), a FROM t1 GROUP BY a HAVING a=123 
+        SELECT typeof(a), a FROM t1 GROUP BY a HAVING a='123'
     ]], {
         -- <tkt3493-2.4.1>
         "string", "123"
@@ -216,7 +206,7 @@ test:do_execsql_test(
 test:do_execsql_test(
     "tkt3493-2.4.2",
     [[
-        SELECT typeof(a), a FROM t1 GROUP BY b HAVING a=123 
+        SELECT typeof(a), a FROM t1 GROUP BY b HAVING a='123'
     ]], {
         -- <tkt3493-2.4.2>
         "string", "123"
@@ -226,7 +216,7 @@ test:do_execsql_test(
 test:do_execsql_test(
     "tkt3493-2.5.1",
     [[
-        SELECT typeof(b), b FROM t1 GROUP BY a HAVING b='456' 
+        SELECT typeof(b), b FROM t1 GROUP BY a HAVING b=456
     ]], {
         -- <tkt3493-2.5.1>
         "integer", 456
@@ -236,7 +226,7 @@ test:do_execsql_test(
 test:do_execsql_test(
     "tkt3493-2.5.2",
     [[
-        SELECT typeof(b), b FROM t1 GROUP BY b HAVING b='456' 
+        SELECT typeof(b), b FROM t1 GROUP BY b HAVING b=456
     ]], {
         -- <tkt3493-2.5.2>
         "integer", 456
diff --git a/test/sql-tap/transitive1.test.lua b/test/sql-tap/transitive1.test.lua
index 96895b4a7..cc7e066bf 100755
--- a/test/sql-tap/transitive1.test.lua
+++ b/test/sql-tap/transitive1.test.lua
@@ -63,7 +63,7 @@ test:do_execsql_test(
         INSERT INTO t2 VALUES(2, 20,20,'20');
         INSERT INTO t2 VALUES(3, 3,3,'3');
 
-        SELECT a,b,c FROM t2 WHERE a=b AND c=b AND c=20;
+        SELECT a,b,c FROM t2 WHERE a=b AND c=CAST(b AS STRING) AND c='20';
     ]], {
         -- <transitive1-200>
         20, 20, "20"
@@ -73,7 +73,7 @@ test:do_execsql_test(
 test:do_execsql_test(
     "transitive1-210",
     [[
-        SELECT a,b,c FROM t2 WHERE a=b AND c=b AND c>='20' ORDER BY +a;
+        SELECT a,b,c FROM t2 WHERE a=b AND c=CAST(b AS STRING) AND c>='20' ORDER BY +a;
     ]], {
         -- <transitive1-210>
         3, 3, "3", 20, 20, "20"
@@ -83,7 +83,7 @@ test:do_execsql_test(
 test:do_execsql_test(
     "transitive1-220",
     [[
-        SELECT a,b,c FROM t2 WHERE a=b AND c=b AND c<='20' ORDER BY +a;
+        SELECT a,b,c FROM t2 WHERE a=b AND c=CAST(b AS STRING) AND c<='20' ORDER BY +a;
     ]], {
         -- <transitive1-220>
         20, 20, "20", 100, 100, "100"
@@ -402,7 +402,7 @@ test:do_execsql_test(
     [[
         CREATE TABLE x(i INTEGER PRIMARY KEY, y TEXT);
         INSERT INTO x VALUES(10, '10');
-        SELECT * FROM x WHERE x.y>='1' AND x.y<'2' AND x.i=x.y;
+        SELECT * FROM x WHERE x.y>='1' AND x.y<'2' AND CAST(x.i AS STRING)=x.y;
     ]], {
         -- <transitive1-500>
         10, "10"
@@ -430,7 +430,7 @@ test:do_execsql_test(
     [[
         CREATE TABLE t3(i INTEGER PRIMARY KEY, t TEXT);
         INSERT INTO t3 VALUES(10, '10');
-        SELECT * FROM t3 WHERE i=t AND t = '10 ';
+        SELECT * FROM t3 WHERE CAST(i AS STRING)=t AND t = '10 ';
     ]], {
         -- <transitive1-520>
 
@@ -443,7 +443,7 @@ test:do_execsql_test(
         CREATE TABLE u1(x TEXT PRIMARY KEY, y INTEGER, z TEXT);
         CREATE INDEX i1 ON u1(x);
         INSERT INTO u1 VALUES('00013', 13, '013');
-        SELECT * FROM u1 WHERE x=y AND y=z AND z='013';
+        SELECT * FROM u1 WHERE CAST(x AS INTEGER)=y AND y=CAST(z AS INTEGER) AND z='013';
     ]], {
         -- <transitive1-530>
         "00013",13,"013"
diff --git a/test/sql-tap/where2.test.lua b/test/sql-tap/where2.test.lua
index f267be8e6..7348a855a 100755
--- a/test/sql-tap/where2.test.lua
+++ b/test/sql-tap/where2.test.lua
@@ -4,7 +4,7 @@ yaml = require("yaml")
 fio = require("fio")
 
 ffi = require("ffi")
-test:plan(74)
+test:plan(62)
 
 ffi.cdef[[
        int dup(int oldfd);
@@ -622,181 +622,12 @@ test:do_test(
         -- </where2-6.6>
     })
 
--- if X(356, "X!cmd", [=[["expr","[permutation] != \"no_optimization\""]]=])
--- then
-    -- Ticket #2249.  Make sure the OR optimization is not attempted if
-    -- comparisons between columns of different affinities are needed.
-    --
-    test:do_test(
-        "where2-6.7",
-        function()
-            test:execsql [[
-                CREATE TABLE t2249a(a TEXT PRIMARY KEY, x VARCHAR(100));
-                CREATE TABLE t2249b(b INTEGER PRIMARY KEY);
-                INSERT INTO t2249a(a) VALUES('0123');
-                INSERT INTO t2249b VALUES(123);
-            ]]
-            return queryplan([[
-    -- Because a is type TEXT and b is type INTEGER, both a and b
-    -- will attempt to convert to NUMERIC before the comparison.
-    -- They will thus compare equal.
-    --
-    SELECT b,a FROM t2249b CROSS JOIN t2249a WHERE a=b;
-  ]])
-        end, {
-            -- <where2-6.7>
-            123, '0123', "nosort", "T2249B", "*", "T2249A", "*"
-            -- </where2-6.7>
-        })
-
-    test:do_test(
-        "where2-6.9",
-        function()
-            return queryplan([[
-    -- The + operator doesn't affect RHS.
-    --
-    SELECT b,a FROM t2249b CROSS JOIN t2249a WHERE a=+b;
-  ]])
-        end, {
-            -- <where2-6.9>
-            123, "0123", "nosort", "T2249B", "*", "T2249A", "*"
-            -- </where2-6.9>
-        })
-
-    test:do_test(
-        "where2-6.9.2",
-        function()
-            -- The same thing but with the expression flipped around.
-            return queryplan([[
-    SELECT b,a FROM t2249b CROSS JOIN t2249a WHERE +b=a
-  ]])
-        end, {
-            -- <where2-6.9.2>
-            123, "0123","nosort", "T2249B", "*", "T2249A", "*"
-            -- </where2-6.9.2>
-        })
-
-    test:do_test(
-        "where2-6.10",
-        function()
-            return queryplan([[
-    SELECT b,a FROM t2249b CROSS JOIN t2249a WHERE +a=+b;
-  ]])
-        end, {
-            -- <where2-6.10>
-            123, "0123", "nosort", "T2249B", "*", "T2249A", "*"
-            -- </where2-6.10>
-        })
-
-    test:do_test(
-        "where2-6.11",
-        function()
-            -- This will not attempt the OR optimization because of the a=b
-            -- comparison.
-            return queryplan([[
-    SELECT b,a FROM t2249b CROSS JOIN t2249a WHERE a=b OR a='hello';
-  ]])
-        end, {
-            -- <where2-6.11>
-            123, '0123', "nosort", "T2249B", "*", "T2249A", "*"
-            -- </where2-6.11>
-        })
-
-    test:do_test(
-        "where2-6.11.2",
-        function()
-            -- Permutations of the expression terms.
-            return queryplan([[
-    SELECT b,a FROM t2249b CROSS JOIN t2249a WHERE b=a OR a='hello';
-  ]])
-        end, {
-            -- <where2-6.11.2>
-            123, '0123', "nosort", "T2249B", "*", "T2249A", "*"
-            -- </where2-6.11.2>
-        })
-
-    test:do_test(
-        "where2-6.11.3",
-        function()
-            -- Permutations of the expression terms.
-            return queryplan([[
-    SELECT b,a FROM t2249b CROSS JOIN t2249a WHERE 'hello'=a OR b=a;
-  ]])
-        end, {
-            -- <where2-6.11.3>
-            123, '0123', "nosort", "T2249B", "*", "T2249A", "*"
-            -- </where2-6.11.3>
-        })
-
-    test:do_test(
-        "where2-6.11.4",
-        function()
-            -- Permutations of the expression terms.
-            return queryplan([[
-    SELECT b,a FROM t2249b CROSS JOIN t2249a WHERE a='hello' OR b=a;
-  ]])
-        end, {
-            -- <where2-6.11.4>
-            123, '0123', "nosort", "T2249B", "*", "T2249A", "*"
-            -- </where2-6.11.4>
-        })
-
-    -- These tests are not run if subquery support is not included in the
-    -- build. This is because these tests test the "a = 1 OR a = 2" to
-    -- "a IN (1, 2)" optimisation transformation, which is not enabled if
-    -- subqueries and the IN operator is not available.
-    --
-    test:do_test(
-        "where2-6.12",
-        function()
-            return queryplan([[
-      SELECT b,a FROM t2249b CROSS JOIN t2249a WHERE a=+b OR a='hello';
-    ]])
-        end, {
-            -- <where2-6.12>
-            123, "0123", "nosort", "T2249B", "*", "T2249A", "*"
-            -- </where2-6.12>
-        })
-
-    test:do_test(
-        "where2-6.12.2",
-        function()
-            return queryplan([[
-      SELECT b,a FROM t2249b CROSS JOIN t2249a WHERE a='hello' OR +b=a;
-    ]])
-        end, {
-            -- <where2-6.12.2>
-            123, "0123", "nosort", "T2249B", "*", "T2249A", "*"
-            -- </where2-6.12.2>
-        })
-
-    test:do_test(
-        "where2-6.12.3",
-        function()
-            return queryplan([[
-      SELECT b,a FROM t2249b CROSS JOIN t2249a WHERE +b=a OR a='hello';
-    ]])
-        end, {
-            -- <where2-6.12.3>
-            123, "0123", "nosort", "T2249B", "*", "T2249A", "*"
-            -- </where2-6.12.3>
-        })
-
-    test:do_test(
-        "where2-6.13",
-        function()
-            -- The addition of +a on the second term disabled the OR optimization.
-            -- But we should still get the same empty-set result as in where2-6.9.
-            return queryplan([[
-      SELECT b,a FROM t2249b CROSS JOIN t2249a WHERE a=+b OR +a='hello';
-    ]])
-        end, {
-            -- <where2-6.13>
-            123, "0123", "nosort", "T2249B", "*", "T2249A", "*"
-            -- </where2-6.13>
-        })
-
-
+    test:execsql [[
+        CREATE TABLE t2249a(a TEXT PRIMARY KEY, x VARCHAR(100));
+        CREATE TABLE t2249b(b INTEGER PRIMARY KEY);
+        INSERT INTO t2249a(a) VALUES('0123');
+        INSERT INTO t2249b VALUES(123);
+    ]]
 
     -- Variations on the order of terms in a WHERE clause in order
     -- to make sure the OR optimizer can recognize them all.
diff --git a/test/sql-tap/where5.test.lua b/test/sql-tap/where5.test.lua
index 3aefcaca5..a93ba7854 100755
--- a/test/sql-tap/where5.test.lua
+++ b/test/sql-tap/where5.test.lua
@@ -34,7 +34,7 @@ test:do_test("where5-1.0", function()
         INSERT INTO t3 SELECT CAST(x AS INTEGER) FROM t1;
     ]]
     return test:execsql [[
-        SELECT * FROM t1 WHERE x<0
+        SELECT * FROM t1 WHERE CAST(x AS INTEGER)<0
     ]]
 end, {
     -- <where5-1.0>
@@ -43,7 +43,7 @@ end, {
 })
 
 test:do_execsql_test("where5-1.1", [[
-    SELECT * FROM t1 WHERE x<=0
+    SELECT * FROM t1 WHERE CAST(x AS INTEGER)<=0
 ]], {
     -- <where5-1.1>
     '-1', '0'
@@ -51,7 +51,7 @@ test:do_execsql_test("where5-1.1", [[
 })
 
 test:do_execsql_test("where5-1.2", [[
-    SELECT * FROM t1 WHERE x=0
+    SELECT * FROM t1 WHERE CAST(x AS INTEGER)=0
 ]], {
     -- <where5-1.2>
     '0'
@@ -59,7 +59,7 @@ test:do_execsql_test("where5-1.2", [[
 })
 
 test:do_execsql_test("where5-1.3", [[
-    SELECT * FROM t1 WHERE x>=0
+    SELECT * FROM t1 WHERE CAST(x AS INTEGER)>=0
 ]], {
     -- <where5-1.3>
     '0', '1'
@@ -67,7 +67,7 @@ test:do_execsql_test("where5-1.3", [[
 })
 
 test:do_execsql_test("where5-1.4", [[
-    SELECT * FROM t1 WHERE x>0
+    SELECT * FROM t1 WHERE CAST(x AS INTEGER)>0
 ]], {
     -- <where5-1.4>
     '1'
@@ -75,7 +75,7 @@ test:do_execsql_test("where5-1.4", [[
 })
 
 test:do_execsql_test("where5-1.5", [[
-    SELECT * FROM t1 WHERE x<>0
+    SELECT * FROM t1 WHERE CAST(x AS INTEGER)<>0
 ]], {
     -- <where5-1.5>
     '-1', '1'
diff --git a/test/sql/types.result b/test/sql/types.result
index 6b0f7a651..9099bcea4 100644
--- a/test/sql/types.result
+++ b/test/sql/types.result
@@ -339,12 +339,12 @@ box.execute("INSERT INTO tboolean VALUES (TRUE);")
 box.execute("SELECT * FROM tboolean WHERE s1 = x'44';")
 ---
 - null
-- 'Type mismatch: can not convert varbinary to boolean'
+- 'Type mismatch: can not convert boolean to varbinary'
 ...
 box.execute("SELECT * FROM tboolean WHERE s1 = 'abc';")
 ---
 - null
-- 'Type mismatch: can not convert abc to boolean'
+- 'Type mismatch: can not convert boolean to text'
 ...
 box.execute("SELECT * FROM tboolean WHERE s1 = 1;")
 ---
@@ -606,14 +606,6 @@ box.execute("SELECT 18446744073709551615.0 > 18446744073709551615")
   rows:
   - [true]
 ...
-box.execute("SELECT 18446744073709551615 IN ('18446744073709551615', 18446744073709551615.0)")
----
-- metadata:
-  - name: 18446744073709551615 IN ('18446744073709551615', 18446744073709551615.0)
-    type: boolean
-  rows:
-  - [true]
-...
 box.execute("SELECT 1 LIMIT 18446744073709551615;")
 ---
 - metadata:
diff --git a/test/sql/types.test.lua b/test/sql/types.test.lua
index bd14b342d..f9603c60d 100644
--- a/test/sql/types.test.lua
+++ b/test/sql/types.test.lua
@@ -151,7 +151,6 @@ box.execute("SELECT 18446744073709551610 - 18446744073709551615;")
 box.execute("SELECT 18446744073709551615 = null;")
 box.execute("SELECT 18446744073709551615 = 18446744073709551615.0;")
 box.execute("SELECT 18446744073709551615.0 > 18446744073709551615")
-box.execute("SELECT 18446744073709551615 IN ('18446744073709551615', 18446744073709551615.0)")
 box.execute("SELECT 1 LIMIT 18446744073709551615;")
 box.execute("SELECT 1 LIMIT 1 OFFSET 18446744073709551614;")
 box.execute("SELECT CAST('18446744073' || '709551616' AS INTEGER);")

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [Tarantool-patches] [PATCH v2 6/7] sql: remove OP_ApplyType
  2020-06-11 12:54 [Tarantool-patches] [PATCH v2 0/7] Remove implicit cast imeevma
                   ` (4 preceding siblings ...)
  2020-06-11 12:54 ` [Tarantool-patches] [PATCH v2 5/7] sql: remove implicit cast from string for comparison imeevma
@ 2020-06-11 12:54 ` imeevma
  2020-06-11 12:54 ` [Tarantool-patches] [PATCH v2 7/7] sql: use type instead of value in type mismatch error imeevma
  6 siblings, 0 replies; 14+ messages in thread
From: imeevma @ 2020-06-11 12:54 UTC (permalink / raw)
  To: v.shpilevoy, tsafin, tarantool-patches

Thank you for the review! My answer, diff and new patch below.

On 10.06.2020 01:29, Vladislav Shpilevoy wrote:
> Thanks for the patch!
>
>> diff --git a/src/box/sql/wherecode.c b/src/box/sql/wherecode.c
>> index 1d7c76670..1ec9f4ed7 100644
>> --- a/src/box/sql/wherecode.c
>> +++ b/src/box/sql/wherecode.c
>> @@ -571,7 +571,7 @@ codeEqualityTerm(Parse * pParse,	/* The parsing context */
>>   *
>>   * Before returning, @types is set to point to a buffer containing a
>>   * copy of the column types array of the index allocated using
>> - * sqlDbMalloc(). This array is passed to OP_ApplyType to provide
>> + * sqlDbMalloc(). This array is passed to OP_CheckType to provide
>
> @types parameter does not exist anymore. I guess it was removed in
> one of the previous commits, and the comment should be updated there
> too.
>
Fixed.

>>   * correct implicit conversions.
>>   */
>>  static int



Diff:

diff --git a/src/box/sql/wherecode.c b/src/box/sql/wherecode.c
index 1ec9f4ed7..2459054ff 100644
--- a/src/box/sql/wherecode.c
+++ b/src/box/sql/wherecode.c
@@ -568,11 +568,6 @@ codeEqualityTerm(Parse * pParse,	/* The parsing context */
  * key value of the loop.  If one or more IN operators appear, then
  * this routine allocates an additional nEq memory cells for internal
  * use.
- *
- * Before returning, @types is set to point to a buffer containing a
- * copy of the column types array of the index allocated using
- * sqlDbMalloc(). This array is passed to OP_CheckType to provide
- * correct implicit conversions.
  */
 static int
 codeAllEqualityTerms(Parse * pParse,	/* Parsing context */


New patch:

From 699e6db0bed7c6af887c0cc0e5c861fbc5b2952b Mon Sep 17 00:00:00 2001
From: Mergen Imeev <imeevma@gmail.com>
Date: Thu, 28 May 2020 13:03:37 +0300
Subject: [PATCH] sql: remove OP_ApplyType

Opcode OP_ApplyType is not needed now, so it should be removed.

Follow-up #4230

diff --git a/src/box/sql/vdbe.c b/src/box/sql/vdbe.c
index a92c9f60f..e22ed98cf 100644
--- a/src/box/sql/vdbe.c
+++ b/src/box/sql/vdbe.c
@@ -2834,35 +2834,6 @@ case OP_Fetch: {
 	break;
 }
 
-/* Opcode: ApplyType P1 P2 * P4 *
- * Synopsis: type(r[P1@P2])
- *
- * Apply types to a range of P2 registers starting with P1.
- *
- * P4 is a string that is P2 characters long. The nth character of the
- * string indicates the column type that should be used for the nth
- * memory cell in the range.
- */
-case OP_ApplyType: {
-	enum field_type *types = pOp->p4.types;
-	assert(types != NULL);
-	assert(types[pOp->p2] == field_type_MAX);
-	pIn1 = &aMem[pOp->p1];
-	enum field_type type;
-	while((type = *(types++)) != field_type_MAX) {
-		assert(pIn1 <= &p->aMem[(p->nMem+1 - p->nCursor)]);
-		assert(memIsValid(pIn1));
-		if (mem_apply_type(pIn1, type) != 0) {
-			diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
-				 sql_value_to_diag_str(pIn1),
-				 field_type_strs[type]);
-			goto abort_due_to_error;
-		}
-		pIn1++;
-	}
-	break;
-}
-
 /* Opcode: CheckType P1 P2 * P4 *
  * Synopsis: type(r[P1@P2])
  *
diff --git a/src/box/sql/wherecode.c b/src/box/sql/wherecode.c
index 1d7c76670..2459054ff 100644
--- a/src/box/sql/wherecode.c
+++ b/src/box/sql/wherecode.c
@@ -568,11 +568,6 @@ codeEqualityTerm(Parse * pParse,	/* The parsing context */
  * key value of the loop.  If one or more IN operators appear, then
  * this routine allocates an additional nEq memory cells for internal
  * use.
- *
- * Before returning, @types is set to point to a buffer containing a
- * copy of the column types array of the index allocated using
- * sqlDbMalloc(). This array is passed to OP_ApplyType to provide
- * correct implicit conversions.
  */
 static int
 codeAllEqualityTerms(Parse * pParse,	/* Parsing context */

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [Tarantool-patches] [PATCH v2 7/7] sql: use type instead of value in type mismatch error
  2020-06-11 12:54 [Tarantool-patches] [PATCH v2 0/7] Remove implicit cast imeevma
                   ` (5 preceding siblings ...)
  2020-06-11 12:54 ` [Tarantool-patches] [PATCH v2 6/7] sql: remove OP_ApplyType imeevma
@ 2020-06-11 12:54 ` imeevma
  2020-06-14 17:03   ` Vladislav Shpilevoy
  6 siblings, 1 reply; 14+ messages in thread
From: imeevma @ 2020-06-11 12:54 UTC (permalink / raw)
  To: v.shpilevoy, tsafin, tarantool-patches

Follow-up #3809
Follow-up #4230
---
 src/box/sql/vdbe.c                            |   28 +-
 test/sql-tap/autoinc.test.lua                 |    2 +-
 test/sql-tap/cast.test.lua                    |   16 +-
 .../gh-4230-del-impl-cast-str-to-num.test.lua |   24 +-
 ...-4766-wrong-cast-from-blob-to-int.test.lua |    9 +-
 test/sql-tap/identifier_case.test.lua         |    6 +-
 test/sql-tap/in1.test.lua                     |    2 +-
 test/sql-tap/index1.test.lua                  |    4 +-
 test/sql-tap/intpkey.test.lua                 |    4 +-
 test/sql-tap/join.test.lua                    |    2 +-
 test/sql-tap/misc1.test.lua                   |    2 +-
 test/sql-tap/numcast.test.lua                 |    2 +-
 test/sql-tap/select1.test.lua                 |    4 +-
 test/sql/boolean.result                       | 1012 ++++++++---------
 test/sql/integer-overflow.result              |    4 +-
 test/sql/types.result                         |   20 +-
 16 files changed, 567 insertions(+), 574 deletions(-)

diff --git a/src/box/sql/vdbe.c b/src/box/sql/vdbe.c
index e22ed98cf..cf0ae8a06 100644
--- a/src/box/sql/vdbe.c
+++ b/src/box/sql/vdbe.c
@@ -1748,12 +1748,12 @@ case OP_Remainder: {           /* same as TK_REM, in1, in2, out3 */
 	} else {
 		if (sqlVdbeRealValue(pIn1, &rA) != 0) {
 			diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
-				 sql_value_to_diag_str(pIn1), "numeric");
+				 mem_type_to_str(pIn1), "numeric");
 			goto abort_due_to_error;
 		}
 		if (sqlVdbeRealValue(pIn2, &rB) != 0) {
 			diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
-				 sql_value_to_diag_str(pIn2), "numeric");
+				 mem_type_to_str(pIn2), "numeric");
 			goto abort_due_to_error;
 		}
 		assert(((type1 | type2) & MEM_Real) != 0);
@@ -2030,12 +2030,12 @@ case OP_ShiftRight: {           /* same as TK_RSHIFT, in1, in2, out3 */
 	bool unused;
 	if (sqlVdbeIntValue(pIn2, (int64_t *) &iA, &unused) != 0) {
 		diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
-			 sql_value_to_diag_str(pIn2), "integer");
+			 mem_type_to_str(pIn2), "integer");
 		goto abort_due_to_error;
 	}
 	if (sqlVdbeIntValue(pIn1, (int64_t *) &iB, &unused) != 0) {
 		diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
-			 sql_value_to_diag_str(pIn1), "integer");
+			 mem_type_to_str(pIn1), "integer");
 		goto abort_due_to_error;
 	}
 	op = pOp->opcode;
@@ -2100,7 +2100,7 @@ case OP_MustBeInt: {            /* jump, in1 */
 		if ((pIn1->flags & (MEM_Int | MEM_UInt)) == 0) {
 			if (pOp->p2==0) {
 				diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
-					 sql_value_to_diag_str(pIn1), "integer");
+					 mem_type_to_str(pIn1), "integer");
 				goto abort_due_to_error;
 			} else {
 				goto jump_to_p2;
@@ -2157,7 +2157,7 @@ case OP_Cast: {                  /* in1 */
 	UPDATE_MAX_BLOBSIZE(pIn1);
 	if (rc == 0)
 		break;
-	diag_set(ClientError, ER_SQL_TYPE_MISMATCH, sql_value_to_diag_str(pIn1),
+	diag_set(ClientError, ER_SQL_TYPE_MISMATCH, mem_type_to_str(pIn1),
 		 field_type_strs[pOp->p2]);
 	goto abort_due_to_error;
 }
@@ -2320,13 +2320,13 @@ case OP_Ge: {             /* same as TK_GE, jump, in1, in3 */
 		if (sql_type_is_numeric(type)) {
 			if ((flags1 & MEM_Str) == MEM_Str) {
 				diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
-					 sql_value_to_diag_str(pIn1),
+					 mem_type_to_str(pIn1),
 					 "numeric");
 				goto abort_due_to_error;
 			}
 			if ((flags3 & MEM_Str) == MEM_Str) {
 				diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
-					 sql_value_to_diag_str(pIn3),
+					 mem_type_to_str(pIn3),
 					 "numeric");
 				goto abort_due_to_error;
 			}
@@ -2576,7 +2576,7 @@ case OP_Or: {             /* same as TK_OR, in1, in2, out3 */
 		v1 = pIn1->u.b;
 	} else {
 		diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
-			 sql_value_to_diag_str(pIn1), "boolean");
+			 mem_type_to_str(pIn1), "boolean");
 		goto abort_due_to_error;
 	}
 	pIn2 = &aMem[pOp->p2];
@@ -2586,7 +2586,7 @@ case OP_Or: {             /* same as TK_OR, in1, in2, out3 */
 		v2 = pIn2->u.b;
 	} else {
 		diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
-			 sql_value_to_diag_str(pIn2), "boolean");
+			 mem_type_to_str(pIn2), "boolean");
 		goto abort_due_to_error;
 	}
 	if (pOp->opcode==OP_And) {
@@ -2616,7 +2616,7 @@ case OP_Not: {                /* same as TK_NOT, in1, out2 */
 	if ((pIn1->flags & MEM_Null)==0) {
 		if ((pIn1->flags & MEM_Bool) == 0) {
 			diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
-				 sql_value_to_diag_str(pIn1), "boolean");
+				 mem_type_to_str(pIn1), "boolean");
 			goto abort_due_to_error;
 		}
 		mem_set_bool(pOut, ! pIn1->u.b);
@@ -2641,7 +2641,7 @@ case OP_BitNot: {             /* same as TK_BITNOT, in1, out2 */
 		bool is_neg;
 		if (sqlVdbeIntValue(pIn1, &i, &is_neg) != 0) {
 			diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
-				 sql_value_to_diag_str(pIn1), "integer");
+				 mem_type_to_str(pIn1), "integer");
 			goto abort_due_to_error;
 		}
 		mem_set_i64(pOut, ~i);
@@ -2687,7 +2687,7 @@ case OP_IfNot: {            /* jump, in1 */
 		c = pOp->opcode == OP_IfNot ? ! pIn1->u.b : pIn1->u.b;
 	} else {
 		diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
-			 sql_value_to_diag_str(pIn1), "boolean");
+			 mem_type_to_str(pIn1), "boolean");
 		goto abort_due_to_error;
 	}
 	VdbeBranchTaken(c!=0, 2);
@@ -3464,7 +3464,7 @@ case OP_SeekGT: {       /* jump, in3 */
 			is_neg = i < 0;
 		} else {
 			diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
-				 sql_value_to_diag_str(pIn3), "integer");
+				 mem_type_to_str(pIn3), "integer");
 			goto abort_due_to_error;
 		}
 		iKey = i;
diff --git a/test/sql-tap/autoinc.test.lua b/test/sql-tap/autoinc.test.lua
index ec8dfeab1..4fbefa0c1 100755
--- a/test/sql-tap/autoinc.test.lua
+++ b/test/sql-tap/autoinc.test.lua
@@ -811,7 +811,7 @@ test:do_catchsql_test(
         INSERT INTO t1 SELECT s2, s2 FROM t1;
     ]], {
         -- <autoinc-gh-3670>
-        1, "Type mismatch: can not convert a to integer"
+        1, "Type mismatch: can not convert text to integer"
         -- </autoinc-gh-3670>
     })
 
diff --git a/test/sql-tap/cast.test.lua b/test/sql-tap/cast.test.lua
index fb0790d04..cb07c27c8 100755
--- a/test/sql-tap/cast.test.lua
+++ b/test/sql-tap/cast.test.lua
@@ -450,7 +450,7 @@ test:do_catchsql_test(
         SELECT CAST('123abc' AS NUMBER)
     ]], {
         -- <cast-1.45>
-        1, 'Type mismatch: can not convert 123abc to number'
+        1, 'Type mismatch: can not convert text to number'
         -- </cast-1.45>
     })
 
@@ -470,7 +470,7 @@ test:do_catchsql_test(
         SELECT CAST('123abc' AS integer)
     ]], {
         -- <cast-1.49>
-        1, 'Type mismatch: can not convert 123abc to integer'
+        1, 'Type mismatch: can not convert text to integer'
         -- </cast-1.49>
     })
 
@@ -480,7 +480,7 @@ test:do_catchsql_test(
         SELECT CAST('123.5abc' AS NUMBER)
     ]], {
         -- <cast-1.51>
-        1, 'Type mismatch: can not convert 123.5abc to number'
+        1, 'Type mismatch: can not convert text to number'
         -- </cast-1.51>
     })
 
@@ -490,7 +490,7 @@ test:do_catchsql_test(
         SELECT CAST('123.5abc' AS integer)
     ]], {
         -- <cast-1.53>
-        1, 'Type mismatch: can not convert 123.5abc to integer'
+        1, 'Type mismatch: can not convert text to integer'
         -- </cast-1.53>
     })
 
@@ -561,7 +561,7 @@ test:do_catchsql_test(
         SELECT CAST('abc' AS NUMBER)
     ]], {
         -- <case-1.66>
-        1, 'Type mismatch: can not convert abc to number'
+        1, 'Type mismatch: can not convert text to number'
         -- </case-1.66>
     })
 
@@ -829,7 +829,7 @@ test:do_test(
         ]]
     end, {
         -- <cast-4.1>
-        1, 'Type mismatch: can not convert abc to integer'
+        1, 'Type mismatch: can not convert text to integer'
         -- </cast-4.1>
     })
 
@@ -841,7 +841,7 @@ test:do_test(
         ]]
     end, {
         -- <cast-4.2>
-        1, 'Type mismatch: can not convert abc to integer'
+        1, 'Type mismatch: can not convert text to integer'
         -- </cast-4.2>
     })
 
@@ -853,7 +853,7 @@ test:do_test(
         ]]
     end, {
         -- <cast-4.4>
-        1, 'Type mismatch: can not convert abc to number'
+        1, 'Type mismatch: can not convert text to number'
         -- </cast-4.4>
     })
 
diff --git a/test/sql-tap/gh-4230-del-impl-cast-str-to-num.test.lua b/test/sql-tap/gh-4230-del-impl-cast-str-to-num.test.lua
index b405a11b6..cbc771125 100755
--- a/test/sql-tap/gh-4230-del-impl-cast-str-to-num.test.lua
+++ b/test/sql-tap/gh-4230-del-impl-cast-str-to-num.test.lua
@@ -11,7 +11,7 @@ test:do_catchsql_test(
     [[
         SELECT '1' > 0;
     ]], {
-        1, "Type mismatch: can not convert 1 to numeric"
+        1, "Type mismatch: can not convert text to numeric"
     })
 
 test:do_catchsql_test(
@@ -19,7 +19,7 @@ test:do_catchsql_test(
     [[
         SELECT 0 > '1';
     ]], {
-        1, "Type mismatch: can not convert 1 to numeric"
+        1, "Type mismatch: can not convert text to numeric"
     })
 
 test:execsql([[
@@ -32,7 +32,7 @@ test:do_catchsql_test(
     [[
         SELECT * from t where i > s;
     ]], {
-        1, "Type mismatch: can not convert 2 to numeric"
+        1, "Type mismatch: can not convert text to numeric"
     })
 
 test:do_catchsql_test(
@@ -40,7 +40,7 @@ test:do_catchsql_test(
     [[
         SELECT * from t WHERE s > i;
     ]], {
-        1, "Type mismatch: can not convert 2 to numeric"
+        1, "Type mismatch: can not convert text to numeric"
     })
 
 test:do_catchsql_test(
@@ -48,7 +48,7 @@ test:do_catchsql_test(
     [[
         SELECT * from t WHERE d > s;
     ]], {
-        1, "Type mismatch: can not convert 2 to numeric"
+        1, "Type mismatch: can not convert text to numeric"
     })
 
 test:do_catchsql_test(
@@ -56,7 +56,7 @@ test:do_catchsql_test(
     [[
         SELECT * from t WHERE s > d;
     ]], {
-        1, "Type mismatch: can not convert 2 to numeric"
+        1, "Type mismatch: can not convert text to numeric"
     })
 
 test:do_catchsql_test(
@@ -64,7 +64,7 @@ test:do_catchsql_test(
     [[
         SELECT * from t WHERE i = 1 and n > s;
     ]], {
-        1, "Type mismatch: can not convert 2 to numeric"
+        1, "Type mismatch: can not convert text to numeric"
     })
 
 test:do_catchsql_test(
@@ -72,7 +72,7 @@ test:do_catchsql_test(
     [[
         SELECT * from t WHERE i = 2 and s > n;
     ]], {
-        1, "Type mismatch: can not convert 2 to numeric"
+        1, "Type mismatch: can not convert text to numeric"
     })
 
 test:execsql([[
@@ -89,7 +89,7 @@ test:do_catchsql_test(
     [[
         SELECT x FROM t1 WHERE x IN (1);
     ]], {
-        1, "Type mismatch: can not convert 1 to numeric"
+        1, "Type mismatch: can not convert text to numeric"
     })
 
 
@@ -98,7 +98,7 @@ test:do_catchsql_test(
     [[
         SELECT x FROM t1 WHERE x IN (1.0);
     ]], {
-        1, "Type mismatch: can not convert 1 to numeric"
+        1, "Type mismatch: can not convert text to numeric"
     })
 
 test:do_execsql_test(
@@ -121,7 +121,7 @@ test:do_catchsql_test(
     [[
         SELECT x FROM t1 WHERE 1 IN (x);
     ]], {
-        1, "Type mismatch: can not convert 1 to numeric"
+        1, "Type mismatch: can not convert text to numeric"
     })
 
 test:do_catchsql_test(
@@ -129,7 +129,7 @@ test:do_catchsql_test(
     [[
         SELECT x FROM t1 WHERE 1.0 IN (x);
     ]], {
-        1, "Type mismatch: can not convert 1 to numeric"
+        1, "Type mismatch: can not convert text to numeric"
     })
 
 test:do_execsql_test(
diff --git a/test/sql-tap/gh-4766-wrong-cast-from-blob-to-int.test.lua b/test/sql-tap/gh-4766-wrong-cast-from-blob-to-int.test.lua
index 929870d27..aef7330d5 100755
--- a/test/sql-tap/gh-4766-wrong-cast-from-blob-to-int.test.lua
+++ b/test/sql-tap/gh-4766-wrong-cast-from-blob-to-int.test.lua
@@ -32,14 +32,7 @@ test:do_execsql_test(
 test:do_catchsql_test(
     "gh-4766-3",
     "SELECT CAST('" .. long_str .. "1234'" .. " AS INTEGER);", {
-        1, "Type mismatch: can not convert 000000000000000000000000000000000" ..
-        "0000000000000000000000000000000000000000000000000000000000000000000" ..
-        "0000000000000000000000000000000000000000000000000000000000000000000" ..
-        "0000000000000000000000000000000000000000000000000000000000000000000" ..
-        "0000000000000000000000000000000000000000000000000000000000000000000" ..
-        "0000000000000000000000000000000000000000000000000000000000000000000" ..
-        "0000000000000000000000000000000000000000000000000000000000000000000" ..
-        "000000000000000000000000000000000000000000000"
+        1, "Type mismatch: can not convert text to integer"
     })
 
 test:finish_test()
diff --git a/test/sql-tap/identifier_case.test.lua b/test/sql-tap/identifier_case.test.lua
index 1d56ffb44..80d224e9e 100755
--- a/test/sql-tap/identifier_case.test.lua
+++ b/test/sql-tap/identifier_case.test.lua
@@ -242,11 +242,11 @@ data = {
     { 2,  [[ 'a' < 'b' collate "binary" ]], {0, {true}}},
     { 3,  [[ 'a' < 'b' collate 'binary' ]], {1, [[Syntax error at line 1 near ''binary'']]}},
     { 4,  [[ 'a' < 'b' collate "unicode" ]], {0, {true}}},
-    { 5,  [[ 5 < 'b' collate "unicode" ]], {1, "Type mismatch: can not convert b to numeric"}},
+    { 5,  [[ 5 < 'b' collate "unicode" ]], {1, "Type mismatch: can not convert text to numeric"}},
     { 6,  [[ 5 < 'b' collate unicode ]], {1,"Collation 'UNICODE' does not exist"}},
-    { 7,  [[ 5 < 'b' collate "unicode_ci" ]], {1, "Type mismatch: can not convert b to numeric"}},
+    { 7,  [[ 5 < 'b' collate "unicode_ci" ]], {1, "Type mismatch: can not convert text to numeric"}},
     { 8,  [[ 5 < 'b' collate NONE ]], {1, "Collation 'NONE' does not exist"}},
-    { 9,  [[ 5 < 'b' collate "none" ]], {1, "Type mismatch: can not convert b to numeric"}},
+    { 9,  [[ 5 < 'b' collate "none" ]], {1, "Type mismatch: can not convert text to numeric"}},
 }
 
 for _, row in ipairs(data) do
diff --git a/test/sql-tap/in1.test.lua b/test/sql-tap/in1.test.lua
index e2f498889..856e9e009 100755
--- a/test/sql-tap/in1.test.lua
+++ b/test/sql-tap/in1.test.lua
@@ -642,7 +642,7 @@ test:do_test(
         ]]
     end, {
         -- <in-11.2>
-        1, "Type mismatch: can not convert 2 to numeric"
+        1, "Type mismatch: can not convert text to numeric"
         -- </in-11.2>
     })
 
diff --git a/test/sql-tap/index1.test.lua b/test/sql-tap/index1.test.lua
index ce66b7c1e..31c276318 100755
--- a/test/sql-tap/index1.test.lua
+++ b/test/sql-tap/index1.test.lua
@@ -777,7 +777,7 @@ test:do_catchsql_test(
         SELECT c FROM t6 WHERE a>123;
     ]], {
         -- <index-14.6>
-        1, "Type mismatch: can not convert  to numeric"
+        1, "Type mismatch: can not convert text to numeric"
         -- </index-14.6>
     })
 
@@ -787,7 +787,7 @@ test:do_catchsql_test(
         SELECT c FROM t6 WHERE a>=123;
     ]], {
         -- <index-14.7>
-        1, "Type mismatch: can not convert  to numeric"
+        1, "Type mismatch: can not convert text to numeric"
         -- </index-14.7>
     })
 
diff --git a/test/sql-tap/intpkey.test.lua b/test/sql-tap/intpkey.test.lua
index bc3d701a7..3fd65da5a 100755
--- a/test/sql-tap/intpkey.test.lua
+++ b/test/sql-tap/intpkey.test.lua
@@ -870,7 +870,7 @@ test:do_catchsql_test(
         SELECT * FROM t3 WHERE a<c;
     ]], {
         -- <intpkey-14.5>
-        1, "Type mismatch: can not convert one to numeric"
+        1, "Type mismatch: can not convert text to numeric"
         -- </intpkey-14.5>
     })
 
@@ -880,7 +880,7 @@ test:do_catchsql_test(
         SELECT * FROM t3 WHERE a=c;
     ]], {
         -- <intpkey-14.6>
-        1, "Type mismatch: can not convert one to numeric"
+        1, "Type mismatch: can not convert text to numeric"
         -- </intpkey-14.6>
     })
 
diff --git a/test/sql-tap/join.test.lua b/test/sql-tap/join.test.lua
index 792302ab5..f0875e28d 100755
--- a/test/sql-tap/join.test.lua
+++ b/test/sql-tap/join.test.lua
@@ -1044,7 +1044,7 @@ test:do_catchsql_test(
         SELECT * FROM t2 NATURAL JOIN t1 
     ]], {
         -- <join-11.10>
-        1, "Type mismatch: can not convert 1 to numeric"
+        1, "Type mismatch: can not convert text to numeric"
         -- </join-11.10>
     })
 
diff --git a/test/sql-tap/misc1.test.lua b/test/sql-tap/misc1.test.lua
index 3cef617f4..2038edc82 100755
--- a/test/sql-tap/misc1.test.lua
+++ b/test/sql-tap/misc1.test.lua
@@ -625,7 +625,7 @@ test:do_catchsql_test(
         SELECT '0'==0.0
     ]], {
         -- <misc1-12.2>
-        1, "Type mismatch: can not convert 0 to numeric"
+        1, "Type mismatch: can not convert text to numeric"
         -- </misc1-12.2>
     })
 
diff --git a/test/sql-tap/numcast.test.lua b/test/sql-tap/numcast.test.lua
index 9bbae5ca4..d8bf6cca3 100755
--- a/test/sql-tap/numcast.test.lua
+++ b/test/sql-tap/numcast.test.lua
@@ -107,7 +107,7 @@ test:do_catchsql_test(
     [[
         SELECT CAST((20000000000000000000.) AS UNSIGNED);
     ]], {
-        1,"Type mismatch: can not convert 2.0e+19 to unsigned"
+        1,"Type mismatch: can not convert real to unsigned"
     })
 
 test:do_execsql_test(
diff --git a/test/sql-tap/select1.test.lua b/test/sql-tap/select1.test.lua
index f5a9b63fe..42cdad366 100755
--- a/test/sql-tap/select1.test.lua
+++ b/test/sql-tap/select1.test.lua
@@ -320,7 +320,7 @@ test:do_catchsql_test(
         SELECT count(*),count(a),count(b) FROM t4 WHERE b=5
     ]], {
         -- <select1-2.5.3>
-        1, "Type mismatch: can not convert This is a string that is too big to fit inside a NBFS buffer to numeric"
+        1, "Type mismatch: can not convert text to numeric"
         -- </select1-2.5.3>
     })
 
@@ -1483,7 +1483,7 @@ test:do_catchsql_test(
         SELECT f1 FROM test1 WHERE 4.3+2.4 OR 1 ORDER BY f1
     ]], {
         -- <select1-8.1>
-        1, 'Type mismatch: can not convert 6.7 to boolean'
+        1, 'Type mismatch: can not convert real to boolean'
         -- </select1-8.1>
     })
 
diff --git a/test/sql/boolean.result b/test/sql/boolean.result
index c74713c34..76439c7f4 100644
--- a/test/sql/boolean.result
+++ b/test/sql/boolean.result
@@ -1120,438 +1120,438 @@ SELECT a, a1, a OR a1 FROM t, t6;
 SELECT -true;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT -false;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT -a FROM t;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 
 SELECT true + true;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT true + false;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT false + true;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT false + false;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT true - true;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT true - false;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT false - true;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT false - false;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT true * true;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT true * false;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT false * true;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT false * false;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT true / true;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT true / false;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT false / true;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT false / false;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT true % true;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT true % false;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT false % true;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT false % false;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 
 SELECT a, true + a FROM t;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a, false + a FROM t;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a, true - a FROM t;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a, false - a FROM t;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a, true * a FROM t;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a, false * a FROM t;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a, true / a FROM t;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a, false / a FROM t;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a, true % a FROM t;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a, false % a FROM t;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a, a + true FROM t;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a, a + false FROM t;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a, a - true FROM t;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a, a - false FROM t;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a, a * true FROM t;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a, a * false FROM t;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a, a / true FROM t;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a, a / false FROM t;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a, a % true FROM t;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a, a % false FROM t;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 
 SELECT a, a1, a + a1 FROM t, t6;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a, a1, a - a1 FROM t, t6;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a, a1, a * a1 FROM t, t6;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a, a1, a / a1 FROM t, t6;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a, a1, a % a1 FROM t, t6;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 
 SELECT ~true;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT ~false;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT true & true;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT true & false;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT false & true;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT false & false;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT true | true;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT true | false;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT false | true;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT false | false;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT true << true;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT true << false;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT false << true;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT false << false;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT true >> true;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT true >> false;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT false >> true;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT false >> false;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 
 SELECT a, true & a FROM t;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT a, false & a FROM t;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT a, true | a FROM t;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT a, false | a FROM t;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT a, true << a FROM t;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT a, false << a FROM t;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT a, true >> a FROM t;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT a, false >> a FROM t;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT a, a & true FROM t;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT a, a & false FROM t;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT a, a | true FROM t;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT a, a | false FROM t;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT a, a << true FROM t;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT a, a << false FROM t;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT a, a >> true FROM t;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT a, a >> false FROM t;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 
 SELECT a, a1, a & a1 FROM t, t6;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT a, a1, a | a1 FROM t, t6;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT a, a1, a << a1 FROM t, t6;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT a, a1, a >> a1 FROM t, t6;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 
 -- Check concatenate.
@@ -2461,7 +2461,7 @@ INSERT INTO t7 VALUES (123);
 SELECT true AND 2;
  | ---
  | - null
- | - 'Type mismatch: can not convert 2 to boolean'
+ | - 'Type mismatch: can not convert unsigned to boolean'
  | ...
 SELECT false AND 2;
  | ---
@@ -2474,17 +2474,17 @@ SELECT false AND 2;
 SELECT true OR 2;
  | ---
  | - null
- | - 'Type mismatch: can not convert 2 to boolean'
+ | - 'Type mismatch: can not convert unsigned to boolean'
  | ...
 SELECT false OR 2;
  | ---
  | - null
- | - 'Type mismatch: can not convert 2 to boolean'
+ | - 'Type mismatch: can not convert unsigned to boolean'
  | ...
 SELECT 2 AND true;
  | ---
  | - null
- | - 'Type mismatch: can not convert 2 to boolean'
+ | - 'Type mismatch: can not convert unsigned to boolean'
  | ...
 SELECT 2 AND false;
  | ---
@@ -2497,59 +2497,59 @@ SELECT 2 AND false;
 SELECT 2 OR true;
  | ---
  | - null
- | - 'Type mismatch: can not convert 2 to boolean'
+ | - 'Type mismatch: can not convert unsigned to boolean'
  | ...
 SELECT 2 OR false;
  | ---
  | - null
- | - 'Type mismatch: can not convert 2 to boolean'
+ | - 'Type mismatch: can not convert unsigned to boolean'
  | ...
 
 SELECT a1, a1 AND 2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert 2 to boolean'
+ | - 'Type mismatch: can not convert unsigned to boolean'
  | ...
 SELECT a1, a1 OR 2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert 2 to boolean'
+ | - 'Type mismatch: can not convert unsigned to boolean'
  | ...
 SELECT a1, 2 AND a1 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert 2 to boolean'
+ | - 'Type mismatch: can not convert unsigned to boolean'
  | ...
 SELECT a1, 2 OR a1 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert 2 to boolean'
+ | - 'Type mismatch: can not convert unsigned to boolean'
  | ...
 SELECT a2, a2 AND 2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert 2 to boolean'
+ | - 'Type mismatch: can not convert unsigned to boolean'
  | ...
 SELECT a2, a2 OR 2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert 2 to boolean'
+ | - 'Type mismatch: can not convert unsigned to boolean'
  | ...
 SELECT a2, 2 AND a2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert 2 to boolean'
+ | - 'Type mismatch: can not convert unsigned to boolean'
  | ...
 SELECT a2, 2 OR a2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert 2 to boolean'
+ | - 'Type mismatch: can not convert unsigned to boolean'
  | ...
 
 SELECT b, true AND b FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert 123 to boolean'
+ | - 'Type mismatch: can not convert unsigned to boolean'
  | ...
 SELECT b, false AND b FROM t7;
  | ---
@@ -2564,17 +2564,17 @@ SELECT b, false AND b FROM t7;
 SELECT b, true OR b FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert 123 to boolean'
+ | - 'Type mismatch: can not convert unsigned to boolean'
  | ...
 SELECT b, false OR b FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert 123 to boolean'
+ | - 'Type mismatch: can not convert unsigned to boolean'
  | ...
 SELECT b, b AND true FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert 123 to boolean'
+ | - 'Type mismatch: can not convert unsigned to boolean'
  | ...
 SELECT b, b AND false FROM t7;
  | ---
@@ -2589,781 +2589,781 @@ SELECT b, b AND false FROM t7;
 SELECT b, b OR true FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert 123 to boolean'
+ | - 'Type mismatch: can not convert unsigned to boolean'
  | ...
 SELECT b, b OR false FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert 123 to boolean'
+ | - 'Type mismatch: can not convert unsigned to boolean'
  | ...
 
 SELECT a1, b, a1 AND b FROM t6, t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert 123 to boolean'
+ | - 'Type mismatch: can not convert unsigned to boolean'
  | ...
 SELECT a1, b, a1 OR b FROM t6, t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert 123 to boolean'
+ | - 'Type mismatch: can not convert unsigned to boolean'
  | ...
 SELECT a1, b, b AND a1 FROM t6, t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert 123 to boolean'
+ | - 'Type mismatch: can not convert unsigned to boolean'
  | ...
 SELECT a1, b, b OR a1 FROM t6, t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert 123 to boolean'
+ | - 'Type mismatch: can not convert unsigned to boolean'
  | ...
 SELECT a2, b, a2 AND b FROM t6, t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert 123 to boolean'
+ | - 'Type mismatch: can not convert unsigned to boolean'
  | ...
 SELECT a2, b, a2 OR b FROM t6, t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert 123 to boolean'
+ | - 'Type mismatch: can not convert unsigned to boolean'
  | ...
 SELECT a2, b, b AND a2 FROM t6, t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert 123 to boolean'
+ | - 'Type mismatch: can not convert unsigned to boolean'
  | ...
 SELECT a2, b, b OR a2 FROM t6, t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert 123 to boolean'
+ | - 'Type mismatch: can not convert unsigned to boolean'
  | ...
 
 SELECT true + 2;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT false + 2;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT true - 2;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT false - 2;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT true * 2;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT false * 2;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT true / 2;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT false / 2;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT true % 2;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT false % 2;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT 2 + true;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT 2 + false;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT 2 - true;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT 2 - false;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT 2 * true;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT 2 * false;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT 2 / true;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT 2 / false;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT 2 % true;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT 2 % false;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 
 SELECT a1, a1 + 2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a1, a1 - 2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a1, a1 * 2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a1, a1 / 2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a1, a1 % 2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a1, 2 + a1 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a1, 2 - a1 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a1, 2 * a1 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a1, 2 / a1 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a1, 2 % a1 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a2, a2 + 2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a2, a2 - 2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a2, a2 * 2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a2, a2 / 2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a2, a2 % 2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a2, 2 + a2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a2, 2 - a2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a2, 2 * a2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a2, 2 / a2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a2, 2 % a2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 
 SELECT b, true + b FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT b, false + b FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT b, true - b FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT b, false - b FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT b, true * b FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT b, false * b FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT b, true / b FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT b, false / b FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT b, true % b FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT b, false % b FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT b, b + true FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT b, b + false FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT b, b - true FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT b, b - false FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT b, b * true FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT b, b * false FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT b, b / true FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT b, b / false FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT b, b % true FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT b, b % false FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 
 SELECT a1, b, a1 + b FROM t6, t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a1, b, a1 - b FROM t6, t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a1, b, a1 * b FROM t6, t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a1, b, a1 / b FROM t6, t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a1, b, a1 % b FROM t6, t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a1, b, b + a1 FROM t6, t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a1, b, b - a1 FROM t6, t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a1, b, b * a1 FROM t6, t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a1, b, b / a1 FROM t6, t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a1, b, b % a1 FROM t6, t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a2, b, a2 + b FROM t6, t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a2, b, a2 - b FROM t6, t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a2, b, a2 * b FROM t6, t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a2, b, a2 / b FROM t6, t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a2, b, a2 % b FROM t6, t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a2, b, b + a2 FROM t6, t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a2, b, b - a2 FROM t6, t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a2, b, b * a2 FROM t6, t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a2, b, b / a2 FROM t6, t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a2, b, b % a2 FROM t6, t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 
 SELECT true & 2;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT false & 2;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT true | 2;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT false | 2;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT true << 2;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT false << 2;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT true >> 2;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT false >> 2;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT 2 & true;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT 2 & false;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT 2 | true;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT 2 | false;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT 2 << true;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT 2 << false;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT 2 >> true;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT 2 >> false;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 
 SELECT a1, a1 & 2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT a1, a1 | 2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT a1, a1 << 2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT a1, a1 >> 2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT a1, 2 & a1 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT a1, 2 | a1 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT a1, 2 << a1 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT a1, 2 >> a1 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT a2, a2 & 2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT a2, a2 | 2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT a2, a2 << 2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT a2, a2 >> 2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT a2, 2 & a2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT a2, 2 | a2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT a2, 2 << a2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT a2, 2 >> a2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 
 SELECT b, true & b FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT b, false & b FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT b, true | b FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT b, false | b FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT b, true << b FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT b, false << b FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT b, true >> b FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT b, false >> b FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT b, b & true FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT b, b & false FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT b, b | true FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT b, b | false FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT b, b << true FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT b, b << false FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT b, b >> true FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT b, b >> false FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 
 SELECT a1, b, a1 & b FROM t6, t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT a1, b, a1 | b FROM t6, t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT a1, b, a1 << b FROM t6, t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT a1, b, a1 >> b FROM t6, t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT a1, b, b & a1 FROM t6, t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT a1, b, b | a1 FROM t6, t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT a1, b, b << a1 FROM t6, t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT a1, b, b >> a1 FROM t6, t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT a2, b, a2 & b FROM t6, t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT a2, b, a2 | b FROM t6, t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT a2, b, a2 << b FROM t6, t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT a2, b, a2 >> b FROM t6, t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT a2, b, b & a2 FROM t6, t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT a2, b, b | a2 FROM t6, t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT a2, b, b << a2 FROM t6, t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 SELECT a2, b, b >> a2 FROM t6, t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 
 SELECT true > 2;
@@ -3930,7 +3930,7 @@ INSERT INTO t8 VALUES (4.56);
 SELECT true AND 2.3;
  | ---
  | - null
- | - 'Type mismatch: can not convert 2.3 to boolean'
+ | - 'Type mismatch: can not convert real to boolean'
  | ...
 SELECT false AND 2.3;
  | ---
@@ -3943,17 +3943,17 @@ SELECT false AND 2.3;
 SELECT true OR 2.3;
  | ---
  | - null
- | - 'Type mismatch: can not convert 2.3 to boolean'
+ | - 'Type mismatch: can not convert real to boolean'
  | ...
 SELECT false OR 2.3;
  | ---
  | - null
- | - 'Type mismatch: can not convert 2.3 to boolean'
+ | - 'Type mismatch: can not convert real to boolean'
  | ...
 SELECT 2.3 AND true;
  | ---
  | - null
- | - 'Type mismatch: can not convert 2.3 to boolean'
+ | - 'Type mismatch: can not convert real to boolean'
  | ...
 SELECT 2.3 AND false;
  | ---
@@ -3966,59 +3966,59 @@ SELECT 2.3 AND false;
 SELECT 2.3 OR true;
  | ---
  | - null
- | - 'Type mismatch: can not convert 2.3 to boolean'
+ | - 'Type mismatch: can not convert real to boolean'
  | ...
 SELECT 2.3 OR false;
  | ---
  | - null
- | - 'Type mismatch: can not convert 2.3 to boolean'
+ | - 'Type mismatch: can not convert real to boolean'
  | ...
 
 SELECT a1, a1 AND 2.3 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert 2.3 to boolean'
+ | - 'Type mismatch: can not convert real to boolean'
  | ...
 SELECT a1, a1 OR 2.3 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert 2.3 to boolean'
+ | - 'Type mismatch: can not convert real to boolean'
  | ...
 SELECT a1, 2.3 AND a1 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert 2.3 to boolean'
+ | - 'Type mismatch: can not convert real to boolean'
  | ...
 SELECT a1, 2.3 OR a1 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert 2.3 to boolean'
+ | - 'Type mismatch: can not convert real to boolean'
  | ...
 SELECT a2, a2 AND 2.3 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert 2.3 to boolean'
+ | - 'Type mismatch: can not convert real to boolean'
  | ...
 SELECT a2, a2 OR 2.3 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert 2.3 to boolean'
+ | - 'Type mismatch: can not convert real to boolean'
  | ...
 SELECT a2, 2.3 AND a2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert 2.3 to boolean'
+ | - 'Type mismatch: can not convert real to boolean'
  | ...
 SELECT a2, 2.3 OR a2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert 2.3 to boolean'
+ | - 'Type mismatch: can not convert real to boolean'
  | ...
 
 SELECT c, true AND c FROM t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert 4.56 to boolean'
+ | - 'Type mismatch: can not convert real to boolean'
  | ...
 SELECT c, false AND c FROM t8;
  | ---
@@ -4033,17 +4033,17 @@ SELECT c, false AND c FROM t8;
 SELECT c, true OR c FROM t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert 4.56 to boolean'
+ | - 'Type mismatch: can not convert real to boolean'
  | ...
 SELECT c, false OR c FROM t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert 4.56 to boolean'
+ | - 'Type mismatch: can not convert real to boolean'
  | ...
 SELECT c, c AND true FROM t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert 4.56 to boolean'
+ | - 'Type mismatch: can not convert real to boolean'
  | ...
 SELECT c, c AND false FROM t8;
  | ---
@@ -4058,457 +4058,457 @@ SELECT c, c AND false FROM t8;
 SELECT c, c OR true FROM t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert 4.56 to boolean'
+ | - 'Type mismatch: can not convert real to boolean'
  | ...
 SELECT c, c OR false FROM t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert 4.56 to boolean'
+ | - 'Type mismatch: can not convert real to boolean'
  | ...
 
 SELECT a1, c, a1 AND c FROM t6, t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert 4.56 to boolean'
+ | - 'Type mismatch: can not convert real to boolean'
  | ...
 SELECT a1, c, a1 OR c FROM t6, t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert 4.56 to boolean'
+ | - 'Type mismatch: can not convert real to boolean'
  | ...
 SELECT a1, c, c AND a1 FROM t6, t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert 4.56 to boolean'
+ | - 'Type mismatch: can not convert real to boolean'
  | ...
 SELECT a1, c, c OR a1 FROM t6, t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert 4.56 to boolean'
+ | - 'Type mismatch: can not convert real to boolean'
  | ...
 SELECT a2, c, a2 AND c FROM t6, t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert 4.56 to boolean'
+ | - 'Type mismatch: can not convert real to boolean'
  | ...
 SELECT a2, c, a2 OR c FROM t6, t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert 4.56 to boolean'
+ | - 'Type mismatch: can not convert real to boolean'
  | ...
 SELECT a2, c, c AND a2 FROM t6, t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert 4.56 to boolean'
+ | - 'Type mismatch: can not convert real to boolean'
  | ...
 SELECT a2, c, c OR a2 FROM t6, t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert 4.56 to boolean'
+ | - 'Type mismatch: can not convert real to boolean'
  | ...
 
 SELECT true + 2.3;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT false + 2.3;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT true - 2.3;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT false - 2.3;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT true * 2.3;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT false * 2.3;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT true / 2.3;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT false / 2.3;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT true % 2.3;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT false % 2.3;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT 2.3 + true;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT 2.3 + false;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT 2.3 - true;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT 2.3 - false;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT 2.3 * true;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT 2.3 * false;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT 2.3 / true;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT 2.3 / false;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT 2.3 % true;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT 2.3 % false;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 
 SELECT a1, a1 + 2.3 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a1, a1 - 2.3 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a1, a1 * 2.3 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a1, a1 / 2.3 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a1, a1 % 2.3 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a1, 2.3 + a1 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a1, 2.3 - a1 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a1, 2.3 * a1 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a1, 2.3 / a1 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a1, 2.3 % a1 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a2, a2 + 2.3 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a2, a2 - 2.3 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a2, a2 * 2.3 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a2, a2 / 2.3 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a2, a2 % 2.3 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a2, 2.3 + a2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a2, 2.3 - a2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a2, 2.3 * a2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a2, 2.3 / a2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a2, 2.3 % a2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 
 SELECT c, true + c FROM t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT c, false + c FROM t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT c, true - c FROM t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT c, false - c FROM t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT c, true * c FROM t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT c, false * c FROM t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT c, true / c FROM t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT c, false / c FROM t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT c, true % c FROM t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT c, false % c FROM t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT c, c + true FROM t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT c, c + false FROM t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT c, c - true FROM t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT c, c - false FROM t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT c, c * true FROM t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT c, c * false FROM t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT c, c / true FROM t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT c, c / false FROM t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT c, c % true FROM t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT c, c % false FROM t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 
 SELECT a1, c, a1 + c FROM t6, t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a1, c, a1 - c FROM t6, t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a1, c, a1 * c FROM t6, t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a1, c, a1 / c FROM t6, t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a1, c, a1 % c FROM t6, t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a1, c, c + a1 FROM t6, t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a1, c, c - a1 FROM t6, t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a1, c, c * a1 FROM t6, t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a1, c, c / a1 FROM t6, t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a1, c, c % a1 FROM t6, t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a2, c, a2 + c FROM t6, t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a2, c, a2 - c FROM t6, t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a2, c, a2 * c FROM t6, t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a2, c, a2 / c FROM t6, t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a2, c, a2 % c FROM t6, t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a2, c, c + a2 FROM t6, t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a2, c, c - a2 FROM t6, t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a2, c, c * a2 FROM t6, t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a2, c, c / a2 FROM t6, t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 SELECT a2, c, c % a2 FROM t6, t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert boolean to numeric'
  | ...
 
 SELECT true > 2.3;
@@ -5090,7 +5090,7 @@ INSERT INTO t9 VALUES ('AsdF');
 SELECT true AND 'abc';
  | ---
  | - null
- | - 'Type mismatch: can not convert abc to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT false AND 'abc';
  | ---
@@ -5103,17 +5103,17 @@ SELECT false AND 'abc';
 SELECT true OR 'abc';
  | ---
  | - null
- | - 'Type mismatch: can not convert abc to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT false OR 'abc';
  | ---
  | - null
- | - 'Type mismatch: can not convert abc to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT 'abc' AND true;
  | ---
  | - null
- | - 'Type mismatch: can not convert abc to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT 'abc' AND false;
  | ---
@@ -5126,59 +5126,59 @@ SELECT 'abc' AND false;
 SELECT 'abc' OR true;
  | ---
  | - null
- | - 'Type mismatch: can not convert abc to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT 'abc' OR false;
  | ---
  | - null
- | - 'Type mismatch: can not convert abc to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 
 SELECT a1, a1 AND 'abc' FROM t6;
  | ---
  | - null
- | - 'Type mismatch: can not convert abc to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT a1, a1 OR 'abc' FROM t6;
  | ---
  | - null
- | - 'Type mismatch: can not convert abc to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT a1, 'abc' AND a1 FROM t6;
  | ---
  | - null
- | - 'Type mismatch: can not convert abc to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT a1, 'abc' OR a1 FROM t6;
  | ---
  | - null
- | - 'Type mismatch: can not convert abc to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT a2, a2 AND 'abc' FROM t6;
  | ---
  | - null
- | - 'Type mismatch: can not convert abc to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT a2, a2 OR 'abc' FROM t6;
  | ---
  | - null
- | - 'Type mismatch: can not convert abc to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT a2, 'abc' AND a2 FROM t6;
  | ---
  | - null
- | - 'Type mismatch: can not convert abc to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT a2, 'abc' OR a2 FROM t6;
  | ---
  | - null
- | - 'Type mismatch: can not convert abc to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 
 SELECT d, true AND d FROM t9;
  | ---
  | - null
- | - 'Type mismatch: can not convert AsdF to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT d, false AND d FROM t9;
  | ---
@@ -5193,17 +5193,17 @@ SELECT d, false AND d FROM t9;
 SELECT d, true OR d FROM t9;
  | ---
  | - null
- | - 'Type mismatch: can not convert AsdF to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT d, false OR d FROM t9;
  | ---
  | - null
- | - 'Type mismatch: can not convert AsdF to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT d, d AND true FROM t9;
  | ---
  | - null
- | - 'Type mismatch: can not convert AsdF to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT d, d AND false FROM t9;
  | ---
@@ -5218,53 +5218,53 @@ SELECT d, d AND false FROM t9;
 SELECT d, d OR true FROM t9;
  | ---
  | - null
- | - 'Type mismatch: can not convert AsdF to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT d, d OR false FROM t9;
  | ---
  | - null
- | - 'Type mismatch: can not convert AsdF to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 
 SELECT a1, d, a1 AND d FROM t6, t9;
  | ---
  | - null
- | - 'Type mismatch: can not convert AsdF to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT a1, d, a1 OR d FROM t6, t9;
  | ---
  | - null
- | - 'Type mismatch: can not convert AsdF to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT a1, d, d AND a1 FROM t6, t9;
  | ---
  | - null
- | - 'Type mismatch: can not convert AsdF to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT a1, d, d OR a1 FROM t6, t9;
  | ---
  | - null
- | - 'Type mismatch: can not convert AsdF to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT a2, d, a2 AND d FROM t6, t9;
  | ---
  | - null
- | - 'Type mismatch: can not convert AsdF to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT a2, d, a2 OR d FROM t6, t9;
  | ---
  | - null
- | - 'Type mismatch: can not convert AsdF to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT a2, d, d AND a2 FROM t6, t9;
  | ---
  | - null
- | - 'Type mismatch: can not convert AsdF to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT a2, d, d OR a2 FROM t6, t9;
  | ---
  | - null
- | - 'Type mismatch: can not convert AsdF to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 
 SELECT true > 'abc';
@@ -5465,7 +5465,7 @@ INSERT INTO t9 VALUES ('TRUE'), ('true'), ('FALSE'), ('false');
 SELECT true AND 'TRUE';
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT false AND 'TRUE';
  | ---
@@ -5478,17 +5478,17 @@ SELECT false AND 'TRUE';
 SELECT true OR 'TRUE';
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT false OR 'TRUE';
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT 'TRUE' AND true;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT 'TRUE' AND false;
  | ---
@@ -5501,59 +5501,59 @@ SELECT 'TRUE' AND false;
 SELECT 'TRUE' OR true;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT 'TRUE' OR false;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 
 SELECT a1, a1 AND 'TRUE' FROM t6;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT a1, a1 OR 'TRUE' FROM t6;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT a1, 'TRUE' AND a1 FROM t6;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT a1, 'TRUE' OR a1 FROM t6;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT a2, a2 AND 'TRUE' FROM t6;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT a2, a2 OR 'TRUE' FROM t6;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT a2, 'TRUE' AND a2 FROM t6;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT a2, 'TRUE' OR a2 FROM t6;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 
 SELECT d, true AND d FROM t9 WHERE d = 'TRUE';
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT d, false AND d FROM t9 WHERE d = 'TRUE';
  | ---
@@ -5568,17 +5568,17 @@ SELECT d, false AND d FROM t9 WHERE d = 'TRUE';
 SELECT d, true OR d FROM t9 WHERE d = 'TRUE';
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT d, false OR d FROM t9 WHERE d = 'TRUE';
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT d, d AND true FROM t9 WHERE d = 'TRUE';
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT d, d AND false FROM t9 WHERE d = 'TRUE';
  | ---
@@ -5593,59 +5593,59 @@ SELECT d, d AND false FROM t9 WHERE d = 'TRUE';
 SELECT d, d OR true FROM t9 WHERE d = 'TRUE';
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT d, d OR false FROM t9 WHERE d = 'TRUE';
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 
 SELECT a1, d, a1 AND d FROM t6, t9 WHERE d = 'TRUE';
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT a1, d, a1 OR d FROM t6, t9 WHERE d = 'TRUE';
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT a1, d, d AND a1 FROM t6, t9 WHERE d = 'TRUE';
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT a1, d, d OR a1 FROM t6, t9 WHERE d = 'TRUE';
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT a2, d, a2 AND d FROM t6, t9 WHERE d = 'TRUE';
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT a2, d, a2 OR d FROM t6, t9 WHERE d = 'TRUE';
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT a2, d, d AND a2 FROM t6, t9 WHERE d = 'TRUE';
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT a2, d, d OR a2 FROM t6, t9 WHERE d = 'TRUE';
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 
 SELECT true AND 'true';
  | ---
  | - null
- | - 'Type mismatch: can not convert true to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT false AND 'true';
  | ---
@@ -5658,17 +5658,17 @@ SELECT false AND 'true';
 SELECT true OR 'true';
  | ---
  | - null
- | - 'Type mismatch: can not convert true to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT false OR 'true';
  | ---
  | - null
- | - 'Type mismatch: can not convert true to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT 'true' AND true;
  | ---
  | - null
- | - 'Type mismatch: can not convert true to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT 'true' AND false;
  | ---
@@ -5681,59 +5681,59 @@ SELECT 'true' AND false;
 SELECT 'true' OR true;
  | ---
  | - null
- | - 'Type mismatch: can not convert true to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT 'true' OR false;
  | ---
  | - null
- | - 'Type mismatch: can not convert true to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 
 SELECT a1, a1 AND 'true' FROM t6;
  | ---
  | - null
- | - 'Type mismatch: can not convert true to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT a1, a1 OR 'true' FROM t6;
  | ---
  | - null
- | - 'Type mismatch: can not convert true to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT a1, 'true' AND a1 FROM t6;
  | ---
  | - null
- | - 'Type mismatch: can not convert true to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT a1, 'true' OR a1 FROM t6;
  | ---
  | - null
- | - 'Type mismatch: can not convert true to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT a2, a2 AND 'true' FROM t6;
  | ---
  | - null
- | - 'Type mismatch: can not convert true to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT a2, a2 OR 'true' FROM t6;
  | ---
  | - null
- | - 'Type mismatch: can not convert true to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT a2, 'true' AND a2 FROM t6;
  | ---
  | - null
- | - 'Type mismatch: can not convert true to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT a2, 'true' OR a2 FROM t6;
  | ---
  | - null
- | - 'Type mismatch: can not convert true to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 
 SELECT d, true AND d FROM t9 WHERE d = 'true';
  | ---
  | - null
- | - 'Type mismatch: can not convert true to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT d, false AND d FROM t9 WHERE d = 'true';
  | ---
@@ -5748,17 +5748,17 @@ SELECT d, false AND d FROM t9 WHERE d = 'true';
 SELECT d, true OR d FROM t9 WHERE d = 'true';
  | ---
  | - null
- | - 'Type mismatch: can not convert true to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT d, false OR d FROM t9 WHERE d = 'true';
  | ---
  | - null
- | - 'Type mismatch: can not convert true to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT d, d AND true FROM t9 WHERE d = 'true';
  | ---
  | - null
- | - 'Type mismatch: can not convert true to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT d, d AND false FROM t9 WHERE d = 'true';
  | ---
@@ -5773,59 +5773,59 @@ SELECT d, d AND false FROM t9 WHERE d = 'true';
 SELECT d, d OR true FROM t9 WHERE d = 'true';
  | ---
  | - null
- | - 'Type mismatch: can not convert true to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT d, d OR false FROM t9 WHERE d = 'true';
  | ---
  | - null
- | - 'Type mismatch: can not convert true to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 
 SELECT a1, d, a1 AND d FROM t6, t9 WHERE d = 'true';
  | ---
  | - null
- | - 'Type mismatch: can not convert true to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT a1, d, a1 OR d FROM t6, t9 WHERE d = 'true';
  | ---
  | - null
- | - 'Type mismatch: can not convert true to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT a1, d, d AND a1 FROM t6, t9 WHERE d = 'true';
  | ---
  | - null
- | - 'Type mismatch: can not convert true to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT a1, d, d OR a1 FROM t6, t9 WHERE d = 'true';
  | ---
  | - null
- | - 'Type mismatch: can not convert true to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT a2, d, a2 AND d FROM t6, t9 WHERE d = 'true';
  | ---
  | - null
- | - 'Type mismatch: can not convert true to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT a2, d, a2 OR d FROM t6, t9 WHERE d = 'true';
  | ---
  | - null
- | - 'Type mismatch: can not convert true to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT a2, d, d AND a2 FROM t6, t9 WHERE d = 'true';
  | ---
  | - null
- | - 'Type mismatch: can not convert true to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT a2, d, d OR a2 FROM t6, t9 WHERE d = 'true';
  | ---
  | - null
- | - 'Type mismatch: can not convert true to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 
 SELECT true AND 'FALSE';
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT false AND 'FALSE';
  | ---
@@ -5838,17 +5838,17 @@ SELECT false AND 'FALSE';
 SELECT true OR 'FALSE';
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT false OR 'FALSE';
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT 'FALSE' AND true;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT 'FALSE' AND false;
  | ---
@@ -5861,59 +5861,59 @@ SELECT 'FALSE' AND false;
 SELECT 'FALSE' OR true;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT 'FALSE' OR false;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 
 SELECT a1, a1 AND 'FALSE' FROM t6;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT a1, a1 OR 'FALSE' FROM t6;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT a1, 'FALSE' AND a1 FROM t6;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT a1, 'FALSE' OR a1 FROM t6;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT a2, a2 AND 'FALSE' FROM t6;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT a2, a2 OR 'FALSE' FROM t6;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT a2, 'FALSE' AND a2 FROM t6;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT a2, 'FALSE' OR a2 FROM t6;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 
 SELECT d, true AND d FROM t9 WHERE d = 'FALSE';
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT d, false AND d FROM t9 WHERE d = 'FALSE';
  | ---
@@ -5928,17 +5928,17 @@ SELECT d, false AND d FROM t9 WHERE d = 'FALSE';
 SELECT d, true OR d FROM t9 WHERE d = 'FALSE';
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT d, false OR d FROM t9 WHERE d = 'FALSE';
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT d, d AND true FROM t9 WHERE d = 'FALSE';
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT d, d AND false FROM t9 WHERE d = 'FALSE';
  | ---
@@ -5953,59 +5953,59 @@ SELECT d, d AND false FROM t9 WHERE d = 'FALSE';
 SELECT d, d OR true FROM t9 WHERE d = 'FALSE';
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT d, d OR false FROM t9 WHERE d = 'FALSE';
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 
 SELECT a1, d, a1 AND d FROM t6, t9 WHERE d = 'FALSE';
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT a1, d, a1 OR d FROM t6, t9 WHERE d = 'FALSE';
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT a1, d, d AND a1 FROM t6, t9 WHERE d = 'FALSE';
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT a1, d, d OR a1 FROM t6, t9 WHERE d = 'FALSE';
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT a2, d, a2 AND d FROM t6, t9 WHERE d = 'FALSE';
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT a2, d, a2 OR d FROM t6, t9 WHERE d = 'FALSE';
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT a2, d, d AND a2 FROM t6, t9 WHERE d = 'FALSE';
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT a2, d, d OR a2 FROM t6, t9 WHERE d = 'FALSE';
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 
 SELECT true AND 'false';
  | ---
  | - null
- | - 'Type mismatch: can not convert false to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT false AND 'false';
  | ---
@@ -6018,17 +6018,17 @@ SELECT false AND 'false';
 SELECT true OR 'false';
  | ---
  | - null
- | - 'Type mismatch: can not convert false to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT false OR 'false';
  | ---
  | - null
- | - 'Type mismatch: can not convert false to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT 'false' AND true;
  | ---
  | - null
- | - 'Type mismatch: can not convert false to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT 'false' AND false;
  | ---
@@ -6041,59 +6041,59 @@ SELECT 'false' AND false;
 SELECT 'false' OR true;
  | ---
  | - null
- | - 'Type mismatch: can not convert false to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT 'false' OR false;
  | ---
  | - null
- | - 'Type mismatch: can not convert false to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 
 SELECT a1, a1 AND 'false' FROM t6;
  | ---
  | - null
- | - 'Type mismatch: can not convert false to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT a1, a1 OR 'false' FROM t6;
  | ---
  | - null
- | - 'Type mismatch: can not convert false to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT a1, 'false' AND a1 FROM t6;
  | ---
  | - null
- | - 'Type mismatch: can not convert false to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT a1, 'false' OR a1 FROM t6;
  | ---
  | - null
- | - 'Type mismatch: can not convert false to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT a2, a2 AND 'false' FROM t6;
  | ---
  | - null
- | - 'Type mismatch: can not convert false to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT a2, a2 OR 'false' FROM t6;
  | ---
  | - null
- | - 'Type mismatch: can not convert false to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT a2, 'false' AND a2 FROM t6;
  | ---
  | - null
- | - 'Type mismatch: can not convert false to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT a2, 'false' OR a2 FROM t6;
  | ---
  | - null
- | - 'Type mismatch: can not convert false to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 
 SELECT d, true AND d FROM t9 WHERE d = 'false';
  | ---
  | - null
- | - 'Type mismatch: can not convert false to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT d, false AND d FROM t9 WHERE d = 'false';
  | ---
@@ -6108,17 +6108,17 @@ SELECT d, false AND d FROM t9 WHERE d = 'false';
 SELECT d, true OR d FROM t9 WHERE d = 'false';
  | ---
  | - null
- | - 'Type mismatch: can not convert false to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT d, false OR d FROM t9 WHERE d = 'false';
  | ---
  | - null
- | - 'Type mismatch: can not convert false to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT d, d AND true FROM t9 WHERE d = 'false';
  | ---
  | - null
- | - 'Type mismatch: can not convert false to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT d, d AND false FROM t9 WHERE d = 'false';
  | ---
@@ -6133,53 +6133,53 @@ SELECT d, d AND false FROM t9 WHERE d = 'false';
 SELECT d, d OR true FROM t9 WHERE d = 'false';
  | ---
  | - null
- | - 'Type mismatch: can not convert false to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT d, d OR false FROM t9 WHERE d = 'false';
  | ---
  | - null
- | - 'Type mismatch: can not convert false to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 
 SELECT a1, d, a1 AND d FROM t6, t9 WHERE d = 'false';
  | ---
  | - null
- | - 'Type mismatch: can not convert false to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT a1, d, a1 OR d FROM t6, t9 WHERE d = 'false';
  | ---
  | - null
- | - 'Type mismatch: can not convert false to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT a1, d, d AND a1 FROM t6, t9 WHERE d = 'false';
  | ---
  | - null
- | - 'Type mismatch: can not convert false to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT a1, d, d OR a1 FROM t6, t9 WHERE d = 'false';
  | ---
  | - null
- | - 'Type mismatch: can not convert false to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT a2, d, a2 AND d FROM t6, t9 WHERE d = 'false';
  | ---
  | - null
- | - 'Type mismatch: can not convert false to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT a2, d, a2 OR d FROM t6, t9 WHERE d = 'false';
  | ---
  | - null
- | - 'Type mismatch: can not convert false to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT a2, d, d AND a2 FROM t6, t9 WHERE d = 'false';
  | ---
  | - null
- | - 'Type mismatch: can not convert false to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 SELECT a2, d, d OR a2 FROM t6, t9 WHERE d = 'false';
  | ---
  | - null
- | - 'Type mismatch: can not convert false to boolean'
+ | - 'Type mismatch: can not convert text to boolean'
  | ...
 
 -- Cleaning.
diff --git a/test/sql/integer-overflow.result b/test/sql/integer-overflow.result
index 6269cb547..f5b5a4156 100644
--- a/test/sql/integer-overflow.result
+++ b/test/sql/integer-overflow.result
@@ -106,7 +106,7 @@ box.execute('SELECT CAST(\'9223372036854775808\' AS INTEGER);')
 box.execute('SELECT CAST(\'18446744073709551616\' AS INTEGER);')
 ---
 - null
-- 'Type mismatch: can not convert 18446744073709551616 to integer'
+- 'Type mismatch: can not convert text to integer'
 ...
 -- Due to inexact represantation of large integers in terms of
 -- floating point numbers, numerics with value < UINT64_MAX
@@ -117,7 +117,7 @@ box.execute('SELECT CAST(\'18446744073709551616\' AS INTEGER);')
 box.execute('SELECT CAST(18446744073709551600. AS INTEGER);')
 ---
 - null
-- 'Type mismatch: can not convert 1.84467440737096e+19 to integer'
+- 'Type mismatch: can not convert real to integer'
 ...
 -- gh-3810: make sure that if space contains integers in range
 -- [INT64_MAX, UINT64_MAX], they are handled inside SQL in a
diff --git a/test/sql/types.result b/test/sql/types.result
index 9099bcea4..53700bbad 100644
--- a/test/sql/types.result
+++ b/test/sql/types.result
@@ -270,7 +270,7 @@ box.space.T1:drop()
 box.execute("SELECT CAST('1.123' AS INTEGER);")
 ---
 - null
-- 'Type mismatch: can not convert 1.123 to integer'
+- 'Type mismatch: can not convert text to integer'
 ...
 box.execute("CREATE TABLE t1 (f TEXT PRIMARY KEY);")
 ---
@@ -283,7 +283,7 @@ box.execute("INSERT INTO t1 VALUES('0.0'), ('1.5'), ('3.9312453');")
 box.execute("SELECT CAST(f AS INTEGER) FROM t1;")
 ---
 - null
-- 'Type mismatch: can not convert 0.0 to integer'
+- 'Type mismatch: can not convert text to integer'
 ...
 box.space.T1:drop()
 ---
@@ -624,7 +624,7 @@ box.execute("SELECT 1 LIMIT 1 OFFSET 18446744073709551614;")
 box.execute("SELECT CAST('18446744073' || '709551616' AS INTEGER);")
 ---
 - null
-- 'Type mismatch: can not convert 18446744073709551616 to integer'
+- 'Type mismatch: can not convert text to integer'
 ...
 box.execute("SELECT CAST('18446744073' || '709551615' AS INTEGER);")
 ---
@@ -1077,7 +1077,7 @@ box.execute("SELECT CAST(123 AS UNSIGNED);")
 box.execute("SELECT CAST(-123 AS UNSIGNED);")
 ---
 - null
-- 'Type mismatch: can not convert -123 to unsigned'
+- 'Type mismatch: can not convert integer to unsigned'
 ...
 box.execute("SELECT CAST(1.5 AS UNSIGNED);")
 ---
@@ -1114,7 +1114,7 @@ box.execute("SELECT CAST('123' AS UNSIGNED);")
 box.execute("SELECT CAST('-123' AS UNSIGNED);")
 ---
 - null
-- 'Type mismatch: can not convert -123 to unsigned'
+- 'Type mismatch: can not convert text to unsigned'
 ...
 box.space.T1:drop()
 ---
@@ -1444,17 +1444,17 @@ box.space.T1:drop()
 box.execute("SELECT CAST(1 AS VARBINARY);")
 ---
 - null
-- 'Type mismatch: can not convert 1 to varbinary'
+- 'Type mismatch: can not convert unsigned to varbinary'
 ...
 box.execute("SELECT CAST(1.123 AS VARBINARY);")
 ---
 - null
-- 'Type mismatch: can not convert 1.123 to varbinary'
+- 'Type mismatch: can not convert real to varbinary'
 ...
 box.execute("SELECT CAST(true AS VARBINARY);")
 ---
 - null
-- 'Type mismatch: can not convert TRUE to varbinary'
+- 'Type mismatch: can not convert boolean to varbinary'
 ...
 box.execute("SELECT CAST('asd' AS VARBINARY);")
 ---
@@ -1710,12 +1710,12 @@ box.execute("SELECT CAST(1.123 AS DOUBLE);")
 box.execute("SELECT CAST(true AS DOUBLE);")
 ---
 - null
-- 'Type mismatch: can not convert TRUE to double'
+- 'Type mismatch: can not convert boolean to double'
 ...
 box.execute("SELECT CAST('asd' AS DOUBLE);")
 ---
 - null
-- 'Type mismatch: can not convert asd to double'
+- 'Type mismatch: can not convert text to double'
 ...
 box.execute("SELECT CAST('1' AS DOUBLE);")
 ---
-- 
2.25.1

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [Tarantool-patches] [PATCH v2 7/7] sql: use type instead of value in type mismatch error
  2020-06-11 12:54 ` [Tarantool-patches] [PATCH v2 7/7] sql: use type instead of value in type mismatch error imeevma
@ 2020-06-14 17:03   ` Vladislav Shpilevoy
  0 siblings, 0 replies; 14+ messages in thread
From: Vladislav Shpilevoy @ 2020-06-14 17:03 UTC (permalink / raw)
  To: imeevma, tsafin, tarantool-patches

Thanks for the patch!

> diff --git a/src/box/sql/vdbe.c b/src/box/sql/vdbe.c
> index e22ed98cf..cf0ae8a06 100644
> --- a/src/box/sql/vdbe.c
> +++ b/src/box/sql/vdbe.c
> @@ -1748,12 +1748,12 @@ case OP_Remainder: {           /* same as TK_REM, in1, in2, out3 */
>  	} else {
>  		if (sqlVdbeRealValue(pIn1, &rA) != 0) {
>  			diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
> -				 sql_value_to_diag_str(pIn1), "numeric");
> +				 mem_type_to_str(pIn1), "numeric");

src/box/sql/func.c still contains lots of sql_value_to_diag_str() calls.
I think, sql_value_to_diag_str() should be removed completely.

It is not only inconsistent with other error messages, but is also unsafe,
because that errors may end up in user logs, and may contain sensitive
data such as password hashes.

Please, remove it in this commit, and then send the whole patchset to
Nikita for a second review. The patchset LGTM except the comment above.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [Tarantool-patches] [PATCH v2 1/7] sql: remove implicit cast for assignment
  2020-06-22 21:08       ` Nikita Pettik
@ 2020-06-23  6:44         ` Mergen Imeev
  0 siblings, 0 replies; 14+ messages in thread
From: Mergen Imeev @ 2020-06-23  6:44 UTC (permalink / raw)
  To: Nikita Pettik, Vladislav Shpilevoy; +Cc: tarantool-patches


On 23.06.2020 00:08, Nikita Pettik wrote:
> On 22 Jun 22:47, Vladislav Shpilevoy wrote:
>>>> +{
>>>> +	if ((mem->flags & MEM_Null) != 0)
>>>> +		return 0;
>>>> +	assert(type < field_type_MAX);
>>>> +	uint32_t flags = mem->flags;
>>>> +	switch (type) {
>>> Instead of such long switch-cases could we organize it in one table
>>> containing valid conversions? I mean sort of field_mp_type_is_compatible()
>>> To provide not only check but execution mechanism you can fill
>>> table with pointers to functions implementing particular casts.
>> Better to do that when MEM_<type> flags will be replaced by field_type.
> I'm afraid it may take a while..Surely, I don't insisnt on this
> refactoring, patch can be pushed without it. Anyway it would be
> nice to see it.

I will try to fix it.


>> In that case you will be able to use the existing compatibility checkers
>> (as I hope).
>>
>>>> +		if ((flags & MEM_Subtype) == 0 ||
>>>> +		    mem->subtype != SQL_SUBTYPE_MSGPACK)
>>>> +			return 0;
>>>> +		assert(mp_typeof(*mem->z) == MP_MAP ||
>>>> +		       mp_typeof(*mem->z) == MP_ARRAY);
>>>> +		return -1;
>>>> @@ -2776,6 +2883,31 @@ case OP_ApplyType: {
>>>>   	break;
>>>>   }
>>>>   
>>>> +/* Opcode: CheckType P1 P2 * P4 *
>>> ApplyType was quite suitable name, meanwhile CheckType is a bit confusing
>>> since in fact it doesn't only check but cast (apply, coerce or whatever)
>>> mem to given type.
>> How about OP_SafeTypeCast? Or OP_SafeApplyType? Or OP_ImplicitCast?
> I don't understand why it is supposed to be 'safe'..
> Any of suggested names is way much better than CheckType, but
> still I see no reason to avoid using original 'ApplyType'.
I can replace OP_CheckType with OP_ApplyType after removing the
original OP_ApplyType, but I think OP_ImplicitCast is better. Do
you mind if I use this name?

>   
>>>> + * Synopsis: type(r[P1@P2])
>>>> + *
>>>> + * Check that types of P2 registers starting from register
>>>> + * P1 are compatible with given with given field types in P4.
>>>> + */
>>>> +case OP_CheckType: {
>>>> +	enum field_type *types = pOp->p4.types;
>>>> +	assert(types != NULL);
>>>> +	assert(types[pOp->p2] == field_type_MAX);
>>>> +	pIn1 = &aMem[pOp->p1];
>>>> +	enum field_type type;
>>>> +	while((type = *(types++)) != field_type_MAX) {
>>>> +		assert(pIn1 <= &p->aMem[(p->nMem+1 - p->nCursor)]);
>>>> +		assert(memIsValid(pIn1));
>>>> +		if (mem_check_types(pIn1, type) != 0) {
>>>> +			diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
>>>> +				 mem_type_to_str(pIn1), field_type_strs[type]);
>>>> +			goto abort_due_to_error;
>>>> +		}
>>>> +		pIn1++;
>>>> +	}
>>>> +	break;
>>>> +}
>>>> +
>>>> diff --git a/src/box/sql/vdbemem.c b/src/box/sql/vdbemem.c
>>>> index 8dad2db9a..9e8586ffc 100644
>>>> --- a/src/box/sql/vdbemem.c
>>>> +++ b/src/box/sql/vdbemem.c
>>>> @@ -839,6 +839,13 @@ mem_set_int(struct Mem *mem, int64_t value, bool is_neg)
>>>>   	}
>>>>   }
>>>>   
>>>> +void
>>>> +mem_set_double(struct Mem *mem, double value)
>>>> +{
>>> I see inconsistency with other setters: they provide auxiliary
>>> clean-up in case mem has one of Agg/Dyn/Frame flags. Please
>>> investigate whether it is really required and if it is so add
>>> it to current one (or remove from other setters).
>> +. I believe we forgot that the mem could contain some dynamically
>> allocated things on the heap.
>>
>> Btw, this function could be added in a separate commit probably. And
>> applied to all the existing places were we set the double type manually.
> Agree.

I will fix it.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [Tarantool-patches] [PATCH v2 1/7] sql: remove implicit cast for assignment
  2020-06-22 20:47     ` Vladislav Shpilevoy
@ 2020-06-22 21:08       ` Nikita Pettik
  2020-06-23  6:44         ` Mergen Imeev
  0 siblings, 1 reply; 14+ messages in thread
From: Nikita Pettik @ 2020-06-22 21:08 UTC (permalink / raw)
  To: Vladislav Shpilevoy; +Cc: tarantool-patches

On 22 Jun 22:47, Vladislav Shpilevoy wrote:
> >> +{
> >> +	if ((mem->flags & MEM_Null) != 0)
> >> +		return 0;
> >> +	assert(type < field_type_MAX);
> >> +	uint32_t flags = mem->flags;
> >> +	switch (type) {
> > 
> > Instead of such long switch-cases could we organize it in one table
> > containing valid conversions? I mean sort of field_mp_type_is_compatible()
> > To provide not only check but execution mechanism you can fill
> > table with pointers to functions implementing particular casts.
> 
> Better to do that when MEM_<type> flags will be replaced by field_type.

I'm afraid it may take a while..Surely, I don't insisnt on this
refactoring, patch can be pushed without it. Anyway it would be
nice to see it.

> In that case you will be able to use the existing compatibility checkers
> (as I hope).
> 
> >> +		if ((flags & MEM_Subtype) == 0 ||
> >> +		    mem->subtype != SQL_SUBTYPE_MSGPACK)
> >> +			return 0;
> >> +		assert(mp_typeof(*mem->z) == MP_MAP ||
> >> +		       mp_typeof(*mem->z) == MP_ARRAY);
> >> +		return -1;
> >> @@ -2776,6 +2883,31 @@ case OP_ApplyType: {
> >>  	break;
> >>  }
> >>  
> >> +/* Opcode: CheckType P1 P2 * P4 *
> > 
> > ApplyType was quite suitable name, meanwhile CheckType is a bit confusing
> > since in fact it doesn't only check but cast (apply, coerce or whatever)
> > mem to given type.
> 
> How about OP_SafeTypeCast? Or OP_SafeApplyType? Or OP_ImplicitCast?

I don't understand why it is supposed to be 'safe'..
Any of suggested names is way much better than CheckType, but
still I see no reason to avoid using original 'ApplyType'.
 
> >> + * Synopsis: type(r[P1@P2])
> >> + *
> >> + * Check that types of P2 registers starting from register
> >> + * P1 are compatible with given with given field types in P4.
> >> + */
> >> +case OP_CheckType: {
> >> +	enum field_type *types = pOp->p4.types;
> >> +	assert(types != NULL);
> >> +	assert(types[pOp->p2] == field_type_MAX);
> >> +	pIn1 = &aMem[pOp->p1];
> >> +	enum field_type type;
> >> +	while((type = *(types++)) != field_type_MAX) {
> >> +		assert(pIn1 <= &p->aMem[(p->nMem+1 - p->nCursor)]);
> >> +		assert(memIsValid(pIn1));
> >> +		if (mem_check_types(pIn1, type) != 0) {
> >> +			diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
> >> +				 mem_type_to_str(pIn1), field_type_strs[type]);
> >> +			goto abort_due_to_error;
> >> +		}
> >> +		pIn1++;
> >> +	}
> >> +	break;
> >> +}
> >> +
> >> diff --git a/src/box/sql/vdbemem.c b/src/box/sql/vdbemem.c
> >> index 8dad2db9a..9e8586ffc 100644
> >> --- a/src/box/sql/vdbemem.c
> >> +++ b/src/box/sql/vdbemem.c
> >> @@ -839,6 +839,13 @@ mem_set_int(struct Mem *mem, int64_t value, bool is_neg)
> >>  	}
> >>  }
> >>  
> >> +void
> >> +mem_set_double(struct Mem *mem, double value)
> >> +{
> > 
> > I see inconsistency with other setters: they provide auxiliary
> > clean-up in case mem has one of Agg/Dyn/Frame flags. Please
> > investigate whether it is really required and if it is so add
> > it to current one (or remove from other setters).
> 
> +. I believe we forgot that the mem could contain some dynamically
> allocated things on the heap.
> 
> Btw, this function could be added in a separate commit probably. And
> applied to all the existing places were we set the double type manually.

Agree.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [Tarantool-patches] [PATCH v2 1/7] sql: remove implicit cast for assignment
  2020-06-22  8:23   ` Nikita Pettik
@ 2020-06-22 20:47     ` Vladislav Shpilevoy
  2020-06-22 21:08       ` Nikita Pettik
  0 siblings, 1 reply; 14+ messages in thread
From: Vladislav Shpilevoy @ 2020-06-22 20:47 UTC (permalink / raw)
  To: Nikita Pettik, imeevma; +Cc: tarantool-patches

>> +{
>> +	if ((mem->flags & MEM_Null) != 0)
>> +		return 0;
>> +	assert(type < field_type_MAX);
>> +	uint32_t flags = mem->flags;
>> +	switch (type) {
> 
> Instead of such long switch-cases could we organize it in one table
> containing valid conversions? I mean sort of field_mp_type_is_compatible()
> To provide not only check but execution mechanism you can fill
> table with pointers to functions implementing particular casts.

Better to do that when MEM_<type> flags will be replaced by field_type.
In that case you will be able to use the existing compatibility checkers
(as I hope).

>> +	case FIELD_TYPE_INTEGER:
>> +		if ((flags & (MEM_Int | MEM_UInt)) != 0)
>> +			return 0;
>> +		if ((flags & MEM_Real) == 0)
>> +			return -1;
>> +		double d = mem->u.r;
>> +		if (d >= (double)UINT64_MAX || d < (double)INT64_MIN)
>> +			return -1;
>> +		if (d < (double)INT64_MAX) {
>> +			int64_t i = (int64_t) d;
>> +			if (i == d) {
>> +				mem_set_int(mem, i, i <= -1);
>> +				return 0;
>> +			}
>> +			return -1;
>> +		}
>> +		uint64_t u = (uint64_t) d;
>> +		if (u == d) {
>> +			mem_set_u64(mem, u);
>> +			return 0;
>> +		}
>> +		return -1;
>> +	case FIELD_TYPE_SCALAR:
>> +		/* Can't cast MAP and ARRAY to scalar types. */
> 
> Except for map and arrays we alread have decimal. IS this function
> able to handle it?

It returns -1. Meaning it can't convert. Since DECIMAL is not yet
supported in SQL. So it should work and give an error, but yeah, a
test would be good to have.

>> +		if ((flags & MEM_Subtype) == 0 ||
>> +		    mem->subtype != SQL_SUBTYPE_MSGPACK)
>> +			return 0;
>> +		assert(mp_typeof(*mem->z) == MP_MAP ||
>> +		       mp_typeof(*mem->z) == MP_ARRAY);
>> +		return -1;
>> @@ -2776,6 +2883,31 @@ case OP_ApplyType: {
>>  	break;
>>  }
>>  
>> +/* Opcode: CheckType P1 P2 * P4 *
> 
> ApplyType was quite suitable name, meanwhile CheckType is a bit confusing
> since in fact it doesn't only check but cast (apply, coerce or whatever)
> mem to given type.

How about OP_SafeTypeCast? Or OP_SafeApplyType? Or OP_ImplicitCast?

>> + * Synopsis: type(r[P1@P2])
>> + *
>> + * Check that types of P2 registers starting from register
>> + * P1 are compatible with given with given field types in P4.
>> + */
>> +case OP_CheckType: {
>> +	enum field_type *types = pOp->p4.types;
>> +	assert(types != NULL);
>> +	assert(types[pOp->p2] == field_type_MAX);
>> +	pIn1 = &aMem[pOp->p1];
>> +	enum field_type type;
>> +	while((type = *(types++)) != field_type_MAX) {
>> +		assert(pIn1 <= &p->aMem[(p->nMem+1 - p->nCursor)]);
>> +		assert(memIsValid(pIn1));
>> +		if (mem_check_types(pIn1, type) != 0) {
>> +			diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
>> +				 mem_type_to_str(pIn1), field_type_strs[type]);
>> +			goto abort_due_to_error;
>> +		}
>> +		pIn1++;
>> +	}
>> +	break;
>> +}
>> +
>> diff --git a/src/box/sql/vdbemem.c b/src/box/sql/vdbemem.c
>> index 8dad2db9a..9e8586ffc 100644
>> --- a/src/box/sql/vdbemem.c
>> +++ b/src/box/sql/vdbemem.c
>> @@ -839,6 +839,13 @@ mem_set_int(struct Mem *mem, int64_t value, bool is_neg)
>>  	}
>>  }
>>  
>> +void
>> +mem_set_double(struct Mem *mem, double value)
>> +{
> 
> I see inconsistency with other setters: they provide auxiliary
> clean-up in case mem has one of Agg/Dyn/Frame flags. Please
> investigate whether it is really required and if it is so add
> it to current one (or remove from other setters).

+. I believe we forgot that the mem could contain some dynamically
allocated things on the heap.

Btw, this function could be added in a separate commit probably. And
applied to all the existing places were we set the double type manually.

>> +	mem->u.r = value;
>> +	MemSetTypeFlag(mem, MEM_Real);
>> +}
>> +

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [Tarantool-patches] [PATCH v2 1/7] sql: remove implicit cast for assignment
  2020-06-17 12:36 ` [Tarantool-patches] [PATCH v2 1/7] sql: remove implicit cast for assignment imeevma
@ 2020-06-22  8:23   ` Nikita Pettik
  2020-06-22 20:47     ` Vladislav Shpilevoy
  0 siblings, 1 reply; 14+ messages in thread
From: Nikita Pettik @ 2020-06-22  8:23 UTC (permalink / raw)
  To: imeevma; +Cc: tarantool-patches

On 17 Jun 15:36, imeevma@tarantool.org wrote:
> This patch removes implicit cast for assignment, however,
> it is allowed to implicitly cast DOUBLE to INTEGER and
> vice versa.
> 
> Closes #3809
> ---
> 
> diff --git a/src/box/sql/vdbe.c b/src/box/sql/vdbe.c
> index 6b769805c..ae2622c9e 100644
> --- a/src/box/sql/vdbe.c
> +++ b/src/box/sql/vdbe.c
> @@ -418,6 +418,113 @@ sql_value_apply_type(
>  	mem_apply_type((Mem *) pVal, type);
>  }
>  
> +/**
> + * Check that mem_type of the mem is compatible with given type.
> + * In the case of numeric values, this function tries to convert
> + * the mem to the specified type and returns -1 if this is not
> + * possible.
> + *
> + * @param mem The value to check.
> + * @param type The type to check.
> + */
> +static int
> +mem_check_types(struct Mem *mem, enum field_type type)

I'd rename it to mem_icast_to_type() or mem_impl_cast_to_type()
or smth like that.

> +{
> +	if ((mem->flags & MEM_Null) != 0)
> +		return 0;
> +	assert(type < field_type_MAX);
> +	uint32_t flags = mem->flags;
> +	switch (type) {

Instead of such long switch-cases could we organize it in one table
containing valid conversions? I mean sort of field_mp_type_is_compatible()
To provide not only check but execution mechanism you can fill
table with pointers to functions implementing particular casts.

> +	case FIELD_TYPE_INTEGER:
> +		if ((flags & (MEM_Int | MEM_UInt)) != 0)
> +			return 0;
> +		if ((flags & MEM_Real) == 0)
> +			return -1;
> +		double d = mem->u.r;
> +		if (d >= (double)UINT64_MAX || d < (double)INT64_MIN)
> +			return -1;
> +		if (d < (double)INT64_MAX) {
> +			int64_t i = (int64_t) d;
> +			if (i == d) {
> +				mem_set_int(mem, i, i <= -1);
> +				return 0;
> +			}
> +			return -1;
> +		}
> +		uint64_t u = (uint64_t) d;
> +		if (u == d) {
> +			mem_set_u64(mem, u);
> +			return 0;
> +		}
> +		return -1;
> +	case FIELD_TYPE_SCALAR:
> +		/* Can't cast MAP and ARRAY to scalar types. */

Except for map and arrays we alread have decimal. IS this function
able to handle it?

> +		if ((flags & MEM_Subtype) == 0 ||
> +		    mem->subtype != SQL_SUBTYPE_MSGPACK)
> +			return 0;
> +		assert(mp_typeof(*mem->z) == MP_MAP ||
> +		       mp_typeof(*mem->z) == MP_ARRAY);
> +		return -1;
> @@ -2776,6 +2883,31 @@ case OP_ApplyType: {
>  	break;
>  }
>  
> +/* Opcode: CheckType P1 P2 * P4 *

ApplyType was quite suitable name, meanwhile CheckType is a bit confusing
since in fact it doesn't only check but cast (apply, coerce or whatever)
mem to given type.

> + * Synopsis: type(r[P1@P2])
> + *
> + * Check that types of P2 registers starting from register
> + * P1 are compatible with given with given field types in P4.
> + */
> +case OP_CheckType: {
> +	enum field_type *types = pOp->p4.types;
> +	assert(types != NULL);
> +	assert(types[pOp->p2] == field_type_MAX);
> +	pIn1 = &aMem[pOp->p1];
> +	enum field_type type;
> +	while((type = *(types++)) != field_type_MAX) {
> +		assert(pIn1 <= &p->aMem[(p->nMem+1 - p->nCursor)]);
> +		assert(memIsValid(pIn1));
> +		if (mem_check_types(pIn1, type) != 0) {
> +			diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
> +				 mem_type_to_str(pIn1), field_type_strs[type]);
> +			goto abort_due_to_error;
> +		}
> +		pIn1++;
> +	}
> +	break;
> +}
> +
> diff --git a/src/box/sql/vdbemem.c b/src/box/sql/vdbemem.c
> index 8dad2db9a..9e8586ffc 100644
> --- a/src/box/sql/vdbemem.c
> +++ b/src/box/sql/vdbemem.c
> @@ -839,6 +839,13 @@ mem_set_int(struct Mem *mem, int64_t value, bool is_neg)
>  	}
>  }
>  
> +void
> +mem_set_double(struct Mem *mem, double value)
> +{

I see inconsistency with other setters: they provide auxiliary
clean-up in case mem has one of Agg/Dyn/Frame flags. Please
investigate whether it is really required and if it is so add
it to current one (or remove from other setters).

> +	mem->u.r = value;
> +	MemSetTypeFlag(mem, MEM_Real);
> +}
> +
> diff --git a/test/sql-tap/autoinc.test.lua b/test/sql-tap/autoinc.test.lua
> index 37e65e541..ec8dfeab1 100755
> --- a/test/sql-tap/autoinc.test.lua
> +++ b/test/sql-tap/autoinc.test.lua
> @@ -618,7 +618,7 @@ test:do_catchsql_test(
>              INSERT INTO t2 VALUES('asd'); 
>      ]], {
>          -- <autoinc-10.2>
> -        1, "Type mismatch: can not convert asd to integer"
> +        1, "Type mismatch: can not convert text to integer"

Having an opportunity to see which particular value can't be
converted is quite helpful. Let's leave it.

> @@ -694,7 +694,7 @@ test:do_test(
>                   INSERT INTO t3928(b) VALUES('after-int-' || CAST(new.b AS TEXT));
>              END;
>              DELETE FROM t3928 WHERE a!=1;
> -            UPDATE t3928 SET b=456 WHERE a=1;
> +            UPDATE t3928 SET b='456' WHERE a=1;
>              SELECT * FROM t3928 ORDER BY a;
>          ]])
>      end, {
> diff --git a/test/sql-tap/gh-3809-implicit-cast-assignment.test.lua b/test/sql-tap/gh-3809-implicit-cast-assignment.test.lua
> new file mode 100755
> index 000000000..de72cf3a4
> --- /dev/null
> +++ b/test/sql-tap/gh-3809-implicit-cast-assignment.test.lua

It's not regression issue, so you can a) remove gh- prefix;
b) amalgamate it with another test (e.g. sql/types.test.lua).
It's up to you tho.

> @@ -0,0 +1,649 @@
> +#!/usr/bin/env tarantool
> +test = require("sqltester")
> +test:plan(77)
> +
> +--
> +-- Make sure there are no implicit casts during assignment,
> +-- except for the implicit cast between numeric values.
> +--

Why do you still avoid .sql test format?

> +test:execsql([[
> +    CREATE TABLE ti (a INT PRIMARY KEY AUTOINCREMENT, i INTEGER);
> +    CREATE TABLE td (a INT PRIMARY KEY AUTOINCREMENT, d DOUBLE);
> +    CREATE TABLE tb (a INT PRIMARY KEY AUTOINCREMENT, b BOOLEAN);
> +    CREATE TABLE tt (a INT PRIMARY KEY AUTOINCREMENT, t TEXT);
> +    CREATE TABLE tv (a INT PRIMARY KEY AUTOINCREMENT, v VARBINARY);
> +    CREATE TABLE ts (a INT PRIMARY KEY AUTOINCREMENT, s SCALAR);
> +]])
> +
> +test:do_catchsql_test(
> +    "gh-3809-1",
> +    [[
> +        INSERT INTO ti(i) VALUES (11)
> +    ]], {
> +        0
> +    })
> +
> +test:do_catchsql_test(
> +    "gh-3809-2",
> +    [[
> +        INSERT INTO ti(i) VALUES (22.2)
> +    ]], {
> +        1, "Type mismatch: can not convert real to integer"
> +    })
> +
> +test:do_catchsql_test(
> +    "gh-3809-3",
> +    [[
> +        INSERT INTO ti(i) VALUES (33.0)

Should this be valid? Could you please ask Peter to clarify this question?

> +test:execsql([[
> +    DELETE FROM ti;
> +    DELETE FROM td;
> +    DELETE FROM tb;
> +    DELETE FROM tt;
> +    DELETE FROM tv;
> +    DELETE FROM ts;
> +    INSERT INTO ti(a) VALUES(1);
> +    INSERT INTO td(a) VALUES(1);
> +    INSERT INTO tb(a) VALUES(1);
> +    INSERT INTO tt(a) VALUES(1);
> +    INSERT INTO tv(a) VALUES(1);
> +    INSERT INTO ts(a) VALUES(1);
> +]])

Strange turn..Could you please supply each batch of tests with
brief description?

> +test:do_execsql_test(
> +    "gh-3809-39",
> +    [[
> +        SELECT * FROM ti, td, tb, tt, tv, ts;
> +    ]], {
> +        1, "", 1, "", 1, "", 1, "", 1, "", 1, ""
> +    })
> diff --git a/test/sql-tap/index1.test.lua b/test/sql-tap/index1.test.lua
> index e173e685c..ce66b7c1e 100755
> --- a/test/sql-tap/index1.test.lua
> +++ b/test/sql-tap/index1.test.lua
> @@ -593,25 +593,17 @@ test:do_test(
>          -- </index-11.1>
>      })
>  end
> --- integrity_check index-11.2
> --- Numeric strings should compare as if they were numbers.  So even if the
> --- strings are not character-by-character the same, if they represent the
> --- same number they should compare equal to one another.  Verify that this
> --- is true in indices.
> ---
> --- Updated for sql v3: sql will now store these values as numbers
> --- (because the affinity of column a is NUMERIC) so the quirky
> --- representations are not retained. i.e. '+1.0' becomes '1'.
> +
>  test:do_execsql_test(
>      "index-12.1",
>      [[
>          CREATE TABLE t4(id  INT primary key, a NUMBER,b INT );
> -        INSERT INTO t4 VALUES(1, '0.0',1);
> -        INSERT INTO t4 VALUES(2, '0.00',2);
> -        INSERT INTO t4 VALUES(4, '-1.0',4);
> -        INSERT INTO t4 VALUES(5, '+1.0',5);
> -        INSERT INTO t4 VALUES(6, '0',6);
> -        INSERT INTO t4 VALUES(7, '00000',7);
> +        INSERT INTO t4 VALUES(1, 0.0, 1);
> +        INSERT INTO t4 VALUES(2, 0.00, 2);
> +        INSERT INTO t4 VALUES(4, -1.0, 4);
> +        INSERT INTO t4 VALUES(5, +1.0, 5);
> +        INSERT INTO t4 VALUES(6, 0, 6);
> +        INSERT INTO t4 VALUES(7, 00000, 7);
>          SELECT a FROM t4 ORDER BY b;

Does this test make any sense now?

>      ]], {
>          -- <index-12.1>
> @@ -692,7 +684,7 @@ test:do_execsql_test(
>             c  TEXT,
>             UNIQUE(a,c)
>          );
> -        INSERT INTO t5 VALUES(1,2,3);
> +        INSERT INTO t5 VALUES(1,2,'3');
>          SELECT * FROM t5;
>      ]], {
>          -- <index-13.1>
> diff --git a/test/sql-tap/intpkey.test.lua b/test/sql-tap/intpkey.test.lua
> index b6b186632..0db18ba91 100755
> --- a/test/sql-tap/intpkey.test.lua
> +++ b/test/sql-tap/intpkey.test.lua
> @@ -770,11 +770,6 @@ test:do_execsql_test(
>          -- </intpkey-11.1>
>      })
>  
> --- integrity_check intpkey-12.1
> --- Try to use a string that looks like a floating point number as
> --- an integer primary key.  This should actually work when the floating
> --- point value can be rounded to an integer without loss of data.
> ---

Ditto

>  test:do_execsql_test(
>      "intpkey-13.1",
>      [[
> @@ -788,7 +783,7 @@ test:do_execsql_test(
>  test:do_execsql_test(
>      "intpkey-13.2",
>      [[
> -        INSERT INTO t1 VALUES('1',2,3);
> +        INSERT INTO t1 VALUES(1,'2','3');
>          SELECT * FROM t1 WHERE a=1;
>      ]], {
>          -- <intpkey-13.2>
> --- a/test/sql-tap/whereB.test.lua
> +++ b/test/sql-tap/whereB.test.lua
> @@ -112,24 +112,16 @@ test:do_execsql_test(
>      -- </whereB-1.102>
>      })
>  
> --- For this set of tests:
> ---
> ---  *   t1.y holds a text value with affinity TEXT
> ---  *   t2.b holds an integer value with affinity NONE
> ---
> --- These values are not equal and because neither affinity is NUMERIC
> --- no type conversion occurs.
> ---

Ditto

>  test:do_execsql_test(
>      "whereB-2.1",
>      [[
>          DROP TABLE t1;
>          DROP TABLE t2;
>  
> -        CREATE TABLE t1(x  INT primary key, y TEXT);    -- affinity of t1.y is TEXT
> -        INSERT INTO t1 VALUES(1,99);
> +        CREATE TABLE t1(x  INT primary key, y TEXT);
> +        INSERT INTO t1 VALUES(1,'99');
>  
> -        CREATE TABLE t2(a  INT primary key, b SCALAR);  -- affinity of t2.b is NONE
> +        CREATE TABLE t2(a  INT primary key, b SCALAR);
>          CREATE INDEX t2b ON t2(b);
>          INSERT INTO t2 VALUES(2, 99);
>  

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [Tarantool-patches] [PATCH v2 1/7] sql: remove implicit cast for assignment
  2020-06-17 12:36 [Tarantool-patches] [PATCH v2 0/7] Remove implicit cast imeevma
@ 2020-06-17 12:36 ` imeevma
  2020-06-22  8:23   ` Nikita Pettik
  0 siblings, 1 reply; 14+ messages in thread
From: imeevma @ 2020-06-17 12:36 UTC (permalink / raw)
  To: korablev, tsafin, tarantool-patches

This patch removes implicit cast for assignment, however,
it is allowed to implicitly cast DOUBLE to INTEGER and
vice versa.

Closes #3809
---
 src/box/sql/insert.c                          |   2 +-
 src/box/sql/vdbe.c                            | 132 ++++
 src/box/sql/vdbeInt.h                         |   5 +
 src/box/sql/vdbemem.c                         |   7 +
 test/sql-tap/autoinc.test.lua                 |   4 +-
 test/sql-tap/default.test.lua                 |   6 +-
 test/sql-tap/e_select1.test.lua               |  10 +-
 .../gh-3809-implicit-cast-assignment.test.lua | 649 ++++++++++++++++++
 test/sql-tap/index1.test.lua                  |  24 +-
 test/sql-tap/insert3.test.lua                 |  10 +-
 test/sql-tap/intpkey.test.lua                 |  13 +-
 test/sql-tap/minmax2.test.lua                 |   6 +-
 test/sql-tap/misc1.test.lua                   |  34 +-
 test/sql-tap/numcast.test.lua                 |   4 +-
 test/sql-tap/select1.test.lua                 |   8 +-
 test/sql-tap/select4.test.lua                 |  12 +-
 test/sql-tap/select7.test.lua                 |   2 +-
 test/sql-tap/sort.test.lua                    |   8 +-
 test/sql-tap/tkt-3998683a16.test.lua          |  26 +-
 test/sql-tap/tkt-54844eea3f.test.lua          |   8 +-
 test/sql-tap/tkt-7bbfb7d442.test.lua          |   4 +-
 test/sql-tap/tkt1444.test.lua                 |   4 +-
 test/sql-tap/tkt3493.test.lua                 |   6 +-
 test/sql-tap/tkt3841.test.lua                 |  12 +-
 test/sql-tap/triggerA.test.lua                |   4 +-
 test/sql-tap/unique.test.lua                  |   8 +-
 test/sql-tap/view.test.lua                    |   2 +-
 test/sql-tap/where5.test.lua                  |  10 +-
 test/sql-tap/whereB.test.lua                  |  14 +-
 test/sql/boolean.result                       |   2 +-
 test/sql/persistency.result                   |   2 +-
 test/sql/types.result                         |  25 +-
 32 files changed, 906 insertions(+), 157 deletions(-)
 create mode 100755 test/sql-tap/gh-3809-implicit-cast-assignment.test.lua

diff --git a/src/box/sql/insert.c b/src/box/sql/insert.c
index 588e142d2..253304ba3 100644
--- a/src/box/sql/insert.c
+++ b/src/box/sql/insert.c
@@ -69,7 +69,7 @@ sql_emit_table_types(struct Vdbe *v, struct space_def *def, int reg)
 	for (uint32_t i = 0; i < field_count; ++i)
 		colls_type[i] = def->fields[i].type;
 	colls_type[field_count] = field_type_MAX;
-	sqlVdbeAddOp4(v, OP_ApplyType, reg, field_count, 0,
+	sqlVdbeAddOp4(v, OP_CheckType, reg, field_count, 0,
 			  (char *)colls_type, P4_DYNAMIC);
 }
 
diff --git a/src/box/sql/vdbe.c b/src/box/sql/vdbe.c
index 6b769805c..ae2622c9e 100644
--- a/src/box/sql/vdbe.c
+++ b/src/box/sql/vdbe.c
@@ -418,6 +418,113 @@ sql_value_apply_type(
 	mem_apply_type((Mem *) pVal, type);
 }
 
+/**
+ * Check that mem_type of the mem is compatible with given type.
+ * In the case of numeric values, this function tries to convert
+ * the mem to the specified type and returns -1 if this is not
+ * possible.
+ *
+ * @param mem The value to check.
+ * @param type The type to check.
+ */
+static int
+mem_check_types(struct Mem *mem, enum field_type type)
+{
+	if ((mem->flags & MEM_Null) != 0)
+		return 0;
+	assert(type < field_type_MAX);
+	uint32_t flags = mem->flags;
+	switch (type) {
+	case FIELD_TYPE_UNSIGNED:
+		if ((flags & MEM_Int) != 0)
+			return -1;
+		if ((flags & MEM_Real) != 0 && mem->u.r < 0)
+			return -1;
+		FALLTHROUGH;
+	case FIELD_TYPE_INTEGER:
+		if ((flags & (MEM_Int | MEM_UInt)) != 0)
+			return 0;
+		if ((flags & MEM_Real) == 0)
+			return -1;
+		double d = mem->u.r;
+		if (d >= (double)UINT64_MAX || d < (double)INT64_MIN)
+			return -1;
+		if (d < (double)INT64_MAX) {
+			int64_t i = (int64_t) d;
+			if (i == d) {
+				mem_set_int(mem, i, i <= -1);
+				return 0;
+			}
+			return -1;
+		}
+		uint64_t u = (uint64_t) d;
+		if (u == d) {
+			mem_set_u64(mem, u);
+			return 0;
+		}
+		return -1;
+	case FIELD_TYPE_BOOLEAN:
+		if ((flags & MEM_Bool) != 0)
+			return 0;
+		return -1;
+	case FIELD_TYPE_NUMBER:
+		if ((flags & (MEM_Real | MEM_Int | MEM_UInt)) != 0)
+			return 0;
+		return -1;
+	case FIELD_TYPE_DOUBLE:
+		if ((flags & MEM_Real) != 0)
+			return 0;
+		if ((flags & (MEM_Int | MEM_UInt)) == 0)
+			return -1;
+		if ((flags & MEM_Int) != 0) {
+			double d = mem->u.i;
+			if (mem->u.i == (int64_t)d) {
+				mem_set_double(mem, d);
+				return 0;
+			}
+		} else {
+			double d = mem->u.u;
+			if (mem->u.u == (uint64_t)d) {
+				mem_set_double(mem, d);
+				return 0;
+			}
+		}
+		return -1;
+	case FIELD_TYPE_STRING:
+		if ((flags & MEM_Str) != 0)
+			return 0;
+		return -1;
+	case FIELD_TYPE_VARBINARY:
+		if ((flags & MEM_Blob) != 0)
+			return 0;
+		return -1;
+	case FIELD_TYPE_SCALAR:
+		/* Can't cast MAP and ARRAY to scalar types. */
+		if ((flags & MEM_Subtype) == 0 ||
+		    mem->subtype != SQL_SUBTYPE_MSGPACK)
+			return 0;
+		assert(mp_typeof(*mem->z) == MP_MAP ||
+		       mp_typeof(*mem->z) == MP_ARRAY);
+		return -1;
+	case FIELD_TYPE_MAP:
+		if ((flags & MEM_Subtype) != 0 &&
+		    mem->subtype == SQL_SUBTYPE_MSGPACK &&
+		    mp_typeof(*mem->z) == MP_MAP)
+			return 0;
+		return -1;
+	case FIELD_TYPE_ARRAY:
+		if ((flags & MEM_Subtype) != 0 &&
+		    mem->subtype == SQL_SUBTYPE_MSGPACK &&
+		    mp_typeof(*mem->z) == MP_ARRAY)
+			return 0;
+		return -1;
+	case FIELD_TYPE_ANY:
+		return 0;
+	default:
+		return -1;
+	}
+}
+
 /*
  * pMem currently only holds a string type (or maybe a BLOB that we can
  * interpret as a string if we want to).  Compute its corresponding
@@ -2776,6 +2883,31 @@ case OP_ApplyType: {
 	break;
 }
 
+/* Opcode: CheckType P1 P2 * P4 *
+ * Synopsis: type(r[P1@P2])
+ *
+ * Check that types of P2 registers starting from register
+ * P1 are compatible with given with given field types in P4.
+ */
+case OP_CheckType: {
+	enum field_type *types = pOp->p4.types;
+	assert(types != NULL);
+	assert(types[pOp->p2] == field_type_MAX);
+	pIn1 = &aMem[pOp->p1];
+	enum field_type type;
+	while((type = *(types++)) != field_type_MAX) {
+		assert(pIn1 <= &p->aMem[(p->nMem+1 - p->nCursor)]);
+		assert(memIsValid(pIn1));
+		if (mem_check_types(pIn1, type) != 0) {
+			diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
+				 mem_type_to_str(pIn1), field_type_strs[type]);
+			goto abort_due_to_error;
+		}
+		pIn1++;
+	}
+	break;
+}
+
 /* Opcode: MakeRecord P1 P2 P3 P4 P5
  * Synopsis: r[P3]=mkrec(r[P1@P2])
  *
diff --git a/src/box/sql/vdbeInt.h b/src/box/sql/vdbeInt.h
index 2c50b6768..edb216a8a 100644
--- a/src/box/sql/vdbeInt.h
+++ b/src/box/sql/vdbeInt.h
@@ -517,6 +517,11 @@ mem_set_u64(struct Mem *mem, uint64_t value);
 void
 mem_set_int(struct Mem *mem, int64_t value, bool is_neg);
 
+/** Set double value and MEM_Real flag. */
+void
+mem_set_double(struct Mem *mem, double value);
+
+
 void sqlVdbeMemSetDouble(Mem *, double);
 void sqlVdbeMemInit(Mem *, sql *, u32);
 void sqlVdbeMemSetNull(Mem *);
diff --git a/src/box/sql/vdbemem.c b/src/box/sql/vdbemem.c
index 8dad2db9a..9e8586ffc 100644
--- a/src/box/sql/vdbemem.c
+++ b/src/box/sql/vdbemem.c
@@ -839,6 +839,13 @@ mem_set_int(struct Mem *mem, int64_t value, bool is_neg)
 	}
 }
 
+void
+mem_set_double(struct Mem *mem, double value)
+{
+	mem->u.r = value;
+	MemSetTypeFlag(mem, MEM_Real);
+}
+
 /*
  * Delete any previous value and set the value stored in *pMem to val,
  * manifest type REAL.
diff --git a/test/sql-tap/autoinc.test.lua b/test/sql-tap/autoinc.test.lua
index 37e65e541..ec8dfeab1 100755
--- a/test/sql-tap/autoinc.test.lua
+++ b/test/sql-tap/autoinc.test.lua
@@ -618,7 +618,7 @@ test:do_catchsql_test(
             INSERT INTO t2 VALUES('asd'); 
     ]], {
         -- <autoinc-10.2>
-        1, "Type mismatch: can not convert asd to integer"
+        1, "Type mismatch: can not convert text to integer"
         -- </autoinc-10.2>
     })
 
@@ -694,7 +694,7 @@ test:do_test(
                  INSERT INTO t3928(b) VALUES('after-int-' || CAST(new.b AS TEXT));
             END;
             DELETE FROM t3928 WHERE a!=1;
-            UPDATE t3928 SET b=456 WHERE a=1;
+            UPDATE t3928 SET b='456' WHERE a=1;
             SELECT * FROM t3928 ORDER BY a;
         ]])
     end, {
diff --git a/test/sql-tap/default.test.lua b/test/sql-tap/default.test.lua
index d3e35c71c..f1def2b10 100755
--- a/test/sql-tap/default.test.lua
+++ b/test/sql-tap/default.test.lua
@@ -109,16 +109,12 @@ test:do_execsql_test(
 	f VARCHAR(15), --COLLATE RTRIM,
 	g INTEGER DEFAULT( 3600*12 )
 	);
-	INSERT INTO t3 VALUES(null, 5, 'row1', 5.25, 8.67, 321, 432);
+	INSERT INTO t3 VALUES(null, 5, 'row1', 5.25, 8.67, '321', 432);
 	SELECT a, typeof(a), b, typeof(b), c, typeof(c), 
 	d, typeof(d), e, typeof(e), f, typeof(f),
 	g, typeof(g) FROM t3;
 	]], {
 	-- <default-3.1>
-	-- TODO: In original test "321" is not a string, its a value.
-	-- 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"
 	-- </default-3.1>
 })
diff --git a/test/sql-tap/e_select1.test.lua b/test/sql-tap/e_select1.test.lua
index 1d3b964b9..7673426f4 100755
--- a/test/sql-tap/e_select1.test.lua
+++ b/test/sql-tap/e_select1.test.lua
@@ -753,11 +753,11 @@ test:do_execsql_test(
         CREATE TABLE z3(id  INT primary key, a NUMBER, b NUMBER);
 
         INSERT INTO z1 VALUES(1, 51.65, -59.58, 'belfries');
-        INSERT INTO z1 VALUES(2, -5, NULL, 75);
+        INSERT INTO z1 VALUES(2, -5, NULL, '75');
         INSERT INTO z1 VALUES(3, -2.2, -23.18, 'suiters');
         INSERT INTO z1 VALUES(4, NULL, 67, 'quartets');
         INSERT INTO z1 VALUES(5, -1.04, -32.3, 'aspen');
-        INSERT INTO z1 VALUES(6, 63, '0', -26);
+        INSERT INTO z1 VALUES(6, 63, 0, '-26');
 
         INSERT INTO z2 VALUES(1, NULL, 21);
         INSERT INTO z2 VALUES(2, 36.0, 6.0);
@@ -1457,13 +1457,13 @@ test:do_execsql_test(
         CREATE TABLE q2(id  INT primary key, d TEXT, e NUMBER);
         CREATE TABLE q3(id  INT primary key, f TEXT, g INT);
 
-        INSERT INTO q1 VALUES(1, 16, -87.66, NULL);
+        INSERT INTO q1 VALUES(1, '16', -87.66, NULL);
         INSERT INTO q1 VALUES(2, 'legible', 94, -42.47);
         INSERT INTO q1 VALUES(3, 'beauty', 36, NULL);
 
         INSERT INTO q2 VALUES(1, 'legible', 1);
         INSERT INTO q2 VALUES(2, 'beauty', 2);
-        INSERT INTO q2 VALUES(3, -65, 4);
+        INSERT INTO q2 VALUES(3, '-65', 4);
         INSERT INTO q2 VALUES(4, 'emanating', -16.56);
 
         INSERT INTO q3 VALUES(1, 'beauty', 2);
@@ -1603,7 +1603,7 @@ test:do_execsql_test(
         CREATE TABLE w2(a  INT PRIMARY KEY, b TEXT);
 
         INSERT INTO w1 VALUES('1', 4.1);
-        INSERT INTO w2 VALUES(1, 4.1);
+        INSERT INTO w2 VALUES(1, '4.1');
     ]], {
         -- <e_select-7.10.0>
 
diff --git a/test/sql-tap/gh-3809-implicit-cast-assignment.test.lua b/test/sql-tap/gh-3809-implicit-cast-assignment.test.lua
new file mode 100755
index 000000000..de72cf3a4
--- /dev/null
+++ b/test/sql-tap/gh-3809-implicit-cast-assignment.test.lua
@@ -0,0 +1,649 @@
+#!/usr/bin/env tarantool
+test = require("sqltester")
+test:plan(77)
+
+--
+-- Make sure there are no implicit casts during assignment,
+-- except for the implicit cast between numeric values.
+--
+test:execsql([[
+    CREATE TABLE ti (a INT PRIMARY KEY AUTOINCREMENT, i INTEGER);
+    CREATE TABLE td (a INT PRIMARY KEY AUTOINCREMENT, d DOUBLE);
+    CREATE TABLE tb (a INT PRIMARY KEY AUTOINCREMENT, b BOOLEAN);
+    CREATE TABLE tt (a INT PRIMARY KEY AUTOINCREMENT, t TEXT);
+    CREATE TABLE tv (a INT PRIMARY KEY AUTOINCREMENT, v VARBINARY);
+    CREATE TABLE ts (a INT PRIMARY KEY AUTOINCREMENT, s SCALAR);
+]])
+
+test:do_catchsql_test(
+    "gh-3809-1",
+    [[
+        INSERT INTO ti(i) VALUES (11)
+    ]], {
+        0
+    })
+
+test:do_catchsql_test(
+    "gh-3809-2",
+    [[
+        INSERT INTO ti(i) VALUES (22.2)
+    ]], {
+        1, "Type mismatch: can not convert real to integer"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-3",
+    [[
+        INSERT INTO ti(i) VALUES (33.0)
+    ]], {
+        0
+    })
+
+test:do_catchsql_test(
+    "gh-3809-4",
+    [[
+        INSERT INTO ti(i) VALUES (true)
+    ]], {
+        1, "Type mismatch: can not convert boolean to integer"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-5",
+    [[
+        INSERT INTO ti(i) VALUES ('33')
+    ]], {
+        1, "Type mismatch: can not convert text to integer"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-6",
+    [[
+        INSERT INTO ti(i) VALUES (X'3434')
+    ]], {
+        1, "Type mismatch: can not convert varbinary to integer"
+    })
+
+test:do_execsql_test(
+    "gh-3809-7",
+    [[
+        SELECT * FROM ti;
+    ]], {
+        1, 11, 2, 33
+    })
+
+test:do_catchsql_test(
+    "gh-3809-8",
+    [[
+        INSERT INTO td(d) VALUES (11)
+    ]], {
+        0
+    })
+
+test:do_catchsql_test(
+    "gh-3809-9",
+    [[
+        INSERT INTO td(d) VALUES (100000000000000001);
+    ]], {
+        1, "Type mismatch: can not convert unsigned to double"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-10",
+    [[
+        INSERT INTO td(d) VALUES (22.2)
+    ]], {
+        0
+    })
+
+test:do_catchsql_test(
+    "gh-3809-11",
+    [[
+        INSERT INTO td(d) VALUES (true)
+    ]], {
+        1, "Type mismatch: can not convert boolean to double"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-12",
+    [[
+        INSERT INTO td(d) VALUES ('33')
+    ]], {
+        1, "Type mismatch: can not convert text to double"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-13",
+    [[
+        INSERT INTO td(d) VALUES (X'3434')
+    ]], {
+        1, "Type mismatch: can not convert varbinary to double"
+    })
+
+test:do_execsql_test(
+    "gh-3809-14",
+    [[
+        SELECT * FROM td;
+    ]], {
+        1, 11, 2, 22.2
+    })
+
+test:do_catchsql_test(
+    "gh-3809-15",
+    [[
+        INSERT INTO tb(b) VALUES (11)
+    ]], {
+        1, "Type mismatch: can not convert unsigned to boolean"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-16",
+    [[
+        INSERT INTO tb(b) VALUES (22.2)
+    ]], {
+        1, "Type mismatch: can not convert real to boolean"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-17",
+    [[
+        INSERT INTO tb(b) VALUES (true)
+    ]], {
+        0
+    })
+
+test:do_catchsql_test(
+    "gh-3809-18",
+    [[
+        INSERT INTO tb(b) VALUES ('33')
+    ]], {
+        1, "Type mismatch: can not convert text to boolean"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-19",
+    [[
+        INSERT INTO tb(b) VALUES (X'3434')
+    ]], {
+        1, "Type mismatch: can not convert varbinary to boolean"
+    })
+
+test:do_execsql_test(
+    "gh-3809-20",
+    [[
+        SELECT * FROM tb;
+    ]], {
+        1, true
+    })
+
+test:do_catchsql_test(
+    "gh-3809-21",
+    [[
+        INSERT INTO tt(t) VALUES (11)
+    ]], {
+        1, "Type mismatch: can not convert unsigned to string"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-22",
+    [[
+        INSERT INTO tt(t) VALUES (22.2)
+    ]], {
+        1, "Type mismatch: can not convert real to string"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-23",
+    [[
+        INSERT INTO tt(t) VALUES (true)
+    ]], {
+        1, "Type mismatch: can not convert boolean to string"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-24",
+    [[
+        INSERT INTO tt(t) VALUES ('33')
+    ]], {
+        0
+    })
+
+test:do_catchsql_test(
+    "gh-3809-25",
+    [[
+        INSERT INTO tt(t) VALUES (X'3434')
+    ]], {
+        1, "Type mismatch: can not convert varbinary to string"
+    })
+
+test:do_execsql_test(
+    "gh-3809-26",
+    [[
+        SELECT * FROM tt;
+    ]], {
+        1, "33"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-27",
+    [[
+        INSERT INTO tv(v) VALUES (11)
+    ]], {
+        1, "Type mismatch: can not convert unsigned to varbinary"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-28",
+    [[
+        INSERT INTO tv(v) VALUES (22.2)
+    ]], {
+        1, "Type mismatch: can not convert real to varbinary"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-29",
+    [[
+        INSERT INTO tv(v) VALUES (true)
+    ]], {
+        1, "Type mismatch: can not convert boolean to varbinary"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-30",
+    [[
+        INSERT INTO tv(v) VALUES ('33')
+    ]], {
+        1, "Type mismatch: can not convert text to varbinary"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-31",
+    [[
+        INSERT INTO tv(v) VALUES (X'3434')
+    ]], {
+        0
+    })
+
+test:do_execsql_test(
+    "gh-3809-32",
+    [[
+        SELECT * FROM tv;
+    ]], {
+        1, "44"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-33",
+    [[
+        INSERT INTO ts(s) VALUES (11)
+    ]], {
+        0
+    })
+
+test:do_catchsql_test(
+    "gh-3809-34",
+    [[
+        INSERT INTO ts(s) VALUES (22.2)
+    ]], {
+        0
+    })
+
+test:do_catchsql_test(
+    "gh-3809-35",
+    [[
+        INSERT INTO ts(s) VALUES (true)
+    ]], {
+        0
+    })
+
+test:do_catchsql_test(
+    "gh-3809-36",
+    [[
+        INSERT INTO ts(s) VALUES ('33')
+    ]], {
+        0
+    })
+
+test:do_catchsql_test(
+    "gh-3809-37",
+    [[
+        INSERT INTO ts(s) VALUES (X'3434')
+    ]], {
+        0
+    })
+
+test:do_execsql_test(
+    "gh-3809-38",
+    [[
+        SELECT * FROM ts;
+    ]], {
+        1, 11, 2, 22.2, 3, true, 4, "33", 5, "44"
+    })
+
+test:execsql([[
+    DELETE FROM ti;
+    DELETE FROM td;
+    DELETE FROM tb;
+    DELETE FROM tt;
+    DELETE FROM tv;
+    DELETE FROM ts;
+    INSERT INTO ti(a) VALUES(1);
+    INSERT INTO td(a) VALUES(1);
+    INSERT INTO tb(a) VALUES(1);
+    INSERT INTO tt(a) VALUES(1);
+    INSERT INTO tv(a) VALUES(1);
+    INSERT INTO ts(a) VALUES(1);
+]])
+
+test:do_execsql_test(
+    "gh-3809-39",
+    [[
+        SELECT * FROM ti, td, tb, tt, tv, ts;
+    ]], {
+        1, "", 1, "", 1, "", 1, "", 1, "", 1, ""
+    })
+
+test:do_catchsql_test(
+    "gh-3809-40",
+    [[
+        UPDATE ti SET i = 11 WHERE a = 1;
+    ]], {
+        0
+    })
+
+test:do_catchsql_test(
+    "gh-3809-41",
+    [[
+        UPDATE ti SET i = 22.2 WHERE a = 1;
+    ]], {
+        1, "Type mismatch: can not convert real to integer"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-42",
+    [[
+        UPDATE ti SET i = 33.0 WHERE a = 1;
+    ]], {
+        0
+    })
+
+test:do_catchsql_test(
+    "gh-3809-43",
+    [[
+        UPDATE ti SET i = true WHERE a = 1;
+    ]], {
+        1, "Type mismatch: can not convert boolean to integer"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-44",
+    [[
+        UPDATE ti SET i = '33' WHERE a = 1;
+    ]], {
+        1, "Type mismatch: can not convert text to integer"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-45",
+    [[
+        UPDATE ti SET i = X'3434' WHERE a = 1;
+    ]], {
+        1, "Type mismatch: can not convert varbinary to integer"
+    })
+
+test:do_execsql_test(
+    "gh-3809-46",
+    [[
+        SELECT * FROM ti;
+    ]], {
+        1, 33
+    })
+
+test:do_catchsql_test(
+    "gh-3809-47",
+    [[
+        UPDATE td SET d = 11 WHERE a = 1;
+    ]], {
+        0
+    })
+
+test:do_catchsql_test(
+    "gh-3809-48",
+    [[
+        UPDATE td SET d = 100000000000000001 WHERE a = 1;
+    ]], {
+        1, "Type mismatch: can not convert unsigned to double"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-49",
+    [[
+        UPDATE td SET d = 22.2 WHERE a = 1;
+    ]], {
+        0
+    })
+
+test:do_catchsql_test(
+    "gh-3809-50",
+    [[
+        UPDATE td SET d = true WHERE a = 1;
+    ]], {
+        1, "Type mismatch: can not convert boolean to double"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-51",
+    [[
+        UPDATE td SET d = '33' WHERE a = 1;
+    ]], {
+        1, "Type mismatch: can not convert text to double"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-52",
+    [[
+        UPDATE td SET d = X'3434' WHERE a = 1;
+    ]], {
+        1, "Type mismatch: can not convert varbinary to double"
+    })
+
+test:do_execsql_test(
+    "gh-3809-53",
+    [[
+        SELECT * FROM td;
+    ]], {
+        1, 22.2
+    })
+
+test:do_catchsql_test(
+    "gh-3809-54",
+    [[
+        UPDATE tb SET b = 11 WHERE a = 1;
+    ]], {
+        1, "Type mismatch: can not convert unsigned to boolean"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-55",
+    [[
+        UPDATE tb SET b = 22.2 WHERE a = 1;
+    ]], {
+        1, "Type mismatch: can not convert real to boolean"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-56",
+    [[
+        UPDATE tb SET b = true WHERE a = 1;
+    ]], {
+        0
+    })
+
+test:do_catchsql_test(
+    "gh-3809-57",
+    [[
+        UPDATE tb SET b = '33' WHERE a = 1;
+    ]], {
+        1, "Type mismatch: can not convert text to boolean"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-58",
+    [[
+        UPDATE tb SET b = X'3434' WHERE a = 1;
+    ]], {
+        1, "Type mismatch: can not convert varbinary to boolean"
+    })
+
+test:do_execsql_test(
+    "gh-3809-59",
+    [[
+        SELECT * FROM tb;
+    ]], {
+        1, true
+    })
+
+test:do_catchsql_test(
+    "gh-3809-60",
+    [[
+        UPDATE tt SET t = 11 WHERE a = 1;
+    ]], {
+        1, "Type mismatch: can not convert unsigned to string"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-61",
+    [[
+        UPDATE tt SET t = 22.2 WHERE a = 1;
+    ]], {
+        1, "Type mismatch: can not convert real to string"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-62",
+    [[
+        UPDATE tt SET t = true WHERE a = 1;
+    ]], {
+        1, "Type mismatch: can not convert boolean to string"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-63",
+    [[
+        UPDATE tt SET t = '33' WHERE a = 1;
+    ]], {
+        0
+    })
+
+test:do_catchsql_test(
+    "gh-3809-64",
+    [[
+        UPDATE tt SET t = X'3434' WHERE a = 1;
+    ]], {
+        1, "Type mismatch: can not convert varbinary to string"
+    })
+
+test:do_execsql_test(
+    "gh-3809-65",
+    [[
+        SELECT * FROM tt;
+    ]], {
+        1, "33"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-66",
+    [[
+        UPDATE tv SET v = 11 WHERE a = 1;
+    ]], {
+        1, "Type mismatch: can not convert unsigned to varbinary"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-67",
+    [[
+        UPDATE tv SET v = 22.2 WHERE a = 1;
+    ]], {
+        1, "Type mismatch: can not convert real to varbinary"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-68",
+    [[
+        UPDATE tv SET v = true WHERE a = 1;
+    ]], {
+        1, "Type mismatch: can not convert boolean to varbinary"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-69",
+    [[
+        UPDATE tv SET v = '33' WHERE a = 1;
+    ]], {
+        1, "Type mismatch: can not convert text to varbinary"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-70",
+    [[
+        UPDATE tv SET v = X'3434' WHERE a = 1;
+    ]], {
+        0
+    })
+
+test:do_execsql_test(
+    "gh-3809-71",
+    [[
+        SELECT * FROM tv;
+    ]], {
+        1, "44"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-72",
+    [[
+        UPDATE ts SET s = 11 WHERE a = 1;
+    ]], {
+        0
+    })
+
+test:do_catchsql_test(
+    "gh-3809-73",
+    [[
+        UPDATE ts SET s = 22.2 WHERE a = 1;
+    ]], {
+        0
+    })
+
+test:do_catchsql_test(
+    "gh-3809-74",
+    [[
+        UPDATE ts SET s = true WHERE a = 1;
+    ]], {
+        0
+    })
+
+test:do_catchsql_test(
+    "gh-3809-75",
+    [[
+        UPDATE ts SET s = '33' WHERE a = 1;
+    ]], {
+        0
+    })
+
+test:do_catchsql_test(
+    "gh-3809-76",
+    [[
+        UPDATE ts SET s = X'3434' WHERE a = 1;
+    ]], {
+        0
+    })
+
+test:do_execsql_test(
+    "gh-3809-77",
+    [[
+        SELECT * FROM ts;
+    ]], {
+        1, "44"
+    })
+
+test:finish_test()
diff --git a/test/sql-tap/index1.test.lua b/test/sql-tap/index1.test.lua
index e173e685c..ce66b7c1e 100755
--- a/test/sql-tap/index1.test.lua
+++ b/test/sql-tap/index1.test.lua
@@ -593,25 +593,17 @@ test:do_test(
         -- </index-11.1>
     })
 end
--- integrity_check index-11.2
--- Numeric strings should compare as if they were numbers.  So even if the
--- strings are not character-by-character the same, if they represent the
--- same number they should compare equal to one another.  Verify that this
--- is true in indices.
---
--- Updated for sql v3: sql will now store these values as numbers
--- (because the affinity of column a is NUMERIC) so the quirky
--- representations are not retained. i.e. '+1.0' becomes '1'.
+
 test:do_execsql_test(
     "index-12.1",
     [[
         CREATE TABLE t4(id  INT primary key, a NUMBER,b INT );
-        INSERT INTO t4 VALUES(1, '0.0',1);
-        INSERT INTO t4 VALUES(2, '0.00',2);
-        INSERT INTO t4 VALUES(4, '-1.0',4);
-        INSERT INTO t4 VALUES(5, '+1.0',5);
-        INSERT INTO t4 VALUES(6, '0',6);
-        INSERT INTO t4 VALUES(7, '00000',7);
+        INSERT INTO t4 VALUES(1, 0.0, 1);
+        INSERT INTO t4 VALUES(2, 0.00, 2);
+        INSERT INTO t4 VALUES(4, -1.0, 4);
+        INSERT INTO t4 VALUES(5, +1.0, 5);
+        INSERT INTO t4 VALUES(6, 0, 6);
+        INSERT INTO t4 VALUES(7, 00000, 7);
         SELECT a FROM t4 ORDER BY b;
     ]], {
         -- <index-12.1>
@@ -692,7 +684,7 @@ test:do_execsql_test(
            c  TEXT,
            UNIQUE(a,c)
         );
-        INSERT INTO t5 VALUES(1,2,3);
+        INSERT INTO t5 VALUES(1,2,'3');
         SELECT * FROM t5;
     ]], {
         -- <index-13.1>
diff --git a/test/sql-tap/insert3.test.lua b/test/sql-tap/insert3.test.lua
index 43bb06630..b92bc508e 100755
--- a/test/sql-tap/insert3.test.lua
+++ b/test/sql-tap/insert3.test.lua
@@ -60,7 +60,7 @@ test:do_execsql_test(
             CREATE TABLE log2(rowid INTEGER PRIMARY KEY AUTOINCREMENT, x TEXT UNIQUE,y INT );
             CREATE TRIGGER r2 BEFORE INSERT ON t1 FOR EACH ROW BEGIN
               UPDATE log2 SET y=y+1 WHERE x=new.b;
-              INSERT OR IGNORE INTO log2(x, y) VALUES(new.b,1);
+              INSERT OR IGNORE INTO log2(x, y) VALUES(CAST(new.b AS STRING),1);
             END;
             INSERT INTO t1(a, b) VALUES('hi', 453);
             SELECT x,y FROM log ORDER BY x;
@@ -129,8 +129,8 @@ test:do_execsql_test(
               INSERT INTO t2dup(a,b,c) VALUES(new.a,new.b,new.c);
             END;
             INSERT INTO t2(a) VALUES(123);
-            INSERT INTO t2(b) VALUES(234);
-            INSERT INTO t2(c) VALUES(345);
+            INSERT INTO t2(b) VALUES('234');
+            INSERT INTO t2(c) VALUES('345');
             SELECT * FROM t2dup;
     ]], {
         -- <insert3-2.1>
@@ -143,8 +143,8 @@ test:do_execsql_test(
     [[
             DELETE FROM t2dup;
             INSERT INTO t2(a) SELECT 1 FROM t1 LIMIT 1;
-            INSERT INTO t2(b) SELECT 987 FROM t1 LIMIT 1;
-            INSERT INTO t2(c) SELECT 876 FROM t1 LIMIT 1;
+            INSERT INTO t2(b) SELECT '987' FROM t1 LIMIT 1;
+            INSERT INTO t2(c) SELECT '876' FROM t1 LIMIT 1;
             SELECT * FROM t2dup;
     ]], {
         -- <insert3-2.2>
diff --git a/test/sql-tap/intpkey.test.lua b/test/sql-tap/intpkey.test.lua
index b6b186632..0db18ba91 100755
--- a/test/sql-tap/intpkey.test.lua
+++ b/test/sql-tap/intpkey.test.lua
@@ -770,11 +770,6 @@ test:do_execsql_test(
         -- </intpkey-11.1>
     })
 
--- integrity_check intpkey-12.1
--- Try to use a string that looks like a floating point number as
--- an integer primary key.  This should actually work when the floating
--- point value can be rounded to an integer without loss of data.
---
 test:do_execsql_test(
     "intpkey-13.1",
     [[
@@ -788,7 +783,7 @@ test:do_execsql_test(
 test:do_execsql_test(
     "intpkey-13.2",
     [[
-        INSERT INTO t1 VALUES('1',2,3);
+        INSERT INTO t1 VALUES(1,'2','3');
         SELECT * FROM t1 WHERE a=1;
     ]], {
         -- <intpkey-13.2>
@@ -825,7 +820,7 @@ end
 test:do_catchsql_test(
     "intpkey-13.5",
     [[
-        INSERT INTO t1 VALUES('+1234567890',3,4);
+        INSERT INTO t1 VALUES(1234567890,'3','4');
     ]], {
         -- <intpkey-13.5>
         0
@@ -842,7 +837,7 @@ test:do_execsql_test(
         CREATE TABLE t3(a INTEGER PRIMARY KEY, b INTEGER, c TEXT);
         INSERT INTO t3 VALUES(1, 1, 'one');
         INSERT INTO t3 VALUES(2, 2, '2');
-        INSERT INTO t3 VALUES(3, 3, 3);
+        INSERT INTO t3 VALUES(3, 3, '3');
     ]], {
         -- <intpkey-14.1>
         
@@ -905,7 +900,7 @@ test:do_execsql_test(
 test:do_execsql_test(
     "intpkey-15.1",
     [[
-        INSERT INTO t1 VALUES(2147483647, 'big-1', 123);
+        INSERT INTO t1 VALUES(2147483647, 'big-1', '123');
         SELECT * FROM t1 WHERE a>2147483648;
     ]], {
         -- <intpkey-15.1>
diff --git a/test/sql-tap/minmax2.test.lua b/test/sql-tap/minmax2.test.lua
index 0e0f0d08e..707d1c4da 100755
--- a/test/sql-tap/minmax2.test.lua
+++ b/test/sql-tap/minmax2.test.lua
@@ -441,9 +441,9 @@ test:do_execsql_test(
     "minmax2-8.2",
     [[
         CREATE TABLE t5(a INTEGER PRIMARY KEY);
-        INSERT INTO t5 VALUES('1234');
-        INSERT INTO t5 VALUES('234');
-        INSERT INTO t5 VALUES('34');
+        INSERT INTO t5 VALUES(1234);
+        INSERT INTO t5 VALUES(234);
+        INSERT INTO t5 VALUES(34);
         SELECT min(a), max(a) FROM t5;
     ]], {
         -- <minmax2-8.2>
diff --git a/test/sql-tap/misc1.test.lua b/test/sql-tap/misc1.test.lua
index 32f38cc97..e0fe50bbe 100755
--- a/test/sql-tap/misc1.test.lua
+++ b/test/sql-tap/misc1.test.lua
@@ -34,9 +34,9 @@ test:do_test(
         end
         cmd = cmd .. ")"
         test:execsql(cmd)
-        cmd = "INSERT INTO manycol VALUES(1, 0"
+        cmd = "INSERT INTO manycol VALUES(1, '0'"
         for i = 1, 99, 1 do
-            cmd = cmd .. ","..i..""
+            cmd = cmd .. ",'"..i.."'"
         end
         cmd = cmd .. ")"
         test:execsql(cmd)
@@ -61,9 +61,9 @@ test:do_test(
     "misc1-1.3.1",
     function()
         for j = 100, 1000, 100 do
-            local cmd = string.format("INSERT INTO manycol VALUES(%s, %s", j, j)
+            local cmd = string.format("INSERT INTO manycol VALUES(%s, '%s'", j, j)
             for i = 1, 99, 1 do
-                cmd = cmd .. ","..(i + j)..""
+                cmd = cmd .. ",'"..(i + j).."'"
             end
             cmd = cmd .. ")"
             test:execsql(cmd)
@@ -178,12 +178,12 @@ test:do_test(
         test:execsql([[
             CREATE TABLE agger(one text primary key, two text, three text, four text);
             START TRANSACTION;
-            INSERT INTO agger VALUES(1, 'one', 'hello', 'yes');
-            INSERT INTO agger VALUES(2, 'two', 'howdy', 'no');
-            INSERT INTO agger VALUES(3, 'thr', 'howareya', 'yes');
-            INSERT INTO agger VALUES(4, 'two', 'lothere', 'yes');
-            INSERT INTO agger VALUES(5, 'one', 'atcha', 'yes');
-            INSERT INTO agger VALUES(6, 'two', 'hello', 'no');
+            INSERT INTO agger VALUES('1', 'one', 'hello', 'yes');
+            INSERT INTO agger VALUES('2', 'two', 'howdy', 'no');
+            INSERT INTO agger VALUES('3', 'thr', 'howareya', 'yes');
+            INSERT INTO agger VALUES('4', 'two', 'lothere', 'yes');
+            INSERT INTO agger VALUES('5', 'one', 'atcha', 'yes');
+            INSERT INTO agger VALUES('6', 'two', 'hello', 'no');
             COMMIT
         ]])
         return test:execsql("SELECT count(*) FROM agger")
@@ -531,7 +531,7 @@ test:do_test(
     "misc1-10.7",
     function()
         where = string.gsub(where, "x0=0", "x0=100")
-        return test:catchsql("UPDATE manycol SET x1=x1+1 "..where.."")
+        return test:catchsql("UPDATE manycol SET x1=CAST(x1+1 AS STRING) "..where.."")
     end, {
         -- <misc1-10.7>
         0
@@ -553,7 +553,7 @@ test:do_execsql_test(
 -- } {0 {}}
 test:do_execsql_test(
     "misc1-10.9",
-    "UPDATE manycol SET x1=x1+1 "..where
+    "UPDATE manycol SET x1=CAST(x1+1 AS STRING) "..where
         --"UPDATE manycol SET x1=x1+1 $::where AND rowid>0"
     , {})
 
@@ -665,7 +665,7 @@ test:do_execsql_test(
 test:do_execsql_test(
     "misc1-12.6",
     [[
-        INSERT OR IGNORE INTO t6 VALUES('y',0);
+        INSERT OR IGNORE INTO t6 VALUES('y','0');
         SELECT * FROM t6;
     ]], {
         -- <misc1-12.6>
@@ -679,10 +679,10 @@ test:do_execsql_test(
     "misc1-12.7",
     [[
         CREATE TABLE t7(x INTEGER, y TEXT, z  INT primary key);
-        INSERT INTO t7 VALUES(0,0,1);
-        INSERT INTO t7 VALUES(0.0,0,2);
-        INSERT INTO t7 VALUES(0,0.0,3);
-        INSERT INTO t7 VALUES(0.0,0.0,4);
+        INSERT INTO t7 VALUES(0,'0',1);
+        INSERT INTO t7 VALUES(0.0,'0',2);
+        INSERT INTO t7 VALUES(0,'0.0',3);
+        INSERT INTO t7 VALUES(0.0,'0.0',4);
         SELECT DISTINCT x, y FROM t7 ORDER BY z;
     ]], {
         -- <misc1-12.7>
diff --git a/test/sql-tap/numcast.test.lua b/test/sql-tap/numcast.test.lua
index eeac5353a..9bbae5ca4 100755
--- a/test/sql-tap/numcast.test.lua
+++ b/test/sql-tap/numcast.test.lua
@@ -135,7 +135,7 @@ test:do_catchsql_test(
         INSERT INTO t VALUES(20000000000000000000.01);
         SELECT * FROM t;
     ]], {
-        1,"Tuple field 1 type does not match one required by operation: expected integer"
+        1,"Type mismatch: can not convert real to integer"
     })
 
 test:do_catchsql_test(
@@ -144,7 +144,7 @@ test:do_catchsql_test(
         INSERT INTO t VALUES(2.1);
         SELECT * FROM t;
     ]], {
-        1,"Tuple field 1 type does not match one required by operation: expected integer"
+        1,"Type mismatch: can not convert real to integer"
     })
 
 --
diff --git a/test/sql-tap/select1.test.lua b/test/sql-tap/select1.test.lua
index fbebfab37..9a969bf3c 100755
--- a/test/sql-tap/select1.test.lua
+++ b/test/sql-tap/select1.test.lua
@@ -231,7 +231,7 @@ string.format([[
         CREATE TABLE t3(id INT, a TEXT, b TEXT, PRIMARY KEY(id));
         INSERT INTO t3 VALUES(1, 'abc',NULL);
         INSERT INTO t3 VALUES(2, NULL,'xyz');
-        INSERT INTO t3 SELECT f1, * FROM test1;
+        INSERT INTO t3 SELECT f1, CAST(f1 AS STRING), CAST(f2 AS STRING) FROM test1;
         DROP TABLE IF EXISTS t4;
         CREATE TABLE t4(id INT, a INT , b TEXT , PRIMARY KEY(id));
         INSERT INTO t4 VALUES(1, NULL,'%s');
@@ -1671,8 +1671,8 @@ test:do_execsql_test(
     [[
         DELETE FROM t3;
         DELETE FROM t4;
-        INSERT INTO t3 VALUES(0,1,2);
-        INSERT INTO t4 VALUES(0,3,4);
+        INSERT INTO t3 VALUES(0,'1','2');
+        INSERT INTO t4 VALUES(0,3,'4');
         SELECT * FROM t3, t4;
     ]], {
         -- <select1-11.1>
@@ -1878,7 +1878,7 @@ test:do_execsql_test(
     "select1-12.4",
     [[
         DELETE FROM t3;
-        INSERT INTO t3 VALUES(0,1,2);
+        INSERT INTO t3 VALUES(0,'1','2');
     ]], {
         -- <select1-12.4>
         
diff --git a/test/sql-tap/select4.test.lua b/test/sql-tap/select4.test.lua
index 23cf1bf1b..f7a320438 100755
--- a/test/sql-tap/select4.test.lua
+++ b/test/sql-tap/select4.test.lua
@@ -761,12 +761,12 @@ test:do_test(
         test:execsql [[
             CREATE TABLE t3(a text primary key, b NUMBER, c text);
             START TRANSACTION;
-            INSERT INTO t3 VALUES(1, 1.1, '1.1');
-            INSERT INTO t3 VALUES(2, 1.10, '1.10');
-            INSERT INTO t3 VALUES(3, 1.10, '1.1');
-            INSERT INTO t3 VALUES(4, 1.1, '1.10');
-            INSERT INTO t3 VALUES(5, 1.2, '1.2');
-            INSERT INTO t3 VALUES(6, 1.3, '1.3');
+            INSERT INTO t3 VALUES('1', 1.1, '1.1');
+            INSERT INTO t3 VALUES('2', 1.10, '1.10');
+            INSERT INTO t3 VALUES('3', 1.10, '1.1');
+            INSERT INTO t3 VALUES('4', 1.1, '1.10');
+            INSERT INTO t3 VALUES('5', 1.2, '1.2');
+            INSERT INTO t3 VALUES('6', 1.3, '1.3');
             COMMIT;
         ]]
         return test:execsql [[
diff --git a/test/sql-tap/select7.test.lua b/test/sql-tap/select7.test.lua
index fec5d7a41..e1e43c557 100755
--- a/test/sql-tap/select7.test.lua
+++ b/test/sql-tap/select7.test.lua
@@ -255,7 +255,7 @@ test:do_execsql_test(
     [[
         DROP TABLE IF EXISTS t5;
         CREATE TABLE t5(a TEXT primary key, b INT);
-        INSERT INTO t5 VALUES(123, 456);
+        INSERT INTO t5 VALUES('123', 456);
         SELECT typeof(a), a FROM t5 GROUP BY a HAVING a<b;
     ]], {
         -- <select7-7.7>
diff --git a/test/sql-tap/sort.test.lua b/test/sql-tap/sort.test.lua
index 36074d6ef..18bfd443d 100755
--- a/test/sql-tap/sort.test.lua
+++ b/test/sql-tap/sort.test.lua
@@ -505,10 +505,10 @@ test:do_execsql_test(
           a INTEGER PRIMARY KEY,
           b VARCHAR(30)
         );
-        INSERT INTO t4 VALUES(1,1);
-        INSERT INTO t4 VALUES(2,2);
-        INSERT INTO t4 VALUES(11,11);
-        INSERT INTO t4 VALUES(12,12);
+        INSERT INTO t4 VALUES(1,'1');
+        INSERT INTO t4 VALUES(2,'2');
+        INSERT INTO t4 VALUES(11,'11');
+        INSERT INTO t4 VALUES(12,'12');
         SELECT a FROM t4 ORDER BY 1;
     ]], {
         -- <sort-7.1>
diff --git a/test/sql-tap/tkt-3998683a16.test.lua b/test/sql-tap/tkt-3998683a16.test.lua
index 885dcf5cd..9bc310358 100755
--- a/test/sql-tap/tkt-3998683a16.test.lua
+++ b/test/sql-tap/tkt-3998683a16.test.lua
@@ -26,29 +26,17 @@ test:do_test(
     function()
         return test:execsql [[
             CREATE TABLE t1(x  INT primary key, y NUMBER);
-            INSERT INTO t1 VALUES(1, '1.0');
-            INSERT INTO t1 VALUES(2, '.125');
-            INSERT INTO t1 VALUES(3, '123.');
-            INSERT INTO t1 VALUES(4, '123.e+2');
-            INSERT INTO t1 VALUES(5, '.125e+3');
-            INSERT INTO t1 VALUES(6, '123e4');
-            INSERT INTO t1 VALUES(11, '  1.0');
-            INSERT INTO t1 VALUES(12, '  .125');
-            INSERT INTO t1 VALUES(13, '  123.');
-            INSERT INTO t1 VALUES(14, '  123.e+2');
-            INSERT INTO t1 VALUES(15, '  .125e+3');
-            INSERT INTO t1 VALUES(16, '  123e4');
-            INSERT INTO t1 VALUES(21, '1.0  ');
-            INSERT INTO t1 VALUES(22, '.125  ');
-            INSERT INTO t1 VALUES(23, '123.  ');
-            INSERT INTO t1 VALUES(24, '123.e+2  ');
-            INSERT INTO t1 VALUES(25, '.125e+3  ');
-            INSERT INTO t1 VALUES(26, '123e4  ');
+            INSERT INTO t1 VALUES(1, 1.0);
+            INSERT INTO t1 VALUES(2, .125);
+            INSERT INTO t1 VALUES(3, 123.);
+            INSERT INTO t1 VALUES(4, 123.e+2);
+            INSERT INTO t1 VALUES(5, .125e+3);
+            INSERT INTO t1 VALUES(6, 123e4);
             SELECT x FROM t1 WHERE typeof(y)=='number' ORDER BY x;
         ]]
     end, {
         -- <tkt-3998683a16.1>
-        1, 2, 3, 4, 5, 6, 11, 12, 13, 14, 15, 16, 21, 22, 23, 24, 25, 26
+        1, 2, 3, 4, 5, 6
         -- </tkt-3998683a16.1>
     })
 
diff --git a/test/sql-tap/tkt-54844eea3f.test.lua b/test/sql-tap/tkt-54844eea3f.test.lua
index d6cd56e52..89d0d1218 100755
--- a/test/sql-tap/tkt-54844eea3f.test.lua
+++ b/test/sql-tap/tkt-54844eea3f.test.lua
@@ -62,10 +62,10 @@ test:do_execsql_test(
     "1.2",
     [[
         CREATE TABLE t4(id INT primary key, a TEXT, b TEXT, c TEXT);
-        INSERT INTO t4 VALUES(1, 'a', 1, 'one');
-        INSERT INTO t4 VALUES(2, 'a', 2, 'two');
-        INSERT INTO t4 VALUES(3, 'b', 1, 'three');
-        INSERT INTO t4 VALUES(4, 'b', 2, 'four');
+        INSERT INTO t4 VALUES(1, 'a', '1', 'one');
+        INSERT INTO t4 VALUES(2, 'a', '2', 'two');
+        INSERT INTO t4 VALUES(3, 'b', '1', 'three');
+        INSERT INTO t4 VALUES(4, 'b', '2', 'four');
         SELECT ( 
           SELECT c FROM (
             SELECT a,b,c FROM t4 WHERE a=output.a ORDER BY b LIMIT 10 OFFSET 1
diff --git a/test/sql-tap/tkt-7bbfb7d442.test.lua b/test/sql-tap/tkt-7bbfb7d442.test.lua
index 535303771..bfddcd920 100755
--- a/test/sql-tap/tkt-7bbfb7d442.test.lua
+++ b/test/sql-tap/tkt-7bbfb7d442.test.lua
@@ -109,13 +109,13 @@ if (1 > 0)
                     T1.Variant AS Variant,
                     T1.ControlDate AS ControlDate,
                     1 AS ControlState,
-                    COALESCE(T2.DeliveredQty,0) AS DeliveredQty
+                    CAST(COALESCE(T2.DeliveredQty,0) AS STRING) AS DeliveredQty
                 FROM (
                     SELECT
                         NEW.InventoryControlId AS InventoryControlId,
                         II.SKU AS SKU,
                         II.Variant AS Variant,
-                        COALESCE(LastClosedIC.ControlDate,NEW.ControlDate) AS ControlDate
+                        CAST(COALESCE(LastClosedIC.ControlDate,NEW.ControlDate) AS STRING) AS ControlDate
                     FROM
                         InventoryItem II
                     LEFT JOIN
diff --git a/test/sql-tap/tkt1444.test.lua b/test/sql-tap/tkt1444.test.lua
index 82a5ded25..fb148bc5f 100755
--- a/test/sql-tap/tkt1444.test.lua
+++ b/test/sql-tap/tkt1444.test.lua
@@ -30,8 +30,8 @@ test:do_execsql_test(
     [[
         CREATE TABLE DemoTable (id  INT primary key, x INTEGER, TextKey TEXT, DKey NUMBER);
         CREATE INDEX DemoTableIdx ON DemoTable (TextKey);
-        INSERT INTO DemoTable VALUES(1, 9,8,7);
-        INSERT INTO DemoTable VALUES(2, 1,2,3);
+        INSERT INTO DemoTable VALUES(1, 9,'8',7);
+        INSERT INTO DemoTable VALUES(2, 1,'2',3);
         CREATE VIEW DemoView AS SELECT x, TextKey, DKey FROM DemoTable ORDER BY TextKey;
         SELECT x,TextKey,DKey FROM DemoTable UNION ALL SELECT * FROM DemoView ORDER BY 1;
     ]], {
diff --git a/test/sql-tap/tkt3493.test.lua b/test/sql-tap/tkt3493.test.lua
index 7ceec4702..de77e61e9 100755
--- a/test/sql-tap/tkt3493.test.lua
+++ b/test/sql-tap/tkt3493.test.lua
@@ -29,8 +29,8 @@ test:do_execsql_test(
         START TRANSACTION;
         INSERT INTO A VALUES(1,'123');
         INSERT INTO A VALUES(2,'456');
-        INSERT INTO B VALUES(1,1);
-        INSERT INTO B VALUES(2,2);
+        INSERT INTO B VALUES(1,'1');
+        INSERT INTO B VALUES(2,'2');
         INSERT INTO A_B VALUES(1,1);
         INSERT INTO A_B VALUES(2,2);
         COMMIT;
@@ -116,7 +116,7 @@ test:do_execsql_test(
     "tkt3493-2.1",
     [[
         CREATE TABLE t1(a TEXT PRIMARY KEY, b INT);
-        INSERT INTO t1 VALUES(123, 456);
+        INSERT INTO t1 VALUES('123', 456);
     ]], {
         -- <tkt3493-2.1>
         
diff --git a/test/sql-tap/tkt3841.test.lua b/test/sql-tap/tkt3841.test.lua
index 5203d0cd4..56668f6a3 100755
--- a/test/sql-tap/tkt3841.test.lua
+++ b/test/sql-tap/tkt3841.test.lua
@@ -31,12 +31,12 @@ test:do_execsql_test(
 
         INSERT INTO table2 VALUES ('a', 'alist');
         INSERT INTO table2 VALUES ('b', 'blist');
-        INSERT INTO list VALUES ('a', 1);
-        INSERT INTO list VALUES ('a', 2);
-        INSERT INTO list VALUES ('a', 3);
-        INSERT INTO list VALUES ('b', 4);
-        INSERT INTO list VALUES ('b', 5);
-        INSERT INTO list VALUES ('b', 6);
+        INSERT INTO list VALUES ('a', '1');
+        INSERT INTO list VALUES ('a', '2');
+        INSERT INTO list VALUES ('a', '3');
+        INSERT INTO list VALUES ('b', '4');
+        INSERT INTO list VALUES ('b', '5');
+        INSERT INTO list VALUES ('b', '6');
 
         SELECT
           table2.x,
diff --git a/test/sql-tap/triggerA.test.lua b/test/sql-tap/triggerA.test.lua
index fac51ca14..fc8ecfe17 100755
--- a/test/sql-tap/triggerA.test.lua
+++ b/test/sql-tap/triggerA.test.lua
@@ -283,7 +283,7 @@ test:do_test(
             CREATE TABLE result2(id INTEGER PRIMARY KEY, a TEXT,b INT);
             CREATE TRIGGER r5d INSTEAD OF DELETE ON v5 FOR EACH ROW BEGIN
               INSERT INTO result2(id, a,b) VALUES((SELECT coalesce(max(id),0) + 1 FROM result2),
-                                                  old.x, old.b);
+                                                  CAST(old.x AS STRING), old.b);
             END;
             DELETE FROM v5 WHERE x=5;
             SELECT a, b FROM result2;
@@ -301,7 +301,7 @@ test:do_test(
             DELETE FROM result4;
             CREATE TRIGGER r5u INSTEAD OF UPDATE ON v5 FOR EACH ROW BEGIN
               INSERT INTO result4(id, a,b,c,d) VALUES((SELECT coalesce(max(id),0) + 1 FROM result4),
-                                                      old.x, old.b, new.x, new.b);
+                                                      CAST(old.x AS STRING), old.b, CAST(new.x AS STRING), new.b);
             END;
             UPDATE v5 SET b = b+9900000 WHERE x BETWEEN 3 AND 5;
             SELECT a,b,c,d FROM result4 ORDER BY a;
diff --git a/test/sql-tap/unique.test.lua b/test/sql-tap/unique.test.lua
index 9818f90a8..6b0a7e20d 100755
--- a/test/sql-tap/unique.test.lua
+++ b/test/sql-tap/unique.test.lua
@@ -52,7 +52,7 @@ test:do_catchsql_test(
 test:do_catchsql_test(
     "unique-1.2",
     [[
-        INSERT INTO t1(a,b,c) VALUES(1,2,3)
+        INSERT INTO t1(a,b,c) VALUES(1,2,'3')
     ]], {
         -- <unique-1.2>
         0
@@ -62,7 +62,7 @@ test:do_catchsql_test(
 test:do_catchsql_test(
     "unique-1.3",
     [[
-        INSERT INTO t1(a,b,c) VALUES(1,3,4)
+        INSERT INTO t1(a,b,c) VALUES(1,3,'4')
     ]], {
         -- <unique-1.3>
         1, "Duplicate key exists in unique index 'pk_unnamed_T1_1' in space 'T1'"
@@ -83,7 +83,7 @@ test:do_execsql_test(
 test:do_catchsql_test(
     "unique-1.5",
     [[
-        INSERT INTO t1(a,b,c) VALUES(3,2,4)
+        INSERT INTO t1(a,b,c) VALUES(3,2,'4')
     ]], {
         -- <unique-1.5>
         1, "Duplicate key exists in unique index 'unique_unnamed_T1_2' in space 'T1'"
@@ -104,7 +104,7 @@ test:do_execsql_test(
 test:do_catchsql_test(
     "unique-1.7",
     [[
-        INSERT INTO t1(a,b,c) VALUES(3,4,5)
+        INSERT INTO t1(a,b,c) VALUES(3,4,'5')
     ]], {
         -- <unique-1.7>
         0
diff --git a/test/sql-tap/view.test.lua b/test/sql-tap/view.test.lua
index e553b91c7..ab14c5edb 100755
--- a/test/sql-tap/view.test.lua
+++ b/test/sql-tap/view.test.lua
@@ -757,7 +757,7 @@ test:do_execsql_test(
     "view-10.1",
     [=[
         CREATE TABLE t3("9" integer primary key, "4" text);
-        INSERT INTO t3 VALUES(1,2);
+        INSERT INTO t3 VALUES(1,'2');
         CREATE VIEW v_t3_a AS SELECT a."9" FROM t3 AS a;
         CREATE VIEW v_t3_b AS SELECT "4" FROM t3;
         SELECT * FROM v_t3_a;
diff --git a/test/sql-tap/where5.test.lua b/test/sql-tap/where5.test.lua
index 749201564..3aefcaca5 100755
--- a/test/sql-tap/where5.test.lua
+++ b/test/sql-tap/where5.test.lua
@@ -27,11 +27,11 @@ test:do_test("where5-1.0", function()
         CREATE TABLE t1(x TEXT primary key);
         CREATE TABLE t2(x integer primary key);
         CREATE TABLE t3(x integer PRIMARY KEY);
-        INSERT INTO t1 VALUES(-1);
-        INSERT INTO t1 VALUES(0);
-        INSERT INTO t1 VALUES(1);
-        INSERT INTO t2 SELECT * FROM t1;
-        INSERT INTO t3 SELECT * FROM t1;
+        INSERT INTO t1 VALUES('-1');
+        INSERT INTO t1 VALUES('0');
+        INSERT INTO t1 VALUES('1');
+        INSERT INTO t2 SELECT CAST(x AS INTEGER) FROM t1;
+        INSERT INTO t3 SELECT CAST(x AS INTEGER) FROM t1;
     ]]
     return test:execsql [[
         SELECT * FROM t1 WHERE x<0
diff --git a/test/sql-tap/whereB.test.lua b/test/sql-tap/whereB.test.lua
index d98645fdc..fe5e28c70 100755
--- a/test/sql-tap/whereB.test.lua
+++ b/test/sql-tap/whereB.test.lua
@@ -112,24 +112,16 @@ test:do_execsql_test(
     -- </whereB-1.102>
     })
 
--- For this set of tests:
---
---  *   t1.y holds a text value with affinity TEXT
---  *   t2.b holds an integer value with affinity NONE
---
--- These values are not equal and because neither affinity is NUMERIC
--- no type conversion occurs.
---
 test:do_execsql_test(
     "whereB-2.1",
     [[
         DROP TABLE t1;
         DROP TABLE t2;
 
-        CREATE TABLE t1(x  INT primary key, y TEXT);    -- affinity of t1.y is TEXT
-        INSERT INTO t1 VALUES(1,99);
+        CREATE TABLE t1(x  INT primary key, y TEXT);
+        INSERT INTO t1 VALUES(1,'99');
 
-        CREATE TABLE t2(a  INT primary key, b SCALAR);  -- affinity of t2.b is NONE
+        CREATE TABLE t2(a  INT primary key, b SCALAR);
         CREATE INDEX t2b ON t2(b);
         INSERT INTO t2 VALUES(2, 99);
 
diff --git a/test/sql/boolean.result b/test/sql/boolean.result
index 112e41a12..e88183854 100644
--- a/test/sql/boolean.result
+++ b/test/sql/boolean.result
@@ -161,7 +161,7 @@ SELECT s FROM ts WHERE s IN (true, 1, 'abcd');
 INSERT INTO ts VALUES (true, 12345);
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to integer'
+ | - 'Type mismatch: can not convert boolean to integer'
  | ...
 
 -- Check that we can create index on field of type BOOLEAN.
diff --git a/test/sql/persistency.result b/test/sql/persistency.result
index 6d14d4c4e..6ec2f06fc 100644
--- a/test/sql/persistency.result
+++ b/test/sql/persistency.result
@@ -370,7 +370,7 @@ box.execute("SELECT \"name\", \"opts\" FROM \"_trigger\"");
 box.execute("INSERT INTO foobar VALUES ('foobar trigger test', 8888)")
 ---
 - null
-- 'Type mismatch: can not convert foobar trigger test to integer'
+- 'Type mismatch: can not convert text to integer'
 ...
 box.execute("SELECT * FROM barfoo WHERE foo = 9999");
 ---
diff --git a/test/sql/types.result b/test/sql/types.result
index 54aff460e..6b0f7a651 100644
--- a/test/sql/types.result
+++ b/test/sql/types.result
@@ -1062,7 +1062,7 @@ box.execute("INSERT INTO t1 VALUES (0), (1), (2);")
 box.execute("INSERT INTO t1 VALUES (-3);")
 ---
 - null
-- 'Type mismatch: can not convert -3 to unsigned'
+- 'Type mismatch: can not convert integer to unsigned'
 ...
 box.execute("SELECT id FROM t1;")
 ---
@@ -1220,22 +1220,22 @@ box.execute("CREATE TABLE t (id INT PRIMARY KEY, v VARBINARY);")
 box.execute("INSERT INTO t VALUES(1, 1);")
 ---
 - null
-- 'Type mismatch: can not convert 1 to varbinary'
+- 'Type mismatch: can not convert unsigned to varbinary'
 ...
 box.execute("INSERT INTO t VALUES(1, 1.123);")
 ---
 - null
-- 'Type mismatch: can not convert 1.123 to varbinary'
+- 'Type mismatch: can not convert real to varbinary'
 ...
 box.execute("INSERT INTO t VALUES(1, true);")
 ---
 - null
-- 'Type mismatch: can not convert TRUE to varbinary'
+- 'Type mismatch: can not convert boolean to varbinary'
 ...
 box.execute("INSERT INTO t VALUES(1, 'asd');")
 ---
 - null
-- 'Type mismatch: can not convert asd to varbinary'
+- 'Type mismatch: can not convert text to varbinary'
 ...
 box.execute("INSERT INTO t VALUES(1, x'616263');")
 ---
@@ -1617,7 +1617,7 @@ s:insert({1, {1,2,3}})
 box.execute('INSERT INTO t1(a) SELECT a FROM t2;')
 ---
 - null
-- 'Type mismatch: can not convert [1, 2, 3] to scalar'
+- 'Type mismatch: can not convert varbinary to scalar'
 ...
 s:replace({1, {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30}})
 ---
@@ -1627,8 +1627,7 @@ s:replace({1, {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25
 box.execute('INSERT INTO t1(a) SELECT a FROM t2;')
 ---
 - null
-- 'Type mismatch: can not convert [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
-  15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30] to scalar'
+- 'Type mismatch: can not convert varbinary to scalar'
 ...
 --
 -- Make sure that the error will be displayed correctly even if
@@ -1653,13 +1652,7 @@ s:replace({1, long_array})
 box.execute('INSERT INTO t1(a) SELECT a FROM t2;')
 ---
 - null
-- 'Type mismatch: can not convert [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
-  15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
-  35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
-  55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74,
-  75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94,
-  95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
-  112, 113, 114, 115, 116, 117, 11'
+- 'Type mismatch: can not convert varbinary to scalar'
 ...
 s:drop()
 ---
@@ -1680,7 +1673,7 @@ s:insert({1, {b = 1}})
 box.execute('INSERT INTO t1(a) SELECT a FROM t2;')
 ---
 - null
-- 'Type mismatch: can not convert {"b": 1} to scalar'
+- 'Type mismatch: can not convert varbinary to scalar'
 ...
 s:drop()
 ---
-- 
2.25.1

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2020-06-23  6:44 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-06-11 12:54 [Tarantool-patches] [PATCH v2 0/7] Remove implicit cast imeevma
2020-06-11 12:54 ` [Tarantool-patches] [PATCH v2 1/7] sql: remove implicit cast for assignment imeevma
2020-06-11 12:54 ` [Tarantool-patches] [PATCH v2 2/7] sql: remove mem_apply_type() from OP_MakeRecord imeevma
2020-06-11 12:54 ` [Tarantool-patches] [PATCH v2 3/7] sql: replace ApplyType by CheckType for IN operator imeevma
2020-06-11 12:54 ` [Tarantool-patches] [PATCH v2 4/7] sql: remove mem_apply_type() from OP_MustBeInt imeevma
2020-06-11 12:54 ` [Tarantool-patches] [PATCH v2 5/7] sql: remove implicit cast from string for comparison imeevma
2020-06-11 12:54 ` [Tarantool-patches] [PATCH v2 6/7] sql: remove OP_ApplyType imeevma
2020-06-11 12:54 ` [Tarantool-patches] [PATCH v2 7/7] sql: use type instead of value in type mismatch error imeevma
2020-06-14 17:03   ` Vladislav Shpilevoy
2020-06-17 12:36 [Tarantool-patches] [PATCH v2 0/7] Remove implicit cast imeevma
2020-06-17 12:36 ` [Tarantool-patches] [PATCH v2 1/7] sql: remove implicit cast for assignment imeevma
2020-06-22  8:23   ` Nikita Pettik
2020-06-22 20:47     ` Vladislav Shpilevoy
2020-06-22 21:08       ` Nikita Pettik
2020-06-23  6:44         ` Mergen Imeev

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox