Tarantool development patches archive
 help / color / mirror / Atom feed
* [Tarantool-patches] [PATCH v3 0/8] Remove implicit cast
@ 2020-06-25 15:17 imeevma
  2020-06-25 15:17 ` [Tarantool-patches] [PATCH v3 1/8] sql: introduce mem_set_double() imeevma
                   ` (7 more replies)
  0 siblings, 8 replies; 32+ messages in thread
From: imeevma @ 2020-06-25 15:17 UTC (permalink / raw)
  To: korablev, 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.

v3:
 - Introduction of mem_set_double() was moved to another commit.
 - Implicit cast rules for assigning were changed.

Mergen Imeev (8):
  sql: introduce mem_set_double()
  sql: change 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 for comparison
  sql: remove unused functions
  sql: show value and its type 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/func.c                            |    8 +-
 src/box/sql/insert.c                          |   16 +-
 src/box/sql/select.c                          |   25 +-
 src/box/sql/sqlInt.h                          |   34 +-
 src/box/sql/update.c                          |   14 +-
 src/box/sql/vdbe.c                            |  322 ++--
 src/box/sql/vdbeInt.h                         |    5 +-
 src/box/sql/vdbeapi.c                         |   31 +-
 src/box/sql/vdbemem.c                         |   38 +-
 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 |  653 ++++++++
 .../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                 |  133 +-
 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                 |    8 +-
 test/sql-tap/select1.test.lua                 |   18 +-
 test/sql-tap/select4.test.lua                 |   12 +-
 test/sql-tap/select5.test.lua                 |    2 +-
 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                       | 1484 ++++++++---------
 test/sql/integer-overflow.result              |    4 +-
 test/sql/persistency.result                   |    2 +-
 test/sql/types.result                         |   67 +-
 test/sql/types.test.lua                       |    1 -
 62 files changed, 2231 insertions(+), 3526 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] 32+ messages in thread

* [Tarantool-patches] [PATCH v3 1/8] sql: introduce mem_set_double()
  2020-06-25 15:17 [Tarantool-patches] [PATCH v3 0/8] Remove implicit cast imeevma
@ 2020-06-25 15:17 ` imeevma
  2020-06-28 13:31   ` Nikita Pettik
  2020-06-25 15:17 ` [Tarantool-patches] [PATCH v3 2/8] sql: change implicit cast for assignment imeevma
                   ` (6 subsequent siblings)
  7 siblings, 1 reply; 32+ messages in thread
From: imeevma @ 2020-06-25 15:17 UTC (permalink / raw)
  To: korablev, tsafin, tarantool-patches

The mem_set_double () function is used to properly set MEM as
containing DOUBLE value.
---
 src/box/sql/func.c    |  8 ++++----
 src/box/sql/vdbe.c    |  9 +++------
 src/box/sql/vdbeInt.h |  5 ++++-
 src/box/sql/vdbeapi.c |  4 ++--
 src/box/sql/vdbemem.c | 25 ++++++++++---------------
 5 files changed, 23 insertions(+), 28 deletions(-)

diff --git a/src/box/sql/func.c b/src/box/sql/func.c
index 4715ffabb..1856fe343 100644
--- a/src/box/sql/func.c
+++ b/src/box/sql/func.c
@@ -267,10 +267,10 @@ port_lua_get_vdbemem(struct port *base, uint32_t *size)
 			mem_set_bool(&val[i], field.bval);
 			break;
 		case MP_FLOAT:
-			sqlVdbeMemSetDouble(&val[i], field.fval);
+			mem_set_double(&val[i], field.fval);
 			break;
 		case MP_DOUBLE:
-			sqlVdbeMemSetDouble(&val[i], field.dval);
+			mem_set_double(&val[i], field.dval);
 			break;
 		case MP_INT:
 			mem_set_i64(&val[i], field.ival);
@@ -338,10 +338,10 @@ port_c_get_vdbemem(struct port *base, uint32_t *size)
 			mem_set_bool(&val[i], mp_decode_bool(&data));
 			break;
 		case MP_FLOAT:
-			sqlVdbeMemSetDouble(&val[i], mp_decode_float(&data));
+			mem_set_double(&val[i], mp_decode_float(&data));
 			break;
 		case MP_DOUBLE:
-			sqlVdbeMemSetDouble(&val[i], mp_decode_double(&data));
+			mem_set_double(&val[i], mp_decode_double(&data));
 			break;
 		case MP_INT:
 			mem_set_i64(&val[i], mp_decode_int(&data));
diff --git a/src/box/sql/vdbe.c b/src/box/sql/vdbe.c
index 6b769805c..950f72ddd 100644
--- a/src/box/sql/vdbe.c
+++ b/src/box/sql/vdbe.c
@@ -271,8 +271,7 @@ mem_apply_numeric_type(struct Mem *record)
 	double float_value;
 	if (sqlAtoF(record->z, &float_value, record->n) == 0)
 		return -1;
-	record->u.r = float_value;
-	MemSetTypeFlag(record, MEM_Real);
+	mem_set_double(record, float_value);
 	return 0;
 }
 
@@ -1198,9 +1197,8 @@ case OP_Int64: {           /* out2 */
  */
 case OP_Real: {            /* same as TK_FLOAT, out2 */
 	pOut = vdbe_prepare_null_out(p, pOp->p2);
-	pOut->flags = MEM_Real;
 	assert(!sqlIsNaN(*pOp->p4.pReal));
-	pOut->u.r = *pOp->p4.pReal;
+	mem_set_double(pOut, *pOp->p4.pReal);
 	break;
 }
 
@@ -1673,8 +1671,7 @@ case OP_Remainder: {           /* same as TK_REM, in1, in2, out3 */
 		if (sqlIsNaN(rB)) {
 			goto arithmetic_result_is_null;
 		}
-		pOut->u.r = rB;
-		MemSetTypeFlag(pOut, MEM_Real);
+		mem_set_double(pOut, rB);
 	}
 	break;
 
diff --git a/src/box/sql/vdbeInt.h b/src/box/sql/vdbeInt.h
index 2c50b6768..a3ecd13af 100644
--- a/src/box/sql/vdbeInt.h
+++ b/src/box/sql/vdbeInt.h
@@ -517,7 +517,10 @@ mem_set_u64(struct Mem *mem, uint64_t value);
 void
 mem_set_int(struct Mem *mem, int64_t value, bool is_neg);
 
-void sqlVdbeMemSetDouble(Mem *, double);
+/** Set double value and MEM_Real flag. */
+void
+mem_set_double(struct Mem *mem, double value);
+
 void sqlVdbeMemInit(Mem *, sql *, u32);
 void sqlVdbeMemSetNull(Mem *);
 void sqlVdbeMemSetZeroBlob(Mem *, int);
diff --git a/src/box/sql/vdbeapi.c b/src/box/sql/vdbeapi.c
index 6e307e97f..4e103a653 100644
--- a/src/box/sql/vdbeapi.c
+++ b/src/box/sql/vdbeapi.c
@@ -330,7 +330,7 @@ sql_result_blob64(sql_context * pCtx,
 void
 sql_result_double(sql_context * pCtx, double rVal)
 {
-	sqlVdbeMemSetDouble(pCtx->pOut, rVal);
+	mem_set_double(pCtx->pOut, rVal);
 }
 
 void
@@ -1021,7 +1021,7 @@ sql_bind_double(sql_stmt * pStmt, int i, double rValue)
 	if (vdbeUnbind(p, i) != 0)
 		return -1;
 	int rc = sql_bind_type(p, i, "numeric");
-	sqlVdbeMemSetDouble(&p->aVar[i - 1], rValue);
+	mem_set_double(&p->aVar[i - 1], rValue);
 	return rc;
 }
 
diff --git a/src/box/sql/vdbemem.c b/src/box/sql/vdbemem.c
index 8dad2db9a..a721afc83 100644
--- a/src/box/sql/vdbemem.c
+++ b/src/box/sql/vdbemem.c
@@ -561,9 +561,7 @@ sqlVdbeMemRealify(Mem * pMem)
 	double v;
 	if (sqlVdbeRealValue(pMem, &v))
 		return -1;
-
-	pMem->u.r = v;
-	MemSetTypeFlag(pMem, MEM_Real);
+	mem_set_double(pMem, v);
 	return 0;
 }
 
@@ -583,9 +581,10 @@ vdbe_mem_numerify(struct Mem *mem)
 	if (sql_atoi64(mem->z, &i, &is_neg, mem->n) == 0) {
 		mem_set_int(mem, i, is_neg);
 	} else {
-		if (sqlAtoF(mem->z, &mem->u.r, mem->n) == 0)
+		double d;
+		if (sqlAtoF(mem->z, &d, mem->n) == 0)
 			return -1;
-		MemSetTypeFlag(mem, MEM_Real);
+		mem_set_double(mem, d);
 	}
 	return 0;
 }
@@ -839,18 +838,14 @@ mem_set_int(struct Mem *mem, int64_t value, bool is_neg)
 	}
 }
 
-/*
- * Delete any previous value and set the value stored in *pMem to val,
- * manifest type REAL.
- */
 void
-sqlVdbeMemSetDouble(Mem * pMem, double val)
+mem_set_double(struct Mem *mem, double value)
 {
-	sqlVdbeMemSetNull(pMem);
-	if (!sqlIsNaN(val)) {
-		pMem->u.r = val;
-		pMem->flags = MEM_Real;
-	}
+	sqlVdbeMemSetNull(mem);
+	if (sqlIsNaN(value))
+		return;
+	mem->u.r = value;
+	MemSetTypeFlag(mem, MEM_Real);
 }
 
 /*
-- 
2.25.1

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

* [Tarantool-patches] [PATCH v3 2/8] sql: change implicit cast for assignment
  2020-06-25 15:17 [Tarantool-patches] [PATCH v3 0/8] Remove implicit cast imeevma
  2020-06-25 15:17 ` [Tarantool-patches] [PATCH v3 1/8] sql: introduce mem_set_double() imeevma
@ 2020-06-25 15:17 ` imeevma
  2020-06-30 11:50   ` Nikita Pettik
  2020-06-25 15:17 ` [Tarantool-patches] [PATCH v3 3/8] sql: remove mem_apply_type() from OP_MakeRecord imeevma
                   ` (5 subsequent siblings)
  7 siblings, 1 reply; 32+ messages in thread
From: imeevma @ 2020-06-25 15:17 UTC (permalink / raw)
  To: korablev, tsafin, tarantool-patches

Hi! Thank you for review. My answers and new patch below. I
haven't included diffs since there were quite a few changes.
I have included answers to review questions in the next three
patches here.

On 22.06.2020 11:23, Nikita Pettik wrote:
> 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.
>
I divided into 2 functions: mem_check_type (), which checks, and
mem_convert_numeric(), which converts.

>> +{
>> +  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.
>
Fixed, I think.

>> +  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?
>
We do not have a MEM type corresponding to MP_EXT, so we cannot
get MP_EXT in this function.

>> +    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.
>
I replaced by ImplicitCast for now.

>> + * 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).
>
Fixed in previous commit. In fact, I found that such a function
already exists, so I renamed it and refactored it a bit.

>> +  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.
>
Fixed. Fully fixed in the last commit of the set.

>> @@ -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?
>
As far as I know, the TAP format is preferable.

>> +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?
>
It should, new rules I described in doc request.

>> +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?
>
Added a comment here.

>> +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?
>
Removed these tests.

>>      ]], {
>>          -- <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
>
Removed these tests.

>>  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
>
Removed these tests.

>>  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);
>>  



On 22.06.2020 11:48, Nikita Pettik wrote:
> On 17 Jun 15:36, imeevma@tarantool.org wrote:
>> This patch removes type changing from OP_MakeRecord.
>
> Please reflect user-visible changes in commit message.
>  
Fixed.

>> 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/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
>>



On 22.06.2020 12:32, Nikita Pettik wrote:
> On 17 Jun 15:36, imeevma@tarantool.org wrote:
>> 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/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>
>>      })
>
> Again, old format of error message containing value which
> can't be converted seems more suitable to me. Mb it is worth
> combining them putting in error message both type and value:
>
> ... convert 'hello' (type : text) to integer
>  
Fixed in the last patch of the set.

> Otherwise LGTM
>
>> 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'
>>   | ...




On 22.06.2020 13:07, Nikita Pettik wrote:
> On 17 Jun 15:36, imeevma@tarantool.org wrote:
>> 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
>> ---
>>  src/box/sql/vdbe.c                   |   2 +-
>>  test/sql-tap/e_select1.test.lua      |  17 +-
>>  test/sql-tap/in4.test.lua            |  97 +--
>>  test/sql-tap/join.test.lua           |   1 -
>>  test/sql-tap/limit.test.lua          |   2 +-
>>  test/sql-tap/tkt-9a8b09f8e6.test.lua |  24 +-
>>  test/sql-tap/tkt-fc7bd6358f.test.lua | 111 ----
>>  test/sql-tap/transitive1.test.lua    |   4 +-
>>  test/sql-tap/whereB.test.lua         | 900 ---------------------------
>>  test/sql-tap/whereC.test.lua         |   8 +-
>>  10 files changed, 19 insertions(+), 1147 deletions(-)
>>  delete mode 100755 test/sql-tap/tkt-fc7bd6358f.test.lua
>>  delete mode 100755 test/sql-tap/whereB.test.lua
>>
>> 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,
>
> Have the code coverage changed after these patches?
> I'm wondering since a lot of tests are removed now (I believe
> due to redundancy, so in perfect case coverage may even increase).
>
The coverage of src/box/sql/* has not changed according to
coverall.io:
https://coveralls.io/builds/31683427

>> 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)
>>  




New patch:

commit 21d7145c1929bc4606c56e9a566477f248637ed1
Author: Mergen Imeev <imeevma@gmail.com>
Date:   Wed May 27 13:49:11 2020 +0300

    sql: change implicit cast for assignment
    
    This patch changes implicit cast for assignment.
    
    Closes #3809
    
    @TarantoolBot document
    Title: change implicit cast for comparison
    
    After this patch, these rules will apply during the implicit cast:
    
    | | STRING | BINARY | BOOLEAN | INTEGER | UNSIGNED | DOUBLE |
    | :--- | :---: | :---: | :---: | :---: | :---: | :---: |
    | STRING | A | N | N | N | N | N |
    | BINARY | N | A | N | N | N | N |
    | BOOLEAN | N | N | A | N | N | N |
    | INTEGER | N | N | N | A | S | Aa |
    | UNSIGNED | N | N | N | A | A | Aa |
    | DOUBLE | N | N | N | Sa | Sa | A |
    
    In this table, the types of the assigned value are on the left,
    and the types that should be after the assignment are at the top.
    
    'A' - the assignment will be completed.
    'N' - the assignment won't be completed.
    'S' - the appointment may be unsuccessful.
    'a' - after assignment, the resulting value may be approximated.
    
    Rules for numeric values are these:
    1) Loss of significant digits (overflow) is an error.
    2) Loss of insignificant digits is not an error.
    
    Example:
    ```
    tarantool> box.execute([[CREATE TABLE t1(i INT PRIMARY KEY);]])
    tarantool> box.execute([[INSERT INTO t1 VALUES ('1');]])
    ---
    - null
    - 'Type mismatch: can not convert 1 to integer'
    ...
    
    tarantool> box.execute('INSERT INTO t1 VALUES (1.2345);')
    tarantool> box.execute('SELECT * FROM t1;')
    ---
    - metadata:
      - name: I
        type: integer
      rows:
      - [1]
    ...
    
    tarantool> box.execute([[CREATE TABLE t2(t text PRIMARY KEY);]])
    tarantool> box.execute([[INSERT INTO t2 VALUES (1);]])
    ---
    - null
    - 'Type mismatch: can not convert 1 to string'
    ...
    ```

diff --git a/src/box/sql/insert.c b/src/box/sql/insert.c
index 588e142d2..8a89f9904 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_ImplicitCast, reg, field_count, 0,
        (char *)colls_type, P4_DYNAMIC);
 }
 
diff --git a/src/box/sql/sqlInt.h b/src/box/sql/sqlInt.h
index 37283e506..f1d0345f9 100644
--- a/src/box/sql/sqlInt.h
+++ b/src/box/sql/sqlInt.h
@@ -397,6 +397,15 @@ sql_value_to_diag_str(sql_value *value);
 enum mp_type
 sql_value_type(sql_value *);
 
+/*
+ * Return the MP_type of the value of the MEM.
+ *
+ * @param mem MEM with the correct MEM_type.
+ * @retval MP_type of the value.
+ */
+enum mp_type
+sql_value_mp_type(struct Mem *mem);
+
 static inline bool
 sql_value_is_null(sql_value *value)
 {
diff --git a/src/box/sql/vdbe.c b/src/box/sql/vdbe.c
index 950f72ddd..009d577d2 100644
--- a/src/box/sql/vdbe.c
+++ b/src/box/sql/vdbe.c
@@ -417,6 +417,143 @@ sql_value_apply_type(
  mem_apply_type((Mem *) pVal, type);
 }
 
+/**
+ * Check that MEM_type of the mem is compatible with given type.
+ *
+ * @param mem The MEM that contains the value to check.
+ * @param type The type to check.
+ * @retval 0 if the MEM_type of the value ​​and the given type are
+ *         compatible, -1 otherwise.
+ */
+static int
+mem_check_type(struct Mem *mem, enum field_type type)
+{
+ enum mp_type mp_type = sql_value_mp_type(mem);
+ assert(mp_type < MP_EXT);
+ if (field_mp_plain_type_is_compatible(type, mp_type, true))
+   return 0;
+ return -1;
+}
+
+/**
+ * Convert the numeric value contained in MEM to double. If the
+ * is_precise flag is set, the conversion will succeed only if it
+ * is lossless.
+ *
+ * @param mem The MEM that contains the numeric value.
+ * @param is_precise Flag.
+ * @retval 0 if the conversion was successful, -1 otherwise.
+ */
+static int
+mem_convert_to_double(struct Mem *mem, bool is_precise)
+{
+ if ((mem->flags & (MEM_Int | MEM_UInt)) == 0)
+   return -1;
+ if ((mem->flags & MEM_Int) != 0) {
+   int64_t i = mem->u.i;
+   double d = (double)i;
+   if (!is_precise || i == (int64_t)d)
+     mem_set_double(mem, d);
+   else
+     return -1;
+ } else {
+   uint64_t u = mem->u.u;
+   double d = (double)u;
+   if (!is_precise || u == (uint64_t)d)
+     mem_set_double(mem, d);
+   else
+     return -1;
+ }
+ mem->field_type = FIELD_TYPE_DOUBLE;
+ return 0;
+}
+
+/**
+ * Convert the numeric value contained in MEM to unsigned. If the
+ * is_precise flag is set, the conversion will succeed only if it
+ * is lossless.
+ *
+ * @param mem The MEM that contains the numeric value.
+ * @param is_precise Flag.
+ * @retval 0 if the conversion was successful, -1 otherwise.
+ */
+static int
+mem_convert_to_unsigned(struct Mem *mem, bool is_precise)
+{
+ if ((mem->flags & MEM_Real) == 0)
+   return -1;
+ double d = mem->u.r;
+ if (d < 0.0 || d >= (double)UINT64_MAX)
+   return -1;
+ uint64_t u = (uint64_t)d;
+ if (!is_precise || d == (double)u)
+   mem_set_u64(mem, (uint64_t) d);
+ else
+   return -1;
+ mem->field_type = FIELD_TYPE_UNSIGNED;
+ return 0;
+}
+
+/**
+ * Convert the numeric value contained in MEM to integer. If the
+ * is_precise flag is set, the conversion will succeed only if it
+ * is lossless.
+ *
+ * @param mem The MEM that contains the numeric value.
+ * @param is_precise Flag.
+ * @retval 0 if the conversion was successful, -1 otherwise.
+ */
+static int
+mem_convert_to_integer(struct Mem *mem, bool is_precise)
+{
+ if ((mem->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 (!is_precise || d == (double)i)
+     mem_set_i64(mem, (int64_t) d);
+   else
+     return -1;
+ } else {
+   uint64_t u = (uint64_t)d;
+   if (!is_precise || d == (double)u)
+     mem_set_u64(mem, (uint64_t) d);
+   else
+     return -1;
+ }
+ mem->field_type = FIELD_TYPE_INTEGER;
+ return 0;
+}
+
+/**
+ * Convert the numeric value contained in MEM to another numeric
+ * type. If the is_precise flag is set, the conversion will
+ * succeed only if it is lossless.
+ *
+ * @param mem The MEM that contains the numeric value.
+ * @param type The type to convert to.
+ * @param is_precise Flag.
+ * @retval 0 if the conversion was successful, -1 otherwise.
+ */
+static int
+mem_convert_numeric(struct Mem *mem, enum field_type type, bool is_precise)
+{
+ if (!sql_type_is_numeric(type) ||
+     (mem->flags & (MEM_Real | MEM_Int | MEM_UInt)) == 0)
+   return -1;
+ if (type == FIELD_TYPE_NUMBER)
+   return 0;
+ if (type == FIELD_TYPE_DOUBLE)
+   return mem_convert_to_double(mem, is_precise);
+ if (type == FIELD_TYPE_UNSIGNED)
+   return mem_convert_to_unsigned(mem, is_precise);
+ assert(type == FIELD_TYPE_INTEGER);
+ return mem_convert_to_integer(mem, is_precise);
+}
+
 /*
  * 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
@@ -2773,6 +2910,36 @@ 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.
+ * If the MEM_type of the value and the given type are
+ * incompatible, but both are numeric, this opcode attempts to
+ * convert the value to the type.
+ */
+case OP_ImplicitCast: {
+ 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_type(pIn1, type) != 0 &&
+       mem_convert_numeric(pIn1, type, false) != 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: MakeRecord P1 P2 P3 P4 P5
  * Synopsis: r[P3]=mkrec(r[P1@P2])
  *
diff --git a/src/box/sql/vdbeapi.c b/src/box/sql/vdbeapi.c
index 4e103a653..087c661ec 100644
--- a/src/box/sql/vdbeapi.c
+++ b/src/box/sql/vdbeapi.c
@@ -225,6 +225,33 @@ sql_value_type(sql_value *pVal)
  }
 }
 
+enum mp_type
+sql_value_mp_type(struct Mem *mem)
+{
+ switch (mem->flags & MEM_PURE_TYPE_MASK) {
+ case MEM_Int:
+   return MP_INT;
+ case MEM_UInt:
+   return MP_UINT;
+ case MEM_Real:
+   return MP_DOUBLE;
+ case MEM_Str:
+   return MP_STR;
+ case MEM_Blob:
+   if ((mem->flags & MEM_Subtype) == 0 ||
+       mem->subtype != SQL_SUBTYPE_MSGPACK)
+     return MP_BIN;
+   assert(mp_typeof(*mem->z) == MP_MAP ||
+          mp_typeof(*mem->z) == MP_ARRAY);
+   return mp_typeof(*mem->z);
+ case MEM_Bool:
+   return MP_BOOL;
+ case MEM_Null:
+   return MP_NIL;
+ default: unreachable();
+ }
+}
+
 /* Make a copy of an sql_value object
  */
 sql_value *
diff --git a/test/sql-tap/autoinc.test.lua b/test/sql-tap/autoinc.test.lua
index 37e65e541..07442b60a 100755
--- a/test/sql-tap/autoinc.test.lua
+++ b/test/sql-tap/autoinc.test.lua
@@ -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..a1809b3cb
--- /dev/null
+++ b/test/sql-tap/gh-3809-implicit-cast-assignment.test.lua
@@ -0,0 +1,653 @@
+#!/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 (100000000000000000000000000000000.1)
+    ]], {
+        1, "Type mismatch: can not convert 1.0e+32 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 TRUE to integer"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-5",
+    [[
+        INSERT INTO ti(i) VALUES ('33')
+    ]], {
+        1, "Type mismatch: can not convert 33 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);
+    ]], {
+        0
+    })
+
+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 TRUE to double"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-12",
+    [[
+        INSERT INTO td(d) VALUES ('33')
+    ]], {
+        1, "Type mismatch: can not convert 33 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, 100000000000000000, 3, 22.2
+    })
+
+test:do_catchsql_test(
+    "gh-3809-15",
+    [[
+        INSERT INTO tb(b) VALUES (11)
+    ]], {
+        1, "Type mismatch: can not convert 11 to boolean"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-16",
+    [[
+        INSERT INTO tb(b) VALUES (22.2)
+    ]], {
+        1, "Type mismatch: can not convert 22.2 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 33 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 11 to string"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-22",
+    [[
+        INSERT INTO tt(t) VALUES (22.2)
+    ]], {
+        1, "Type mismatch: can not convert 22.2 to string"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-23",
+    [[
+        INSERT INTO tt(t) VALUES (true)
+    ]], {
+        1, "Type mismatch: can not convert TRUE 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 11 to varbinary"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-28",
+    [[
+        INSERT INTO tv(v) VALUES (22.2)
+    ]], {
+        1, "Type mismatch: can not convert 22.2 to varbinary"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-29",
+    [[
+        INSERT INTO tv(v) VALUES (true)
+    ]], {
+        1, "Type mismatch: can not convert TRUE to varbinary"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-30",
+    [[
+        INSERT INTO tv(v) VALUES ('33')
+    ]], {
+        1, "Type mismatch: can not convert 33 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"
+    })
+
+--
+-- This test suite verifies that ASSIGNMENT is working correctly
+-- during an UPDATE.
+--
+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 = 100000000000000000000000000000000.1 WHERE a = 1;
+    ]], {
+        1, "Type mismatch: can not convert 1.0e+32 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 TRUE to integer"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-44",
+    [[
+        UPDATE ti SET i = '33' WHERE a = 1;
+    ]], {
+        1, "Type mismatch: can not convert 33 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;
+    ]], {
+        0
+    })
+
+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 TRUE to double"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-51",
+    [[
+        UPDATE td SET d = '33' WHERE a = 1;
+    ]], {
+        1, "Type mismatch: can not convert 33 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 11 to boolean"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-55",
+    [[
+        UPDATE tb SET b = 22.2 WHERE a = 1;
+    ]], {
+        1, "Type mismatch: can not convert 22.2 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 33 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 11 to string"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-61",
+    [[
+        UPDATE tt SET t = 22.2 WHERE a = 1;
+    ]], {
+        1, "Type mismatch: can not convert 22.2 to string"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-62",
+    [[
+        UPDATE tt SET t = true WHERE a = 1;
+    ]], {
+        1, "Type mismatch: can not convert TRUE 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 11 to varbinary"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-67",
+    [[
+        UPDATE tv SET v = 22.2 WHERE a = 1;
+    ]], {
+        1, "Type mismatch: can not convert 22.2 to varbinary"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-68",
+    [[
+        UPDATE tv SET v = true WHERE a = 1;
+    ]], {
+        1, "Type mismatch: can not convert TRUE to varbinary"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-69",
+    [[
+        UPDATE tv SET v = '33' WHERE a = 1;
+    ]], {
+        1, "Type mismatch: can not convert 33 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..684a24114 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(31)
 
 --!./tcltestrunner.lua
 -- 2001 September 15
@@ -770,142 +770,13 @@ 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",
-    [[
-        SELECT * FROM t1 WHERE a=1;
-    ]], {
-        -- <intpkey-13.1>
-        
-        -- </intpkey-13.1>
-    })
-
-test:do_execsql_test(
-    "intpkey-13.2",
-    [[
-        INSERT INTO t1 VALUES('1',2,3);
-        SELECT * FROM t1 WHERE a=1;
-    ]], {
-        -- <intpkey-13.2>
-        1, "2", "3"
-        -- </intpkey-13.2>
-    })
-
--- MUST_WORK_TEST
-if (0 > 0) then
-    -- Tarantool: issue submitted #2315
-    test:do_catchsql_test(
-        "intpkey-13.3",
-        [[
-            INSERT INTO t1 VALUES('1.5',3,4);
-        ]], {
-            -- <intpkey-13.3>
-            1, "datatype mismatch"
-            -- </intpkey-13.3>
-        })
-
-    test:do_catchsql_test(
-        "intpkey-13.4",
-        [[
-            INSERT INTO t1 VALUES(x'123456',3,4);
-        ]], {
-            -- <intpkey-13.4>
-            1, "datatype mismatch"
-            -- </intpkey-13.4>
-        })
-
-
-
-end
-test:do_catchsql_test(
-    "intpkey-13.5",
-    [[
-        INSERT INTO t1 VALUES('+1234567890',3,4);
-    ]], {
-        -- <intpkey-13.5>
-        0
-        -- </intpkey-13.5>
-    })
-
--- Compare an INTEGER PRIMARY KEY against a TEXT expression. The INTEGER
--- affinity should be applied to the text value before the comparison
--- takes place.
---
-test:do_execsql_test(
-    "intpkey-14.1",
-    [[
-        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);
-    ]], {
-        -- <intpkey-14.1>
-        
-        -- </intpkey-14.1>
-    })
-
-test:do_execsql_test(
-    "intpkey-14.2",
-    [[
-        SELECT * FROM t3 WHERE a>2;
-    ]], {
-        -- <intpkey-14.2>
-        3, 3, "3"
-        -- </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(
-    "intpkey-14.4",
-    [[
-        SELECT * FROM t3 WHERE a<'2';
-    ]], {
-        -- <intpkey-14.4>
-        1, 1, "one"
-        -- </intpkey-14.4>
-    })
-
-test:do_execsql_test(
-    "intpkey-14.5",
-    [[
-        SELECT * FROM t3 WHERE a<c;
-    ]], {
-        -- <intpkey-14.5>
-        1, 1, "one"
-        -- </intpkey-14.5>
-    })
-
-test:do_execsql_test(
-    "intpkey-14.6",
-    [[
-        SELECT * FROM t3 WHERE a=c;
-    ]], {
-        -- <intpkey-14.6>
-        2, 2, "2", 3, 3, "3"
-        -- </intpkey-14.6>
-    })
-
 -- Check for proper handling of primary keys greater than 2^31.
 -- Ticket #1188
 --
 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..3161e48fa 100755
--- a/test/sql-tap/numcast.test.lua
+++ b/test/sql-tap/numcast.test.lua
@@ -135,16 +135,16 @@ 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 2.0e+19 to integer"
     })
 
-test:do_catchsql_test(
+test:do_execsql_test(
     "cast-2.9",
     [[
         INSERT INTO t VALUES(2.1);
         SELECT * FROM t;
     ]], {
-        1,"Tuple field 1 type does not match one required by operation: expected integer"
+        2, 9223372036854775808ULL, 18000000000000000000ULL
     })
 
 --
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);
 

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

* [Tarantool-patches] [PATCH v3 3/8] sql: remove mem_apply_type() from OP_MakeRecord
  2020-06-25 15:17 [Tarantool-patches] [PATCH v3 0/8] Remove implicit cast imeevma
  2020-06-25 15:17 ` [Tarantool-patches] [PATCH v3 1/8] sql: introduce mem_set_double() imeevma
  2020-06-25 15:17 ` [Tarantool-patches] [PATCH v3 2/8] sql: change implicit cast for assignment imeevma
@ 2020-06-25 15:17 ` imeevma
  2020-06-25 15:17 ` [Tarantool-patches] [PATCH v3 4/8] sql: replace ApplyType by CheckType for IN operator imeevma
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 32+ messages in thread
From: imeevma @ 2020-06-25 15:17 UTC (permalink / raw)
  To: korablev, tsafin, tarantool-patches

This patch removes the type change from OP_MakeRecord. This allows
us to remove unnecessary implicit casts. So far, this only affects
the IN operator.

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 4b069addb..1687448d4 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;
@@ -3137,12 +3128,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 009d577d2..276956170 100644
--- a/src/box/sql/vdbe.c
+++ b/src/box/sql/vdbe.c
@@ -2940,24 +2940,17 @@ case OP_ImplicitCast: {
 	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 */
@@ -2979,7 +2972,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];
@@ -2990,15 +2982,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] 32+ messages in thread

* [Tarantool-patches] [PATCH v3 4/8] sql: replace ApplyType by CheckType for IN operator
  2020-06-25 15:17 [Tarantool-patches] [PATCH v3 0/8] Remove implicit cast imeevma
                   ` (2 preceding siblings ...)
  2020-06-25 15:17 ` [Tarantool-patches] [PATCH v3 3/8] sql: remove mem_apply_type() from OP_MakeRecord imeevma
@ 2020-06-25 15:17 ` imeevma
  2020-06-29 12:56   ` Nikita Pettik
  2020-06-25 15:17 ` [Tarantool-patches] [PATCH v3 5/8] sql: remove mem_apply_type() from OP_MustBeInt imeevma
                   ` (3 subsequent siblings)
  7 siblings, 1 reply; 32+ messages in thread
From: imeevma @ 2020-06-25 15:17 UTC (permalink / raw)
  To: korablev, 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 +---------------------------------
 3 files changed, 3 insertions(+), 82 deletions(-)

diff --git a/src/box/sql/expr.c b/src/box/sql/expr.c
index 019628a26..745011d35 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_ImplicitCast, 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.
-- 
2.25.1

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

* [Tarantool-patches] [PATCH v3 5/8] sql: remove mem_apply_type() from OP_MustBeInt
  2020-06-25 15:17 [Tarantool-patches] [PATCH v3 0/8] Remove implicit cast imeevma
                   ` (3 preceding siblings ...)
  2020-06-25 15:17 ` [Tarantool-patches] [PATCH v3 4/8] sql: replace ApplyType by CheckType for IN operator imeevma
@ 2020-06-25 15:17 ` imeevma
  2020-06-29 13:29   ` Nikita Pettik
  2020-06-25 15:17 ` [Tarantool-patches] [PATCH v3 6/8] sql: remove implicit cast for comparison imeevma
                   ` (2 subsequent siblings)
  7 siblings, 1 reply; 32+ messages in thread
From: imeevma @ 2020-06-25 15:17 UTC (permalink / raw)
  To: korablev, tsafin, tarantool-patches

This patch replaces mem_apply_type() with
mem_convert_to_integer(), since this mem_convert_to_integer()
contains the only functionality needed here from the
mem_apply_type().
---
 src/box/sql/vdbe.c                   |  18 +-
 test/sql-tap/e_select1.test.lua      |  17 +-
 test/sql-tap/in4.test.lua            |  97 +--
 test/sql-tap/join.test.lua           |   1 -
 test/sql-tap/limit.test.lua          |   2 +-
 test/sql-tap/tkt-9a8b09f8e6.test.lua |  24 +-
 test/sql-tap/tkt-fc7bd6358f.test.lua | 111 ----
 test/sql-tap/transitive1.test.lua    |   4 +-
 test/sql-tap/whereB.test.lua         | 900 ---------------------------
 test/sql-tap/whereC.test.lua         |   8 +-
 10 files changed, 25 insertions(+), 1157 deletions(-)
 delete mode 100755 test/sql-tap/tkt-fc7bd6358f.test.lua
 delete mode 100755 test/sql-tap/whereB.test.lua

diff --git a/src/box/sql/vdbe.c b/src/box/sql/vdbe.c
index 276956170..a609fa985 100644
--- a/src/box/sql/vdbe.c
+++ b/src/box/sql/vdbe.c
@@ -2122,17 +2122,13 @@ 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);
-		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");
-				goto abort_due_to_error;
-			} else {
-				goto jump_to_p2;
-			}
-		}
+	if ((pIn1->flags & (MEM_Int | MEM_UInt)) == 0 &&
+	    mem_convert_to_integer(pIn1, true) != 0) {
+		if (pOp->p2 != 0)
+			goto jump_to_p2;
+		diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
+			 sql_value_to_diag_str(pIn1), "integer");
+		goto abort_due_to_error;
 	}
 	break;
 }
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
-- 
2.25.1

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

* [Tarantool-patches] [PATCH v3 6/8] sql: remove implicit cast for comparison
  2020-06-25 15:17 [Tarantool-patches] [PATCH v3 0/8] Remove implicit cast imeevma
                   ` (4 preceding siblings ...)
  2020-06-25 15:17 ` [Tarantool-patches] [PATCH v3 5/8] sql: remove mem_apply_type() from OP_MustBeInt imeevma
@ 2020-06-25 15:17 ` imeevma
  2020-06-29 23:51   ` Nikita Pettik
  2020-06-25 15:17 ` [Tarantool-patches] [PATCH v3 7/8] sql: remove unused functions imeevma
  2020-06-25 15:17 ` [Tarantool-patches] [PATCH v3 8/8] sql: show value and its type in type mismatch error imeevma
  7 siblings, 1 reply; 32+ messages in thread
From: imeevma @ 2020-06-25 15:17 UTC (permalink / raw)
  To: korablev, tsafin, tarantool-patches

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

On 22.06.2020 15:25, Nikita Pettik wrote:
> On 17 Jun 15:36, imeevma@tarantool.org wrote:
>> @@ -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;
>> -
>
> Replace these assertions with relevant ones.
>
Not sure if this is necessary, since now we have much less flag
changes after removal of mem_apply_type().

>> @@ -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;
>
> Could you substitute routine below with mem_check_types()
> (or whatever this function is called)?
>
Partially substituted.

>> @@ -3590,6 +3568,26 @@ skip_truncate:
>>  	assert(oc!=OP_SeekLT || r.default_rc==+1);
>>  
>>  	r.aMem = &aMem[pOp->p3];
>
> Code below definitely lacks some comments.
>
Fixed.

>> +	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)) {
>
> What if key_def contains scalar/any type?
>
It will be fine since mem_check_type() process these cases.

>> +			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;
>
> Why this procedure is different from one in Seek* opcode
> handling routine? Could you put it in one function and reuse?
> Also lacks comments.
>
At Seek*, we convert numbers to use them in an iterator. This is
not so in Idx*. In addition, Seek* is used only once during a
selection from space, but Idx* can be used more than once, so we
cannot convert here.

>> +		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;
>> +		}
>> +	}
>> 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)
>>  	}
>>  }
>>  
>> -/**
>> -			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
>>  			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;
>
> Solid code removal. I won't review it, I hope you verified that all
> tests are working as desired.
>
Sure.

>> -		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,
>> --- /dev/null
>> +++ b/test/sql-tap/gh-4230-del-impl-cast-str-to-num.test.lua
>
> Same note: I'd better use .sql test format and/or amalgamate it with
> already existing test file.
>
I was said that TAP is preferred.

>> @@ -0,0 +1,281 @@
>> +#!/usr/bin/env tarantool
>> +test = require("sqltester")
>> +test:plan(32)
>> +
>> +--
>> +
>> +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);
>
> What about table with scalar/any fields?
>
I think this is too big a problem to solve it here.


New patch:

From 64653f49b79f2888243a76c30425d762acd301db Mon Sep 17 00:00:00 2001
From: Mergen Imeev <imeevma@gmail.com>
Date: Thu, 25 Jun 2020 12:39:19 +0300
Subject: [PATCH] sql: remove implicit cast for comparison
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

This patch removes implicit cast for comparison.

Closes #4230

@TarantoolBot document
Title: remove implicit cast for comparison

After this patch-set, there will be no implicit casts for
comparison. This means that the values ​​of the field types STRING,
BOOLEAN and VARBINARY can be compared with the values ​​of the same
field type. Any numerical value can be compared with any other
numerical value.

Example:

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

tarantool> box.execute([[SELECT true > X'33';]])
---
- null
- 'Type mismatch: can not convert ''TRUE'' (type: boolean) to varbinary'
...

tarantool> box.execute([[SELECT 1.23 > 123;]])
---
- metadata:
  - name: 1.23 > 123
    type: boolean
  rows:
  - [false]
...
```

diff --git a/src/box/sql/vdbe.c b/src/box/sql/vdbe.c
index a609fa985..f531a2241 100644
--- a/src/box/sql/vdbe.c
+++ b/src/box/sql/vdbe.c
@@ -2283,8 +2283,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) {
@@ -2343,22 +2341,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()
@@ -2391,22 +2384,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);
@@ -2422,14 +2410,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 */
@@ -3524,8 +3504,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;
@@ -3617,7 +3595,38 @@ skip_truncate:
 	assert(oc!=OP_SeekGE || r.default_rc==+1);
 	assert(oc!=OP_SeekLT || r.default_rc==+1);
 
+	/*
+	 * Make sure that the types of all the fields in the tuple
+	 * that will be used in the iterator match the field types
+	 * of the space.
+	 */
 	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_check_type(mem, type) == 0 ||
+		    mem_convert_numeric(mem, type, true) == 0)
+			continue;
+		/*
+		 * If the number was not converted without loss,
+		 * we will not find tuples using the EQ iterator.
+		 */
+		if ((mem->flags & MEM_Real) != 0 &&
+		    (type == FIELD_TYPE_INTEGER ||
+		     type == FIELD_TYPE_UNSIGNED)) {
+			assert(eqOnly == 1);
+			res = 1;
+			goto seek_not_found;
+		}
+		if ((mem->flags & (MEM_Int | MEM_UInt)) != 0 &&
+		    type == FIELD_TYPE_DOUBLE && eqOnly == 1) {
+			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
@@ -4744,7 +4753,25 @@ case OP_IdxGE:  {       /* jump */
 		assert(pOp->opcode==OP_IdxGE || pOp->opcode==OP_IdxLT);
 		r.default_rc = 0;
 	}
+
+	/*
+	 * Make sure that the types of all the fields in the tuple
+	 * that will be used in the iterator comparable with the
+	 * fields of the space.
+	 */
 	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_check_type(mem, type) == 0)
+			continue;
+		if (sql_type_is_numeric(type) &&
+		    (mem->flags & (MEM_Real | MEM_Int | MEM_UInt)) != 0)
+			continue;
+		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
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/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..381f29c65 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 54aff460e..62161cfe1 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] 32+ messages in thread

* [Tarantool-patches] [PATCH v3 7/8] sql: remove unused functions
  2020-06-25 15:17 [Tarantool-patches] [PATCH v3 0/8] Remove implicit cast imeevma
                   ` (5 preceding siblings ...)
  2020-06-25 15:17 ` [Tarantool-patches] [PATCH v3 6/8] sql: remove implicit cast for comparison imeevma
@ 2020-06-25 15:17 ` imeevma
  2020-06-29 23:52   ` Nikita Pettik
  2020-06-25 15:17 ` [Tarantool-patches] [PATCH v3 8/8] sql: show value and its type in type mismatch error imeevma
  7 siblings, 1 reply; 32+ messages in thread
From: imeevma @ 2020-06-25 15:17 UTC (permalink / raw)
  To: korablev, tsafin, tarantool-patches

After previous patches, some functions and the ApplyType opcode
become unused, so this patch removes them.

Follow-up #4230
---
 src/box/sql/expr.c      | 43 -----------------------------------------
 src/box/sql/insert.c    | 14 --------------
 src/box/sql/sqlInt.h    | 25 ------------------------
 src/box/sql/vdbe.c      | 29 ---------------------------
 src/box/sql/wherecode.c |  5 -----
 5 files changed, 116 deletions(-)

diff --git a/src/box/sql/expr.c b/src/box/sql/expr.c
index 745011d35..61ed89830 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 8a89f9904..6639ceff0 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 f1d0345f9..59c62ebf9 100644
--- a/src/box/sql/sqlInt.h
+++ b/src/box/sql/sqlInt.h
@@ -3238,19 +3238,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
@@ -3875,10 +3862,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.
@@ -3920,14 +3903,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 f531a2241..cabe5aa9e 100644
--- a/src/box/sql/vdbe.c
+++ b/src/box/sql/vdbe.c
@@ -2857,35 +2857,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 */
-- 
2.25.1

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

* [Tarantool-patches] [PATCH v3 8/8] sql: show value and its type in type mismatch error
  2020-06-25 15:17 [Tarantool-patches] [PATCH v3 0/8] Remove implicit cast imeevma
                   ` (6 preceding siblings ...)
  2020-06-25 15:17 ` [Tarantool-patches] [PATCH v3 7/8] sql: remove unused functions imeevma
@ 2020-06-25 15:17 ` imeevma
  2020-06-30  0:22   ` Nikita Pettik
  7 siblings, 1 reply; 32+ messages in thread
From: imeevma @ 2020-06-25 15:17 UTC (permalink / raw)
  To: korablev, tsafin, tarantool-patches

After this patch value and its type will be shown in description
of type mismatch error
---
 src/box/sql/vdbe.c                            |   17 +-
 src/box/sql/vdbemem.c                         |   13 +-
 test/sql-tap/autoinc.test.lua                 |    4 +-
 test/sql-tap/cast.test.lua                    |   16 +-
 .../gh-3809-implicit-cast-assignment.test.lua |   60 +-
 .../gh-4230-del-impl-cast-str-to-num.test.lua |   40 +-
 ...-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/in4.test.lua                     |    2 +-
 test/sql-tap/index1.test.lua                  |    4 +-
 test/sql-tap/join.test.lua                    |    4 +-
 test/sql-tap/misc1.test.lua                   |    2 +-
 test/sql-tap/numcast.test.lua                 |    4 +-
 test/sql-tap/select1.test.lua                 |    6 +-
 test/sql-tap/select5.test.lua                 |    2 +-
 test/sql-tap/subquery.test.lua                |    2 +-
 test/sql-tap/tkt-80e031a00f.test.lua          |    4 +-
 test/sql/boolean.result                       | 1484 ++++++++---------
 test/sql/integer-overflow.result              |    4 +-
 test/sql/persistency.result                   |    2 +-
 test/sql/types.result                         |   61 +-
 22 files changed, 867 insertions(+), 881 deletions(-)

diff --git a/src/box/sql/vdbe.c b/src/box/sql/vdbe.c
index cabe5aa9e..2bc8c9817 100644
--- a/src/box/sql/vdbe.c
+++ b/src/box/sql/vdbe.c
@@ -2327,14 +2327,9 @@ case OP_Ge: {             /* same as TK_GE, jump, in1, in3 */
 		int type_arg1 = flags1 & (MEM_Bool | MEM_Blob);
 		int type_arg3 = flags3 & (MEM_Bool | MEM_Blob);
 		if (type_arg1 != type_arg3) {
-			char *inconsistent_type = type_arg1 != 0 ?
-						  mem_type_to_str(pIn3) :
-						  mem_type_to_str(pIn1);
-			char *expected_type     = type_arg1 != 0 ?
-						  mem_type_to_str(pIn1) :
-						  mem_type_to_str(pIn3);
 			diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
-				 inconsistent_type, expected_type);
+				 sql_value_to_diag_str(pIn3),
+				 mem_type_to_str(pIn1));
 			goto abort_due_to_error;
 		}
 		res = sqlMemCompare(pIn3, pIn1, NULL);
@@ -2386,13 +2381,13 @@ case OP_Ge: {             /* same as TK_GE, jump, in1, in3 */
 		} else if (type == FIELD_TYPE_STRING) {
 			if ((flags1 & MEM_Str) == 0) {
 				diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
-					 mem_type_to_str(pIn3),
+					 sql_value_to_diag_str(pIn3),
 					 mem_type_to_str(pIn1));
 				goto abort_due_to_error;
 			}
 			if ((flags3 & MEM_Str) == 0) {
 				diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
-					 mem_type_to_str(pIn1),
+					 sql_value_to_diag_str(pIn1),
 					 mem_type_to_str(pIn3));
 				goto abort_due_to_error;
 			}
@@ -3595,7 +3590,7 @@ skip_truncate:
 			goto seek_not_found;
 		}
 		diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
-			field_type_strs[type], mem_type_to_str(mem));
+			sql_value_to_diag_str(mem), field_type_strs[type]);
 		goto abort_due_to_error;
 	}
 #ifdef SQL_DEBUG
@@ -4740,7 +4735,7 @@ case OP_IdxGE:  {       /* jump */
 		    (mem->flags & (MEM_Real | MEM_Int | MEM_UInt)) != 0)
 			continue;
 		diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
-			field_type_strs[type], mem_type_to_str(mem));
+			sql_value_to_diag_str(mem), mem_type_to_str(mem));
 		goto abort_due_to_error;
 	}
 #ifdef SQL_DEBUG
diff --git a/src/box/sql/vdbemem.c b/src/box/sql/vdbemem.c
index a721afc83..bb7676354 100644
--- a/src/box/sql/vdbemem.c
+++ b/src/box/sql/vdbemem.c
@@ -1166,12 +1166,15 @@ sqlValueText(sql_value * pVal)
 const char *
 sql_value_to_diag_str(sql_value *value)
 {
-	if (sql_value_type(value) == MP_BIN) {
-		if (mem_has_msgpack_subtype(value))
-			return sqlValueText(value);
+	if (sql_value_mp_type(value) == MP_BIN)
 		return "varbinary";
-	}
-	return sqlValueText(value);
+	char *type = mem_type_to_str(value);
+	char *str = (char *)sqlValueText(value);
+	if (str == NULL)
+		return "NULL";
+	if (strlen(str) < 80)
+		return tt_sprintf("'%s' (type: %s)", str, type);
+	return tt_sprintf("'%.80s...' (type: %s)", str, type);
 }
 
 /*
diff --git a/test/sql-tap/autoinc.test.lua b/test/sql-tap/autoinc.test.lua
index 07442b60a..1547ffcd3 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 'asd' (type: text) to integer"
         -- </autoinc-10.2>
     })
 
@@ -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 'a' (type: text) to integer"
         -- </autoinc-gh-3670>
     })
 
diff --git a/test/sql-tap/cast.test.lua b/test/sql-tap/cast.test.lua
index fb0790d04..ceb3e690f 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 '123abc' (type: 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 '123abc' (type: 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 '123.5abc' (type: 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 '123.5abc' (type: 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 'abc' (type: 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 'abc' (type: 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 'abc' (type: 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 'abc' (type: text) to number"
         -- </cast-4.4>
     })
 
diff --git a/test/sql-tap/gh-3809-implicit-cast-assignment.test.lua b/test/sql-tap/gh-3809-implicit-cast-assignment.test.lua
index a1809b3cb..f1edfa0f6 100755
--- a/test/sql-tap/gh-3809-implicit-cast-assignment.test.lua
+++ b/test/sql-tap/gh-3809-implicit-cast-assignment.test.lua
@@ -28,7 +28,7 @@ test:do_catchsql_test(
     [[
         INSERT INTO ti(i) VALUES (100000000000000000000000000000000.1)
     ]], {
-        1, "Type mismatch: can not convert 1.0e+32 to integer"
+        1, "Type mismatch: can not convert '1.0e+32' (type: real) to integer"
     })
 
 test:do_catchsql_test(
@@ -44,7 +44,7 @@ test:do_catchsql_test(
     [[
         INSERT INTO ti(i) VALUES (true)
     ]], {
-        1, "Type mismatch: can not convert TRUE to integer"
+        1, "Type mismatch: can not convert 'TRUE' (type: boolean) to integer"
     })
 
 test:do_catchsql_test(
@@ -52,7 +52,7 @@ test:do_catchsql_test(
     [[
         INSERT INTO ti(i) VALUES ('33')
     ]], {
-        1, "Type mismatch: can not convert 33 to integer"
+        1, "Type mismatch: can not convert '33' (type: text) to integer"
     })
 
 test:do_catchsql_test(
@@ -100,7 +100,7 @@ test:do_catchsql_test(
     [[
         INSERT INTO td(d) VALUES (true)
     ]], {
-        1, "Type mismatch: can not convert TRUE to double"
+        1, "Type mismatch: can not convert 'TRUE' (type: boolean) to double"
     })
 
 test:do_catchsql_test(
@@ -108,7 +108,7 @@ test:do_catchsql_test(
     [[
         INSERT INTO td(d) VALUES ('33')
     ]], {
-        1, "Type mismatch: can not convert 33 to double"
+        1, "Type mismatch: can not convert '33' (type: text) to double"
     })
 
 test:do_catchsql_test(
@@ -132,7 +132,7 @@ test:do_catchsql_test(
     [[
         INSERT INTO tb(b) VALUES (11)
     ]], {
-        1, "Type mismatch: can not convert 11 to boolean"
+        1, "Type mismatch: can not convert '11' (type: unsigned) to boolean"
     })
 
 test:do_catchsql_test(
@@ -140,7 +140,7 @@ test:do_catchsql_test(
     [[
         INSERT INTO tb(b) VALUES (22.2)
     ]], {
-        1, "Type mismatch: can not convert 22.2 to boolean"
+        1, "Type mismatch: can not convert '22.2' (type: real) to boolean"
     })
 
 test:do_catchsql_test(
@@ -156,7 +156,7 @@ test:do_catchsql_test(
     [[
         INSERT INTO tb(b) VALUES ('33')
     ]], {
-        1, "Type mismatch: can not convert 33 to boolean"
+        1, "Type mismatch: can not convert '33' (type: text) to boolean"
     })
 
 test:do_catchsql_test(
@@ -180,7 +180,7 @@ test:do_catchsql_test(
     [[
         INSERT INTO tt(t) VALUES (11)
     ]], {
-        1, "Type mismatch: can not convert 11 to string"
+        1, "Type mismatch: can not convert '11' (type: unsigned) to string"
     })
 
 test:do_catchsql_test(
@@ -188,7 +188,7 @@ test:do_catchsql_test(
     [[
         INSERT INTO tt(t) VALUES (22.2)
     ]], {
-        1, "Type mismatch: can not convert 22.2 to string"
+        1, "Type mismatch: can not convert '22.2' (type: real) to string"
     })
 
 test:do_catchsql_test(
@@ -196,7 +196,7 @@ test:do_catchsql_test(
     [[
         INSERT INTO tt(t) VALUES (true)
     ]], {
-        1, "Type mismatch: can not convert TRUE to string"
+        1, "Type mismatch: can not convert 'TRUE' (type: boolean) to string"
     })
 
 test:do_catchsql_test(
@@ -228,7 +228,7 @@ test:do_catchsql_test(
     [[
         INSERT INTO tv(v) VALUES (11)
     ]], {
-        1, "Type mismatch: can not convert 11 to varbinary"
+        1, "Type mismatch: can not convert '11' (type: unsigned) to varbinary"
     })
 
 test:do_catchsql_test(
@@ -236,7 +236,7 @@ test:do_catchsql_test(
     [[
         INSERT INTO tv(v) VALUES (22.2)
     ]], {
-        1, "Type mismatch: can not convert 22.2 to varbinary"
+        1, "Type mismatch: can not convert '22.2' (type: real) to varbinary"
     })
 
 test:do_catchsql_test(
@@ -244,7 +244,7 @@ test:do_catchsql_test(
     [[
         INSERT INTO tv(v) VALUES (true)
     ]], {
-        1, "Type mismatch: can not convert TRUE to varbinary"
+        1, "Type mismatch: can not convert 'TRUE' (type: boolean) to varbinary"
     })
 
 test:do_catchsql_test(
@@ -252,7 +252,7 @@ test:do_catchsql_test(
     [[
         INSERT INTO tv(v) VALUES ('33')
     ]], {
-        1, "Type mismatch: can not convert 33 to varbinary"
+        1, "Type mismatch: can not convert '33' (type: text) to varbinary"
     })
 
 test:do_catchsql_test(
@@ -359,7 +359,7 @@ test:do_catchsql_test(
     [[
         UPDATE ti SET i = 100000000000000000000000000000000.1 WHERE a = 1;
     ]], {
-        1, "Type mismatch: can not convert 1.0e+32 to integer"
+        1, "Type mismatch: can not convert '1.0e+32' (type: real) to integer"
     })
 
 test:do_catchsql_test(
@@ -375,7 +375,7 @@ test:do_catchsql_test(
     [[
         UPDATE ti SET i = true WHERE a = 1;
     ]], {
-        1, "Type mismatch: can not convert TRUE to integer"
+        1, "Type mismatch: can not convert 'TRUE' (type: boolean) to integer"
     })
 
 test:do_catchsql_test(
@@ -383,7 +383,7 @@ test:do_catchsql_test(
     [[
         UPDATE ti SET i = '33' WHERE a = 1;
     ]], {
-        1, "Type mismatch: can not convert 33 to integer"
+        1, "Type mismatch: can not convert '33' (type: text) to integer"
     })
 
 test:do_catchsql_test(
@@ -431,7 +431,7 @@ test:do_catchsql_test(
     [[
         UPDATE td SET d = true WHERE a = 1;
     ]], {
-        1, "Type mismatch: can not convert TRUE to double"
+        1, "Type mismatch: can not convert 'TRUE' (type: boolean) to double"
     })
 
 test:do_catchsql_test(
@@ -439,7 +439,7 @@ test:do_catchsql_test(
     [[
         UPDATE td SET d = '33' WHERE a = 1;
     ]], {
-        1, "Type mismatch: can not convert 33 to double"
+        1, "Type mismatch: can not convert '33' (type: text) to double"
     })
 
 test:do_catchsql_test(
@@ -463,7 +463,7 @@ test:do_catchsql_test(
     [[
         UPDATE tb SET b = 11 WHERE a = 1;
     ]], {
-        1, "Type mismatch: can not convert 11 to boolean"
+        1, "Type mismatch: can not convert '11' (type: unsigned) to boolean"
     })
 
 test:do_catchsql_test(
@@ -471,7 +471,7 @@ test:do_catchsql_test(
     [[
         UPDATE tb SET b = 22.2 WHERE a = 1;
     ]], {
-        1, "Type mismatch: can not convert 22.2 to boolean"
+        1, "Type mismatch: can not convert '22.2' (type: real) to boolean"
     })
 
 test:do_catchsql_test(
@@ -487,7 +487,7 @@ test:do_catchsql_test(
     [[
         UPDATE tb SET b = '33' WHERE a = 1;
     ]], {
-        1, "Type mismatch: can not convert 33 to boolean"
+        1, "Type mismatch: can not convert '33' (type: text) to boolean"
     })
 
 test:do_catchsql_test(
@@ -511,7 +511,7 @@ test:do_catchsql_test(
     [[
         UPDATE tt SET t = 11 WHERE a = 1;
     ]], {
-        1, "Type mismatch: can not convert 11 to string"
+        1, "Type mismatch: can not convert '11' (type: unsigned) to string"
     })
 
 test:do_catchsql_test(
@@ -519,7 +519,7 @@ test:do_catchsql_test(
     [[
         UPDATE tt SET t = 22.2 WHERE a = 1;
     ]], {
-        1, "Type mismatch: can not convert 22.2 to string"
+        1, "Type mismatch: can not convert '22.2' (type: real) to string"
     })
 
 test:do_catchsql_test(
@@ -527,7 +527,7 @@ test:do_catchsql_test(
     [[
         UPDATE tt SET t = true WHERE a = 1;
     ]], {
-        1, "Type mismatch: can not convert TRUE to string"
+        1, "Type mismatch: can not convert 'TRUE' (type: boolean) to string"
     })
 
 test:do_catchsql_test(
@@ -559,7 +559,7 @@ test:do_catchsql_test(
     [[
         UPDATE tv SET v = 11 WHERE a = 1;
     ]], {
-        1, "Type mismatch: can not convert 11 to varbinary"
+        1, "Type mismatch: can not convert '11' (type: unsigned) to varbinary"
     })
 
 test:do_catchsql_test(
@@ -567,7 +567,7 @@ test:do_catchsql_test(
     [[
         UPDATE tv SET v = 22.2 WHERE a = 1;
     ]], {
-        1, "Type mismatch: can not convert 22.2 to varbinary"
+        1, "Type mismatch: can not convert '22.2' (type: real) to varbinary"
     })
 
 test:do_catchsql_test(
@@ -575,7 +575,7 @@ test:do_catchsql_test(
     [[
         UPDATE tv SET v = true WHERE a = 1;
     ]], {
-        1, "Type mismatch: can not convert TRUE to varbinary"
+        1, "Type mismatch: can not convert 'TRUE' (type: boolean) to varbinary"
     })
 
 test:do_catchsql_test(
@@ -583,7 +583,7 @@ test:do_catchsql_test(
     [[
         UPDATE tv SET v = '33' WHERE a = 1;
     ]], {
-        1, "Type mismatch: can not convert 33 to varbinary"
+        1, "Type mismatch: can not convert '33' (type: text) to varbinary"
     })
 
 test:do_catchsql_test(
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..536e414ba 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 '1' (type: 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 '1' (type: 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 '2' (type: 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 '2' (type: 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 '2' (type: 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 '2' (type: 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 '2' (type: 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 '2' (type: 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 '1' (type: 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 '1' (type: 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 '1' (type: 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 '1' (type: text) to numeric"
     })
 
 test:do_execsql_test(
@@ -171,7 +171,7 @@ test:do_catchsql_test(
     [[
         SELECT x FROM t2 WHERE x IN ('1');
     ]], {
-        1, "Type mismatch: can not convert integer to text"
+        1, "Type mismatch: can not convert '1' (type: text) to integer"
     })
 
 test:do_catchsql_test(
@@ -179,7 +179,7 @@ test:do_catchsql_test(
     [[
         SELECT x FROM t2 WHERE x IN ('1.0');
     ]], {
-        1, "Type mismatch: can not convert integer to text"
+        1, "Type mismatch: can not convert '1.0' (type: text) to integer"
     })
 
 test:do_execsql_test(
@@ -203,7 +203,7 @@ test:do_catchsql_test(
     [[
         SELECT x FROM t2 WHERE '1' IN (x);
     ]], {
-        1, "Type mismatch: can not convert integer to text"
+        1, "Type mismatch: can not convert '1' (type: text) to integer"
     })
 
 test:do_catchsql_test(
@@ -211,7 +211,7 @@ test:do_catchsql_test(
     [[
         SELECT x FROM t2 WHERE '1.0' IN (x);
     ]], {
-        1, "Type mismatch: can not convert integer to text"
+        1, "Type mismatch: can not convert '1.0' (type: text) to integer"
     })
 
 test:do_execsql_test(
@@ -235,7 +235,7 @@ test:do_catchsql_test(
     [[
         SELECT x FROM t3 WHERE x IN ('1');
     ]], {
-        1, "Type mismatch: can not convert double to text"
+        1, "Type mismatch: can not convert '1' (type: text) to double"
     })
 
 test:do_catchsql_test(
@@ -243,7 +243,7 @@ test:do_catchsql_test(
     [[
         SELECT x FROM t3 WHERE x IN ('1.0');
     ]], {
-        1, "Type mismatch: can not convert double to text"
+        1, "Type mismatch: can not convert '1.0' (type: text) to double"
     })
 
 test:do_execsql_test(
@@ -267,7 +267,7 @@ test:do_catchsql_test(
     [[
         SELECT x FROM t3 WHERE '1' IN (x);
     ]], {
-        1, "Type mismatch: can not convert double to text"
+        1, "Type mismatch: can not convert '1' (type: text) to double"
     })
 
 test:do_catchsql_test(
@@ -275,7 +275,7 @@ test:do_catchsql_test(
     [[
         SELECT x FROM t3 WHERE '1.0' IN (x);
     ]], {
-        1, "Type mismatch: can not convert double to text"
+        1, "Type mismatch: can not convert '1.0' (type: text) to double"
     })
 
 test:finish_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..4fdd03b42 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 '00000000000000000000000000000000000000000000000000000000000000000000000000000000...' (type: 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..96458ada8 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 'b' (type: 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 'b' (type: 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 'b' (type: 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..c55271eeb 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 '2' (type: text) to numeric"
         -- </in-11.2>
     })
 
diff --git a/test/sql-tap/in4.test.lua b/test/sql-tap/in4.test.lua
index a494e846f..1840841b0 100755
--- a/test/sql-tap/in4.test.lua
+++ b/test/sql-tap/in4.test.lua
@@ -153,7 +153,7 @@ test:do_catchsql_test(
         SELECT b FROM t2 WHERE a IN ('', '0.0.0', '2') 
     ]], {
         -- <in4-2.8>
-        1, "Type mismatch: can not convert integer to text"
+        1, "Type mismatch: can not convert '' (type: text) to integer"
         -- </in4-2.8>
     })
 
diff --git a/test/sql-tap/index1.test.lua b/test/sql-tap/index1.test.lua
index ce66b7c1e..d6a837e05 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 '' (type: 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 '' (type: text) to numeric"
         -- </index-14.7>
     })
 
diff --git a/test/sql-tap/join.test.lua b/test/sql-tap/join.test.lua
index 792302ab5..7068f0865 100755
--- a/test/sql-tap/join.test.lua
+++ b/test/sql-tap/join.test.lua
@@ -1034,7 +1034,7 @@ test:do_catchsql_test(
         SELECT * FROM t1 NATURAL JOIN t2 
     ]], {
         -- <join-11.9>
-        1, "Type mismatch: can not convert integer to text"
+        1, "Type mismatch: can not convert '1' (type: text) to integer"
         -- </join-11.9>
     })
 
@@ -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 '1' (type: text) to numeric"
         -- </join-11.10>
     })
 
diff --git a/test/sql-tap/misc1.test.lua b/test/sql-tap/misc1.test.lua
index 3cef617f4..528076f00 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 '0' (type: text) to numeric"
         -- </misc1-12.2>
     })
 
diff --git a/test/sql-tap/numcast.test.lua b/test/sql-tap/numcast.test.lua
index 3161e48fa..b5930daf3 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 '2.0e+19' (type: real) to unsigned"
     })
 
 test:do_execsql_test(
@@ -135,7 +135,7 @@ test:do_catchsql_test(
         INSERT INTO t VALUES(20000000000000000000.01);
         SELECT * FROM t;
     ]], {
-        1,"Type mismatch: can not convert 2.0e+19 to integer"
+        1,"Type mismatch: can not convert '2.0e+19' (type: real) to integer"
     })
 
 test:do_execsql_test(
diff --git a/test/sql-tap/select1.test.lua b/test/sql-tap/select1.test.lua
index f5a9b63fe..911f24341 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 'This is a string that is too big to fit inside a NBFS buffer' (type: text) to numeric"
         -- </select1-2.5.3>
     })
 
@@ -515,7 +515,7 @@ test:do_catchsql_test(
         SELECT sum(a) FROM t3
     ]], {
         -- <select1-2.17.1>
-        1, "Type mismatch: can not convert abc to number"
+        1, "Type mismatch: can not convert 'abc' (type: text) to number"
         -- </select1-2.17.1>
     })
 
@@ -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 '6.7' (type: real) to boolean"
         -- </select1-8.1>
     })
 
diff --git a/test/sql-tap/select5.test.lua b/test/sql-tap/select5.test.lua
index d34de3139..f87873b8e 100755
--- a/test/sql-tap/select5.test.lua
+++ b/test/sql-tap/select5.test.lua
@@ -558,7 +558,7 @@ test:do_catchsql_test(
             SELECT 1 FROM jj HAVING avg(s2) = 1 AND avg(s2) = 0;
     ]], {
     -- <select5-9.13.2>
-    1, "Type mismatch: can not convert A to number"
+    1, "Type mismatch: can not convert 'A' (type: text) to number"
     -- </select5-9.13.2>
 })
 
diff --git a/test/sql-tap/subquery.test.lua b/test/sql-tap/subquery.test.lua
index bad702de9..2ef474930 100755
--- a/test/sql-tap/subquery.test.lua
+++ b/test/sql-tap/subquery.test.lua
@@ -290,7 +290,7 @@ test:do_catchsql_test(
         SELECT a IN (10.0, 20) FROM t3;
     ]], {
         -- <subquery-2.3.2>
-        1, "Type mismatch: can not convert text to real"
+        1, "Type mismatch: can not convert '10' (type: text) to real"
         -- </subquery-2.3.2>
     })
 
diff --git a/test/sql-tap/tkt-80e031a00f.test.lua b/test/sql-tap/tkt-80e031a00f.test.lua
index a0e6539e0..8a10508d8 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 'hello' (type: 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 'hello' (type: text) to integer"
         -- </tkt-80e031a00f.28>
     })
 
diff --git a/test/sql/boolean.result b/test/sql/boolean.result
index 112e41a12..80f88a481 100644
--- a/test/sql/boolean.result
+++ b/test/sql/boolean.result
@@ -138,12 +138,12 @@ INSERT INTO ts(s) VALUES ('abc'), (12.5);
 SELECT s FROM ts WHERE s = true;
  | ---
  | - null
- | - 'Type mismatch: can not convert text to boolean'
+ | - 'Type mismatch: can not convert ''abc'' (type: text) to boolean'
  | ...
 SELECT s FROM ts WHERE s < true;
  | ---
  | - null
- | - 'Type mismatch: can not convert text to boolean'
+ | - 'Type mismatch: can not convert ''abc'' (type: text) to boolean'
  | ...
 SELECT s FROM ts WHERE s IN (true, 1, 'abcd');
  | ---
@@ -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 ''TRUE'' (type: boolean) to integer'
  | ...
 
 -- Check that we can create index on field of type BOOLEAN.
@@ -339,7 +339,7 @@ SELECT typeof(a) FROM t0;
 SELECT AVG(a) FROM t0;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to number'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to number'
  | ...
 SELECT MIN(a) FROM t0;
  | ---
@@ -360,7 +360,7 @@ SELECT MAX(a) FROM t0;
 SELECT SUM(a) FROM t0;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to number'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to number'
  | ...
 SELECT COUNT(a) FROM t0;
  | ---
@@ -373,7 +373,7 @@ SELECT COUNT(a) FROM t0;
 SELECT TOTAL(a) FROM t0;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to number'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to number'
  | ...
 SELECT GROUP_CONCAT(a, ' +++ ') FROM t0;
  | ---
@@ -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 ''TRUE'' (type: boolean) to numeric'
  | ...
 SELECT -false;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to numeric'
  | ...
 SELECT -a FROM t;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to numeric'
  | ...
 
 SELECT true + true;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to numeric'
  | ...
 SELECT true + false;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to numeric'
  | ...
 SELECT false + true;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to numeric'
  | ...
 SELECT false + false;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to numeric'
  | ...
 SELECT true - true;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to numeric'
  | ...
 SELECT true - false;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to numeric'
  | ...
 SELECT false - true;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to numeric'
  | ...
 SELECT false - false;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to numeric'
  | ...
 SELECT true * true;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to numeric'
  | ...
 SELECT true * false;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to numeric'
  | ...
 SELECT false * true;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to numeric'
  | ...
 SELECT false * false;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to numeric'
  | ...
 SELECT true / true;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to numeric'
  | ...
 SELECT true / false;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to numeric'
  | ...
 SELECT false / true;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to numeric'
  | ...
 SELECT false / false;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to numeric'
  | ...
 SELECT true % true;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to numeric'
  | ...
 SELECT true % false;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to numeric'
  | ...
 SELECT false % true;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to numeric'
  | ...
 SELECT false % false;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to numeric'
  | ...
 
 SELECT a, true + a FROM t;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to numeric'
  | ...
 SELECT a, false + a FROM t;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to numeric'
  | ...
 SELECT a, true - a FROM t;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to numeric'
  | ...
 SELECT a, false - a FROM t;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to numeric'
  | ...
 SELECT a, true * a FROM t;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to numeric'
  | ...
 SELECT a, false * a FROM t;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to numeric'
  | ...
 SELECT a, true / a FROM t;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to numeric'
  | ...
 SELECT a, false / a FROM t;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to numeric'
  | ...
 SELECT a, true % a FROM t;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to numeric'
  | ...
 SELECT a, false % a FROM t;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to numeric'
  | ...
 SELECT a, a + true FROM t;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to numeric'
  | ...
 SELECT a, a + false FROM t;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to numeric'
  | ...
 SELECT a, a - true FROM t;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to numeric'
  | ...
 SELECT a, a - false FROM t;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to numeric'
  | ...
 SELECT a, a * true FROM t;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to numeric'
  | ...
 SELECT a, a * false FROM t;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to numeric'
  | ...
 SELECT a, a / true FROM t;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to numeric'
  | ...
 SELECT a, a / false FROM t;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to numeric'
  | ...
 SELECT a, a % true FROM t;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to numeric'
  | ...
 SELECT a, a % false FROM t;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: 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 ''FALSE'' (type: 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 ''FALSE'' (type: 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 ''FALSE'' (type: 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 ''FALSE'' (type: 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 ''FALSE'' (type: boolean) to numeric'
  | ...
 
 SELECT ~true;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to integer'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to integer'
  | ...
 SELECT ~false;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to integer'
  | ...
 SELECT true & true;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to integer'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to integer'
  | ...
 SELECT true & false;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to integer'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to integer'
  | ...
 SELECT false & true;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to integer'
  | ...
 SELECT false & false;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to integer'
  | ...
 SELECT true | true;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to integer'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to integer'
  | ...
 SELECT true | false;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to integer'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to integer'
  | ...
 SELECT false | true;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to integer'
  | ...
 SELECT false | false;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to integer'
  | ...
 SELECT true << true;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to integer'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to integer'
  | ...
 SELECT true << false;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to integer'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to integer'
  | ...
 SELECT false << true;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to integer'
  | ...
 SELECT false << false;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to integer'
  | ...
 SELECT true >> true;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to integer'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to integer'
  | ...
 SELECT true >> false;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to integer'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to integer'
  | ...
 SELECT false >> true;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to integer'
  | ...
 SELECT false >> false;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to integer'
  | ...
 
 SELECT a, true & a FROM t;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to integer'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to integer'
  | ...
 SELECT a, false & a FROM t;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to integer'
  | ...
 SELECT a, true | a FROM t;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to integer'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to integer'
  | ...
 SELECT a, false | a FROM t;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to integer'
  | ...
 SELECT a, true << a FROM t;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to integer'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to integer'
  | ...
 SELECT a, false << a FROM t;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to integer'
  | ...
 SELECT a, true >> a FROM t;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to integer'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to integer'
  | ...
 SELECT a, false >> a FROM t;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to integer'
  | ...
 SELECT a, a & true FROM t;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to integer'
  | ...
 SELECT a, a & false FROM t;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to integer'
  | ...
 SELECT a, a | true FROM t;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to integer'
  | ...
 SELECT a, a | false FROM t;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to integer'
  | ...
 SELECT a, a << true FROM t;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to integer'
  | ...
 SELECT a, a << false FROM t;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to integer'
  | ...
 SELECT a, a >> true FROM t;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to integer'
  | ...
 SELECT a, a >> false FROM t;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: 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 ''FALSE'' (type: 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 ''FALSE'' (type: 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 ''FALSE'' (type: 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 ''FALSE'' (type: 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 ''2'' (type: 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 ''2'' (type: unsigned) to boolean'
  | ...
 SELECT false OR 2;
  | ---
  | - null
- | - 'Type mismatch: can not convert 2 to boolean'
+ | - 'Type mismatch: can not convert ''2'' (type: unsigned) to boolean'
  | ...
 SELECT 2 AND true;
  | ---
  | - null
- | - 'Type mismatch: can not convert 2 to boolean'
+ | - 'Type mismatch: can not convert ''2'' (type: 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 ''2'' (type: unsigned) to boolean'
  | ...
 SELECT 2 OR false;
  | ---
  | - null
- | - 'Type mismatch: can not convert 2 to boolean'
+ | - 'Type mismatch: can not convert ''2'' (type: unsigned) to boolean'
  | ...
 
 SELECT a1, a1 AND 2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert 2 to boolean'
+ | - 'Type mismatch: can not convert ''2'' (type: unsigned) to boolean'
  | ...
 SELECT a1, a1 OR 2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert 2 to boolean'
+ | - 'Type mismatch: can not convert ''2'' (type: unsigned) to boolean'
  | ...
 SELECT a1, 2 AND a1 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert 2 to boolean'
+ | - 'Type mismatch: can not convert ''2'' (type: unsigned) to boolean'
  | ...
 SELECT a1, 2 OR a1 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert 2 to boolean'
+ | - 'Type mismatch: can not convert ''2'' (type: unsigned) to boolean'
  | ...
 SELECT a2, a2 AND 2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert 2 to boolean'
+ | - 'Type mismatch: can not convert ''2'' (type: unsigned) to boolean'
  | ...
 SELECT a2, a2 OR 2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert 2 to boolean'
+ | - 'Type mismatch: can not convert ''2'' (type: unsigned) to boolean'
  | ...
 SELECT a2, 2 AND a2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert 2 to boolean'
+ | - 'Type mismatch: can not convert ''2'' (type: unsigned) to boolean'
  | ...
 SELECT a2, 2 OR a2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert 2 to boolean'
+ | - 'Type mismatch: can not convert ''2'' (type: unsigned) to boolean'
  | ...
 
 SELECT b, true AND b FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert 123 to boolean'
+ | - 'Type mismatch: can not convert ''123'' (type: 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 ''123'' (type: unsigned) to boolean'
  | ...
 SELECT b, false OR b FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert 123 to boolean'
+ | - 'Type mismatch: can not convert ''123'' (type: unsigned) to boolean'
  | ...
 SELECT b, b AND true FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert 123 to boolean'
+ | - 'Type mismatch: can not convert ''123'' (type: unsigned) to boolean'
  | ...
 SELECT b, b AND false FROM t7;
  | ---
@@ -2589,1273 +2589,1273 @@ 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 ''123'' (type: unsigned) to boolean'
  | ...
 SELECT b, b OR false FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert 123 to boolean'
+ | - 'Type mismatch: can not convert ''123'' (type: 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 ''123'' (type: 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 ''123'' (type: 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 ''123'' (type: 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 ''123'' (type: 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 ''123'' (type: 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 ''123'' (type: 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 ''123'' (type: 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 ''123'' (type: unsigned) to boolean'
  | ...
 
 SELECT true + 2;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to numeric'
  | ...
 SELECT false + 2;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to numeric'
  | ...
 SELECT true - 2;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to numeric'
  | ...
 SELECT false - 2;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to numeric'
  | ...
 SELECT true * 2;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to numeric'
  | ...
 SELECT false * 2;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to numeric'
  | ...
 SELECT true / 2;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to numeric'
  | ...
 SELECT false / 2;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to numeric'
  | ...
 SELECT true % 2;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to numeric'
  | ...
 SELECT false % 2;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to numeric'
  | ...
 SELECT 2 + true;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to numeric'
  | ...
 SELECT 2 + false;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to numeric'
  | ...
 SELECT 2 - true;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to numeric'
  | ...
 SELECT 2 - false;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to numeric'
  | ...
 SELECT 2 * true;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to numeric'
  | ...
 SELECT 2 * false;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to numeric'
  | ...
 SELECT 2 / true;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to numeric'
  | ...
 SELECT 2 / false;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to numeric'
  | ...
 SELECT 2 % true;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to numeric'
  | ...
 SELECT 2 % false;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to numeric'
  | ...
 
 SELECT a1, a1 + 2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to numeric'
  | ...
 SELECT a1, a1 - 2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to numeric'
  | ...
 SELECT a1, a1 * 2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to numeric'
  | ...
 SELECT a1, a1 / 2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to numeric'
  | ...
 SELECT a1, a1 % 2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to numeric'
  | ...
 SELECT a1, 2 + a1 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to numeric'
  | ...
 SELECT a1, 2 - a1 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to numeric'
  | ...
 SELECT a1, 2 * a1 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to numeric'
  | ...
 SELECT a1, 2 / a1 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to numeric'
  | ...
 SELECT a1, 2 % a1 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to numeric'
  | ...
 SELECT a2, a2 + 2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to numeric'
  | ...
 SELECT a2, a2 - 2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to numeric'
  | ...
 SELECT a2, a2 * 2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to numeric'
  | ...
 SELECT a2, a2 / 2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to numeric'
  | ...
 SELECT a2, a2 % 2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to numeric'
  | ...
 SELECT a2, 2 + a2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to numeric'
  | ...
 SELECT a2, 2 - a2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to numeric'
  | ...
 SELECT a2, 2 * a2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to numeric'
  | ...
 SELECT a2, 2 / a2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to numeric'
  | ...
 SELECT a2, 2 % a2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to numeric'
  | ...
 
 SELECT b, true + b FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to numeric'
  | ...
 SELECT b, false + b FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to numeric'
  | ...
 SELECT b, true - b FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to numeric'
  | ...
 SELECT b, false - b FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to numeric'
  | ...
 SELECT b, true * b FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to numeric'
  | ...
 SELECT b, false * b FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to numeric'
  | ...
 SELECT b, true / b FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to numeric'
  | ...
 SELECT b, false / b FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to numeric'
  | ...
 SELECT b, true % b FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to numeric'
  | ...
 SELECT b, false % b FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to numeric'
  | ...
 SELECT b, b + true FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to numeric'
  | ...
 SELECT b, b + false FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to numeric'
  | ...
 SELECT b, b - true FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to numeric'
  | ...
 SELECT b, b - false FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to numeric'
  | ...
 SELECT b, b * true FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to numeric'
  | ...
 SELECT b, b * false FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to numeric'
  | ...
 SELECT b, b / true FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to numeric'
  | ...
 SELECT b, b / false FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to numeric'
  | ...
 SELECT b, b % true FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to numeric'
  | ...
 SELECT b, b % false FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: 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 ''FALSE'' (type: 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 ''FALSE'' (type: 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 ''FALSE'' (type: 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 ''FALSE'' (type: 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 ''FALSE'' (type: 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 ''FALSE'' (type: 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 ''FALSE'' (type: 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 ''FALSE'' (type: 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 ''FALSE'' (type: 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 ''FALSE'' (type: 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 ''TRUE'' (type: 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 ''TRUE'' (type: 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 ''TRUE'' (type: 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 ''TRUE'' (type: 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 ''TRUE'' (type: 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 ''TRUE'' (type: 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 ''TRUE'' (type: 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 ''TRUE'' (type: 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 ''TRUE'' (type: 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 ''TRUE'' (type: boolean) to numeric'
  | ...
 
 SELECT true & 2;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to integer'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to integer'
  | ...
 SELECT false & 2;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to integer'
  | ...
 SELECT true | 2;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to integer'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to integer'
  | ...
 SELECT false | 2;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to integer'
  | ...
 SELECT true << 2;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to integer'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to integer'
  | ...
 SELECT false << 2;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to integer'
  | ...
 SELECT true >> 2;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to integer'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to integer'
  | ...
 SELECT false >> 2;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to integer'
  | ...
 SELECT 2 & true;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to integer'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to integer'
  | ...
 SELECT 2 & false;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to integer'
  | ...
 SELECT 2 | true;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to integer'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to integer'
  | ...
 SELECT 2 | false;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to integer'
  | ...
 SELECT 2 << true;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to integer'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to integer'
  | ...
 SELECT 2 << false;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to integer'
  | ...
 SELECT 2 >> true;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to integer'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to integer'
  | ...
 SELECT 2 >> false;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to integer'
  | ...
 
 SELECT a1, a1 & 2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to integer'
  | ...
 SELECT a1, a1 | 2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to integer'
  | ...
 SELECT a1, a1 << 2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to integer'
  | ...
 SELECT a1, a1 >> 2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to integer'
  | ...
 SELECT a1, 2 & a1 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to integer'
  | ...
 SELECT a1, 2 | a1 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to integer'
  | ...
 SELECT a1, 2 << a1 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to integer'
  | ...
 SELECT a1, 2 >> a1 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to integer'
  | ...
 SELECT a2, a2 & 2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to integer'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to integer'
  | ...
 SELECT a2, a2 | 2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to integer'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to integer'
  | ...
 SELECT a2, a2 << 2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to integer'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to integer'
  | ...
 SELECT a2, a2 >> 2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to integer'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to integer'
  | ...
 SELECT a2, 2 & a2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to integer'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to integer'
  | ...
 SELECT a2, 2 | a2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to integer'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to integer'
  | ...
 SELECT a2, 2 << a2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to integer'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to integer'
  | ...
 SELECT a2, 2 >> a2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to integer'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to integer'
  | ...
 
 SELECT b, true & b FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to integer'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to integer'
  | ...
 SELECT b, false & b FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to integer'
  | ...
 SELECT b, true | b FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to integer'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to integer'
  | ...
 SELECT b, false | b FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to integer'
  | ...
 SELECT b, true << b FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to integer'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to integer'
  | ...
 SELECT b, false << b FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to integer'
  | ...
 SELECT b, true >> b FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to integer'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to integer'
  | ...
 SELECT b, false >> b FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to integer'
  | ...
 SELECT b, b & true FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to integer'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to integer'
  | ...
 SELECT b, b & false FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to integer'
  | ...
 SELECT b, b | true FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to integer'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to integer'
  | ...
 SELECT b, b | false FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to integer'
  | ...
 SELECT b, b << true FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to integer'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to integer'
  | ...
 SELECT b, b << false FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to integer'
  | ...
 SELECT b, b >> true FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to integer'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to integer'
  | ...
 SELECT b, b >> false FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: 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 ''FALSE'' (type: 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 ''FALSE'' (type: 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 ''FALSE'' (type: 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 ''FALSE'' (type: 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 ''FALSE'' (type: 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 ''FALSE'' (type: 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 ''FALSE'' (type: 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 ''FALSE'' (type: 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 ''TRUE'' (type: 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 ''TRUE'' (type: 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 ''TRUE'' (type: 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 ''TRUE'' (type: 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 ''TRUE'' (type: 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 ''TRUE'' (type: 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 ''TRUE'' (type: 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 ''TRUE'' (type: boolean) to integer'
  | ...
 
 SELECT true > 2;
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to unsigned'
  | ...
 SELECT false > 2;
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to unsigned'
  | ...
 SELECT true < 2;
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to unsigned'
  | ...
 SELECT false < 2;
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to unsigned'
  | ...
 SELECT 2 > true;
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''2'' (type: unsigned) to boolean'
  | ...
 SELECT 2 > false;
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''2'' (type: unsigned) to boolean'
  | ...
 SELECT 2 < true;
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''2'' (type: unsigned) to boolean'
  | ...
 SELECT 2 < false;
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''2'' (type: unsigned) to boolean'
  | ...
 
 SELECT a1, a1 > 2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to unsigned'
  | ...
 SELECT a1, a1 < 2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to unsigned'
  | ...
 SELECT a1, 2 > a1 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''2'' (type: unsigned) to boolean'
  | ...
 SELECT a1, 2 < a1 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''2'' (type: unsigned) to boolean'
  | ...
 SELECT a2, a2 > 2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to unsigned'
  | ...
 SELECT a2, a2 < 2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to unsigned'
  | ...
 SELECT a2, 2 > a2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''2'' (type: unsigned) to boolean'
  | ...
 SELECT a2, 2 < a2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''2'' (type: unsigned) to boolean'
  | ...
 
 SELECT b, true > b FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to unsigned'
  | ...
 SELECT b, false > b FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to unsigned'
  | ...
 SELECT b, true < b FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to unsigned'
  | ...
 SELECT b, false < b FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to unsigned'
  | ...
 SELECT b, b > true FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''123'' (type: unsigned) to boolean'
  | ...
 SELECT b, b > false FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''123'' (type: unsigned) to boolean'
  | ...
 SELECT b, b < true FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''123'' (type: unsigned) to boolean'
  | ...
 SELECT b, b < false FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''123'' (type: unsigned) to boolean'
  | ...
 
 SELECT a1, b, a1 > b FROM t6, t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to unsigned'
  | ...
 SELECT a1, b, a1 < b FROM t6, t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to unsigned'
  | ...
 SELECT a1, b, b > a1 FROM t6, t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''123'' (type: unsigned) to boolean'
  | ...
 SELECT a1, b, b < a1 FROM t6, t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''123'' (type: unsigned) to boolean'
  | ...
 SELECT a2, b, a2 > b FROM t6, t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to unsigned'
  | ...
 SELECT a2, b, a2 < b FROM t6, t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to unsigned'
  | ...
 SELECT a2, b, b > a2 FROM t6, t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''123'' (type: unsigned) to boolean'
  | ...
 SELECT a2, b, b < a2 FROM t6, t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''123'' (type: unsigned) to boolean'
  | ...
 
 SELECT true >= 2;
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to unsigned'
  | ...
 SELECT false >= 2;
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to unsigned'
  | ...
 SELECT true <= 2;
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to unsigned'
  | ...
 SELECT false <= 2;
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to unsigned'
  | ...
 SELECT 2 >= true;
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''2'' (type: unsigned) to boolean'
  | ...
 SELECT 2 >= false;
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''2'' (type: unsigned) to boolean'
  | ...
 SELECT 2 <= true;
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''2'' (type: unsigned) to boolean'
  | ...
 SELECT 2 <= false;
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''2'' (type: unsigned) to boolean'
  | ...
 
 SELECT a1, a1 >= 2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to unsigned'
  | ...
 SELECT a1, a1 <= 2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to unsigned'
  | ...
 SELECT a1, 2 >= a1 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''2'' (type: unsigned) to boolean'
  | ...
 SELECT a1, 2 <= a1 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''2'' (type: unsigned) to boolean'
  | ...
 SELECT a2, a2 >= 2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to unsigned'
  | ...
 SELECT a2, a2 <= 2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to unsigned'
  | ...
 SELECT a2, 2 >= a2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''2'' (type: unsigned) to boolean'
  | ...
 SELECT a2, 2 <= a2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''2'' (type: unsigned) to boolean'
  | ...
 
 SELECT b, true >= b FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to unsigned'
  | ...
 SELECT b, false >= b FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to unsigned'
  | ...
 SELECT b, true <= b FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to unsigned'
  | ...
 SELECT b, false <= b FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to unsigned'
  | ...
 SELECT b, b >= true FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''123'' (type: unsigned) to boolean'
  | ...
 SELECT b, b >= false FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''123'' (type: unsigned) to boolean'
  | ...
 SELECT b, b <= true FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''123'' (type: unsigned) to boolean'
  | ...
 SELECT b, b <= false FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''123'' (type: unsigned) to boolean'
  | ...
 
 SELECT a1, b, a1 >= b FROM t6, t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to unsigned'
  | ...
 SELECT a1, b, a1 <= b FROM t6, t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to unsigned'
  | ...
 SELECT a1, b, b >= a1 FROM t6, t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''123'' (type: unsigned) to boolean'
  | ...
 SELECT a1, b, b <= a1 FROM t6, t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''123'' (type: unsigned) to boolean'
  | ...
 SELECT a2, b, a2 >= b FROM t6, t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to unsigned'
  | ...
 SELECT a2, b, a2 <= b FROM t6, t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to unsigned'
  | ...
 SELECT a2, b, b >= a2 FROM t6, t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''123'' (type: unsigned) to boolean'
  | ...
 SELECT a2, b, b <= a2 FROM t6, t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''123'' (type: unsigned) to boolean'
  | ...
 
 SELECT true == 2;
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to unsigned'
  | ...
 SELECT false == 2;
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to unsigned'
  | ...
 SELECT true != 2;
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to unsigned'
  | ...
 SELECT false != 2;
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to unsigned'
  | ...
 SELECT 2 == true;
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''2'' (type: unsigned) to boolean'
  | ...
 SELECT 2 == false;
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''2'' (type: unsigned) to boolean'
  | ...
 SELECT 2 != true;
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''2'' (type: unsigned) to boolean'
  | ...
 SELECT 2 != false;
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''2'' (type: unsigned) to boolean'
  | ...
 
 SELECT a1, a1 == 2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to unsigned'
  | ...
 SELECT a1, a1 != 2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to unsigned'
  | ...
 SELECT a1, 2 == a1 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''2'' (type: unsigned) to boolean'
  | ...
 SELECT a1, 2 != a1 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''2'' (type: unsigned) to boolean'
  | ...
 SELECT a2, a2 == 2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to unsigned'
  | ...
 SELECT a2, a2 != 2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to unsigned'
  | ...
 SELECT a2, 2 == a2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''2'' (type: unsigned) to boolean'
  | ...
 SELECT a2, 2 != a2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''2'' (type: unsigned) to boolean'
  | ...
 
 SELECT b, true == b FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to unsigned'
  | ...
 SELECT b, false == b FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to unsigned'
  | ...
 SELECT b, true != b FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to unsigned'
  | ...
 SELECT b, false != b FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to unsigned'
  | ...
 SELECT b, b == true FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''123'' (type: unsigned) to boolean'
  | ...
 SELECT b, b == false FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''123'' (type: unsigned) to boolean'
  | ...
 SELECT b, b != true FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''123'' (type: unsigned) to boolean'
  | ...
 SELECT b, b != false FROM t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''123'' (type: unsigned) to boolean'
  | ...
 
 SELECT a1, b, a1 == b FROM t6, t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to unsigned'
  | ...
 SELECT a1, b, a1 != b FROM t6, t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to unsigned'
  | ...
 SELECT a1, b, b == a1 FROM t6, t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''123'' (type: unsigned) to boolean'
  | ...
 SELECT a1, b, b != a1 FROM t6, t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''123'' (type: unsigned) to boolean'
  | ...
 SELECT a2, b, a2 == b FROM t6, t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to unsigned'
  | ...
 SELECT a2, b, a2 != b FROM t6, t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to unsigned'
  | ...
 SELECT a2, b, b == a2 FROM t6, t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''123'' (type: unsigned) to boolean'
  | ...
 SELECT a2, b, b != a2 FROM t6, t7;
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''123'' (type: unsigned) to boolean'
  | ...
 
 SELECT true IN (0, 1, 2, 3);
@@ -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 ''TRUE'' (type: boolean) to integer'
  | ...
 SELECT false IN (SELECT b FROM t7);
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to integer'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to integer'
  | ...
 SELECT a1, a1 IN (0, 1, 2, 3) FROM t6
  | ---
@@ -3899,22 +3899,22 @@ SELECT a1, a1 IN (0, 1, 2, 3) FROM t6
 SELECT true BETWEEN 0 and 10;
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to unsigned'
  | ...
 SELECT false BETWEEN 0 and 10;
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to unsigned'
  | ...
 SELECT a1, a1 BETWEEN 0 and 10 FROM t6;
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to unsigned'
  | ...
 SELECT a2, a2 BETWEEN 0 and 10 FROM t6;
  | ---
  | - null
- | - 'Type mismatch: can not convert unsigned to boolean'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to unsigned'
  | ...
 
 -- Check interaction of BOOLEAN and NUMBER.
@@ -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 ''2.3'' (type: 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 ''2.3'' (type: real) to boolean'
  | ...
 SELECT false OR 2.3;
  | ---
  | - null
- | - 'Type mismatch: can not convert 2.3 to boolean'
+ | - 'Type mismatch: can not convert ''2.3'' (type: real) to boolean'
  | ...
 SELECT 2.3 AND true;
  | ---
  | - null
- | - 'Type mismatch: can not convert 2.3 to boolean'
+ | - 'Type mismatch: can not convert ''2.3'' (type: 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 ''2.3'' (type: real) to boolean'
  | ...
 SELECT 2.3 OR false;
  | ---
  | - null
- | - 'Type mismatch: can not convert 2.3 to boolean'
+ | - 'Type mismatch: can not convert ''2.3'' (type: 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 ''2.3'' (type: 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 ''2.3'' (type: 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 ''2.3'' (type: 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 ''2.3'' (type: 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 ''2.3'' (type: 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 ''2.3'' (type: 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 ''2.3'' (type: 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 ''2.3'' (type: 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 ''4.56'' (type: 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 ''4.56'' (type: 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 ''4.56'' (type: 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 ''4.56'' (type: real) to boolean'
  | ...
 SELECT c, c AND false FROM t8;
  | ---
@@ -4058,949 +4058,949 @@ 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 ''4.56'' (type: 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 ''4.56'' (type: 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 ''4.56'' (type: 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 ''4.56'' (type: 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 ''4.56'' (type: 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 ''4.56'' (type: 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 ''4.56'' (type: 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 ''4.56'' (type: 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 ''4.56'' (type: 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 ''4.56'' (type: real) to boolean'
  | ...
 
 SELECT true + 2.3;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to numeric'
  | ...
 SELECT false + 2.3;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to numeric'
  | ...
 SELECT true - 2.3;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to numeric'
  | ...
 SELECT false - 2.3;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to numeric'
  | ...
 SELECT true * 2.3;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to numeric'
  | ...
 SELECT false * 2.3;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to numeric'
  | ...
 SELECT true / 2.3;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to numeric'
  | ...
 SELECT false / 2.3;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to numeric'
  | ...
 SELECT true % 2.3;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to numeric'
  | ...
 SELECT false % 2.3;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to numeric'
  | ...
 SELECT 2.3 + true;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to numeric'
  | ...
 SELECT 2.3 + false;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to numeric'
  | ...
 SELECT 2.3 - true;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to numeric'
  | ...
 SELECT 2.3 - false;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to numeric'
  | ...
 SELECT 2.3 * true;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to numeric'
  | ...
 SELECT 2.3 * false;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to numeric'
  | ...
 SELECT 2.3 / true;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to numeric'
  | ...
 SELECT 2.3 / false;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to numeric'
  | ...
 SELECT 2.3 % true;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to numeric'
  | ...
 SELECT 2.3 % false;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to numeric'
  | ...
 
 SELECT a1, a1 + 2.3 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to numeric'
  | ...
 SELECT a1, a1 - 2.3 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to numeric'
  | ...
 SELECT a1, a1 * 2.3 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to numeric'
  | ...
 SELECT a1, a1 / 2.3 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to numeric'
  | ...
 SELECT a1, a1 % 2.3 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to numeric'
  | ...
 SELECT a1, 2.3 + a1 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to numeric'
  | ...
 SELECT a1, 2.3 - a1 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to numeric'
  | ...
 SELECT a1, 2.3 * a1 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to numeric'
  | ...
 SELECT a1, 2.3 / a1 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to numeric'
  | ...
 SELECT a1, 2.3 % a1 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to numeric'
  | ...
 SELECT a2, a2 + 2.3 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to numeric'
  | ...
 SELECT a2, a2 - 2.3 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to numeric'
  | ...
 SELECT a2, a2 * 2.3 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to numeric'
  | ...
 SELECT a2, a2 / 2.3 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to numeric'
  | ...
 SELECT a2, a2 % 2.3 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to numeric'
  | ...
 SELECT a2, 2.3 + a2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to numeric'
  | ...
 SELECT a2, 2.3 - a2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to numeric'
  | ...
 SELECT a2, 2.3 * a2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to numeric'
  | ...
 SELECT a2, 2.3 / a2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to numeric'
  | ...
 SELECT a2, 2.3 % a2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to numeric'
  | ...
 
 SELECT c, true + c FROM t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to numeric'
  | ...
 SELECT c, false + c FROM t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to numeric'
  | ...
 SELECT c, true - c FROM t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to numeric'
  | ...
 SELECT c, false - c FROM t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to numeric'
  | ...
 SELECT c, true * c FROM t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to numeric'
  | ...
 SELECT c, false * c FROM t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to numeric'
  | ...
 SELECT c, true / c FROM t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to numeric'
  | ...
 SELECT c, false / c FROM t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to numeric'
  | ...
 SELECT c, true % c FROM t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to numeric'
  | ...
 SELECT c, false % c FROM t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to numeric'
  | ...
 SELECT c, c + true FROM t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to numeric'
  | ...
 SELECT c, c + false FROM t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to numeric'
  | ...
 SELECT c, c - true FROM t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to numeric'
  | ...
 SELECT c, c - false FROM t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to numeric'
  | ...
 SELECT c, c * true FROM t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to numeric'
  | ...
 SELECT c, c * false FROM t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to numeric'
  | ...
 SELECT c, c / true FROM t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to numeric'
  | ...
 SELECT c, c / false FROM t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to numeric'
  | ...
 SELECT c, c % true FROM t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to numeric'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to numeric'
  | ...
 SELECT c, c % false FROM t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to numeric'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: 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 ''FALSE'' (type: 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 ''FALSE'' (type: 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 ''FALSE'' (type: 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 ''FALSE'' (type: 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 ''FALSE'' (type: 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 ''FALSE'' (type: 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 ''FALSE'' (type: 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 ''FALSE'' (type: 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 ''FALSE'' (type: 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 ''FALSE'' (type: 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 ''TRUE'' (type: 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 ''TRUE'' (type: 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 ''TRUE'' (type: 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 ''TRUE'' (type: 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 ''TRUE'' (type: 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 ''TRUE'' (type: 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 ''TRUE'' (type: 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 ''TRUE'' (type: 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 ''TRUE'' (type: 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 ''TRUE'' (type: boolean) to numeric'
  | ...
 
 SELECT true > 2.3;
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to real'
  | ...
 SELECT false > 2.3;
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to real'
  | ...
 SELECT true < 2.3;
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to real'
  | ...
 SELECT false < 2.3;
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to real'
  | ...
 SELECT 2.3 > true;
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''2.3'' (type: real) to boolean'
  | ...
 SELECT 2.3 > false;
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''2.3'' (type: real) to boolean'
  | ...
 SELECT 2.3 < true;
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''2.3'' (type: real) to boolean'
  | ...
 SELECT 2.3 < false;
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''2.3'' (type: real) to boolean'
  | ...
 
 SELECT a1, a1 > 2.3 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to real'
  | ...
 SELECT a1, a1 < 2.3 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to real'
  | ...
 SELECT a1, 2.3 > a1 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''2.3'' (type: real) to boolean'
  | ...
 SELECT a1, 2.3 < a1 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''2.3'' (type: real) to boolean'
  | ...
 SELECT a2, a2 > 2.3 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to real'
  | ...
 SELECT a2, a2 < 2.3 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to real'
  | ...
 SELECT a2, 2.3 > a2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''2.3'' (type: real) to boolean'
  | ...
 SELECT a2, 2.3 < a2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''2.3'' (type: real) to boolean'
  | ...
 
 SELECT c, true > c FROM t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to real'
  | ...
 SELECT c, false > c FROM t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to real'
  | ...
 SELECT c, true < c FROM t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to real'
  | ...
 SELECT c, false < c FROM t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to real'
  | ...
 SELECT c, c > true FROM t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''4.56'' (type: real) to boolean'
  | ...
 SELECT c, c > false FROM t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''4.56'' (type: real) to boolean'
  | ...
 SELECT c, c < true FROM t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''4.56'' (type: real) to boolean'
  | ...
 SELECT c, c < false FROM t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''4.56'' (type: real) to boolean'
  | ...
 
 SELECT a1, c, a1 > c FROM t6, t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to real'
  | ...
 SELECT a1, c, a1 < c FROM t6, t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to real'
  | ...
 SELECT a1, c, c > a1 FROM t6, t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''4.56'' (type: real) to boolean'
  | ...
 SELECT a1, c, c < a1 FROM t6, t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''4.56'' (type: real) to boolean'
  | ...
 SELECT a2, c, a2 > c FROM t6, t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to real'
  | ...
 SELECT a2, c, a2 < c FROM t6, t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to real'
  | ...
 SELECT a2, c, c > a2 FROM t6, t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''4.56'' (type: real) to boolean'
  | ...
 SELECT a2, c, c < a2 FROM t6, t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''4.56'' (type: real) to boolean'
  | ...
 
 SELECT true >= 2.3;
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to real'
  | ...
 SELECT false >= 2.3;
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to real'
  | ...
 SELECT true <= 2.3;
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to real'
  | ...
 SELECT false <= 2.3;
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to real'
  | ...
 SELECT 2.3 >= true;
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''2.3'' (type: real) to boolean'
  | ...
 SELECT 2.3 >= false;
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''2.3'' (type: real) to boolean'
  | ...
 SELECT 2.3 <= true;
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''2.3'' (type: real) to boolean'
  | ...
 SELECT 2.3 <= false;
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''2.3'' (type: real) to boolean'
  | ...
 
 SELECT a1, a1 >= 2.3 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to real'
  | ...
 SELECT a1, a1 <= 2.3 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to real'
  | ...
 SELECT a1, 2.3 >= a1 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''2.3'' (type: real) to boolean'
  | ...
 SELECT a1, 2.3 <= a1 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''2.3'' (type: real) to boolean'
  | ...
 SELECT a2, a2 >= 2.3 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to real'
  | ...
 SELECT a2, a2 <= 2.3 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to real'
  | ...
 SELECT a2, 2.3 >= a2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''2.3'' (type: real) to boolean'
  | ...
 SELECT a2, 2.3 <= a2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''2.3'' (type: real) to boolean'
  | ...
 
 SELECT c, true >= c FROM t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to real'
  | ...
 SELECT c, false >= c FROM t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to real'
  | ...
 SELECT c, true <= c FROM t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to real'
  | ...
 SELECT c, false <= c FROM t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to real'
  | ...
 SELECT c, c >= true FROM t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''4.56'' (type: real) to boolean'
  | ...
 SELECT c, c >= false FROM t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''4.56'' (type: real) to boolean'
  | ...
 SELECT c, c <= true FROM t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''4.56'' (type: real) to boolean'
  | ...
 SELECT c, c <= false FROM t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''4.56'' (type: real) to boolean'
  | ...
 
 SELECT a1, c, a1 >= c FROM t6, t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to real'
  | ...
 SELECT a1, c, a1 <= c FROM t6, t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to real'
  | ...
 SELECT a1, c, c >= a1 FROM t6, t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''4.56'' (type: real) to boolean'
  | ...
 SELECT a1, c, c <= a1 FROM t6, t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''4.56'' (type: real) to boolean'
  | ...
 SELECT a2, c, a2 >= c FROM t6, t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to real'
  | ...
 SELECT a2, c, a2 <= c FROM t6, t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to real'
  | ...
 SELECT a2, c, c >= a2 FROM t6, t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''4.56'' (type: real) to boolean'
  | ...
 SELECT a2, c, c <= a2 FROM t6, t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''4.56'' (type: real) to boolean'
  | ...
 
 SELECT true == 2.3;
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to real'
  | ...
 SELECT false == 2.3;
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to real'
  | ...
 SELECT true != 2.3;
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to real'
  | ...
 SELECT false != 2.3;
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to real'
  | ...
 SELECT 2.3 == true;
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''2.3'' (type: real) to boolean'
  | ...
 SELECT 2.3 == false;
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''2.3'' (type: real) to boolean'
  | ...
 SELECT 2.3 != true;
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''2.3'' (type: real) to boolean'
  | ...
 SELECT 2.3 != false;
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''2.3'' (type: real) to boolean'
  | ...
 
 SELECT a1, a1 == 2.3 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to real'
  | ...
 SELECT a1, a1 != 2.3 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to real'
  | ...
 SELECT a1, 2.3 == a1 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''2.3'' (type: real) to boolean'
  | ...
 SELECT a1, 2.3 != a1 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''2.3'' (type: real) to boolean'
  | ...
 SELECT a2, a2 == 2.3 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to real'
  | ...
 SELECT a2, a2 != 2.3 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to real'
  | ...
 SELECT a2, 2.3 == a2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''2.3'' (type: real) to boolean'
  | ...
 SELECT a2, 2.3 != a2 FROM t6
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''2.3'' (type: real) to boolean'
  | ...
 
 SELECT c, true == c FROM t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to real'
  | ...
 SELECT c, false == c FROM t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to real'
  | ...
 SELECT c, true != c FROM t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to real'
  | ...
 SELECT c, false != c FROM t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to real'
  | ...
 SELECT c, c == true FROM t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''4.56'' (type: real) to boolean'
  | ...
 SELECT c, c == false FROM t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''4.56'' (type: real) to boolean'
  | ...
 SELECT c, c != true FROM t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''4.56'' (type: real) to boolean'
  | ...
 SELECT c, c != false FROM t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''4.56'' (type: real) to boolean'
  | ...
 
 SELECT a1, c, a1 == c FROM t6, t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to real'
  | ...
 SELECT a1, c, a1 != c FROM t6, t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to real'
  | ...
 SELECT a1, c, c == a1 FROM t6, t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''4.56'' (type: real) to boolean'
  | ...
 SELECT a1, c, c != a1 FROM t6, t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''4.56'' (type: real) to boolean'
  | ...
 SELECT a2, c, a2 == c FROM t6, t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to real'
  | ...
 SELECT a2, c, a2 != c FROM t6, t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to real'
  | ...
 SELECT a2, c, c == a2 FROM t6, t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''4.56'' (type: real) to boolean'
  | ...
 SELECT a2, c, c != a2 FROM t6, t8;
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''4.56'' (type: real) to boolean'
  | ...
 
 SELECT true IN (0.1, 1.2, 2.3, 3.4);
@@ -5038,43 +5038,43 @@ 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 ''TRUE'' (type: boolean) to number'
  | ...
 SELECT false IN (SELECT c FROM t8);
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to number'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: 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 ''FALSE'' (type: 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 ''TRUE'' (type: boolean) to number'
  | ...
 
 SELECT true BETWEEN 0.1 and 9.9;
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to real'
  | ...
 SELECT false BETWEEN 0.1 and 9.9;
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to real'
  | ...
 SELECT a1, a1 BETWEEN 0.1 and 9.9 FROM t6;
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to real'
  | ...
 SELECT a2, a2 BETWEEN 0.1 and 9.9 FROM t6;
  | ---
  | - null
- | - 'Type mismatch: can not convert real to boolean'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to real'
  | ...
 
 -- Check interaction of BOOLEAN and TEXT.
@@ -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 ''abc'' (type: 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 ''abc'' (type: text) to boolean'
  | ...
 SELECT false OR 'abc';
  | ---
  | - null
- | - 'Type mismatch: can not convert abc to boolean'
+ | - 'Type mismatch: can not convert ''abc'' (type: text) to boolean'
  | ...
 SELECT 'abc' AND true;
  | ---
  | - null
- | - 'Type mismatch: can not convert abc to boolean'
+ | - 'Type mismatch: can not convert ''abc'' (type: 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 ''abc'' (type: text) to boolean'
  | ...
 SELECT 'abc' OR false;
  | ---
  | - null
- | - 'Type mismatch: can not convert abc to boolean'
+ | - 'Type mismatch: can not convert ''abc'' (type: text) to boolean'
  | ...
 
 SELECT a1, a1 AND 'abc' FROM t6;
  | ---
  | - null
- | - 'Type mismatch: can not convert abc to boolean'
+ | - 'Type mismatch: can not convert ''abc'' (type: text) to boolean'
  | ...
 SELECT a1, a1 OR 'abc' FROM t6;
  | ---
  | - null
- | - 'Type mismatch: can not convert abc to boolean'
+ | - 'Type mismatch: can not convert ''abc'' (type: text) to boolean'
  | ...
 SELECT a1, 'abc' AND a1 FROM t6;
  | ---
  | - null
- | - 'Type mismatch: can not convert abc to boolean'
+ | - 'Type mismatch: can not convert ''abc'' (type: text) to boolean'
  | ...
 SELECT a1, 'abc' OR a1 FROM t6;
  | ---
  | - null
- | - 'Type mismatch: can not convert abc to boolean'
+ | - 'Type mismatch: can not convert ''abc'' (type: text) to boolean'
  | ...
 SELECT a2, a2 AND 'abc' FROM t6;
  | ---
  | - null
- | - 'Type mismatch: can not convert abc to boolean'
+ | - 'Type mismatch: can not convert ''abc'' (type: text) to boolean'
  | ...
 SELECT a2, a2 OR 'abc' FROM t6;
  | ---
  | - null
- | - 'Type mismatch: can not convert abc to boolean'
+ | - 'Type mismatch: can not convert ''abc'' (type: text) to boolean'
  | ...
 SELECT a2, 'abc' AND a2 FROM t6;
  | ---
  | - null
- | - 'Type mismatch: can not convert abc to boolean'
+ | - 'Type mismatch: can not convert ''abc'' (type: text) to boolean'
  | ...
 SELECT a2, 'abc' OR a2 FROM t6;
  | ---
  | - null
- | - 'Type mismatch: can not convert abc to boolean'
+ | - 'Type mismatch: can not convert ''abc'' (type: text) to boolean'
  | ...
 
 SELECT d, true AND d FROM t9;
  | ---
  | - null
- | - 'Type mismatch: can not convert AsdF to boolean'
+ | - 'Type mismatch: can not convert ''AsdF'' (type: 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 ''AsdF'' (type: text) to boolean'
  | ...
 SELECT d, false OR d FROM t9;
  | ---
  | - null
- | - 'Type mismatch: can not convert AsdF to boolean'
+ | - 'Type mismatch: can not convert ''AsdF'' (type: text) to boolean'
  | ...
 SELECT d, d AND true FROM t9;
  | ---
  | - null
- | - 'Type mismatch: can not convert AsdF to boolean'
+ | - 'Type mismatch: can not convert ''AsdF'' (type: text) to boolean'
  | ...
 SELECT d, d AND false FROM t9;
  | ---
@@ -5218,176 +5218,176 @@ 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 ''AsdF'' (type: text) to boolean'
  | ...
 SELECT d, d OR false FROM t9;
  | ---
  | - null
- | - 'Type mismatch: can not convert AsdF to boolean'
+ | - 'Type mismatch: can not convert ''AsdF'' (type: 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 ''AsdF'' (type: 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 ''AsdF'' (type: 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 ''AsdF'' (type: 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 ''AsdF'' (type: 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 ''AsdF'' (type: 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 ''AsdF'' (type: 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 ''AsdF'' (type: 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 ''AsdF'' (type: text) to boolean'
  | ...
 
 SELECT true > 'abc';
  | ---
  | - null
- | - 'Type mismatch: can not convert text to boolean'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to text'
  | ...
 SELECT false > 'abc';
  | ---
  | - null
- | - 'Type mismatch: can not convert text to boolean'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to text'
  | ...
 SELECT true < 'abc';
  | ---
  | - null
- | - 'Type mismatch: can not convert text to boolean'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to text'
  | ...
 SELECT false < 'abc';
  | ---
  | - null
- | - 'Type mismatch: can not convert text to boolean'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to text'
  | ...
 SELECT 'abc' > true;
  | ---
  | - null
- | - 'Type mismatch: can not convert text to boolean'
+ | - 'Type mismatch: can not convert ''abc'' (type: text) to boolean'
  | ...
 SELECT 'abc' > false;
  | ---
  | - null
- | - 'Type mismatch: can not convert text to boolean'
+ | - 'Type mismatch: can not convert ''abc'' (type: text) to boolean'
  | ...
 SELECT 'abc' < true;
  | ---
  | - null
- | - 'Type mismatch: can not convert text to boolean'
+ | - 'Type mismatch: can not convert ''abc'' (type: text) to boolean'
  | ...
 SELECT 'abc' < false;
  | ---
  | - null
- | - 'Type mismatch: can not convert text to boolean'
+ | - 'Type mismatch: can not convert ''abc'' (type: text) to boolean'
  | ...
 
 SELECT d, true > d FROM t9;
  | ---
  | - null
- | - 'Type mismatch: can not convert text to boolean'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to text'
  | ...
 SELECT d, false > d FROM t9;
  | ---
  | - null
- | - 'Type mismatch: can not convert text to boolean'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to text'
  | ...
 SELECT d, true < d FROM t9;
  | ---
  | - null
- | - 'Type mismatch: can not convert text to boolean'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to text'
  | ...
 SELECT d, false < d FROM t9;
  | ---
  | - null
- | - 'Type mismatch: can not convert text to boolean'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to text'
  | ...
 SELECT d, d > true FROM t9;
  | ---
  | - null
- | - 'Type mismatch: can not convert text to boolean'
+ | - 'Type mismatch: can not convert ''AsdF'' (type: text) to boolean'
  | ...
 SELECT d, d > false FROM t9;
  | ---
  | - null
- | - 'Type mismatch: can not convert text to boolean'
+ | - 'Type mismatch: can not convert ''AsdF'' (type: text) to boolean'
  | ...
 SELECT d, d < true FROM t9;
  | ---
  | - null
- | - 'Type mismatch: can not convert text to boolean'
+ | - 'Type mismatch: can not convert ''AsdF'' (type: text) to boolean'
  | ...
 SELECT d, d < false FROM t9;
  | ---
  | - null
- | - 'Type mismatch: can not convert text to boolean'
+ | - 'Type mismatch: can not convert ''AsdF'' (type: text) to boolean'
  | ...
 
 SELECT a1, d, a1 > d FROM t6, t9;
  | ---
  | - null
- | - 'Type mismatch: can not convert text to boolean'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to text'
  | ...
 SELECT a1, d, a1 < d FROM t6, t9;
  | ---
  | - null
- | - 'Type mismatch: can not convert text to boolean'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: boolean) to text'
  | ...
 SELECT a1, d, d > a1 FROM t6, t9;
  | ---
  | - null
- | - 'Type mismatch: can not convert text to boolean'
+ | - 'Type mismatch: can not convert ''AsdF'' (type: text) to boolean'
  | ...
 SELECT a1, d, d < a1 FROM t6, t9;
  | ---
  | - null
- | - 'Type mismatch: can not convert text to boolean'
+ | - 'Type mismatch: can not convert ''AsdF'' (type: text) to boolean'
  | ...
 SELECT a2, d, a2 > d FROM t6, t9;
  | ---
  | - null
- | - 'Type mismatch: can not convert text to boolean'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to text'
  | ...
 SELECT a2, d, a2 < d FROM t6, t9;
  | ---
  | - null
- | - 'Type mismatch: can not convert text to boolean'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to text'
  | ...
 SELECT a2, d, d > a2 FROM t6, t9;
  | ---
  | - null
- | - 'Type mismatch: can not convert text to boolean'
+ | - 'Type mismatch: can not convert ''AsdF'' (type: text) to boolean'
  | ...
 SELECT a2, d, d < a2 FROM t6, t9;
  | ---
  | - null
- | - 'Type mismatch: can not convert text to boolean'
+ | - 'Type mismatch: can not convert ''AsdF'' (type: 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 ''TRUE'' (type: 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 ''TRUE'' (type: text) to boolean'
  | ...
 SELECT false OR 'TRUE';
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to boolean'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: text) to boolean'
  | ...
 SELECT 'TRUE' AND true;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to boolean'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: 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 ''TRUE'' (type: text) to boolean'
  | ...
 SELECT 'TRUE' OR false;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to boolean'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: text) to boolean'
  | ...
 
 SELECT a1, a1 AND 'TRUE' FROM t6;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to boolean'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: text) to boolean'
  | ...
 SELECT a1, a1 OR 'TRUE' FROM t6;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to boolean'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: text) to boolean'
  | ...
 SELECT a1, 'TRUE' AND a1 FROM t6;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to boolean'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: text) to boolean'
  | ...
 SELECT a1, 'TRUE' OR a1 FROM t6;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to boolean'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: text) to boolean'
  | ...
 SELECT a2, a2 AND 'TRUE' FROM t6;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to boolean'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: text) to boolean'
  | ...
 SELECT a2, a2 OR 'TRUE' FROM t6;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to boolean'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: text) to boolean'
  | ...
 SELECT a2, 'TRUE' AND a2 FROM t6;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to boolean'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: text) to boolean'
  | ...
 SELECT a2, 'TRUE' OR a2 FROM t6;
  | ---
  | - null
- | - 'Type mismatch: can not convert TRUE to boolean'
+ | - 'Type mismatch: can not convert ''TRUE'' (type: 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 ''TRUE'' (type: 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 ''TRUE'' (type: 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 ''TRUE'' (type: 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 ''TRUE'' (type: 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 ''TRUE'' (type: 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 ''TRUE'' (type: 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 ''TRUE'' (type: 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 ''TRUE'' (type: 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 ''TRUE'' (type: 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 ''TRUE'' (type: 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 ''TRUE'' (type: 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 ''TRUE'' (type: 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 ''TRUE'' (type: 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 ''TRUE'' (type: text) to boolean'
  | ...
 
 SELECT true AND 'true';
  | ---
  | - null
- | - 'Type mismatch: can not convert true to boolean'
+ | - 'Type mismatch: can not convert ''true'' (type: 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 ''true'' (type: text) to boolean'
  | ...
 SELECT false OR 'true';
  | ---
  | - null
- | - 'Type mismatch: can not convert true to boolean'
+ | - 'Type mismatch: can not convert ''true'' (type: text) to boolean'
  | ...
 SELECT 'true' AND true;
  | ---
  | - null
- | - 'Type mismatch: can not convert true to boolean'
+ | - 'Type mismatch: can not convert ''true'' (type: 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 ''true'' (type: text) to boolean'
  | ...
 SELECT 'true' OR false;
  | ---
  | - null
- | - 'Type mismatch: can not convert true to boolean'
+ | - 'Type mismatch: can not convert ''true'' (type: text) to boolean'
  | ...
 
 SELECT a1, a1 AND 'true' FROM t6;
  | ---
  | - null
- | - 'Type mismatch: can not convert true to boolean'
+ | - 'Type mismatch: can not convert ''true'' (type: text) to boolean'
  | ...
 SELECT a1, a1 OR 'true' FROM t6;
  | ---
  | - null
- | - 'Type mismatch: can not convert true to boolean'
+ | - 'Type mismatch: can not convert ''true'' (type: text) to boolean'
  | ...
 SELECT a1, 'true' AND a1 FROM t6;
  | ---
  | - null
- | - 'Type mismatch: can not convert true to boolean'
+ | - 'Type mismatch: can not convert ''true'' (type: text) to boolean'
  | ...
 SELECT a1, 'true' OR a1 FROM t6;
  | ---
  | - null
- | - 'Type mismatch: can not convert true to boolean'
+ | - 'Type mismatch: can not convert ''true'' (type: text) to boolean'
  | ...
 SELECT a2, a2 AND 'true' FROM t6;
  | ---
  | - null
- | - 'Type mismatch: can not convert true to boolean'
+ | - 'Type mismatch: can not convert ''true'' (type: text) to boolean'
  | ...
 SELECT a2, a2 OR 'true' FROM t6;
  | ---
  | - null
- | - 'Type mismatch: can not convert true to boolean'
+ | - 'Type mismatch: can not convert ''true'' (type: text) to boolean'
  | ...
 SELECT a2, 'true' AND a2 FROM t6;
  | ---
  | - null
- | - 'Type mismatch: can not convert true to boolean'
+ | - 'Type mismatch: can not convert ''true'' (type: text) to boolean'
  | ...
 SELECT a2, 'true' OR a2 FROM t6;
  | ---
  | - null
- | - 'Type mismatch: can not convert true to boolean'
+ | - 'Type mismatch: can not convert ''true'' (type: 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 ''true'' (type: 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 ''true'' (type: 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 ''true'' (type: 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 ''true'' (type: 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 ''true'' (type: 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 ''true'' (type: 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 ''true'' (type: 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 ''true'' (type: 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 ''true'' (type: 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 ''true'' (type: 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 ''true'' (type: 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 ''true'' (type: 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 ''true'' (type: 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 ''true'' (type: text) to boolean'
  | ...
 
 SELECT true AND 'FALSE';
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to boolean'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: 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 ''FALSE'' (type: text) to boolean'
  | ...
 SELECT false OR 'FALSE';
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to boolean'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: text) to boolean'
  | ...
 SELECT 'FALSE' AND true;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to boolean'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: 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 ''FALSE'' (type: text) to boolean'
  | ...
 SELECT 'FALSE' OR false;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to boolean'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: text) to boolean'
  | ...
 
 SELECT a1, a1 AND 'FALSE' FROM t6;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to boolean'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: text) to boolean'
  | ...
 SELECT a1, a1 OR 'FALSE' FROM t6;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to boolean'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: text) to boolean'
  | ...
 SELECT a1, 'FALSE' AND a1 FROM t6;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to boolean'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: text) to boolean'
  | ...
 SELECT a1, 'FALSE' OR a1 FROM t6;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to boolean'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: text) to boolean'
  | ...
 SELECT a2, a2 AND 'FALSE' FROM t6;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to boolean'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: text) to boolean'
  | ...
 SELECT a2, a2 OR 'FALSE' FROM t6;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to boolean'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: text) to boolean'
  | ...
 SELECT a2, 'FALSE' AND a2 FROM t6;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to boolean'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: text) to boolean'
  | ...
 SELECT a2, 'FALSE' OR a2 FROM t6;
  | ---
  | - null
- | - 'Type mismatch: can not convert FALSE to boolean'
+ | - 'Type mismatch: can not convert ''FALSE'' (type: 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 ''FALSE'' (type: 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 ''FALSE'' (type: 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 ''FALSE'' (type: 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 ''FALSE'' (type: 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 ''FALSE'' (type: 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 ''FALSE'' (type: 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 ''FALSE'' (type: 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 ''FALSE'' (type: 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 ''FALSE'' (type: 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 ''FALSE'' (type: 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 ''FALSE'' (type: 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 ''FALSE'' (type: 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 ''FALSE'' (type: 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 ''FALSE'' (type: text) to boolean'
  | ...
 
 SELECT true AND 'false';
  | ---
  | - null
- | - 'Type mismatch: can not convert false to boolean'
+ | - 'Type mismatch: can not convert ''false'' (type: 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 ''false'' (type: text) to boolean'
  | ...
 SELECT false OR 'false';
  | ---
  | - null
- | - 'Type mismatch: can not convert false to boolean'
+ | - 'Type mismatch: can not convert ''false'' (type: text) to boolean'
  | ...
 SELECT 'false' AND true;
  | ---
  | - null
- | - 'Type mismatch: can not convert false to boolean'
+ | - 'Type mismatch: can not convert ''false'' (type: 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 ''false'' (type: text) to boolean'
  | ...
 SELECT 'false' OR false;
  | ---
  | - null
- | - 'Type mismatch: can not convert false to boolean'
+ | - 'Type mismatch: can not convert ''false'' (type: text) to boolean'
  | ...
 
 SELECT a1, a1 AND 'false' FROM t6;
  | ---
  | - null
- | - 'Type mismatch: can not convert false to boolean'
+ | - 'Type mismatch: can not convert ''false'' (type: text) to boolean'
  | ...
 SELECT a1, a1 OR 'false' FROM t6;
  | ---
  | - null
- | - 'Type mismatch: can not convert false to boolean'
+ | - 'Type mismatch: can not convert ''false'' (type: text) to boolean'
  | ...
 SELECT a1, 'false' AND a1 FROM t6;
  | ---
  | - null
- | - 'Type mismatch: can not convert false to boolean'
+ | - 'Type mismatch: can not convert ''false'' (type: text) to boolean'
  | ...
 SELECT a1, 'false' OR a1 FROM t6;
  | ---
  | - null
- | - 'Type mismatch: can not convert false to boolean'
+ | - 'Type mismatch: can not convert ''false'' (type: text) to boolean'
  | ...
 SELECT a2, a2 AND 'false' FROM t6;
  | ---
  | - null
- | - 'Type mismatch: can not convert false to boolean'
+ | - 'Type mismatch: can not convert ''false'' (type: text) to boolean'
  | ...
 SELECT a2, a2 OR 'false' FROM t6;
  | ---
  | - null
- | - 'Type mismatch: can not convert false to boolean'
+ | - 'Type mismatch: can not convert ''false'' (type: text) to boolean'
  | ...
 SELECT a2, 'false' AND a2 FROM t6;
  | ---
  | - null
- | - 'Type mismatch: can not convert false to boolean'
+ | - 'Type mismatch: can not convert ''false'' (type: text) to boolean'
  | ...
 SELECT a2, 'false' OR a2 FROM t6;
  | ---
  | - null
- | - 'Type mismatch: can not convert false to boolean'
+ | - 'Type mismatch: can not convert ''false'' (type: 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 ''false'' (type: 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 ''false'' (type: 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 ''false'' (type: 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 ''false'' (type: 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 ''false'' (type: 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 ''false'' (type: 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 ''false'' (type: 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 ''false'' (type: 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 ''false'' (type: 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 ''false'' (type: 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 ''false'' (type: 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 ''false'' (type: 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 ''false'' (type: 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 ''false'' (type: text) to boolean'
  | ...
 
 -- Cleaning.
diff --git a/test/sql/integer-overflow.result b/test/sql/integer-overflow.result
index 6269cb547..1048e594a 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 ''18446744073709551616'' (type: 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 ''1.84467440737096e+19'' (type: 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/persistency.result b/test/sql/persistency.result
index 6d14d4c4e..14534bc51 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 ''foobar trigger test'' (type: text) to integer'
 ...
 box.execute("SELECT * FROM barfoo WHERE foo = 9999");
 ---
diff --git a/test/sql/types.result b/test/sql/types.result
index 62161cfe1..d4975af85 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 ''1.123'' (type: 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 ''0.0'' (type: text) to integer'
 ...
 box.space.T1:drop()
 ---
@@ -339,22 +339,22 @@ box.execute("INSERT INTO tboolean VALUES (TRUE);")
 box.execute("SELECT * FROM tboolean WHERE s1 = x'44';")
 ---
 - null
-- 'Type mismatch: can not convert boolean to varbinary'
+- 'Type mismatch: can not convert varbinary to boolean'
 ...
 box.execute("SELECT * FROM tboolean WHERE s1 = 'abc';")
 ---
 - null
-- 'Type mismatch: can not convert boolean to text'
+- 'Type mismatch: can not convert ''abc'' (type: text) to boolean'
 ...
 box.execute("SELECT * FROM tboolean WHERE s1 = 1;")
 ---
 - null
-- 'Type mismatch: can not convert unsigned to boolean'
+- 'Type mismatch: can not convert ''TRUE'' (type: boolean) to unsigned'
 ...
 box.execute("SELECT * FROM tboolean WHERE s1 = 1.123;")
 ---
 - null
-- 'Type mismatch: can not convert real to boolean'
+- 'Type mismatch: can not convert ''TRUE'' (type: boolean) to real'
 ...
 box.space.TBOOLEAN: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 ''18446744073709551616'' (type: text) to integer'
 ...
 box.execute("SELECT CAST('18446744073' || '709551615' AS INTEGER);")
 ---
@@ -1054,7 +1054,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 ''-3'' (type: integer) to unsigned'
 ...
 box.execute("SELECT id FROM t1;")
 ---
@@ -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 ''-123'' (type: 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 ''-123'' (type: text) to unsigned'
 ...
 box.space.T1:drop()
 ---
@@ -1212,22 +1212,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 ''1'' (type: 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 ''1.123'' (type: 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 ''TRUE'' (type: 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 ''asd'' (type: text) to varbinary'
 ...
 box.execute("INSERT INTO t VALUES(1, x'616263');")
 ---
@@ -1236,17 +1236,17 @@ box.execute("INSERT INTO t VALUES(1, x'616263');")
 box.execute("SELECT * FROM t WHERE v = 1")
 ---
 - null
-- 'Type mismatch: can not convert unsigned to varbinary'
+- 'Type mismatch: can not convert varbinary to unsigned'
 ...
 box.execute("SELECT * FROM t WHERE v = 1.123")
 ---
 - null
-- 'Type mismatch: can not convert real to varbinary'
+- 'Type mismatch: can not convert varbinary to real'
 ...
 box.execute("SELECT * FROM t WHERE v = 'str'")
 ---
 - null
-- 'Type mismatch: can not convert text to varbinary'
+- 'Type mismatch: can not convert varbinary to text'
 ...
 box.execute("SELECT * FROM t WHERE v = x'616263'")
 ---
@@ -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 ''1'' (type: 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 ''1.123'' (type: real) to varbinary'
 ...
 box.execute("SELECT CAST(true AS VARBINARY);")
 ---
 - null
-- 'Type mismatch: can not convert TRUE to varbinary'
+- 'Type mismatch: can not convert ''TRUE'' (type: boolean) to varbinary'
 ...
 box.execute("SELECT CAST('asd' AS VARBINARY);")
 ---
@@ -1609,7 +1609,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 ''[1, 2, 3]'' (type: 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}})
 ---
@@ -1619,8 +1619,8 @@ 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 ''[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+  15, 16, 17, 18, 19, 20, 21, 22, ...'' (type: varbinary) to scalar'
 ...
 --
 -- Make sure that the error will be displayed correctly even if
@@ -1645,13 +1645,8 @@ 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 ''[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+  15, 16, 17, 18, 19, 20, 21, 22, ...'' (type: varbinary) to scalar'
 ...
 s:drop()
 ---
@@ -1672,7 +1667,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 ''{"b": 1}'' (type: varbinary) to scalar'
 ...
 s:drop()
 ---
@@ -1717,12 +1712,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 ''TRUE'' (type: boolean) to double'
 ...
 box.execute("SELECT CAST('asd' AS DOUBLE);")
 ---
 - null
-- 'Type mismatch: can not convert asd to double'
+- 'Type mismatch: can not convert ''asd'' (type: text) to double'
 ...
 box.execute("SELECT CAST('1' AS DOUBLE);")
 ---
-- 
2.25.1

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

* Re: [Tarantool-patches] [PATCH v3 1/8] sql: introduce mem_set_double()
  2020-06-25 15:17 ` [Tarantool-patches] [PATCH v3 1/8] sql: introduce mem_set_double() imeevma
@ 2020-06-28 13:31   ` Nikita Pettik
  2020-07-06 14:02     ` Nikita Pettik
  0 siblings, 1 reply; 32+ messages in thread
From: Nikita Pettik @ 2020-06-28 13:31 UTC (permalink / raw)
  To: imeevma; +Cc: tarantool-patches

On 25 Jun 18:17, imeevma@tarantool.org wrote:
> The mem_set_double () function is used to properly set MEM as
> containing DOUBLE value.

Nit: it has been introduced a long ago (sqlVdbeMemSetDouble()).
You refactor it and use in several other places.

LGTM

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

* Re: [Tarantool-patches] [PATCH v3 4/8] sql: replace ApplyType by CheckType for IN operator
  2020-06-25 15:17 ` [Tarantool-patches] [PATCH v3 4/8] sql: replace ApplyType by CheckType for IN operator imeevma
@ 2020-06-29 12:56   ` Nikita Pettik
  2020-07-05 14:28     ` Mergen Imeev
  0 siblings, 1 reply; 32+ messages in thread
From: Nikita Pettik @ 2020-06-29 12:56 UTC (permalink / raw)
  To: imeevma; +Cc: tarantool-patches

On 25 Jun 18:17, imeevma@tarantool.org wrote:
> 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>
> -    })
> -

I'd rather not drop this test. It's about scalar-numeric types
interaction. Mb it is not the most suitable place for such test,
but make sure this scenario is covered somewhere else.

The rest is OK as obvious.

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

* Re: [Tarantool-patches] [PATCH v3 5/8] sql: remove mem_apply_type() from OP_MustBeInt
  2020-06-25 15:17 ` [Tarantool-patches] [PATCH v3 5/8] sql: remove mem_apply_type() from OP_MustBeInt imeevma
@ 2020-06-29 13:29   ` Nikita Pettik
  2020-07-05 14:29     ` Mergen Imeev
  0 siblings, 1 reply; 32+ messages in thread
From: Nikita Pettik @ 2020-06-29 13:29 UTC (permalink / raw)
  To: imeevma; +Cc: tarantool-patches

On 25 Jun 18:17, imeevma@tarantool.org wrote:
> diff --git a/src/box/sql/vdbe.c b/src/box/sql/vdbe.c
> index 276956170..a609fa985 100644
> --- a/src/box/sql/vdbe.c
> +++ b/src/box/sql/vdbe.c
> @@ -2122,17 +2122,13 @@ 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);
> -		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");
> -				goto abort_due_to_error;
> -			} else {
> -				goto jump_to_p2;
> -			}
> -		}
> +	if ((pIn1->flags & (MEM_Int | MEM_UInt)) == 0 &&
> +	    mem_convert_to_integer(pIn1, true) != 0) {

Please split this conditions into two branches. Like this:

diff --git a/src/box/sql/vdbe.c b/src/box/sql/vdbe.c
index 2bc8c9817..da76d7321 100644
--- a/src/box/sql/vdbe.c
+++ b/src/box/sql/vdbe.c
@@ -2122,13 +2122,14 @@ case OP_AddImm: {            /* in1 */
  */
 case OP_MustBeInt: {            /* jump, in1 */
        pIn1 = &aMem[pOp->p1];
-       if ((pIn1->flags & (MEM_Int | MEM_UInt)) == 0 &&
-           mem_convert_to_integer(pIn1, true) != 0) {
-               if (pOp->p2 != 0)
-                       goto jump_to_p2;
-               diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
-                        sql_value_to_diag_str(pIn1), "integer");
-               goto abort_due_to_error;
+       if ((pIn1->flags & (MEM_Int | MEM_UInt)) == 0) {
+               if (mem_convert_to_integer(pIn1, true) != 0) {
+                       if (pOp->p2 != 0)
+                               goto jump_to_p2;
+                       diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
+                                sql_value_to_diag_str(pIn1), "integer");
+                       goto abort_due_to_error;
+               }
        }
        break;

It ehcnances code readability. Or even integrate this check into
mem_covert_to_ingeger().

The rest is OK (hope you carefully verified changed tests, since
I've only briefly looked through).

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

* Re: [Tarantool-patches] [PATCH v3 6/8] sql: remove implicit cast for comparison
  2020-06-25 15:17 ` [Tarantool-patches] [PATCH v3 6/8] sql: remove implicit cast for comparison imeevma
@ 2020-06-29 23:51   ` Nikita Pettik
  2020-07-05 14:47     ` Mergen Imeev
  0 siblings, 1 reply; 32+ messages in thread
From: Nikita Pettik @ 2020-06-29 23:51 UTC (permalink / raw)
  To: imeevma; +Cc: tarantool-patches

On 25 Jun 18:17, imeevma@tarantool.org wrote:
> Thank you for review! My answers and new patch below.
> 
> On 22.06.2020 15:25, Nikita Pettik wrote:
> > On 17 Jun 15:36, imeevma@tarantool.org wrote:
> >> @@ -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;
> >> -
> >
> > Replace these assertions with relevant ones.
> >
> Not sure if this is necessary, since now we have much less flag
> changes after removal of mem_apply_type().

Не понял как это связано...Твои изменения не затрагивают
инвариант MEM_Dyn.
 
> >> @@ -0,0 +1,281 @@
> >> +#!/usr/bin/env tarantool
> >> +test = require("sqltester")
> >> +test:plan(32)
> >> +
> >> +--
> >> +
> >> +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);
> >
> > What about table with scalar/any fields?
> >
> I think this is too big a problem to solve it here.

Гораздо лучше потом клепать фоллоу-апы, точечно затыкая креши..
Я бы добавил хотя бы самых базовых примеров.

>  			i = pIn3->u.i;
> @@ -3617,7 +3595,38 @@ skip_truncate:
>  	assert(oc!=OP_SeekGE || r.default_rc==+1);
>  	assert(oc!=OP_SeekLT || r.default_rc==+1);
>  
> +	/*
> +	 * Make sure that the types of all the fields in the tuple
> +	 * that will be used in the iterator match the field types
> +	 * of the space.
> +	 */
>  	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_check_type(mem, type) == 0 ||
> +		    mem_convert_numeric(mem, type, true) == 0)
> +			continue;

Я бы все-таки разбил бы эту проверку на два условия:

if (...)
	continue
if (...)
	continue

А еще лучше вынести этот чанк в хелпер.

> +		/*
> +		 * If the number was not converted without loss,
> +		 * we will not find tuples using the EQ iterator.
> +		 */

Пожайлуста, не используй двойное отрицание - комментарий очень
сложно воспринимать. Давай это переформулируем, можно пример
добавить. Это довольно скользкое место.

> +		if ((mem->flags & MEM_Real) != 0 &&
> +		    (type == FIELD_TYPE_INTEGER ||
> +		     type == FIELD_TYPE_UNSIGNED)) {
> +			assert(eqOnly == 1);
> +			res = 1;
> +			goto seek_not_found;
> +		}
> +		if ((mem->flags & (MEM_Int | MEM_UInt)) != 0 &&
> +		    type == FIELD_TYPE_DOUBLE && eqOnly == 1) {
> +			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
> @@ -4744,7 +4753,25 @@ case OP_IdxGE:  {       /* jump */
>  		assert(pOp->opcode==OP_IdxGE || pOp->opcode==OP_IdxLT);
>  		r.default_rc = 0;
>  	}
> +
> +	/*
> +	 * Make sure that the types of all the fields in the tuple
> +	 * that will be used in the iterator comparable with the
> +	 * fields of the space.
> +	 */
>  	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];

Как-то мне эти два места (выше в SeekGE) вообще не нравятся.
Какие-то они запутанные. Давай подумаем как можно зарефакторить их.

> +		if (mem_check_type(mem, type) == 0)
> +			continue;
> +		if (sql_type_is_numeric(type) &&
> +		    (mem->flags & (MEM_Real | MEM_Int | MEM_UInt)) != 0)
> +			continue;
> +		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
> 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)

Ты в следующем коммите как раз делаешь клин-ап. Давай эту функцию
там и удалим (как и остальные).

>  			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

Когда кто-то ищет где посмотреть тесты связанные с типами,
первое что приходит в голову - грепнуть *types*. Этот тест
по сути ничего и не тестирует (уверен, эти пути уже покрыты
в других тестах), зато хорошо отображает работу системы типов.
Я бы просто подумал о других разработчиках, и все же замержил
его в какой-нибудь тест типа sql/types.test.lua.

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

* Re: [Tarantool-patches] [PATCH v3 7/8] sql: remove unused functions
  2020-06-25 15:17 ` [Tarantool-patches] [PATCH v3 7/8] sql: remove unused functions imeevma
@ 2020-06-29 23:52   ` Nikita Pettik
  2020-07-05 14:50     ` Mergen Imeev
  0 siblings, 1 reply; 32+ messages in thread
From: Nikita Pettik @ 2020-06-29 23:52 UTC (permalink / raw)
  To: imeevma; +Cc: tarantool-patches

On 25 Jun 18:17, imeevma@tarantool.org wrote:
> After previous patches, some functions and the ApplyType opcode
> become unused, so this patch removes them.
> 
> Follow-up #4230
> ---

Все еще можно нагрепать OP_ApplyType. Перепроверь.

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

* Re: [Tarantool-patches] [PATCH v3 8/8] sql: show value and its type in type mismatch error
  2020-06-25 15:17 ` [Tarantool-patches] [PATCH v3 8/8] sql: show value and its type in type mismatch error imeevma
@ 2020-06-30  0:22   ` Nikita Pettik
  2020-07-05 15:03     ` Mergen Imeev
  0 siblings, 1 reply; 32+ messages in thread
From: Nikita Pettik @ 2020-06-30  0:22 UTC (permalink / raw)
  To: imeevma; +Cc: tarantool-patches

On 25 Jun 18:17, imeevma@tarantool.org wrote:
> After this patch value and its type will be shown in description
> of type mismatch error

Какие цели преследует этот патч? Зачем мы это делаем?
Диф то на 1.5 кслок. Забыл точку в конце :)

>  	}
>  #ifdef SQL_DEBUG
> @@ -4740,7 +4735,7 @@ case OP_IdxGE:  {       /* jump */
>  		    (mem->flags & (MEM_Real | MEM_Int | MEM_UInt)) != 0)
>  			continue;
>  		diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
> -			field_type_strs[type], mem_type_to_str(mem));
> +			sql_value_to_diag_str(mem), mem_type_to_str(mem));
>  		goto abort_due_to_error;
>  	}
>  #ifdef SQL_DEBUG
> diff --git a/src/box/sql/vdbemem.c b/src/box/sql/vdbemem.c
> index a721afc83..bb7676354 100644
> --- a/src/box/sql/vdbemem.c
> +++ b/src/box/sql/vdbemem.c
> @@ -1166,12 +1166,15 @@ sqlValueText(sql_value * pVal)
>  const char *
>  sql_value_to_diag_str(sql_value *value)
>  {
> -	if (sql_value_type(value) == MP_BIN) {
> -		if (mem_has_msgpack_subtype(value))
> -			return sqlValueText(value);
> +	if (sql_value_mp_type(value) == MP_BIN)
>  		return "varbinary";
> -	}
> -	return sqlValueText(value);
> +	char *type = mem_type_to_str(value);
> +	char *str = (char *)sqlValueText(value);
> +	if (str == NULL)
> +		return "NULL";
> +	if (strlen(str) < 80)

https://en.wikipedia.org/wiki/Magic_number_(programming)

> +		return tt_sprintf("'%s' (type: %s)", str, type);
> +	return tt_sprintf("'%.80s...' (type: %s)", str, type);
>  }
>  
>  /*
> diff --git a/test/sql-tap/autoinc.test.lua b/test/sql-tap/autoinc.test.lua
> index 07442b60a..1547ffcd3 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 'asd' (type: text) to integer"

Выглядит зачотно, выглядит all right!

> diff --git a/test/sql-tap/gh-3809-implicit-cast-assignment.test.lua b/test/sql-tap/gh-3809-implicit-cast-assignment.test.lua
> index a1809b3cb..f1edfa0f6 100755
> --- a/test/sql-tap/gh-3809-implicit-cast-assignment.test.lua
> +++ b/test/sql-tap/gh-3809-implicit-cast-assignment.test.lua
> @@ -28,7 +28,7 @@ test:do_catchsql_test(
>      [[
>          INSERT INTO ti(i) VALUES (100000000000000000000000000000000.1)
>      ]], {
> -        1, "Type mismatch: can not convert 1.0e+32 to integer"
> +        1, "Type mismatch: can not convert '1.0e+32' (type: real) to integer"
>      })

Я бы может еще кавычки вокруг чиселок/буленов не добавлял, но это
в принципе мелочь - тип то печатается.

В остальном - ОК.

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

* Re: [Tarantool-patches] [PATCH v3 2/8] sql: change implicit cast for assignment
  2020-06-25 15:17 ` [Tarantool-patches] [PATCH v3 2/8] sql: change implicit cast for assignment imeevma
@ 2020-06-30 11:50   ` Nikita Pettik
  2020-07-05 14:26     ` Mergen Imeev
  0 siblings, 1 reply; 32+ messages in thread
From: Nikita Pettik @ 2020-06-30 11:50 UTC (permalink / raw)
  To: imeevma; +Cc: tarantool-patches

On 25 Jun 18:17, imeevma@tarantool.org wrote:
> On 22.06.2020 11:48, Nikita Pettik wrote:
> > On 17 Jun 15:36, imeevma@tarantool.org wrote:
> >> This patch removes type changing from OP_MakeRecord.
> >
> > Please reflect user-visible changes in commit message.
> >  
> Fixed.

Seems to be the next patch..
 
> On 22.06.2020 12:32, Nikita Pettik wrote:
> > On 17 Jun 15:36, imeevma@tarantool.org wrote:
> >> 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(-)
> 
> On 22.06.2020 13:07, Nikita Pettik wrote:
> > On 17 Jun 15:36, imeevma@tarantool.org wrote:
> >> 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
> >> ---
> >>  src/box/sql/vdbe.c                   |   2 +-
> >>  test/sql-tap/e_select1.test.lua      |  17 +-
> >>  test/sql-tap/in4.test.lua            |  97 +--
> >>  test/sql-tap/join.test.lua           |   1 -
> >>  test/sql-tap/limit.test.lua          |   2 +-
> >>  test/sql-tap/tkt-9a8b09f8e6.test.lua |  24 +-
> >>  test/sql-tap/tkt-fc7bd6358f.test.lua | 111 ----
> >>  test/sql-tap/transitive1.test.lua    |   4 +-
> >>  test/sql-tap/whereB.test.lua         | 900 ---------------------------
> >>  test/sql-tap/whereC.test.lua         |   8 +-
> >>  10 files changed, 19 insertions(+), 1147 deletions(-)
> >>  delete mode 100755 test/sql-tap/tkt-fc7bd6358f.test.lua
> >>  delete mode 100755 test/sql-tap/whereB.test.lua
> >>
> 
> New patch:
> 
> commit 21d7145c1929bc4606c56e9a566477f248637ed1
> Author: Mergen Imeev <imeevma@gmail.com>
> Date:   Wed May 27 13:49:11 2020 +0300
> 
> diff --git a/src/box/sql/sqlInt.h b/src/box/sql/sqlInt.h
> index 37283e506..f1d0345f9 100644
> --- a/src/box/sql/sqlInt.h
> +++ b/src/box/sql/sqlInt.h
> @@ -397,6 +397,15 @@ sql_value_to_diag_str(sql_value *value);
>  enum mp_type
>  sql_value_type(sql_value *);
>  
> +/*
> + * Return the MP_type of the value of the MEM.
> + *
> + * @param mem MEM with the correct MEM_type.
> + * @retval MP_type of the value.
> + */
> +enum mp_type
> +sql_value_mp_type(struct Mem *mem);

It's not sql_value *, it's struct Mem. So the name of function
is misleading.

> diff --git a/src/box/sql/vdbe.c b/src/box/sql/vdbe.c
> index 950f72ddd..009d577d2 100644
> --- a/src/box/sql/vdbe.c
> +++ b/src/box/sql/vdbe.c
> @@ -417,6 +417,143 @@ sql_value_apply_type(
>   mem_apply_type((Mem *) pVal, type);
>  }
>  
> + *
> + * @param mem The MEM that contains the value to check.
> + * @param type The type to check.
> + * @retval 0 if the MEM_type of the value ​​and the given type are

Wrong symbols.

> + *         compatible, -1 otherwise.
> + */
> +static int
> +mem_check_type(struct Mem *mem, enum field_type type)

mem_test_type_compatibility
mem_check_type_consistency
mem_is_type_compatible

I'd prefer last one and change return value to boolean.
Then it turns into simple return field_mp_plain_type_is_compatible()..

> + enum mp_type mp_type = sql_value_mp_type(mem);
> + assert(mp_type < MP_EXT);
> + if (field_mp_plain_type_is_compatible(type, mp_type, true))
> +   return 0;
> + return -1;
> +}
> +
> +/**
> + * Convert the numeric value contained in MEM to double. If the
> + * is_precise flag is set, the conversion will succeed only if it
> + * is lossless.
> + *
> + * @param mem The MEM that contains the numeric value.
> + * @param is_precise Flag.
> + * @retval 0 if the conversion was successful, -1 otherwise.
> + */
> +static int
> +mem_convert_to_double(struct Mem *mem, bool is_precise)
> +{
> + if ((mem->flags & (MEM_Int | MEM_UInt)) == 0)
> +   return -1;
> + if ((mem->flags & MEM_Int) != 0) {
> +   int64_t i = mem->u.i;
> +   double d = (double)i;
> +   if (!is_precise || i == (int64_t)d)
> +     mem_set_double(mem, d);
> +   else
> +     return -1;
> + } else {
> +   uint64_t u = mem->u.u;
> +   double d = (double)u;
> +   if (!is_precise || u == (uint64_t)d)
> +     mem_set_double(mem, d);
> +   else
> +     return -1;
> + }
> + mem->field_type = FIELD_TYPE_DOUBLE;

Why not incorparate field_type assingment into mem_set_double()?
The same concerns other converting functions.

> +/**
> + * Convert the numeric value contained in MEM to another numeric
> + * type. If the is_precise flag is set, the conversion will
> + * succeed only if it is lossless.
> + *
> + * @param mem The MEM that contains the numeric value.
> + * @param type The type to convert to.
> + * @param is_precise Flag.
> + * @retval 0 if the conversion was successful, -1 otherwise.
> + */
> +static int
> +mem_convert_numeric(struct Mem *mem, enum field_type type, bool is_precise)

mem_convert_to_numeric ?
mem_cast_to_numeric

> +{
> + if (!sql_type_is_numeric(type) ||
> +     (mem->flags & (MEM_Real | MEM_Int | MEM_UInt)) == 0)

It's somehow unnatural passing to _numeric function non-numeric type
to convert to. Instead let's use this function properly and replace
branching with assertion.

> +   return -1;
> + if (type == FIELD_TYPE_NUMBER)
> +   return 0;
> + if (type == FIELD_TYPE_DOUBLE)
> +   return mem_convert_to_double(mem, is_precise);
> + if (type == FIELD_TYPE_UNSIGNED)
> +   return mem_convert_to_unsigned(mem, is_precise);
> + assert(type == FIELD_TYPE_INTEGER);
> + return mem_convert_to_integer(mem, is_precise);
> +}
> +
>  /*
>   * 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
> @@ -2773,6 +2910,36 @@ 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.

-> double  'with given'

> + * If the MEM_type of the value and the given type are
> + * incompatible, but both are numeric, this opcode attempts to

Incompatible but numeric? Could you please be more specific.

> + * convert the value to the type.
> + */
> +case OP_ImplicitCast: {
> + 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_type(pIn1, type) != 0 &&
> +       mem_convert_numeric(pIn1, type, false) != 0) {
> +     diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
> +        sql_value_to_diag_str(pIn1),
> +        field_type_strs[type]);
> +     goto abort_due_to_error;
> +   }
> +   pIn1++;
> + }

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

* Re: [Tarantool-patches] [PATCH v3 2/8] sql: change implicit cast for assignment
  2020-06-30 11:50   ` Nikita Pettik
@ 2020-07-05 14:26     ` Mergen Imeev
  2020-07-06 21:27       ` Nikita Pettik
  0 siblings, 1 reply; 32+ messages in thread
From: Mergen Imeev @ 2020-07-05 14:26 UTC (permalink / raw)
  To: Nikita Pettik; +Cc: tarantool-patches

Hi! Thank you for the review. My answers and new patch
below. Sorry, I didn't include diff.

On Tue, Jun 30, 2020 at 11:50:56AM +0000, Nikita Pettik wrote:
> On 25 Jun 18:17, imeevma@tarantool.org wrote:
> > On 22.06.2020 11:48, Nikita Pettik wrote:
> > > On 17 Jun 15:36, imeevma@tarantool.org wrote:
> > >> This patch removes type changing from OP_MakeRecord.
> > >
> > > Please reflect user-visible changes in commit message.
> > >  
> > Fixed.
> 
> Seems to be the next patch..
>  
True. Sorry about this.

> > On 22.06.2020 12:32, Nikita Pettik wrote:
> > > On 17 Jun 15:36, imeevma@tarantool.org wrote:
> > >> 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(-)
> > 
> > On 22.06.2020 13:07, Nikita Pettik wrote:
> > > On 17 Jun 15:36, imeevma@tarantool.org wrote:
> > >> 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
> > >> ---
> > >>  src/box/sql/vdbe.c                   |   2 +-
> > >>  test/sql-tap/e_select1.test.lua      |  17 +-
> > >>  test/sql-tap/in4.test.lua            |  97 +--
> > >>  test/sql-tap/join.test.lua           |   1 -
> > >>  test/sql-tap/limit.test.lua          |   2 +-
> > >>  test/sql-tap/tkt-9a8b09f8e6.test.lua |  24 +-
> > >>  test/sql-tap/tkt-fc7bd6358f.test.lua | 111 ----
> > >>  test/sql-tap/transitive1.test.lua    |   4 +-
> > >>  test/sql-tap/whereB.test.lua         | 900 ---------------------------
> > >>  test/sql-tap/whereC.test.lua         |   8 +-
> > >>  10 files changed, 19 insertions(+), 1147 deletions(-)
> > >>  delete mode 100755 test/sql-tap/tkt-fc7bd6358f.test.lua
> > >>  delete mode 100755 test/sql-tap/whereB.test.lua
> > >>
> > 
> > New patch:
> > 
> > commit 21d7145c1929bc4606c56e9a566477f248637ed1
> > Author: Mergen Imeev <imeevma@gmail.com>
> > Date:   Wed May 27 13:49:11 2020 +0300
> > 
> > diff --git a/src/box/sql/sqlInt.h b/src/box/sql/sqlInt.h
> > index 37283e506..f1d0345f9 100644
> > --- a/src/box/sql/sqlInt.h
> > +++ b/src/box/sql/sqlInt.h
> > @@ -397,6 +397,15 @@ sql_value_to_diag_str(sql_value *value);
> >  enum mp_type
> >  sql_value_type(sql_value *);
> >  
> > +/*
> > + * Return the MP_type of the value of the MEM.
> > + *
> > + * @param mem MEM with the correct MEM_type.
> > + * @retval MP_type of the value.
> > + */
> > +enum mp_type
> > +sql_value_mp_type(struct Mem *mem);
> 
> It's not sql_value *, it's struct Mem. So the name of function
> is misleading.
Changed name to 'mem_mp_type'.

> 
> > diff --git a/src/box/sql/vdbe.c b/src/box/sql/vdbe.c
> > index 950f72ddd..009d577d2 100644
> > --- a/src/box/sql/vdbe.c
> > +++ b/src/box/sql/vdbe.c
> > @@ -417,6 +417,143 @@ sql_value_apply_type(
> >   mem_apply_type((Mem *) pVal, type);
> >  }
> >  
> > + *
> > + * @param mem The MEM that contains the value to check.
> > + * @param type The type to check.
> > + * @retval 0 if the MEM_type of the value ​​and the given type are
> 
> Wrong symbols.
> 
Fixed.

> > + *         compatible, -1 otherwise.
> > + */
> > +static int
> > +mem_check_type(struct Mem *mem, enum field_type type)
> 
> mem_test_type_compatibility
> mem_check_type_consistency
> mem_is_type_compatible
> 
> I'd prefer last one and change return value to boolean.
> Then it turns into simple return field_mp_plain_type_is_compatible()..
> 
Fixed, used third option.

> > + enum mp_type mp_type = sql_value_mp_type(mem);
> > + assert(mp_type < MP_EXT);
> > + if (field_mp_plain_type_is_compatible(type, mp_type, true))
> > +   return 0;
> > + return -1;
> > +}
> > +
> > +/**
> > + * Convert the numeric value contained in MEM to double. If the
> > + * is_precise flag is set, the conversion will succeed only if it
> > + * is lossless.
> > + *
> > + * @param mem The MEM that contains the numeric value.
> > + * @param is_precise Flag.
> > + * @retval 0 if the conversion was successful, -1 otherwise.
> > + */
> > +static int
> > +mem_convert_to_double(struct Mem *mem, bool is_precise)
> > +{
> > + if ((mem->flags & (MEM_Int | MEM_UInt)) == 0)
> > +   return -1;
> > + if ((mem->flags & MEM_Int) != 0) {
> > +   int64_t i = mem->u.i;
> > +   double d = (double)i;
> > +   if (!is_precise || i == (int64_t)d)
> > +     mem_set_double(mem, d);
> > +   else
> > +     return -1;
> > + } else {
> > +   uint64_t u = mem->u.u;
> > +   double d = (double)u;
> > +   if (!is_precise || u == (uint64_t)d)
> > +     mem_set_double(mem, d);
> > +   else
> > +     return -1;
> > + }
> > + mem->field_type = FIELD_TYPE_DOUBLE;
> 
> Why not incorparate field_type assingment into mem_set_double()?
> The same concerns other converting functions.
> 
I think this should be done in #4906 issue since it may
lead to not always simple to understand changes.

> > +/**
> > + * Convert the numeric value contained in MEM to another numeric
> > + * type. If the is_precise flag is set, the conversion will
> > + * succeed only if it is lossless.
> > + *
> > + * @param mem The MEM that contains the numeric value.
> > + * @param type The type to convert to.
> > + * @param is_precise Flag.
> > + * @retval 0 if the conversion was successful, -1 otherwise.
> > + */
> > +static int
> > +mem_convert_numeric(struct Mem *mem, enum field_type type, bool is_precise)
> 
> mem_convert_to_numeric ?
> mem_cast_to_numeric
> 
Used first option.

> > +{
> > + if (!sql_type_is_numeric(type) ||
> > +     (mem->flags & (MEM_Real | MEM_Int | MEM_UInt)) == 0)
> 
> It's somehow unnatural passing to _numeric function non-numeric type
> to convert to. Instead let's use this function properly and replace
> branching with assertion.
> 
No, I think it is good as it is. More that that, due to
some other comments I added similar checks to all other
mem_convert_to>* functions.

My reason is: in all places we use this function we have
to check that field type and MEM_type are numeric, so it
make sence to move this check inside of the function.

> > +   return -1;
> > + if (type == FIELD_TYPE_NUMBER)
> > +   return 0;
> > + if (type == FIELD_TYPE_DOUBLE)
> > +   return mem_convert_to_double(mem, is_precise);
> > + if (type == FIELD_TYPE_UNSIGNED)
> > +   return mem_convert_to_unsigned(mem, is_precise);
> > + assert(type == FIELD_TYPE_INTEGER);
> > + return mem_convert_to_integer(mem, is_precise);
> > +}
> > +
> >  /*
> >   * 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
> > @@ -2773,6 +2910,36 @@ 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.
> 
> -> double  'with given'
> 
Fixed.

> > + * If the MEM_type of the value and the given type are
> > + * incompatible, but both are numeric, this opcode attempts to
> 
> Incompatible but numeric? Could you please be more specific.
> 
Incompatible and incompareble have different definitions
here. I changed to 'incompatible according to
field_mp_plain_type_is_compatible()'.

> > + * convert the value to the type.
> > + */
> > +case OP_ImplicitCast: {
> > + 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_type(pIn1, type) != 0 &&
> > +       mem_convert_numeric(pIn1, type, false) != 0) {
> > +     diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
> > +        sql_value_to_diag_str(pIn1),
> > +        field_type_strs[type]);
> > +     goto abort_due_to_error;
> > +   }
> > +   pIn1++;
> > + }


New patch:


commit 6468f9c853e51565e73423ccf29b92862783d42e
Author: Mergen Imeev <imeevma@gmail.com>
Date:   Wed May 27 13:49:11 2020 +0300

    sql: change implicit cast for assignment
    
    This patch changes implicit cast for assignment.
    
    Closes #3809
    
    @TarantoolBot document
    Title: change implicit cast for comparison
    
    After this patch, these rules will apply during the implicit cast:
    
    | | STRING | BINARY | BOOLEAN | INTEGER | UNSIGNED | DOUBLE |
    | :--- | :---: | :---: | :---: | :---: | :---: | :---: |
    | STRING | A | N | N | N | N | N |
    | BINARY | N | A | N | N | N | N |
    | BOOLEAN | N | N | A | N | N | N |
    | INTEGER | N | N | N | A | S | Aa |
    | UNSIGNED | N | N | N | A | A | Aa |
    | DOUBLE | N | N | N | Sa | Sa | A |
    
    In this table, the types of the assigned value are on the left,
    and the types that should be after the assignment are at the top.
    
    'A' - the assignment will be completed.
    'N' - the assignment won't be completed.
    'S' - the appointment may be unsuccessful.
    'a' - after assignment, the resulting value may be approximated.
    
    Rules for numeric values are these:
    1) Loss of significant digits (overflow) is an error.
    2) Loss of insignificant digits is not an error.
    
    Example:
    ```
    tarantool> box.execute([[CREATE TABLE t1(i INT PRIMARY KEY);]])
    tarantool> box.execute([[INSERT INTO t1 VALUES ('1');]])
    ---
    - null
    - 'Type mismatch: can not convert 1 to integer'
    ...
    
    tarantool> box.execute('INSERT INTO t1 VALUES (1.2345);')
    tarantool> box.execute('SELECT * FROM t1;')
    ---
    - metadata:
      - name: I
        type: integer
      rows:
      - [1]
    ...
    
    tarantool> box.execute([[CREATE TABLE t2(t text PRIMARY KEY);]])
    tarantool> box.execute([[INSERT INTO t2 VALUES (1);]])
    ---
    - null
    - 'Type mismatch: can not convert 1 to string'
    ...
    ```

diff --git a/src/box/sql/insert.c b/src/box/sql/insert.c
index 588e142d2..8a89f9904 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_ImplicitCast, reg, field_count, 0,
 			  (char *)colls_type, P4_DYNAMIC);
 }
 
diff --git a/src/box/sql/sqlInt.h b/src/box/sql/sqlInt.h
index 37283e506..bd0055668 100644
--- a/src/box/sql/sqlInt.h
+++ b/src/box/sql/sqlInt.h
@@ -397,6 +397,15 @@ sql_value_to_diag_str(sql_value *value);
 enum mp_type
 sql_value_type(sql_value *);
 
+/*
+ * Return the MP_type of the value of the MEM.
+ *
+ * @param mem MEM with the correct MEM_type.
+ * @retval MP_type of the value.
+ */
+enum mp_type
+mem_mp_type(struct Mem *mem);
+
 static inline bool
 sql_value_is_null(sql_value *value)
 {
diff --git a/src/box/sql/vdbe.c b/src/box/sql/vdbe.c
index 950f72ddd..1386ea2c0 100644
--- a/src/box/sql/vdbe.c
+++ b/src/box/sql/vdbe.c
@@ -417,6 +417,150 @@ sql_value_apply_type(
 	mem_apply_type((Mem *) pVal, type);
 }
 
+/**
+ * Check that MEM_type of the mem is compatible with given type.
+ *
+ * @param mem The MEM that contains the value to check.
+ * @param type The type to check.
+ * @retval TRUE if the MEM_type of the value and the given type
+ *         are compatible, FALSE otherwise.
+ */
+static bool
+mem_is_type_compatible(struct Mem *mem, enum field_type type)
+{
+	enum mp_type mp_type = mem_mp_type(mem);
+	assert(mp_type < MP_EXT);
+	return field_mp_plain_type_is_compatible(type, mp_type, true);
+}
+
+/**
+ * Convert the numeric value contained in MEM to double. If the
+ * is_precise flag is set, the conversion will succeed only if it
+ * is lossless.
+ *
+ * @param mem The MEM that contains the numeric value.
+ * @param is_precise Flag.
+ * @retval 0 if the conversion was successful, -1 otherwise.
+ */
+static int
+mem_convert_to_double(struct Mem *mem, bool is_precise)
+{
+	if ((mem->flags & MEM_Real) != 0)
+		return 0;
+	if ((mem->flags & (MEM_Int | MEM_UInt)) == 0)
+		return -1;
+	if ((mem->flags & MEM_Int) != 0) {
+		int64_t i = mem->u.i;
+		double d = (double)i;
+		if (!is_precise || i == (int64_t)d)
+			mem_set_double(mem, d);
+		else
+			return -1;
+	} else {
+		uint64_t u = mem->u.u;
+		double d = (double)u;
+		if (!is_precise || u == (uint64_t)d)
+			mem_set_double(mem, d);
+		else
+			return -1;
+	}
+	mem->field_type = FIELD_TYPE_DOUBLE;
+	return 0;
+}
+
+/**
+ * Convert the numeric value contained in MEM to unsigned. If the
+ * is_precise flag is set, the conversion will succeed only if it
+ * is lossless.
+ *
+ * @param mem The MEM that contains the numeric value.
+ * @param is_precise Flag.
+ * @retval 0 if the conversion was successful, -1 otherwise.
+ */
+static int
+mem_convert_to_unsigned(struct Mem *mem, bool is_precise)
+{
+	if ((mem->flags & MEM_UInt) != 0)
+		return 0;
+	if ((mem->flags & MEM_Int) != 0)
+		return -1;
+	if ((mem->flags & MEM_Real) == 0)
+		return -1;
+	double d = mem->u.r;
+	if (d < 0.0 || d >= (double)UINT64_MAX)
+		return -1;
+	uint64_t u = (uint64_t)d;
+	if (!is_precise || d == (double)u)
+		mem_set_u64(mem, (uint64_t) d);
+	else
+		return -1;
+	mem->field_type = FIELD_TYPE_UNSIGNED;
+	return 0;
+}
+
+/**
+ * Convert the numeric value contained in MEM to integer. If the
+ * is_precise flag is set, the conversion will succeed only if it
+ * is lossless.
+ *
+ * @param mem The MEM that contains the numeric value.
+ * @param is_precise Flag.
+ * @retval 0 if the conversion was successful, -1 otherwise.
+ */
+static int
+mem_convert_to_integer(struct Mem *mem, bool is_precise)
+{
+	if ((mem->flags & (MEM_UInt | MEM_Int)) != 0)
+		return 0;
+	if ((mem->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 (!is_precise || d == (double)i)
+			mem_set_i64(mem, (int64_t) d);
+		else
+			return -1;
+	} else {
+		uint64_t u = (uint64_t)d;
+		if (!is_precise || d == (double)u)
+			mem_set_u64(mem, (uint64_t) d);
+		else
+			return -1;
+	}
+	mem->field_type = FIELD_TYPE_INTEGER;
+	return 0;
+}
+
+/**
+ * Convert the numeric value contained in MEM to another numeric
+ * type. If the is_precise flag is set, the conversion will
+ * succeed only if it is lossless.
+ *
+ * @param mem The MEM that contains the numeric value.
+ * @param type The type to convert to.
+ * @param is_precise Flag.
+ * @retval 0 if the conversion was successful, -1 otherwise.
+ */
+static int
+mem_convert_to_numeric(struct Mem *mem, enum field_type type, bool is_precise)
+{
+	if (!sql_type_is_numeric(type))
+		return -1;
+	if ((mem->flags & (MEM_Real | MEM_Int | MEM_UInt)) == 0)
+		return -1;
+	if (type == FIELD_TYPE_NUMBER)
+		return 0;
+	if (type == FIELD_TYPE_DOUBLE)
+		return mem_convert_to_double(mem, is_precise);
+	if (type == FIELD_TYPE_UNSIGNED)
+		return mem_convert_to_unsigned(mem, is_precise);
+	assert(type == FIELD_TYPE_INTEGER);
+	return mem_convert_to_integer(mem, is_precise);
+}
+
 /*
  * 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
@@ -2773,6 +2917,36 @@ case OP_ApplyType: {
 	break;
 }
 
+/* Opcode: ImplicitCast P1 P2 * P4 *
+ * Synopsis: type(r[P1@P2])
+ *
+ * Check that types of P2 registers starting from register
+ * P1 are compatible with given field types in P4.
+ * If the MEM_type of the value and the given type are
+ * incompatible according to field_mp_plain_type_is_compatible(),
+ * but both are numeric, this opcode attempts to convert the value
+ * to the type.
+ */
+case OP_ImplicitCast: {
+	enum field_type *types = pOp->p4.types;
+	assert(types != NULL);
+	assert(types[pOp->p2] == field_type_MAX);
+	for (int i = 0; types[i] != field_type_MAX; ++i) {
+		enum field_type type = types[i];
+		pIn1 = &aMem[pOp->p1 + i];
+		assert(pIn1 <= &p->aMem[(p->nMem+1 - p->nCursor)]);
+		assert(memIsValid(pIn1));
+		if (mem_is_type_compatible(pIn1, type))
+			continue;
+		if (mem_convert_to_numeric(pIn1, type, false) == 0)
+			continue;
+		diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
+			 sql_value_to_diag_str(pIn1), field_type_strs[type]);
+		goto abort_due_to_error;
+	}
+	break;
+}
+
 /* Opcode: MakeRecord P1 P2 P3 P4 P5
  * Synopsis: r[P3]=mkrec(r[P1@P2])
  *
diff --git a/src/box/sql/vdbeapi.c b/src/box/sql/vdbeapi.c
index 4e103a653..b106ce6bd 100644
--- a/src/box/sql/vdbeapi.c
+++ b/src/box/sql/vdbeapi.c
@@ -225,6 +225,33 @@ sql_value_type(sql_value *pVal)
 	}
 }
 
+enum mp_type
+mem_mp_type(struct Mem *mem)
+{
+	switch (mem->flags & MEM_PURE_TYPE_MASK) {
+	case MEM_Int:
+		return MP_INT;
+	case MEM_UInt:
+		return MP_UINT;
+	case MEM_Real:
+		return MP_DOUBLE;
+	case MEM_Str:
+		return MP_STR;
+	case MEM_Blob:
+		if ((mem->flags & MEM_Subtype) == 0 ||
+		    mem->subtype != SQL_SUBTYPE_MSGPACK)
+			return MP_BIN;
+		assert(mp_typeof(*mem->z) == MP_MAP ||
+		       mp_typeof(*mem->z) == MP_ARRAY);
+		return mp_typeof(*mem->z);
+	case MEM_Bool:
+		return MP_BOOL;
+	case MEM_Null:
+		return MP_NIL;
+	default: unreachable();
+	}
+}
+
 /* Make a copy of an sql_value object
  */
 sql_value *
diff --git a/test/sql-tap/autoinc.test.lua b/test/sql-tap/autoinc.test.lua
index 37e65e541..07442b60a 100755
--- a/test/sql-tap/autoinc.test.lua
+++ b/test/sql-tap/autoinc.test.lua
@@ -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..a1809b3cb
--- /dev/null
+++ b/test/sql-tap/gh-3809-implicit-cast-assignment.test.lua
@@ -0,0 +1,653 @@
+#!/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 (100000000000000000000000000000000.1)
+    ]], {
+        1, "Type mismatch: can not convert 1.0e+32 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 TRUE to integer"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-5",
+    [[
+        INSERT INTO ti(i) VALUES ('33')
+    ]], {
+        1, "Type mismatch: can not convert 33 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);
+    ]], {
+        0
+    })
+
+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 TRUE to double"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-12",
+    [[
+        INSERT INTO td(d) VALUES ('33')
+    ]], {
+        1, "Type mismatch: can not convert 33 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, 100000000000000000, 3, 22.2
+    })
+
+test:do_catchsql_test(
+    "gh-3809-15",
+    [[
+        INSERT INTO tb(b) VALUES (11)
+    ]], {
+        1, "Type mismatch: can not convert 11 to boolean"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-16",
+    [[
+        INSERT INTO tb(b) VALUES (22.2)
+    ]], {
+        1, "Type mismatch: can not convert 22.2 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 33 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 11 to string"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-22",
+    [[
+        INSERT INTO tt(t) VALUES (22.2)
+    ]], {
+        1, "Type mismatch: can not convert 22.2 to string"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-23",
+    [[
+        INSERT INTO tt(t) VALUES (true)
+    ]], {
+        1, "Type mismatch: can not convert TRUE 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 11 to varbinary"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-28",
+    [[
+        INSERT INTO tv(v) VALUES (22.2)
+    ]], {
+        1, "Type mismatch: can not convert 22.2 to varbinary"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-29",
+    [[
+        INSERT INTO tv(v) VALUES (true)
+    ]], {
+        1, "Type mismatch: can not convert TRUE to varbinary"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-30",
+    [[
+        INSERT INTO tv(v) VALUES ('33')
+    ]], {
+        1, "Type mismatch: can not convert 33 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"
+    })
+
+--
+-- This test suite verifies that ASSIGNMENT is working correctly
+-- during an UPDATE.
+--
+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 = 100000000000000000000000000000000.1 WHERE a = 1;
+    ]], {
+        1, "Type mismatch: can not convert 1.0e+32 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 TRUE to integer"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-44",
+    [[
+        UPDATE ti SET i = '33' WHERE a = 1;
+    ]], {
+        1, "Type mismatch: can not convert 33 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;
+    ]], {
+        0
+    })
+
+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 TRUE to double"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-51",
+    [[
+        UPDATE td SET d = '33' WHERE a = 1;
+    ]], {
+        1, "Type mismatch: can not convert 33 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 11 to boolean"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-55",
+    [[
+        UPDATE tb SET b = 22.2 WHERE a = 1;
+    ]], {
+        1, "Type mismatch: can not convert 22.2 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 33 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 11 to string"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-61",
+    [[
+        UPDATE tt SET t = 22.2 WHERE a = 1;
+    ]], {
+        1, "Type mismatch: can not convert 22.2 to string"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-62",
+    [[
+        UPDATE tt SET t = true WHERE a = 1;
+    ]], {
+        1, "Type mismatch: can not convert TRUE 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 11 to varbinary"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-67",
+    [[
+        UPDATE tv SET v = 22.2 WHERE a = 1;
+    ]], {
+        1, "Type mismatch: can not convert 22.2 to varbinary"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-68",
+    [[
+        UPDATE tv SET v = true WHERE a = 1;
+    ]], {
+        1, "Type mismatch: can not convert TRUE to varbinary"
+    })
+
+test:do_catchsql_test(
+    "gh-3809-69",
+    [[
+        UPDATE tv SET v = '33' WHERE a = 1;
+    ]], {
+        1, "Type mismatch: can not convert 33 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..684a24114 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(31)
 
 --!./tcltestrunner.lua
 -- 2001 September 15
@@ -770,142 +770,13 @@ 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",
-    [[
-        SELECT * FROM t1 WHERE a=1;
-    ]], {
-        -- <intpkey-13.1>
-        
-        -- </intpkey-13.1>
-    })
-
-test:do_execsql_test(
-    "intpkey-13.2",
-    [[
-        INSERT INTO t1 VALUES('1',2,3);
-        SELECT * FROM t1 WHERE a=1;
-    ]], {
-        -- <intpkey-13.2>
-        1, "2", "3"
-        -- </intpkey-13.2>
-    })
-
--- MUST_WORK_TEST
-if (0 > 0) then
-    -- Tarantool: issue submitted #2315
-    test:do_catchsql_test(
-        "intpkey-13.3",
-        [[
-            INSERT INTO t1 VALUES('1.5',3,4);
-        ]], {
-            -- <intpkey-13.3>
-            1, "datatype mismatch"
-            -- </intpkey-13.3>
-        })
-
-    test:do_catchsql_test(
-        "intpkey-13.4",
-        [[
-            INSERT INTO t1 VALUES(x'123456',3,4);
-        ]], {
-            -- <intpkey-13.4>
-            1, "datatype mismatch"
-            -- </intpkey-13.4>
-        })
-
-
-
-end
-test:do_catchsql_test(
-    "intpkey-13.5",
-    [[
-        INSERT INTO t1 VALUES('+1234567890',3,4);
-    ]], {
-        -- <intpkey-13.5>
-        0
-        -- </intpkey-13.5>
-    })
-
--- Compare an INTEGER PRIMARY KEY against a TEXT expression. The INTEGER
--- affinity should be applied to the text value before the comparison
--- takes place.
---
-test:do_execsql_test(
-    "intpkey-14.1",
-    [[
-        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);
-    ]], {
-        -- <intpkey-14.1>
-        
-        -- </intpkey-14.1>
-    })
-
-test:do_execsql_test(
-    "intpkey-14.2",
-    [[
-        SELECT * FROM t3 WHERE a>2;
-    ]], {
-        -- <intpkey-14.2>
-        3, 3, "3"
-        -- </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(
-    "intpkey-14.4",
-    [[
-        SELECT * FROM t3 WHERE a<'2';
-    ]], {
-        -- <intpkey-14.4>
-        1, 1, "one"
-        -- </intpkey-14.4>
-    })
-
-test:do_execsql_test(
-    "intpkey-14.5",
-    [[
-        SELECT * FROM t3 WHERE a<c;
-    ]], {
-        -- <intpkey-14.5>
-        1, 1, "one"
-        -- </intpkey-14.5>
-    })
-
-test:do_execsql_test(
-    "intpkey-14.6",
-    [[
-        SELECT * FROM t3 WHERE a=c;
-    ]], {
-        -- <intpkey-14.6>
-        2, 2, "2", 3, 3, "3"
-        -- </intpkey-14.6>
-    })
-
 -- Check for proper handling of primary keys greater than 2^31.
 -- Ticket #1188
 --
 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..3161e48fa 100755
--- a/test/sql-tap/numcast.test.lua
+++ b/test/sql-tap/numcast.test.lua
@@ -135,16 +135,16 @@ 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 2.0e+19 to integer"
     })
 
-test:do_catchsql_test(
+test:do_execsql_test(
     "cast-2.9",
     [[
         INSERT INTO t VALUES(2.1);
         SELECT * FROM t;
     ]], {
-        1,"Tuple field 1 type does not match one required by operation: expected integer"
+        2, 9223372036854775808ULL, 18000000000000000000ULL
     })
 
 --
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);
 

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

* Re: [Tarantool-patches] [PATCH v3 4/8] sql: replace ApplyType by CheckType for IN operator
  2020-06-29 12:56   ` Nikita Pettik
@ 2020-07-05 14:28     ` Mergen Imeev
  2020-07-06 22:06       ` Nikita Pettik
  0 siblings, 1 reply; 32+ messages in thread
From: Mergen Imeev @ 2020-07-05 14:28 UTC (permalink / raw)
  To: Nikita Pettik; +Cc: tarantool-patches

On Mon, Jun 29, 2020 at 12:56:30PM +0000, Nikita Pettik wrote:
> On 25 Jun 18:17, imeevma@tarantool.org wrote:
> > 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>
> > -    })
> > -
> 
> I'd rather not drop this test. It's about scalar-numeric types
> interaction. Mb it is not the most suitable place for such test,
> but make sure this scenario is covered somewhere else.
> 
I added a few tests with SCALARS in 'sql: remove implicit
cast for comparison' commit. However, there is a lot
problems with SCALARS at the moment.

> The rest is OK as obvious.
> 

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

* Re: [Tarantool-patches] [PATCH v3 5/8] sql: remove mem_apply_type() from OP_MustBeInt
  2020-06-29 13:29   ` Nikita Pettik
@ 2020-07-05 14:29     ` Mergen Imeev
  0 siblings, 0 replies; 32+ messages in thread
From: Mergen Imeev @ 2020-07-05 14:29 UTC (permalink / raw)
  To: Nikita Pettik; +Cc: tarantool-patches

On Mon, Jun 29, 2020 at 01:29:57PM +0000, Nikita Pettik wrote:
> On 25 Jun 18:17, imeevma@tarantool.org wrote:
> > diff --git a/src/box/sql/vdbe.c b/src/box/sql/vdbe.c
> > index 276956170..a609fa985 100644
> > --- a/src/box/sql/vdbe.c
> > +++ b/src/box/sql/vdbe.c
> > @@ -2122,17 +2122,13 @@ 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);
> > -		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");
> > -				goto abort_due_to_error;
> > -			} else {
> > -				goto jump_to_p2;
> > -			}
> > -		}
> > +	if ((pIn1->flags & (MEM_Int | MEM_UInt)) == 0 &&
> > +	    mem_convert_to_integer(pIn1, true) != 0) {
> 
> Please split this conditions into two branches. Like this:
> 
> diff --git a/src/box/sql/vdbe.c b/src/box/sql/vdbe.c
> index 2bc8c9817..da76d7321 100644
> --- a/src/box/sql/vdbe.c
> +++ b/src/box/sql/vdbe.c
> @@ -2122,13 +2122,14 @@ case OP_AddImm: {            /* in1 */
>   */
>  case OP_MustBeInt: {            /* jump, in1 */
>         pIn1 = &aMem[pOp->p1];
> -       if ((pIn1->flags & (MEM_Int | MEM_UInt)) == 0 &&
> -           mem_convert_to_integer(pIn1, true) != 0) {
> -               if (pOp->p2 != 0)
> -                       goto jump_to_p2;
> -               diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
> -                        sql_value_to_diag_str(pIn1), "integer");
> -               goto abort_due_to_error;
> +       if ((pIn1->flags & (MEM_Int | MEM_UInt)) == 0) {
> +               if (mem_convert_to_integer(pIn1, true) != 0) {
> +                       if (pOp->p2 != 0)
> +                               goto jump_to_p2;
> +                       diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
> +                                sql_value_to_diag_str(pIn1), "integer");
> +                       goto abort_due_to_error;
> +               }
>         }
>         break;
> 
> It ehcnances code readability. Or even integrate this check into
> mem_covert_to_ingeger().
> 
I integrated this check in mem_convert_to_integer().

> The rest is OK (hope you carefully verified changed tests, since
> I've only briefly looked through).
> 

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

* Re: [Tarantool-patches] [PATCH v3 6/8] sql: remove implicit cast for comparison
  2020-06-29 23:51   ` Nikita Pettik
@ 2020-07-05 14:47     ` Mergen Imeev
  2020-07-06 23:11       ` Nikita Pettik
  0 siblings, 1 reply; 32+ messages in thread
From: Mergen Imeev @ 2020-07-05 14:47 UTC (permalink / raw)
  To: Nikita Pettik; +Cc: tarantool-patches

My answers and new patch below.

On Mon, Jun 29, 2020 at 11:51:29PM +0000, Nikita Pettik wrote:
> On 25 Jun 18:17, imeevma@tarantool.org wrote:
> > Thank you for review! My answers and new patch below.
> > 
> > On 22.06.2020 15:25, Nikita Pettik wrote:
> > > On 17 Jun 15:36, imeevma@tarantool.org wrote:
> > >> @@ -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;
> > >> -
> > >
> > > Replace these assertions with relevant ones.
> > >
> > Not sure if this is necessary, since now we have much less flag
> > changes after removal of mem_apply_type().
> 
> Не понял как это связано...Твои изменения не затрагивают
> инвариант MEM_Dyn.
>  
True, however original asserts checked that
mem_apply_type() does not changed it. Now we can say that
it definitely won't be changed. I can return flags*
variables for the sake of these asserts. Should I do this?

Also, after #4906 these asserts become outdated since flags
of the mems won't change at all. Well, it will be so if we
close #4906.

> > >> @@ -0,0 +1,281 @@
> > >> +#!/usr/bin/env tarantool
> > >> +test = require("sqltester")
> > >> +test:plan(32)
> > >> +
> > >> +--
> > >> +
> > >> +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);
> > >
> > > What about table with scalar/any fields?
> > >
> > I think this is too big a problem to solve it here.
> 
> Гораздо лучше потом клепать фоллоу-апы, точечно затыкая креши..
> Я бы добавил хотя бы самых базовых примеров.
> 
Added.

> >  			i = pIn3->u.i;
> > @@ -3617,7 +3595,38 @@ skip_truncate:
> >  	assert(oc!=OP_SeekGE || r.default_rc==+1);
> >  	assert(oc!=OP_SeekLT || r.default_rc==+1);
> >  
> > +	/*
> > +	 * Make sure that the types of all the fields in the tuple
> > +	 * that will be used in the iterator match the field types
> > +	 * of the space.
> > +	 */
> >  	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_check_type(mem, type) == 0 ||
> > +		    mem_convert_numeric(mem, type, true) == 0)
> > +			continue;
> 
> Я бы все-таки разбил бы эту проверку на два условия:
> 
> if (...)
> 	continue
> if (...)
> 	continue
> 
> А еще лучше вынести этот чанк в хелпер.
> 
Moved to a new function.

> > +		/*
> > +		 * If the number was not converted without loss,
> > +		 * we will not find tuples using the EQ iterator.
> > +		 */
> 
> Пожайлуста, не используй двойное отрицание - комментарий очень
> сложно воспринимать. Давай это переформулируем, можно пример
> добавить. Это довольно скользкое место.
> 
Removed. Added comment in description of a new function.

> > +		if ((mem->flags & MEM_Real) != 0 &&
> > +		    (type == FIELD_TYPE_INTEGER ||
> > +		     type == FIELD_TYPE_UNSIGNED)) {
> > +			assert(eqOnly == 1);
> > +			res = 1;
> > +			goto seek_not_found;
> > +		}
> > +		if ((mem->flags & (MEM_Int | MEM_UInt)) != 0 &&
> > +		    type == FIELD_TYPE_DOUBLE && eqOnly == 1) {
> > +			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
> > @@ -4744,7 +4753,25 @@ case OP_IdxGE:  {       /* jump */
> >  		assert(pOp->opcode==OP_IdxGE || pOp->opcode==OP_IdxLT);
> >  		r.default_rc = 0;
> >  	}
> > +
> > +	/*
> > +	 * Make sure that the types of all the fields in the tuple
> > +	 * that will be used in the iterator comparable with the
> > +	 * fields of the space.
> > +	 */
> >  	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];
> 
> Как-то мне эти два места (выше в SeekGE) вообще не нравятся.
> Какие-то они запутанные. Давай подумаем как можно зарефакторить их.
> 
Moved to a new function. However, previously cast
here didn't always worked since in some cases field_type
and MEM_type of the mem not always were compatible. I think
this was fixed in previous commits. All tests passes.

However, there is another possiblity: it may be that I
already removed tests that fail on convertion but worked
on check. I do not think that it is the case though.

This also can be fully fixed in #4906 issue.

> > +		if (mem_check_type(mem, type) == 0)
> > +			continue;
> > +		if (sql_type_is_numeric(type) &&
> > +		    (mem->flags & (MEM_Real | MEM_Int | MEM_UInt)) != 0)
> > +			continue;
> > +		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
> > 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)
> 
> Ты в следующем коммите как раз делаешь клин-ап. Давай эту функцию
> там и удалим (как и остальные).
> 
It is a bit troublesome since the functions I remove here
are 'static'. I think, that instead of removing 'static'
keyword here and removing the function in the next commit
it is better to just remove these runctions here.

I can change it if you think that removing in two commits
is better.

> >  			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
> 
> Когда кто-то ищет где посмотреть тесты связанные с типами,
> первое что приходит в голову - грепнуть *types*. Этот тест
> по сути ничего и не тестирует (уверен, эти пути уже покрыты
> в других тестах), зато хорошо отображает работу системы типов.
> Я бы просто подумал о других разработчиках, и все же замержил
> его в какой-нибудь тест типа sql/types.test.lua.
Moved to sql/types.test.lua


New patch:


commit f52e6669146e7a06b78d167abf369d67d9327789
Author: Mergen Imeev <imeevma@gmail.com>
Date:   Thu Jun 25 12:39:19 2020 +0300

    sql: remove implicit cast for comparison
    
    This patch removes implicit cast for comparison.
    
    Closes #4230
    
    @TarantoolBot document
    Title: remove implicit cast for comparison
    
    After this patch-set, there will be no implicit casts for
    comparison. This means that the values ​​of the field types STRING,
    BOOLEAN and VARBINARY can be compared with the values ​​of the same
    field type. Any numerical value can be compared with any other
    numerical value.
    
    Example:
    
    For comparison:
    ```
    tarantool> box.execute([[SELECT '1' > 0;]])
    ---
    - null
    - "Type mismatch: can not convert '1' (type: text) to numeric"
    ...
    
    tarantool> box.execute([[SELECT true > X'33';]])
    ---
    - null
    - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to varbinary'
    ...
    
    tarantool> box.execute([[SELECT 1.23 > 123;]])
    ---
    - metadata:
      - name: 1.23 > 123
        type: boolean
      rows:
      - [false]
    ...
    ```

diff --git a/src/box/sql/vdbe.c b/src/box/sql/vdbe.c
index ce9edaad9..0d3da49d3 100644
--- a/src/box/sql/vdbe.c
+++ b/src/box/sql/vdbe.c
@@ -561,6 +561,50 @@ mem_convert_to_numeric(struct Mem *mem, enum field_type type, bool is_precise)
 	return mem_convert_to_integer(mem, is_precise);
 }
 
+/**
+ * Check that MEM types of mems are compatible with the
+ * corresponding types from key_def.
+ *
+ * If mem and type are comparable but incompatible according to
+ * field_mp_plain_type_is_compatible() and the comparison
+ * operation is EQ, we can say that the result of the comparison
+ * will be FALSE. This allows us to compare DOUBLE and INTEGER
+ * values.
+ *
+ * @param mems The first mem of the array.
+ * @param def key_def that contains types to check.
+ * @param size Size of the array.
+ * @param is_op_eq TRUE is comparison operator is EQ.
+ * @param[out] is_not_converted TRUE if operation is EQ and mem
+                                and type are comparable but not
+                                compatible. FALSE otherwise.
+ * @retval TRUE if the MEM types and types from key_def are
+ *         comparable, FALSE otherwise.
+ */
+static bool
+mem_are_types_comparable(struct Mem *mems, struct key_def *def, uint32_t size,
+			 bool is_op_eq, bool *is_not_converted) {
+	assert(!is_op_eq || !*is_not_converted);
+	for (uint32_t i = 0; i < size; ++i) {
+		enum field_type type = def->parts[i].type;
+		struct Mem *mem = &mems[i];
+		if (mem_is_type_compatible(mem, type))
+			continue;
+		if (mem_convert_to_numeric(mem, type, true) == 0)
+			continue;
+		if (sql_type_is_numeric(type) &&
+		    (mem->flags & (MEM_Int | MEM_UInt | MEM_Real)) != 0) {
+			if (is_op_eq)
+				*is_not_converted = true;
+			continue;
+		}
+		diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
+			field_type_strs[type], mem_type_to_str(mem));
+		return false;
+	}
+	return true;
+}
+
 /*
  * 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
@@ -2289,8 +2333,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) {
@@ -2349,22 +2391,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()
@@ -2397,22 +2434,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);
@@ -2428,14 +2460,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 */
@@ -3530,8 +3554,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;
@@ -3623,7 +3645,20 @@ skip_truncate:
 	assert(oc!=OP_SeekGE || r.default_rc==+1);
 	assert(oc!=OP_SeekLT || r.default_rc==+1);
 
+	/*
+	 * Make sure that the types of all the fields in the tuple
+	 * that will be used in the iterator match the field types
+	 * of the space.
+	 */
 	r.aMem = &aMem[pOp->p3];
+	bool is_not_found = false;
+	if (!mem_are_types_comparable(r.aMem, r.key_def, r.nField, eqOnly == 1,
+				      &is_not_found))
+		goto abort_due_to_error;
+	if (is_not_found) {
+		res = 1;
+		goto seek_not_found;
+	}
 #ifdef SQL_DEBUG
 	{ int i; for(i=0; i<r.nField; i++) assert(memIsValid(&r.aMem[i])); }
 #endif
@@ -4750,7 +4785,16 @@ case OP_IdxGE:  {       /* jump */
 		assert(pOp->opcode==OP_IdxGE || pOp->opcode==OP_IdxLT);
 		r.default_rc = 0;
 	}
+
+	/*
+	 * Make sure that the types of mems are comparable with
+	 * the field types of the space.
+	 */
 	r.aMem = &aMem[pOp->p3];
+	bool unused = false;
+	if (!mem_are_types_comparable(r.aMem, r.key_def, r.nField, false,
+				      &unused))
+		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/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/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..381f29c65 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 54aff460e..1c8357bce 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:
@@ -2152,6 +2144,231 @@ box.execute([[SELECT * FROM "s" WHERE "id" = ?;]])
     type: string
   rows: []
 ...
+--
+-- gh-4230: Make sure that there is no implicit cast between
+-- string and number.
+--
+box.execute([[SELECT '1' > 0;]]);
+---
+- null
+- 'Type mismatch: can not convert 1 to numeric'
+...
+box.execute([[SELECT 1 > '0';]]);
+---
+- null
+- 'Type mismatch: can not convert 0 to numeric'
+...
+box.execute([[CREATE TABLE t (i INT PRIMARY KEY, d DOUBLE, n NUMBER, s STRING);]])
+---
+- row_count: 1
+...
+box.execute([[INSERT INTO t VALUES (1, 1.0, 1, '2'), (2, 2.0, 2.0, '2');]])
+---
+- row_count: 2
+...
+box.execute([[SELECT * from t WHERE i > s;]])
+---
+- null
+- 'Type mismatch: can not convert 2 to numeric'
+...
+box.execute([[SELECT * from t WHERE s > i;]])
+---
+- null
+- 'Type mismatch: can not convert 2 to numeric'
+...
+box.execute([[SELECT * from t WHERE d > s;]])
+---
+- null
+- 'Type mismatch: can not convert 2 to numeric'
+...
+box.execute([[SELECT * from t WHERE s > d;]])
+---
+- null
+- 'Type mismatch: can not convert 2 to numeric'
+...
+box.execute([[SELECT * from t WHERE i = 1 and n > s;]])
+---
+- null
+- 'Type mismatch: can not convert 2 to numeric'
+...
+box.execute([[SELECT * from t WHERE i = 2 and s > n;]])
+---
+- null
+- 'Type mismatch: can not convert 2 to numeric'
+...
+box.execute([[SELECT i FROM t WHERE i in (1);]])
+---
+- metadata:
+  - name: I
+    type: integer
+  rows:
+  - [1]
+...
+box.execute([[SELECT i FROM t WHERE d in (1);]])
+---
+- metadata:
+  - name: I
+    type: integer
+  rows:
+  - [1]
+...
+box.execute([[SELECT i FROM t WHERE n in (1);]])
+---
+- metadata:
+  - name: I
+    type: integer
+  rows:
+  - [1]
+...
+box.execute([[SELECT i FROM t WHERE s in (1);]])
+---
+- null
+- 'Type mismatch: can not convert 2 to numeric'
+...
+box.execute([[SELECT i FROM t WHERE i in (1.0);]])
+---
+- metadata:
+  - name: I
+    type: integer
+  rows:
+  - [1]
+...
+box.execute([[SELECT i FROM t WHERE d in (1.0);]])
+---
+- metadata:
+  - name: I
+    type: integer
+  rows:
+  - [1]
+...
+box.execute([[SELECT i FROM t WHERE n in (1.0);]])
+---
+- metadata:
+  - name: I
+    type: integer
+  rows:
+  - [1]
+...
+box.execute([[SELECT i FROM t WHERE s in (1.0);]])
+---
+- null
+- 'Type mismatch: can not convert 2 to numeric'
+...
+box.execute([[SELECT i FROM t WHERE i in ('1');]])
+---
+- null
+- 'Type mismatch: can not convert integer to text'
+...
+box.execute([[SELECT i FROM t WHERE d in ('1');]])
+---
+- null
+- 'Type mismatch: can not convert 1 to numeric'
+...
+box.execute([[SELECT i FROM t WHERE n in ('1');]])
+---
+- null
+- 'Type mismatch: can not convert 1 to numeric'
+...
+box.execute([[SELECT i FROM t WHERE s in ('1');]])
+---
+- metadata:
+  - name: I
+    type: integer
+  rows: []
+...
+box.execute([[SELECT i FROM t WHERE i in ('1.0');]])
+---
+- null
+- 'Type mismatch: can not convert integer to text'
+...
+box.execute([[SELECT i FROM t WHERE d in ('1.0');]])
+---
+- null
+- 'Type mismatch: can not convert 1.0 to numeric'
+...
+box.execute([[SELECT i FROM t WHERE n in ('1.0');]])
+---
+- null
+- 'Type mismatch: can not convert 1.0 to numeric'
+...
+box.execute([[SELECT i FROM t WHERE s in ('1.0');]])
+---
+- metadata:
+  - name: I
+    type: integer
+  rows: []
+...
+box.execute([[DROP TABLE t;]])
+---
+- row_count: 1
+...
+-- Comparison with SCALAR.
+box.execute([[CREATE TABLE t(a SCALAR PRIMARY KEY);]])
+---
+- row_count: 1
+...
+box.execute([[INSERT INTO t VALUES (1), (2.2), ('3');]]);
+---
+- row_count: 3
+...
+box.execute([[SELECT a FROM t WHERE a > 1]]);
+---
+- null
+- 'Type mismatch: can not convert 3 to numeric'
+...
+box.execute([[SELECT a FROM t WHERE a > 1.0]]);
+---
+- null
+- 'Type mismatch: can not convert 3 to numeric'
+...
+box.execute([[SELECT a FROM t WHERE a > '1']]);
+---
+- metadata:
+  - name: A
+    type: scalar
+  rows:
+  - ['3']
+...
+box.execute([[SELECT a FROM t WHERE a < 1]]);
+---
+- null
+- 'Type mismatch: can not convert 3 to numeric'
+...
+box.execute([[SELECT a FROM t WHERE a < 1.0]]);
+---
+- null
+- 'Type mismatch: can not convert 3 to numeric'
+...
+box.execute([[SELECT a FROM t WHERE a < '1']]);
+---
+- metadata:
+  - name: A
+    type: scalar
+  rows:
+  - [1]
+  - [2.2]
+...
+box.execute([[SELECT a FROM t WHERE a = 1]]);
+---
+- null
+- 'Type mismatch: can not convert 3 to numeric'
+...
+box.execute([[SELECT a FROM t WHERE a = 1.0]]);
+---
+- null
+- 'Type mismatch: can not convert 3 to numeric'
+...
+box.execute([[SELECT a FROM t WHERE a = '1']]);
+---
+- metadata:
+  - name: A
+    type: scalar
+  rows: []
+...
+box.execute([[DROP TABLE t;]])
+---
+- row_count: 1
+...
 s:drop()
 ---
 ...
diff --git a/test/sql/types.test.lua b/test/sql/types.test.lua
index bd14b342d..cf0db5ae0 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);")
@@ -486,4 +485,56 @@ s:format({ \
 })
 
 box.execute([[SELECT * FROM "s" WHERE "id" = ?;]])
+
+--
+-- gh-4230: Make sure that there is no implicit cast between
+-- string and number.
+--
+box.execute([[SELECT '1' > 0;]]);
+box.execute([[SELECT 1 > '0';]]);
+box.execute([[CREATE TABLE t (i INT PRIMARY KEY, d DOUBLE, n NUMBER, s STRING);]])
+box.execute([[INSERT INTO t VALUES (1, 1.0, 1, '2'), (2, 2.0, 2.0, '2');]])
+box.execute([[SELECT * from t WHERE i > s;]])
+box.execute([[SELECT * from t WHERE s > i;]])
+box.execute([[SELECT * from t WHERE d > s;]])
+box.execute([[SELECT * from t WHERE s > d;]])
+box.execute([[SELECT * from t WHERE i = 1 and n > s;]])
+box.execute([[SELECT * from t WHERE i = 2 and s > n;]])
+
+box.execute([[SELECT i FROM t WHERE i in (1);]])
+box.execute([[SELECT i FROM t WHERE d in (1);]])
+box.execute([[SELECT i FROM t WHERE n in (1);]])
+box.execute([[SELECT i FROM t WHERE s in (1);]])
+
+box.execute([[SELECT i FROM t WHERE i in (1.0);]])
+box.execute([[SELECT i FROM t WHERE d in (1.0);]])
+box.execute([[SELECT i FROM t WHERE n in (1.0);]])
+box.execute([[SELECT i FROM t WHERE s in (1.0);]])
+
+box.execute([[SELECT i FROM t WHERE i in ('1');]])
+box.execute([[SELECT i FROM t WHERE d in ('1');]])
+box.execute([[SELECT i FROM t WHERE n in ('1');]])
+box.execute([[SELECT i FROM t WHERE s in ('1');]])
+
+box.execute([[SELECT i FROM t WHERE i in ('1.0');]])
+box.execute([[SELECT i FROM t WHERE d in ('1.0');]])
+box.execute([[SELECT i FROM t WHERE n in ('1.0');]])
+box.execute([[SELECT i FROM t WHERE s in ('1.0');]])
+
+box.execute([[DROP TABLE t;]])
+
+-- Comparison with SCALAR.
+box.execute([[CREATE TABLE t(a SCALAR PRIMARY KEY);]])
+box.execute([[INSERT INTO t VALUES (1), (2.2), ('3');]]);
+box.execute([[SELECT a FROM t WHERE a > 1]]);
+box.execute([[SELECT a FROM t WHERE a > 1.0]]);
+box.execute([[SELECT a FROM t WHERE a > '1']]);
+box.execute([[SELECT a FROM t WHERE a < 1]]);
+box.execute([[SELECT a FROM t WHERE a < 1.0]]);
+box.execute([[SELECT a FROM t WHERE a < '1']]);
+box.execute([[SELECT a FROM t WHERE a = 1]]);
+box.execute([[SELECT a FROM t WHERE a = 1.0]]);
+box.execute([[SELECT a FROM t WHERE a = '1']]);
+box.execute([[DROP TABLE t;]])
+
 s:drop()

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

* Re: [Tarantool-patches] [PATCH v3 7/8] sql: remove unused functions
  2020-06-29 23:52   ` Nikita Pettik
@ 2020-07-05 14:50     ` Mergen Imeev
  0 siblings, 0 replies; 32+ messages in thread
From: Mergen Imeev @ 2020-07-05 14:50 UTC (permalink / raw)
  To: Nikita Pettik; +Cc: tarantool-patches

On Mon, Jun 29, 2020 at 11:52:17PM +0000, Nikita Pettik wrote:
> On 25 Jun 18:17, imeevma@tarantool.org wrote:
> > After previous patches, some functions and the ApplyType opcode
> > become unused, so this patch removes them.
> > 
> > Follow-up #4230
> > ---
> 
> Все еще можно нагрепать OP_ApplyType. Перепроверь.
> 
Fixed:

diff --git a/src/box/sql/sqlInt.h b/src/box/sql/sqlInt.h
index e7826519b..0879ccbfa 100644
--- a/src/box/sql/sqlInt.h
+++ b/src/box/sql/sqlInt.h
@@ -3863,7 +3863,7 @@ int sqlVarintLen(u64 v);
 #define putVarint    sqlPutVarint

 /**
- * Code an OP_ApplyType opcode that will force types
+ * Code an OP_ImplicitCast opcode that will force types
  * for given range of register starting from @reg.
  *
  * @param v VDBE.

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

* Re: [Tarantool-patches] [PATCH v3 8/8] sql: show value and its type in type mismatch error
  2020-06-30  0:22   ` Nikita Pettik
@ 2020-07-05 15:03     ` Mergen Imeev
  2020-07-06 21:44       ` Nikita Pettik
  0 siblings, 1 reply; 32+ messages in thread
From: Mergen Imeev @ 2020-07-05 15:03 UTC (permalink / raw)
  To: Nikita Pettik; +Cc: tarantool-patches

My answers and diff below.

On Tue, Jun 30, 2020 at 12:22:32AM +0000, Nikita Pettik wrote:
> On 25 Jun 18:17, imeevma@tarantool.org wrote:
> > After this patch value and its type will be shown in description
> > of type mismatch error
> 
> Какие цели преследует этот патч? Зачем мы это делаем?
> Диф то на 1.5 кслок.
It is just a refactoring. It can be dropped.

> Забыл точку в конце :)
> 
Fixed.

> >  	}
> >  #ifdef SQL_DEBUG
> > @@ -4740,7 +4735,7 @@ case OP_IdxGE:  {       /* jump */
> >  		    (mem->flags & (MEM_Real | MEM_Int | MEM_UInt)) != 0)
> >  			continue;
> >  		diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
> > -			field_type_strs[type], mem_type_to_str(mem));
> > +			sql_value_to_diag_str(mem), mem_type_to_str(mem));
> >  		goto abort_due_to_error;
> >  	}
> >  #ifdef SQL_DEBUG
> > diff --git a/src/box/sql/vdbemem.c b/src/box/sql/vdbemem.c
> > index a721afc83..bb7676354 100644
> > --- a/src/box/sql/vdbemem.c
> > +++ b/src/box/sql/vdbemem.c
> > @@ -1166,12 +1166,15 @@ sqlValueText(sql_value * pVal)
> >  const char *
> >  sql_value_to_diag_str(sql_value *value)
> >  {
> > -	if (sql_value_type(value) == MP_BIN) {
> > -		if (mem_has_msgpack_subtype(value))
> > -			return sqlValueText(value);
> > +	if (sql_value_mp_type(value) == MP_BIN)
> >  		return "varbinary";
> > -	}
> > -	return sqlValueText(value);
> > +	char *type = mem_type_to_str(value);
> > +	char *str = (char *)sqlValueText(value);
> > +	if (str == NULL)
> > +		return "NULL";
> > +	if (strlen(str) < 80)
> 
> https://en.wikipedia.org/wiki/Magic_number_(programming)
> 
Added a enum here.

> > +		return tt_sprintf("'%s' (type: %s)", str, type);
> > +	return tt_sprintf("'%.80s...' (type: %s)", str, type);
> >  }
> >  
> >  /*
> > diff --git a/test/sql-tap/autoinc.test.lua b/test/sql-tap/autoinc.test.lua
> > index 07442b60a..1547ffcd3 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 'asd' (type: text) to integer"
> 
> Выглядит зачотно, выглядит all right!
> 
> > diff --git a/test/sql-tap/gh-3809-implicit-cast-assignment.test.lua b/test/sql-tap/gh-3809-implicit-cast-assignment.test.lua
> > index a1809b3cb..f1edfa0f6 100755
> > --- a/test/sql-tap/gh-3809-implicit-cast-assignment.test.lua
> > +++ b/test/sql-tap/gh-3809-implicit-cast-assignment.test.lua
> > @@ -28,7 +28,7 @@ test:do_catchsql_test(
> >      [[
> >          INSERT INTO ti(i) VALUES (100000000000000000000000000000000.1)
> >      ]], {
> > -        1, "Type mismatch: can not convert 1.0e+32 to integer"
> > +        1, "Type mismatch: can not convert '1.0e+32' (type: real) to integer"
> >      })
> 
> Я бы может еще кавычки вокруг чиселок/буленов не добавлял, но это
> в принципе мелочь - тип то печатается.
> 
I think it is better as it is now since in some cases
STRING value and BOOLEAN values look the same.

> В остальном - ОК.

Diff:

diff --git a/src/box/sql/vdbemem.c b/src/box/sql/vdbemem.c
index 32f4ae0b6..7cff881c0 100644
--- a/src/box/sql/vdbemem.c
+++ b/src/box/sql/vdbemem.c
@@ -1163,6 +1163,10 @@ sqlValueText(sql_value * pVal)
        return valueToText(pVal);
 }
 
+enum {
+       DIAG_STR_LEN_MAX = 80,
+};
+
 const char *
 sql_value_to_diag_str(sql_value *value)
 {
@@ -1172,7 +1176,7 @@ sql_value_to_diag_str(sql_value *value)
        char *str = (char *)sqlValueText(value);
        if (str == NULL)
                return "NULL";
-       if (strlen(str) < 80)
+       if (strlen(str) < DIAG_STR_LEN_MAX)
                return tt_sprintf("'%s' (type: %s)", str, type);
        return tt_sprintf("'%.80s...' (type: %s)", str, type);
 }

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

* Re: [Tarantool-patches] [PATCH v3 1/8] sql: introduce mem_set_double()
  2020-06-28 13:31   ` Nikita Pettik
@ 2020-07-06 14:02     ` Nikita Pettik
  0 siblings, 0 replies; 32+ messages in thread
From: Nikita Pettik @ 2020-07-06 14:02 UTC (permalink / raw)
  To: imeevma; +Cc: tarantool-patches

On 28 Jun 13:31, Nikita Pettik wrote:
> On 25 Jun 18:17, imeevma@tarantool.org wrote:
> > The mem_set_double () function is used to properly set MEM as
> > containing DOUBLE value.
> 
> Nit: it has been introduced a long ago (sqlVdbeMemSetDouble()).
> You refactor it and use in several other places.
> 
> LGTM
>

I've fixed a bit commit message and pushed to master as trivial.

sql: refactor sqlVdbeMemSetDouble()

sqlVdbeMemSetDouble() function is used to properly set double value to
VDBE memory cell. Let's refactor it according to our codestyle and
rename it to mem_set_double() since we are going to use it instead of
raw mem's value modification.
 

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

* Re: [Tarantool-patches] [PATCH v3 2/8] sql: change implicit cast for assignment
  2020-07-05 14:26     ` Mergen Imeev
@ 2020-07-06 21:27       ` Nikita Pettik
  2020-07-07  9:29         ` Mergen Imeev
  0 siblings, 1 reply; 32+ messages in thread
From: Nikita Pettik @ 2020-07-06 21:27 UTC (permalink / raw)
  To: Mergen Imeev; +Cc: tarantool-patches

On 05 Jul 17:26, Mergen Imeev wrote:
> Hi! Thank you for the review. My answers and new patch
> below. Sorry, I didn't include diff.
> > > commit 21d7145c1929bc4606c56e9a566477f248637ed1
> > > Author: Mergen Imeev <imeevma@gmail.com>
> > > Date:   Wed May 27 13:49:11 2020 +0300
> > > 
> > > + if (field_mp_plain_type_is_compatible(type, mp_type, true))
> > > +   return 0;
> > > + return -1;
> > > +}
> > > +
> > > +/**
> > > + * Convert the numeric value contained in MEM to double. If the
> > > + * is_precise flag is set, the conversion will succeed only if it
> > > + * is lossless.
> > > + *
> > > + * @param mem The MEM that contains the numeric value.
> > > + * @param is_precise Flag.
> > > + * @retval 0 if the conversion was successful, -1 otherwise.
> > > + */
> > > +static int
> > > +mem_convert_to_double(struct Mem *mem, bool is_precise)
> > > +{
> > > + if ((mem->flags & (MEM_Int | MEM_UInt)) == 0)
> > > +   return -1;
> > > + if ((mem->flags & MEM_Int) != 0) {
> > > +   int64_t i = mem->u.i;
> > > +   double d = (double)i;
> > > +   if (!is_precise || i == (int64_t)d)
> > > +     mem_set_double(mem, d);
> > > +   else
> > > +     return -1;
> > > + } else {
> > > +   uint64_t u = mem->u.u;
> > > +   double d = (double)u;
> > > +   if (!is_precise || u == (uint64_t)d)
> > > +     mem_set_double(mem, d);
> > > +   else
> > > +     return -1;
> > > + }
> > > + mem->field_type = FIELD_TYPE_DOUBLE;
> > 
> > Why not incorparate field_type assingment into mem_set_double()?
> > The same concerns other converting functions.
> > 
> I think this should be done in #4906 issue since it may
> lead to not always simple to understand changes.

Эм, не очень понял как трактовать твой ответ. Типо тут работает,
а если там засунуть, то что-то начинает падать..? 4906 немного про
другое: в любом случае у нас в меме будет и field_type и mp_type.
К тому же, и то, и это - рефакторинг и функциональных изменений быть
не должно.
 
> > > +/**
> > > + * Convert the numeric value contained in MEM to another numeric
> > > + * type. If the is_precise flag is set, the conversion will
> > > + * succeed only if it is lossless.
> > > + * @param mem The MEM that contains the numeric value.
> > > + * @param type The type to convert to.
> > > + * @param is_precise Flag.
> > > + * @retval 0 if the conversion was successful, -1 otherwise.
> > > + */
> > > +static int
> > > +mem_convert_numeric(struct Mem *mem, enum field_type type, bool is_precise)
> > 
> > mem_convert_to_numeric ?
> > mem_cast_to_numeric
> > 
> Used first option.
> 
> > > +{
> > > + if (!sql_type_is_numeric(type) ||
> > > +     (mem->flags & (MEM_Real | MEM_Int | MEM_UInt)) == 0)
> > 
> > It's somehow unnatural passing to _numeric function non-numeric type
> > to convert to. Instead let's use this function properly and replace
> > branching with assertion.
> > 
> No, I think it is good as it is. More that that, due to
> some other comments I added similar checks to all other
> mem_convert_to>* functions.

В остальных случаях ты туда тип вообще не передаешь.
 
> My reason is: in all places we use this function we have
> to check that field type and MEM_type are numeric, so it
> make sence to move this check inside of the function.

Еще раз: это полный идиотизм передавать ТИП (отличный от нумерика) к
которому ты собираешься кастовать в функцию, которая по названию
предполагает каст к нумерику. Считай, что я настаиваю на этом
изменении.

> > > +   return -1;
> > > + if (type == FIELD_TYPE_NUMBER)
> > > +   return 0;
> > > + if (type == FIELD_TYPE_DOUBLE)
> > > +   return mem_convert_to_double(mem, is_precise);
> > > + if (type == FIELD_TYPE_UNSIGNED)
> > > +   return mem_convert_to_unsigned(mem, is_precise);
> > > + assert(type == FIELD_TYPE_INTEGER);
> > > + return mem_convert_to_integer(mem, is_precise);
> > > +}
> > > +
> > >  /*
> index 37283e506..bd0055668 100644
> --- a/src/box/sql/sqlInt.h
> +++ b/src/box/sql/sqlInt.h
> @@ -397,6 +397,15 @@ sql_value_to_diag_str(sql_value *value);
>  enum mp_type
>  sql_value_type(sql_value *);
>  
> +/*
> + * Return the MP_type of the value of the MEM.
> + *
> + * @param mem MEM with the correct MEM_type.
> + * @retval MP_type of the value.
> + */
> +enum mp_type
> +mem_mp_type(struct Mem *mem);

Я вытащил добавление этой функции в отдельный патч и добавил
рефакторинг чтобы соеденить ее с sql_value_type().
https://github.com/tarantool/tarantool/tree/np/gh-3809-remastered

Если ты ОК, я пушну вне очереди в мастер.

> diff --git a/src/box/sql/vdbe.c b/src/box/sql/vdbe.c
> index 950f72ddd..1386ea2c0 100644
> --- a/src/box/sql/vdbe.c
> +++ b/src/box/sql/vdbe.c
> +		uint64_t u = mem->u.u;
> +		double d = (double)u;
> +		if (!is_precise || u == (uint64_t)d)
> +			mem_set_double(mem, d);
> +		else
> +			return -1;
> +	}
> +	mem->field_type = FIELD_TYPE_DOUBLE;
> +	return 0;
> +}
> +
> + * P1 are compatible with given field types in P4.
> + * If the MEM_type of the value and the given type are
> + * incompatible according to field_mp_plain_type_is_compatible(),
> + * but both are numeric, this opcode attempts to convert the value
> + * to the type.
> + */
> +case OP_ImplicitCast: {
> +	enum field_type *types = pOp->p4.types;
> +	assert(types != NULL);
> +	assert(types[pOp->p2] == field_type_MAX);
> +	for (int i = 0; types[i] != field_type_MAX; ++i) {
> +		enum field_type type = types[i];
> +		pIn1 = &aMem[pOp->p1 + i];
> +		assert(pIn1 <= &p->aMem[(p->nMem+1 - p->nCursor)]);
> +		assert(memIsValid(pIn1));
> +		if (mem_is_type_compatible(pIn1, type))
> +			continue;
> +		if (mem_convert_to_numeric(pIn1, type, false) == 0)

Инвертируй, пожайлуйста условие:

if (mem_convert_to_numeric(pIn1, type, false) !=) {
	//raise an error
}

Это будет больще соответствовать нашему кодстайлу.

> +			continue;
> +		diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
> +			 sql_value_to_diag_str(pIn1), field_type_strs[type]);
> +		goto abort_due_to_error;
> +	}
> +	break;
> +}
> +
>  /* Opcode: MakeRecord P1 P2 P3 P4 P5
>   * Synopsis: r[P3]=mkrec(r[P1@P2])
>   *
> diff --git a/src/box/sql/vdbeapi.c b/src/box/sql/vdbeapi.c
> index 4e103a653..b106ce6bd 100644
> --- a/src/box/sql/vdbeapi.c
> +++ b/src/box/sql/vdbeapi.c
> @@ -225,6 +225,33 @@ sql_value_type(sql_value *pVal)
>  	}
>  }
>  
> +enum mp_type
> +mem_mp_type(struct Mem *mem)

Еще раз: это не апишная функция (хотя бы в терминологии скулайта),
ей место скорее в vdbemem.c. См. мой рефакторинг.

> +{
> --- a/test/sql-tap/autoinc.test.lua
> +++ b/test/sql-tap/autoinc.test.lua

Тесты не смотрел, предполагая что нет изменений по сравнению с
предыдущей версией.

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

* Re: [Tarantool-patches] [PATCH v3 8/8] sql: show value and its type in type mismatch error
  2020-07-05 15:03     ` Mergen Imeev
@ 2020-07-06 21:44       ` Nikita Pettik
  0 siblings, 0 replies; 32+ messages in thread
From: Nikita Pettik @ 2020-07-06 21:44 UTC (permalink / raw)
  To: Mergen Imeev; +Cc: tarantool-patches

On 05 Jul 18:03, Mergen Imeev wrote:
> My answers and diff below.
> 
> On Tue, Jun 30, 2020 at 12:22:32AM +0000, Nikita Pettik wrote:
> > On 25 Jun 18:17, imeevma@tarantool.org wrote:
> > > After this patch value and its type will be shown in description
> > > of type mismatch error
> > 
> > Какие цели преследует этот патч? Зачем мы это делаем?
> > Диф то на 1.5 кслок.
> It is just a refactoring. It can be dropped.

Хороший аргумент, добавить нечего.

> > > diff --git a/test/sql-tap/gh-3809-implicit-cast-assignment.test.lua b/test/sql-tap/gh-3809-implicit-cast-assignment.test.lua
> > > index a1809b3cb..f1edfa0f6 100755
> > > --- a/test/sql-tap/gh-3809-implicit-cast-assignment.test.lua
> > > +++ b/test/sql-tap/gh-3809-implicit-cast-assignment.test.lua
> > > @@ -28,7 +28,7 @@ test:do_catchsql_test(
> > >      [[
> > >          INSERT INTO ti(i) VALUES (100000000000000000000000000000000.1)
> > >      ]], {
> > > -        1, "Type mismatch: can not convert 1.0e+32 to integer"
> > > +        1, "Type mismatch: can not convert '1.0e+32' (type: real) to integer"
> > >      })
> > 
> > Я бы может еще кавычки вокруг чиселок/буленов не добавлял, но это
> > в принципе мелочь - тип то печатается.
> > 
> I think it is better as it is now since in some cases
> STRING value and BOOLEAN values look the same.

В смысле? Булеан без кавычек, стринг - всегда в кавычках.
Но как хочешь, тут настаивать не буду.

> > В остальном - ОК.
> 
> Diff:
> 
> diff --git a/src/box/sql/vdbemem.c b/src/box/sql/vdbemem.c
> index 32f4ae0b6..7cff881c0 100644
> --- a/src/box/sql/vdbemem.c
> +++ b/src/box/sql/vdbemem.c
> @@ -1163,6 +1163,10 @@ sqlValueText(sql_value * pVal)
>         return valueToText(pVal);
>  }
>  
> +enum {
> +       DIAG_STR_LEN_MAX = 80,

Но это же не длина диага. Не сильно лучше получилось.
Давай что-нибудь в духи SQL_VALUE_DIAG_LEN_MAX и комментарий
что это такое и почему 80..

> +};
> +
>  const char *
>  sql_value_to_diag_str(sql_value *value)
>  {
> @@ -1172,7 +1176,7 @@ sql_value_to_diag_str(sql_value *value)
>         char *str = (char *)sqlValueText(value);
>         if (str == NULL)
>                 return "NULL";
> -       if (strlen(str) < 80)
> +       if (strlen(str) < DIAG_STR_LEN_MAX)
>                 return tt_sprintf("'%s' (type: %s)", str, type);
>         return tt_sprintf("'%.80s...' (type: %s)", str, type);

У тебя в принте осталась эта константа. Посмотри на магию %.*s

> 

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

* Re: [Tarantool-patches] [PATCH v3 4/8] sql: replace ApplyType by CheckType for IN operator
  2020-07-05 14:28     ` Mergen Imeev
@ 2020-07-06 22:06       ` Nikita Pettik
  2020-07-07 11:26         ` Mergen Imeev
  0 siblings, 1 reply; 32+ messages in thread
From: Nikita Pettik @ 2020-07-06 22:06 UTC (permalink / raw)
  To: Mergen Imeev; +Cc: tarantool-patches

On 05 Jul 17:28, Mergen Imeev wrote:
> On Mon, Jun 29, 2020 at 12:56:30PM +0000, Nikita Pettik wrote:
> > On 25 Jun 18:17, imeevma@tarantool.org wrote:
> > > 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>
> > > -    })
> > > -
> > 
> > I'd rather not drop this test. It's about scalar-numeric types
> > interaction. Mb it is not the most suitable place for such test,
> > but make sure this scenario is covered somewhere else.
> > 
> I added a few tests with SCALARS in 'sql: remove implicit
> cast for comparison' commit. However, there is a lot
> problems with SCALARS at the moment.

Давай с этим что-то делать. Проблемы где-то описаны? Если нет,
давай подробно разберем и заведем тикет(ы). Иначе это звучит как
"idgs потом кто-нибудь это разгребет". В тикете 4230 есть
пункт про скаляр, но мы почему-то обходим его, оставляя
проблему as is.
 
> > The rest is OK as obvious.
> > 

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

* Re: [Tarantool-patches] [PATCH v3 6/8] sql: remove implicit cast for comparison
  2020-07-05 14:47     ` Mergen Imeev
@ 2020-07-06 23:11       ` Nikita Pettik
  0 siblings, 0 replies; 32+ messages in thread
From: Nikita Pettik @ 2020-07-06 23:11 UTC (permalink / raw)
  To: Mergen Imeev; +Cc: tarantool-patches

On 05 Jul 17:47, Mergen Imeev wrote:
> My answers and new patch below.
> 
> On Mon, Jun 29, 2020 at 11:51:29PM +0000, Nikita Pettik wrote:
> > On 25 Jun 18:17, imeevma@tarantool.org wrote:
> > > Thank you for review! My answers and new patch below.
> > > 
> > > On 22.06.2020 15:25, Nikita Pettik wrote:
> > > > On 17 Jun 15:36, imeevma@tarantool.org wrote:
> > > >> @@ -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;
> > > >> -
> > > >
> > > > Replace these assertions with relevant ones.
> > > >
> > > Not sure if this is necessary, since now we have much less flag
> > > changes after removal of mem_apply_type().
> > 
> > Не понял как это связано...Твои изменения не затрагивают
> > инвариант MEM_Dyn.
> >  
> True, however original asserts checked that
> mem_apply_type() does not changed it. Now we can say that
> it definitely won't be changed. I can return flags*
> variables for the sake of these asserts. Should I do this?
> 
> Also, after #4906 these asserts become outdated since flags
> of the mems won't change at all. Well, it will be so if we
> close #4906.

У этого тикета даже майлстоуна нет, если что.
 
> > > @@ -4744,7 +4753,25 @@ case OP_IdxGE:  {       /* jump */
> > >  		assert(pOp->opcode==OP_IdxGE || pOp->opcode==OP_IdxLT);
> > >  		r.default_rc = 0;
> > >  	}
> > > +
> > > +	/*
> > > +	 * Make sure that the types of all the fields in the tuple
> > > +	 * that will be used in the iterator comparable with the
> > > +	 * fields of the space.
> > > +	 */
> > >  	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];
> > 
> > Как-то мне эти два места (выше в SeekGE) вообще не нравятся.
> > Какие-то они запутанные. Давай подумаем как можно зарефакторить их.
> > 
> Moved to a new function. However, previously cast
> here didn't always worked since in some cases field_type
> and MEM_type of the mem not always were compatible. I think
> this was fixed in previous commits. All tests passes.
> 
> However, there is another possiblity: it may be that I
> already removed tests that fail on convertion but worked
> on check. I do not think that it is the case though.

Свят-свят. Давай подробнее. То что все тесты (которые перекромсали
десять раз) ходят - не особо важно. Катить в релиз что-то над чем
есть сомнения - не лучшая идея.
 
> This also can be fully fixed in #4906 issue.

Как?! Тот тикет про рефакторинг!

> > > +		if (mem_check_type(mem, type) == 0)
> > > +			continue;
> > > +		if (sql_type_is_numeric(type) &&
> > > +		    (mem->flags & (MEM_Real | MEM_Int | MEM_UInt)) != 0)
> > > +			continue;
> > > +		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
> > > 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)
> > 
> > Ты в следующем коммите как раз делаешь клин-ап. Давай эту функцию
> > там и удалим (как и остальные).
> > 
> It is a bit troublesome since the functions I remove here
> are 'static'. I think, that instead of removing 'static'
> keyword here and removing the function in the next commit
> it is better to just remove these runctions here.
> 
> I can change it if you think that removing in two commits
> is better.

> 
> commit f52e6669146e7a06b78d167abf369d67d9327789
> Author: Mergen Imeev <imeevma@gmail.com>
> Date:   Thu Jun 25 12:39:19 2020 +0300
> 
>     sql: remove implicit cast for comparison
>     
>     This patch removes implicit cast for comparison.
>     
>     Closes #4230
>     
>     @TarantoolBot document
>     Title: remove implicit cast for comparison
>     
>     After this patch-set, there will be no implicit casts for
>     comparison. This means that the values ​​of the field types STRING,
>     BOOLEAN and VARBINARY can be compared with the values ​​of the same

Непечатные символы в тексте, проверь.

>     field type. Any numerical value can be compared with any other
>     numerical value.
>     
>     Example:
>     
>     For comparison:
>     ```
>     tarantool> box.execute([[SELECT '1' > 0;]])
>     ---
>     - null
>     - "Type mismatch: can not convert '1' (type: text) to numeric"
>     ...
>     
>     tarantool> box.execute([[SELECT true > X'33';]])
>     ---
>     - null
>     - 'Type mismatch: can not convert ''TRUE'' (type: boolean) to varbinary'
>     ...
>     
>     tarantool> box.execute([[SELECT 1.23 > 123;]])
>     ---
>     - metadata:
>       - name: 1.23 > 123
>         type: boolean
>       rows:
>       - [false]
>     ...
>     ```
> 
> diff --git a/src/box/sql/vdbe.c b/src/box/sql/vdbe.c
> index ce9edaad9..0d3da49d3 100644
> --- a/src/box/sql/vdbe.c
> +++ b/src/box/sql/vdbe.c
> @@ -561,6 +561,50 @@ mem_convert_to_numeric(struct Mem *mem, enum field_type type, bool is_precise)
>  	return mem_convert_to_integer(mem, is_precise);
>  }
>  
> +/**
> + * Check that MEM types of mems are compatible with the
> + * corresponding types from key_def.

Так compatible или comparable?

> + * If mem and type are comparable but incompatible according to
> + * field_mp_plain_type_is_compatible() and the comparison
> + * operation is EQ, we can say that the result of the comparison
> + * will be FALSE. This allows us to compare DOUBLE and INTEGER

Почему false? Не очевидно.

> + * values.
> + *
> + * @param mems The first mem of the array.
> + * @param def key_def that contains types to check.
> + * @param size Size of the array.
> + * @param is_op_eq TRUE is comparison operator is EQ.

-> if. Как на результат совместимости типов влияет оператор сравнения?

> + * @param[out] is_not_converted TRUE if operation is EQ and mem
> +                                and type are comparable but not
> +                                compatible. FALSE otherwise.

Ты просто перечислил условия, при котором выставляешь этот флаг.
Какой смысл в этом комментарии?

> + * @retval TRUE if the MEM types and types from key_def are
> + *         comparable, FALSE otherwise.

Ты про диаг забыл...

> + */
> +static bool
> +mem_are_types_comparable(struct Mem *mems, struct key_def *def, uint32_t size,
> +			 bool is_op_eq, bool *is_not_converted) {

Извини, но в этой функции плохо просто все. Давай по порядку:

- название: почему mem_are? Откуда types, если там кей деф. Сайз чего?
Что значит is_not_converted, если ты просто делаешь проверку на
совместимость?

- предполагается, что функция что-то проверяет и возвращает как
следствие результат проверки (_are_). Но почему-то она еще и
диаг выставляет. Не надо так.

> +	assert(!is_op_eq || !*is_not_converted);

- зачем тебе два флага, которые друг на друга как-то нетривиально
завязаны, причем в половине вызовов (1 из 2) они вообще не использу-
ются?

> +	for (uint32_t i = 0; i < size; ++i) {

- где ассерт i < def->part_count ?

> +		enum field_type type = def->parts[i].type;
> +		struct Mem *mem = &mems[i];
> +		if (mem_is_type_compatible(mem, type))
> +			continue;
> +		if (mem_convert_to_numeric(mem, type, true) == 0)
> +			continue;
> +		if (sql_type_is_numeric(type) &&
> +		    (mem->flags & (MEM_Int | MEM_UInt | MEM_Real)) != 0) {
> +			if (is_op_eq)
> +				*is_not_converted = true;
> +			continue;
> +		}

- тут вообще не понятно что происходит - тройной if с выставлением
выходного параметра. Я честно говорю, что я не понимаю что тут происходит.
sql_type_is_numeric() уже вызывается в mem_convert_to_numeric()...
Давай на днях вместе сядем и подумаем как это все исправить.

> +		diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
> +			field_type_strs[type], mem_type_to_str(mem));
> +		return false;
> +	}
> +	return true;
> +}
> +
> @@ -3623,7 +3645,20 @@ skip_truncate:
>  	assert(oc!=OP_SeekGE || r.default_rc==+1);
>  	assert(oc!=OP_SeekLT || r.default_rc==+1);
>  
> +	/*
> +	 * Make sure that the types of all the fields in the tuple
> +	 * that will be used in the iterator match the field types
> +	 * of the space.
> +	 */
>  	r.aMem = &aMem[pOp->p3];
> +	bool is_not_found = false;

Не очень логично, что функция проверяющая на совместимость типов, еще
принимает флаг is_not_found..?? Что она ищет?

> +	if (!mem_are_types_comparable(r.aMem, r.key_def, r.nField, eqOnly == 1,
> +				      &is_not_found))
> +		goto abort_due_to_error;
> +	if (is_not_found) {
> +		res = 1;
> +		goto seek_not_found;
> +	}
>  #ifdef SQL_DEBUG
>  	{ int i; for(i=0; i<r.nField; i++) assert(memIsValid(&r.aMem[i])); }
>  #endif
> @@ -4750,7 +4785,16 @@ case OP_IdxGE:  {       /* jump */
>  		assert(pOp->opcode==OP_IdxGE || pOp->opcode==OP_IdxLT);
>  		r.default_rc = 0;
>  	}
> +
> +	/*
> +	 * Make sure that the types of mems are comparable with
> +	 * the field types of the space.
> +	 */
>  	r.aMem = &aMem[pOp->p3];
> +	bool unused = false;
> +	if (!mem_are_types_comparable(r.aMem, r.key_def, r.nField, false,
> +				      &unused))
> +		goto abort_due_to_error;
>  #ifdef SQL_DEBUG
>  	{ int i; for(i=0; i<r.nField; i++) assert(memIsValid(&r.aMem[i])); }
>  #endif

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

* Re: [Tarantool-patches] [PATCH v3 2/8] sql: change implicit cast for assignment
  2020-07-06 21:27       ` Nikita Pettik
@ 2020-07-07  9:29         ` Mergen Imeev
  2020-07-07 15:35           ` Nikita Pettik
  2020-07-10 10:49           ` Nikita Pettik
  0 siblings, 2 replies; 32+ messages in thread
From: Mergen Imeev @ 2020-07-07  9:29 UTC (permalink / raw)
  To: Nikita Pettik; +Cc: tarantool-patches


On 07.07.2020 00:27, Nikita Pettik wrote:
> On 05 Jul 17:26, Mergen Imeev wrote:
>> Hi! Thank you for the review. My answers and new patch
>> below. Sorry, I didn't include diff.
>>>> commit 21d7145c1929bc4606c56e9a566477f248637ed1
>>>> Author: Mergen Imeev <imeevma@gmail.com>
>>>> Date:   Wed May 27 13:49:11 2020 +0300
>>>>
>>>> + if (field_mp_plain_type_is_compatible(type, mp_type, true))
>>>> +   return 0;
>>>> + return -1;
>>>> +}
>>>> +
>>>> +/**
>>>> + * Convert the numeric value contained in MEM to double. If the
>>>> + * is_precise flag is set, the conversion will succeed only if it
>>>> + * is lossless.
>>>> + *
>>>> + * @param mem The MEM that contains the numeric value.
>>>> + * @param is_precise Flag.
>>>> + * @retval 0 if the conversion was successful, -1 otherwise.
>>>> + */
>>>> +static int
>>>> +mem_convert_to_double(struct Mem *mem, bool is_precise)
>>>> +{
>>>> + if ((mem->flags & (MEM_Int | MEM_UInt)) == 0)
>>>> +   return -1;
>>>> + if ((mem->flags & MEM_Int) != 0) {
>>>> +   int64_t i = mem->u.i;
>>>> +   double d = (double)i;
>>>> +   if (!is_precise || i == (int64_t)d)
>>>> +     mem_set_double(mem, d);
>>>> +   else
>>>> +     return -1;
>>>> + } else {
>>>> +   uint64_t u = mem->u.u;
>>>> +   double d = (double)u;
>>>> +   if (!is_precise || u == (uint64_t)d)
>>>> +     mem_set_double(mem, d);
>>>> +   else
>>>> +     return -1;
>>>> + }
>>>> + mem->field_type = FIELD_TYPE_DOUBLE;
>>> Why not incorparate field_type assingment into mem_set_double()?
>>> The same concerns other converting functions.
>>>
>> I think this should be done in #4906 issue since it may
>> lead to not always simple to understand changes.
> Эм, не очень понял как трактовать твой ответ. Типо тут работает,
> а если там засунуть, то что-то начинает падать..? 4906 немного про
> другое: в любом случае у нас в меме будет и field_type и mp_type.
> К тому же, и то, и это - рефакторинг и функциональных изменений быть
> не должно.
Не уверен, что это чистый рефакторинг, т.к. точно помны возникала
проблема с тем, что MEM_type мог быть не совместимым с field_type
т.к. field_type не изменился при переписывании мема.

Стоит сделать это изменение для mem_set_* отдельным тикетом?

>   
>>>> +/**
>>>> + * Convert the numeric value contained in MEM to another numeric
>>>> + * type. If the is_precise flag is set, the conversion will
>>>> + * succeed only if it is lossless.
>>>> + * @param mem The MEM that contains the numeric value.
>>>> + * @param type The type to convert to.
>>>> + * @param is_precise Flag.
>>>> + * @retval 0 if the conversion was successful, -1 otherwise.
>>>> + */
>>>> +static int
>>>> +mem_convert_numeric(struct Mem *mem, enum field_type type, bool is_precise)
>>> mem_convert_to_numeric ?
>>> mem_cast_to_numeric
>>>
>> Used first option.
>>
>>>> +{
>>>> + if (!sql_type_is_numeric(type) ||
>>>> +     (mem->flags & (MEM_Real | MEM_Int | MEM_UInt)) == 0)
>>> It's somehow unnatural passing to _numeric function non-numeric type
>>> to convert to. Instead let's use this function properly and replace
>>> branching with assertion.
>>>
>> No, I think it is good as it is. More that that, due to
>> some other comments I added similar checks to all other
>> mem_convert_to>* functions.
> В остальных случаях ты туда тип вообще не передаешь.
>   
>> My reason is: in all places we use this function we have
>> to check that field type and MEM_type are numeric, so it
>> make sence to move this check inside of the function.
> Еще раз: это полный идиотизм передавать ТИП (отличный от нумерика) к
> которому ты собираешься кастовать в функцию, которая по названию
> предполагает каст к нумерику. Считай, что я настаиваю на этом
> изменении.

Сделаю.


>>>> +   return -1;
>>>> + if (type == FIELD_TYPE_NUMBER)
>>>> +   return 0;
>>>> + if (type == FIELD_TYPE_DOUBLE)
>>>> +   return mem_convert_to_double(mem, is_precise);
>>>> + if (type == FIELD_TYPE_UNSIGNED)
>>>> +   return mem_convert_to_unsigned(mem, is_precise);
>>>> + assert(type == FIELD_TYPE_INTEGER);
>>>> + return mem_convert_to_integer(mem, is_precise);
>>>> +}
>>>> +
>>>>   /*
>> index 37283e506..bd0055668 100644
>> --- a/src/box/sql/sqlInt.h
>> +++ b/src/box/sql/sqlInt.h
>> @@ -397,6 +397,15 @@ sql_value_to_diag_str(sql_value *value);
>>   enum mp_type
>>   sql_value_type(sql_value *);
>>   
>> +/*
>> + * Return the MP_type of the value of the MEM.
>> + *
>> + * @param mem MEM with the correct MEM_type.
>> + * @retval MP_type of the value.
>> + */
>> +enum mp_type
>> +mem_mp_type(struct Mem *mem);
> Я вытащил добавление этой функции в отдельный патч и добавил
> рефакторинг чтобы соеденить ее с sql_value_type().
> https://github.com/tarantool/tarantool/tree/np/gh-3809-remastered
>
> Если ты ОК, я пушну вне очереди в мастер.
Я ОК.
>> diff --git a/src/box/sql/vdbe.c b/src/box/sql/vdbe.c
>> index 950f72ddd..1386ea2c0 100644
>> --- a/src/box/sql/vdbe.c
>> +++ b/src/box/sql/vdbe.c
>> +		uint64_t u = mem->u.u;
>> +		double d = (double)u;
>> +		if (!is_precise || u == (uint64_t)d)
>> +			mem_set_double(mem, d);
>> +		else
>> +			return -1;
>> +	}
>> +	mem->field_type = FIELD_TYPE_DOUBLE;
>> +	return 0;
>> +}
>> +
>> + * P1 are compatible with given field types in P4.
>> + * If the MEM_type of the value and the given type are
>> + * incompatible according to field_mp_plain_type_is_compatible(),
>> + * but both are numeric, this opcode attempts to convert the value
>> + * to the type.
>> + */
>> +case OP_ImplicitCast: {
>> +	enum field_type *types = pOp->p4.types;
>> +	assert(types != NULL);
>> +	assert(types[pOp->p2] == field_type_MAX);
>> +	for (int i = 0; types[i] != field_type_MAX; ++i) {
>> +		enum field_type type = types[i];
>> +		pIn1 = &aMem[pOp->p1 + i];
>> +		assert(pIn1 <= &p->aMem[(p->nMem+1 - p->nCursor)]);
>> +		assert(memIsValid(pIn1));
>> +		if (mem_is_type_compatible(pIn1, type))
>> +			continue;
>> +		if (mem_convert_to_numeric(pIn1, type, false) == 0)
> Инвертируй, пожайлуйста условие:
>
> if (mem_convert_to_numeric(pIn1, type, false) !=) {
> 	//raise an error
> }
>
> Это будет больще соответствовать нашему кодстайлу.

Сделаю.


>> +			continue;
>> +		diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
>> +			 sql_value_to_diag_str(pIn1), field_type_strs[type]);
>> +		goto abort_due_to_error;
>> +	}
>> +	break;
>> +}
>> +
>>   /* Opcode: MakeRecord P1 P2 P3 P4 P5
>>    * Synopsis: r[P3]=mkrec(r[P1@P2])
>>    *
>> diff --git a/src/box/sql/vdbeapi.c b/src/box/sql/vdbeapi.c
>> index 4e103a653..b106ce6bd 100644
>> --- a/src/box/sql/vdbeapi.c
>> +++ b/src/box/sql/vdbeapi.c
>> @@ -225,6 +225,33 @@ sql_value_type(sql_value *pVal)
>>   	}
>>   }
>>   
>> +enum mp_type
>> +mem_mp_type(struct Mem *mem)
> Еще раз: это не апишная функция (хотя бы в терминологии скулайта),
> ей место скорее в vdbemem.c. См. мой рефакторинг.
>
>> +{
>> --- a/test/sql-tap/autoinc.test.lua
>> +++ b/test/sql-tap/autoinc.test.lua
> Тесты не смотрел, предполагая что нет изменений по сравнению с
> предыдущей версией.
>
Да, тесты не изменились.

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

* Re: [Tarantool-patches] [PATCH v3 4/8] sql: replace ApplyType by CheckType for IN operator
  2020-07-06 22:06       ` Nikita Pettik
@ 2020-07-07 11:26         ` Mergen Imeev
  2020-07-07 16:29           ` Nikita Pettik
  0 siblings, 1 reply; 32+ messages in thread
From: Mergen Imeev @ 2020-07-07 11:26 UTC (permalink / raw)
  To: Nikita Pettik; +Cc: tarantool-patches


On 07.07.2020 01:06, Nikita Pettik wrote:
> On 05 Jul 17:28, Mergen Imeev wrote:
>> On Mon, Jun 29, 2020 at 12:56:30PM +0000, Nikita Pettik wrote:
>>> On 25 Jun 18:17, imeevma@tarantool.org wrote:
>>>> 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>
>>>> -    })
>>>> -
>>> I'd rather not drop this test. It's about scalar-numeric types
>>> interaction. Mb it is not the most suitable place for such test,
>>> but make sure this scenario is covered somewhere else.
>>>
>> I added a few tests with SCALARS in 'sql: remove implicit
>> cast for comparison' commit. However, there is a lot
>> problems with SCALARS at the moment.
> Давай с этим что-то делать. Проблемы где-то описаны? Если нет,
> давай подробно разберем и заведем тикет(ы). Иначе это звучит как
> "idgs потом кто-нибудь это разгребет". В тикете 4230 есть
> пункт про скаляр, но мы почему-то обходим его, оставляя
> проблему as is.
Создал тикет: https://github.com/tarantool/tarantool/issues/5148

В последнем письме ("Re: Check implicit cast between strings and
numbers") Гулузан тоже согласен с тем, что по скалярам мы не
договорились.

>   
>>> The rest is OK as obvious.
>>>

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

* Re: [Tarantool-patches] [PATCH v3 2/8] sql: change implicit cast for assignment
  2020-07-07  9:29         ` Mergen Imeev
@ 2020-07-07 15:35           ` Nikita Pettik
  2020-07-10 10:49           ` Nikita Pettik
  1 sibling, 0 replies; 32+ messages in thread
From: Nikita Pettik @ 2020-07-07 15:35 UTC (permalink / raw)
  To: Mergen Imeev; +Cc: tarantool-patches

On 07 Jul 12:29, Mergen Imeev wrote:
> 
> On 07.07.2020 00:27, Nikita Pettik wrote:
> > On 05 Jul 17:26, Mergen Imeev wrote:
> > > Hi! Thank you for the review. My answers and new patch
> > > below. Sorry, I didn't include diff.
> > > > > commit 21d7145c1929bc4606c56e9a566477f248637ed1
> > > > > Author: Mergen Imeev <imeevma@gmail.com>
> > > > > Date:   Wed May 27 13:49:11 2020 +0300
> > > > > 
> > > > > + if (field_mp_plain_type_is_compatible(type, mp_type, true))
> > > > > +   return 0;
> > > > > + return -1;
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > + * Convert the numeric value contained in MEM to double. If the
> > > > > + * is_precise flag is set, the conversion will succeed only if it
> > > > > + * is lossless.
> > > > > + *
> > > > > + * @param mem The MEM that contains the numeric value.
> > > > > + * @param is_precise Flag.
> > > > > + * @retval 0 if the conversion was successful, -1 otherwise.
> > > > > + */
> > > > > +static int
> > > > > +mem_convert_to_double(struct Mem *mem, bool is_precise)
> > > > > +{
> > > > > + if ((mem->flags & (MEM_Int | MEM_UInt)) == 0)
> > > > > +   return -1;
> > > > > + if ((mem->flags & MEM_Int) != 0) {
> > > > > +   int64_t i = mem->u.i;
> > > > > +   double d = (double)i;
> > > > > +   if (!is_precise || i == (int64_t)d)
> > > > > +     mem_set_double(mem, d);
> > > > > +   else
> > > > > +     return -1;
> > > > > + } else {
> > > > > +   uint64_t u = mem->u.u;
> > > > > +   double d = (double)u;
> > > > > +   if (!is_precise || u == (uint64_t)d)
> > > > > +     mem_set_double(mem, d);
> > > > > +   else
> > > > > +     return -1;
> > > > > + }
> > > > > + mem->field_type = FIELD_TYPE_DOUBLE;
> > > > Why not incorparate field_type assingment into mem_set_double()?
> > > > The same concerns other converting functions.
> > > > 
> > > I think this should be done in #4906 issue since it may
> > > lead to not always simple to understand changes.
> > Эм, не очень понял как трактовать твой ответ. Типо тут работает,
> > а если там засунуть, то что-то начинает падать..? 4906 немного про
> > другое: в любом случае у нас в меме будет и field_type и mp_type.
> > К тому же, и то, и это - рефакторинг и функциональных изменений быть
> > не должно.
> Не уверен, что это чистый рефакторинг, т.к. точно помны возникала
> проблема с тем, что MEM_type мог быть не совместимым с field_type
> т.к. field_type не изменился при переписывании мема.
> 
> Стоит сделать это изменение для mem_set_* отдельным тикетом?

Тикетом, патчем, фолоу-апом - как хочешь.
 

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

* Re: [Tarantool-patches] [PATCH v3 4/8] sql: replace ApplyType by CheckType for IN operator
  2020-07-07 11:26         ` Mergen Imeev
@ 2020-07-07 16:29           ` Nikita Pettik
  0 siblings, 0 replies; 32+ messages in thread
From: Nikita Pettik @ 2020-07-07 16:29 UTC (permalink / raw)
  To: Mergen Imeev; +Cc: tarantool-patches

On 07 Jul 14:26, Mergen Imeev wrote:
> 
> On 07.07.2020 01:06, Nikita Pettik wrote:
> > On 05 Jul 17:28, Mergen Imeev wrote:
> > > On Mon, Jun 29, 2020 at 12:56:30PM +0000, Nikita Pettik wrote:
> > > > On 25 Jun 18:17, imeevma@tarantool.org wrote:
> > > > > 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>
> > > > > -    })
> > > > > -
> > > > I'd rather not drop this test. It's about scalar-numeric types
> > > > interaction. Mb it is not the most suitable place for such test,
> > > > but make sure this scenario is covered somewhere else.
> > > > 
> > > I added a few tests with SCALARS in 'sql: remove implicit
> > > cast for comparison' commit. However, there is a lot
> > > problems with SCALARS at the moment.
> > Давай с этим что-то делать. Проблемы где-то описаны? Если нет,
> > давай подробно разберем и заведем тикет(ы). Иначе это звучит как
> > "idgs потом кто-нибудь это разгребет". В тикете 4230 есть
> > пункт про скаляр, но мы почему-то обходим его, оставляя
> > проблему as is.
> Создал тикет: https://github.com/tarantool/tarantool/issues/5148
> 
> В последнем письме ("Re: Check implicit cast between strings and
> numbers") Гулузан тоже согласен с тем, что по скалярам мы не
> договорились.

Можешь поднять старую переписку? Давай распишем пункты где у нас
не совпадало мнение и придем к консенсусу?
 
> > > > The rest is OK as obvious.
> > > > 

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

* Re: [Tarantool-patches] [PATCH v3 2/8] sql: change implicit cast for assignment
  2020-07-07  9:29         ` Mergen Imeev
  2020-07-07 15:35           ` Nikita Pettik
@ 2020-07-10 10:49           ` Nikita Pettik
  1 sibling, 0 replies; 32+ messages in thread
From: Nikita Pettik @ 2020-07-10 10:49 UTC (permalink / raw)
  To: Mergen Imeev; +Cc: tarantool-patches

On 07 Jul 12:29, Mergen Imeev wrote:
> 
> On 07.07.2020 00:27, Nikita Pettik wrote:
> > On 05 Jul 17:26, Mergen Imeev wrote:
> > > index 37283e506..bd0055668 100644
> > > --- a/src/box/sql/sqlInt.h
> > > +++ b/src/box/sql/sqlInt.h
> > > @@ -397,6 +397,15 @@ sql_value_to_diag_str(sql_value *value);
> > >   enum mp_type
> > >   sql_value_type(sql_value *);
> > > +/*
> > > + * Return the MP_type of the value of the MEM.
> > > + *
> > > + * @param mem MEM with the correct MEM_type.
> > > + * @retval MP_type of the value.
> > > + */
> > > +enum mp_type
> > > +mem_mp_type(struct Mem *mem);
> > Я вытащил добавление этой функции в отдельный патч и добавил
> > рефакторинг чтобы соеденить ее с sql_value_type().
> > https://github.com/tarantool/tarantool/tree/np/gh-3809-remastered
> > 
> > Если ты ОК, я пушну вне очереди в мастер.
> Я ОК.

Pushed to master as trivial refactoring.

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

end of thread, other threads:[~2020-07-10 10:49 UTC | newest]

Thread overview: 32+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-06-25 15:17 [Tarantool-patches] [PATCH v3 0/8] Remove implicit cast imeevma
2020-06-25 15:17 ` [Tarantool-patches] [PATCH v3 1/8] sql: introduce mem_set_double() imeevma
2020-06-28 13:31   ` Nikita Pettik
2020-07-06 14:02     ` Nikita Pettik
2020-06-25 15:17 ` [Tarantool-patches] [PATCH v3 2/8] sql: change implicit cast for assignment imeevma
2020-06-30 11:50   ` Nikita Pettik
2020-07-05 14:26     ` Mergen Imeev
2020-07-06 21:27       ` Nikita Pettik
2020-07-07  9:29         ` Mergen Imeev
2020-07-07 15:35           ` Nikita Pettik
2020-07-10 10:49           ` Nikita Pettik
2020-06-25 15:17 ` [Tarantool-patches] [PATCH v3 3/8] sql: remove mem_apply_type() from OP_MakeRecord imeevma
2020-06-25 15:17 ` [Tarantool-patches] [PATCH v3 4/8] sql: replace ApplyType by CheckType for IN operator imeevma
2020-06-29 12:56   ` Nikita Pettik
2020-07-05 14:28     ` Mergen Imeev
2020-07-06 22:06       ` Nikita Pettik
2020-07-07 11:26         ` Mergen Imeev
2020-07-07 16:29           ` Nikita Pettik
2020-06-25 15:17 ` [Tarantool-patches] [PATCH v3 5/8] sql: remove mem_apply_type() from OP_MustBeInt imeevma
2020-06-29 13:29   ` Nikita Pettik
2020-07-05 14:29     ` Mergen Imeev
2020-06-25 15:17 ` [Tarantool-patches] [PATCH v3 6/8] sql: remove implicit cast for comparison imeevma
2020-06-29 23:51   ` Nikita Pettik
2020-07-05 14:47     ` Mergen Imeev
2020-07-06 23:11       ` Nikita Pettik
2020-06-25 15:17 ` [Tarantool-patches] [PATCH v3 7/8] sql: remove unused functions imeevma
2020-06-29 23:52   ` Nikita Pettik
2020-07-05 14:50     ` Mergen Imeev
2020-06-25 15:17 ` [Tarantool-patches] [PATCH v3 8/8] sql: show value and its type in type mismatch error imeevma
2020-06-30  0:22   ` Nikita Pettik
2020-07-05 15:03     ` Mergen Imeev
2020-07-06 21:44       ` Nikita Pettik

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