[Tarantool-patches] [PATCH 5/6] sql: remove implicit cast from string for comparison

Mergen Imeev imeevma at tarantool.org
Tue Jun 9 14:51:26 MSK 2020


Thanks for the review! My answers and new patch below.


On 01.06.2020 20:04, Vladislav Shpilevoy wrote:
> Thanks for the patch!
>
> See 7 comments below.
>
> On 28/05/2020 16:17, Mergen Imeev wrote:
>> This patch removes implicit cast from strings to numbers for
>> comparison.
>>
>> Closes #4230
>>
>> @TarantoolBot document
>> Title: remove implicit cast between strings and numbers
>>
>> This patch-set removes implicit cast from string to number and
>> from number to string.
>>
>> Example:
>>
>> For comparison:
>>
>> tarantool> box.execute([[SELECT '1' > 0;]])
>> ---
>> - null
>> - 'Type mismatch: can not convert 1 to numeric'
>> ...
>>
>> tarantool> box.execute([[SELECT "id" FROM "_space" WHERE '1' > "id";]])
>> ---
>> - null
>> - 'Type mismatch: can not convert text to unsigned'
>> ...
>>
>> For assignment:
>>
>> tarantool> box.execute([[CREATE TABLE t1(i INT PRIMARY KEY);]])
>> tarantool> box.execute([[INSERT INTO t1 VALUES ('1');]])
>> ---
>> - null
>> - 'Type mismatch: can not convert text to integer'
>> ...
>>
>> tarantool> box.execute([[CREATE TABLE t2(t text PRIMARY KEY);]])
>> tarantool> box.execute([[INSERT INTO t2 VALUES (1);]])
>> ---
>> - null
>> - 'Type mismatch: can not convert unsigned to string'
>> ...
>> ---
>>   src/box/sql/vdbe.c                            | 105 ++++----
>>   src/box/sql/wherecode.c                       | 203 +--------------
>>   .../gh-4230-del-impl-cast-str-to-num.test.lua |  78 ++++++
>>   test/sql-tap/identifier_case.test.lua         |   6 +-
>>   test/sql-tap/in1.test.lua                     |   4 +-
>>   test/sql-tap/in4.test.lua                     |   3 +-
>>   test/sql-tap/insert3.test.lua                 |   2 +-
>>   test/sql-tap/intpkey.test.lua                 |  24 +-
>>   test/sql-tap/join.test.lua                    |   7 +-
>>   test/sql-tap/misc1.test.lua                   |  32 +--
>>   test/sql-tap/select1.test.lua                 |   4 +-
>>   test/sql-tap/select7.test.lua                 |   2 +-
>>   test/sql-tap/subquery.test.lua                |   4 +-
>>   test/sql-tap/tkt-9a8b09f8e6.test.lua          |  84 ++++---
>>   test/sql-tap/tkt-f973c7ac31.test.lua          |  32 +--
>>   test/sql-tap/tkt-fc7bd6358f.test.lua          |   6 +-
>>   test/sql-tap/tkt3493.test.lua                 |  40 ++-
>>   test/sql-tap/transitive1.test.lua             |  12 +-
>>   test/sql-tap/where2.test.lua                  | 183 +-------------
>>   test/sql-tap/where5.test.lua                  |  12 +-
>>   test/sql-tap/whereB.test.lua                  | 238 ++++++++++--------
>>   test/sql/types.result                         |  12 +-
>>   test/sql/types.test.lua                       |   1 -
>>   23 files changed, 418 insertions(+), 676 deletions(-)
>>   create mode 100755 test/sql-tap/gh-4230-del-impl-cast-str-to-num.test.lua
>>
>> diff --git a/src/box/sql/vdbe.c b/src/box/sql/vdbe.c
>> index 7add67ae7..021e09d1e 100644
>> --- a/src/box/sql/vdbe.c
>> +++ b/src/box/sql/vdbe.c
>> @@ -2345,22 +2338,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_Int | MEM_UInt | MEM_Real)) != 0) {
> 1. Maybe it would be better to check '(flags1 & MEM_Str) == 0'. Otherwise
> every time when we will add a new type, we will need to add it here. The
> same below.

Thanks, fixed.


>
>> +				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_Int | MEM_UInt | MEM_Real)) != 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);
>> diff --git a/src/box/sql/wherecode.c b/src/box/sql/wherecode.c
>> index 5bc27f134..1d7c76670 100644
>> --- a/src/box/sql/wherecode.c
>> +++ b/src/box/sql/wherecode.c
>> @@ -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);
> 2. This function is now unused and can be deleted.

Removed.


>
>> -	assert(type != NULL || pParse->db->mallocFailed);
>> -
>>   	if (nSkip) {
>>   		int iIdxCur = pLevel->iIdxCur;
>>   		sqlVdbeAddOp1(v, (bRev ? OP_Last : OP_Rewind), iIdxCur);> diff --git a/test/sql-tap/tkt-9a8b09f8e6.test.lua b/test/sql-tap/tkt-9a8b09f8e6.test.lua
>> index 854ed774f..2a18b17be 100755
>> --- a/test/sql-tap/tkt-9a8b09f8e6.test.lua
>> +++ b/test/sql-tap/tkt-9a8b09f8e6.test.lua
>> @@ -83,23 +83,23 @@ test:do_execsql_test(
>>           -- </1.5>
>>       })
>>   
>> -test:do_execsql_test(
>> +test:do_catchsql_test(
>>       2.1,
>>       [[
>>           SELECT x FROM t1 WHERE x IN (1);
>>       ]], {
>>           -- <2.1>
>> -        "1"
>> +        1,"Type mismatch: can not convert 1 to numeric"
> 3. Can tests in this file be fixed to return the same results
> as before?
I fixed this in most cases, but am not sure if this is correct.
I think most tests are out of date.

>
>>           -- </2.1>
>>       })
>>   
>> -test:do_execsql_test(
>> +test:do_catchsql_test(
>>       2.2,
>>       [[
>>           SELECT x FROM t1 WHERE x IN (1.0);
>>       ]], {
>>           -- <2.2>
>> -        "1"
>> +        1,"Type mismatch: can not convert 1 to numeric"
>>           -- </2.2>
>>       })
>>   
>> diff --git a/test/sql-tap/tkt-f973c7ac31.test.lua b/test/sql-tap/tkt-f973c7ac31.test.lua
>> index 82bdb52f8..5239a7785 100755
>> --- a/test/sql-tap/tkt-f973c7ac31.test.lua
>> +++ b/test/sql-tap/tkt-f973c7ac31.test.lua
>> @@ -36,12 +36,12 @@ local sqls = {
>>   
>>   for tn, sql in ipairs(sqls) do
>>       test:execsql(sql)
>> -    test:do_execsql_test(
>> +    test:do_catchsql_test(
>>           "tkt-f973c7ac3-1."..tn..".1",
>>           [[
>>               SELECT c1,c2 FROM t WHERE c1 = 5 AND c2>0 AND c2<='2' ORDER BY c2 DESC
>>           ]], {
>> -
>> +            1, "/Type mismatch: can not convert/"
> 4. The same for this file.

Fixed, used CAST().


>
>>           })
>>   
>>       test:do_execsql_test(
>> diff --git a/test/sql-tap/tkt3493.test.lua b/test/sql-tap/tkt3493.test.lua
>> index de77e61e9..ec12a4492 100755
>> --- a/test/sql-tap/tkt3493.test.lua
>> +++ b/test/sql-tap/tkt3493.test.lua
>> @@ -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
> 5. Trailing whitespace.

Removed.


>
>>       ]], {
>>           -- <tkt3493-2.2.1>
>>           true
>>           -- </tkt3493-2.2.1>
>>       })
>> @@ -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
> 6. Trailing whitespace here and in the test above.

Removed.


>
>>       ]], {
>>           -- <tkt3493-2.2.5>
>>           1, true
>> diff --git a/test/sql-tap/whereB.test.lua b/test/sql-tap/whereB.test.lua
>> index 970ff1dec..9e99ea41c 100755
>> --- a/test/sql-tap/whereB.test.lua
>> +++ b/test/sql-tap/whereB.test.lua
>> @@ -36,49 +35,54 @@ test:do_execsql_test(
>>           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');
>> +    ]]
>> +)
>>   
>> +test:do_catchsql_test(
>> +    "whereB-1.1",
> 7. The whole whereB-1 now fails because of type conversions banned.
> Is this test still needed at all? I didn't check other whereB tests,
> but seems like most of them also fail now. So either almost the entire
> test file is not needed, or it should be fixed so as the test still
> would work.

Removed whereB.test.lua in the previous patch.


New patch:


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

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

Closes #4230

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

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

Example:

For comparison:

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

tarantool> box.execute([[SELECT "id" FROM "_space" WHERE '1' > "id";]])
---
- null
- 'Type mismatch: can not convert text to unsigned'
...

For assignment:

tarantool> box.execute([[CREATE TABLE t1(i INT PRIMARY KEY);]])
tarantool> box.execute([[INSERT INTO t1 VALUES ('1');]])
---
- null
- 'Type mismatch: can not convert text to integer'
...

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

review fix

diff --git a/src/box/sql/insert.c b/src/box/sql/insert.c
index 253304ba3..7b9cda504 100644
--- a/src/box/sql/insert.c
+++ b/src/box/sql/insert.c
@@ -41,20 +41,6 @@
  #include "box/box.h"
  #include "box/schema.h"

-enum field_type *
-sql_index_type_str(struct sql *db, const struct index_def *idx_def)
-{
-    uint32_t column_count = idx_def->key_def->part_count;
-    uint32_t sz = (column_count + 1) * sizeof(enum field_type);
-    enum field_type *types = (enum field_type *) sqlDbMallocRaw(db, sz);
-    if (types == NULL)
-        return NULL;
-    for (uint32_t i = 0; i < column_count; i++)
-        types[i] = idx_def->key_def->parts[i].type;
-    types[column_count] = field_type_MAX;
-    return types;
-}
-
  void
  sql_emit_table_types(struct Vdbe *v, struct space_def *def, int reg)
  {
diff --git a/src/box/sql/sqlInt.h b/src/box/sql/sqlInt.h
index 37283e506..01c32d518 100644
--- a/src/box/sql/sqlInt.h
+++ b/src/box/sql/sqlInt.h
@@ -3866,10 +3866,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.
diff --git a/src/box/sql/vdbe.c b/src/box/sql/vdbe.c
index 77b758833..a92c9f60f 100644
--- a/src/box/sql/vdbe.c
+++ b/src/box/sql/vdbe.c
@@ -2260,8 +2260,6 @@ case OP_Ge: {             /* same as TK_GE, jump, 
in1, in3 */
      pIn3 = &aMem[pOp->p3];
      flags1 = pIn1->flags;
      flags3 = pIn3->flags;
-    enum field_type ft_p1 = pIn1->field_type;
-    enum field_type ft_p3 = pIn3->field_type;
      if ((flags1 | flags3)&MEM_Null) {
          /* One or both operands are NULL */
          if (pOp->p5 & SQL_NULLEQ) {
@@ -2320,22 +2318,17 @@ case OP_Ge: {             /* same as TK_GE, 
jump, in1, in3 */
      } else {
          enum field_type type = pOp->p5 & FIELD_TYPE_MASK;
          if (sql_type_is_numeric(type)) {
-            if ((flags1 | flags3)&MEM_Str) {
-                if ((flags1 & MEM_Str) == MEM_Str) {
-                    mem_apply_numeric_type(pIn1);
-                    testcase( flags3!=pIn3->flags); /* Possible if 
pIn1==pIn3 */
-                    flags3 = pIn3->flags;
-                }
-                if ((flags3 & MEM_Str) == MEM_Str) {
-                    if (mem_apply_numeric_type(pIn3) != 0) {
-                        diag_set(ClientError,
-                             ER_SQL_TYPE_MISMATCH,
-                             sql_value_to_diag_str(pIn3),
-                             "numeric");
-                        goto abort_due_to_error;
-                    }
-
-                }
+            if ((flags1 & MEM_Str) == MEM_Str) {
+                diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
+                     sql_value_to_diag_str(pIn1),
+                     "numeric");
+                goto abort_due_to_error;
+            }
+            if ((flags3 & MEM_Str) == MEM_Str) {
+                diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
+                     sql_value_to_diag_str(pIn3),
+                     "numeric");
+                goto abort_due_to_error;
              }
              /* Handle the common case of integer comparison here, as an
               * optimization, to avoid a call to sqlMemCompare()
@@ -2368,22 +2361,17 @@ case OP_Ge: {             /* same as TK_GE, 
jump, in1, in3 */
                  goto compare_op;
              }
          } else if (type == FIELD_TYPE_STRING) {
-            if ((flags1 & MEM_Str) == 0 &&
-                (flags1 & (MEM_Int | MEM_UInt | MEM_Real)) != 0) {
-                testcase( pIn1->flags & MEM_Int);
-                testcase( pIn1->flags & MEM_Real);
-                sqlVdbeMemStringify(pIn1);
-                testcase( (flags1&MEM_Dyn) != (pIn1->flags&MEM_Dyn));
-                flags1 = (pIn1->flags & ~MEM_TypeMask) | (flags1 & 
MEM_TypeMask);
-                assert(pIn1!=pIn3);
+            if ((flags1 & MEM_Str) == 0) {
+                diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
+                     mem_type_to_str(pIn3),
+                     mem_type_to_str(pIn1));
+                goto abort_due_to_error;
              }
-            if ((flags3 & MEM_Str) == 0 &&
-                (flags3 & (MEM_Int | MEM_UInt | MEM_Real)) != 0) {
-                testcase( pIn3->flags & MEM_Int);
-                testcase( pIn3->flags & MEM_Real);
-                sqlVdbeMemStringify(pIn3);
-                testcase( (flags3&MEM_Dyn) != (pIn3->flags&MEM_Dyn));
-                flags3 = (pIn3->flags & ~MEM_TypeMask) | (flags3 & 
MEM_TypeMask);
+            if ((flags3 & MEM_Str) == 0) {
+                diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
+                     mem_type_to_str(pIn1),
+                     mem_type_to_str(pIn3));
+                goto abort_due_to_error;
              }
          }
          assert(pOp->p4type==P4_COLLSEQ || pOp->p4.pColl==0);
@@ -2399,14 +2387,6 @@ case OP_Ge: {             /* same as TK_GE, jump, 
in1, in3 */
      default:       res2 = res>=0;     break;
      }

-    /* Undo any changes made by mem_apply_type() to the input registers. */
-    assert((pIn1->flags & MEM_Dyn) == (flags1 & MEM_Dyn));
-    pIn1->flags = flags1;
-    pIn1->field_type = ft_p1;
-    assert((pIn3->flags & MEM_Dyn) == (flags3 & MEM_Dyn));
-    pIn3->flags = flags3;
-    pIn3->field_type = ft_p3;
-
      if (pOp->p5 & SQL_STOREP2) {
          iCompare = res;
          res2 = res2!=0;  /* For this path res2 must be exactly 0 or 1 */
@@ -3496,8 +3476,6 @@ case OP_SeekGT: {       /* jump, in3 */
          pIn3 = &aMem[int_field];
          if ((pIn3->flags & MEM_Null) != 0)
              goto skip_truncate;
-        if ((pIn3->flags & MEM_Str) != 0)
-            mem_apply_numeric_type(pIn3);
          int64_t i;
          if ((pIn3->flags & MEM_Int) == MEM_Int) {
              i = pIn3->u.i;
@@ -3590,6 +3568,26 @@ skip_truncate:
      assert(oc!=OP_SeekLT || r.default_rc==+1);

      r.aMem = &aMem[pOp->p3];
+    for (int i = 0; i < r.nField; ++i) {
+        enum field_type type = r.key_def->parts[i].type;
+        struct Mem *mem = &r.aMem[i];
+        if ((mem->flags & MEM_Str) != 0 && sql_type_is_numeric(type)) {
+            diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
+                field_type_strs[type], mem_type_to_str(mem));
+            goto abort_due_to_error;
+        }
+        if (mem_check_types(mem, type) == 0)
+            continue;
+        if ((mem->flags & MEM_Real) != 0 &&
+            (type == FIELD_TYPE_INTEGER ||
+             type == FIELD_TYPE_UNSIGNED)) {
+            res = 1;
+            goto seek_not_found;
+        }
+        diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
+            field_type_strs[type], mem_type_to_str(mem));
+        goto abort_due_to_error;
+    }
  #ifdef SQL_DEBUG
      { int i; for(i=0; i<r.nField; i++) assert(memIsValid(&r.aMem[i])); }
  #endif
@@ -4717,6 +4715,27 @@ case OP_IdxGE:  {       /* jump */
          r.default_rc = 0;
      }
      r.aMem = &aMem[pOp->p3];
+    for (int i = 0; i < r.nField; ++i) {
+        struct Mem *mem = &r.aMem[i];
+        enum mp_type mp_type = sql_value_type(mem);
+        enum field_type field_type = r.key_def->parts[i].type;
+        if (field_type == FIELD_TYPE_SCALAR ||
+            mem->field_type == FIELD_TYPE_SCALAR)
+            continue;
+        bool is_nullable = r.key_def->parts[i].nullable_action ==
+                   ON_CONFLICT_ACTION_NONE;
+        if (field_mp_plain_type_is_compatible(field_type, mp_type,
+                              is_nullable))
+            continue;
+        if (!sql_type_is_numeric(field_type) ||
+            !(mp_type == MP_INT || mp_type == MP_UINT ||
+              mp_type == MP_DOUBLE || mp_type == MP_FLOAT)) {
+            diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
+                 mem_type_to_str(mem),
+                 field_type_strs[field_type]);
+            goto abort_due_to_error;
+        }
+    }
  #ifdef SQL_DEBUG
      { int i; for(i=0; i<r.nField; i++) assert(memIsValid(&r.aMem[i])); }
  #endif
diff --git a/src/box/sql/wherecode.c b/src/box/sql/wherecode.c
index 6d8768865..1d7c76670 100644
--- a/src/box/sql/wherecode.c
+++ b/src/box/sql/wherecode.c
@@ -335,72 +335,6 @@ disableTerm(WhereLevel * pLevel, WhereTerm * pTerm)
      }
  }

-/**
- * Code an OP_ApplyType opcode to apply the column type string
- * @types to the n registers starting at @base.
- *
- * As an optimization, SCALAR entries (which are no-ops) at the
- * beginning and end of @types are ignored.  If all entries in
- * @types are SCALAR, then no code gets generated.
- *
- * This routine makes its own copy of @types so that the caller is
- * free to modify @types after this routine returns.
- */
-static void
-emit_apply_type(Parse *pParse, int base, int n, enum field_type *types)
-{
-    Vdbe *v = pParse->pVdbe;
-    if (types == NULL) {
-        assert(pParse->db->mallocFailed);
-        return;
-    }
-    assert(v != 0);
-
-    /*
-     * Adjust base and n to skip over SCALAR entries at the
-     * beginning and end of the type sequence.
-     */
-    while (n > 0 && types[0] == FIELD_TYPE_SCALAR) {
-        n--;
-        base++;
-        types++;
-    }
-    while (n > 1 && types[n - 1] == FIELD_TYPE_SCALAR) {
-        n--;
-    }
-
-    if (n > 0) {
-        enum field_type *types_dup = field_type_sequence_dup(pParse,
-                                     types, n);
-        sqlVdbeAddOp4(v, OP_ApplyType, base, n, 0,
-                  (char *) types_dup, P4_DYNAMIC);
-        sql_expr_type_cache_change(pParse, base, n);
-    }
-}
-
-/**
- * Expression @rhs, which is the RHS of a comparison operation, is
- * either a vector of n elements or, if n==1, a scalar expression.
- * Before the comparison operation, types @types are to be applied
- * to the @rhs values. This function modifies entries within the
- * field sequence to SCALAR if either:
- *
- *   * the comparison will be performed with no type, or
- *   * the type change in @types is guaranteed not to change the value.
- */
-static void
-expr_cmp_update_rhs_type(struct Expr *rhs, int n, enum field_type *types)
-{
-    for (int i = 0; i < n; i++) {
-        Expr *p = sqlVectorFieldSubexpr(rhs, i);
-        enum field_type expr_type = sql_expr_type(p);
-        if (sql_type_result(expr_type, types[i]) == FIELD_TYPE_SCALAR ||
-            sql_expr_needs_no_type_change(p, types[i])) {
-            types[i] = FIELD_TYPE_SCALAR;
-        }
-    }
-}
-
  /*
   * Generate code for a single equality term of the WHERE clause. An 
equality
   * term can be either X=expr or X IN (...).   pTerm is the term to be
@@ -644,8 +578,7 @@ static int
  codeAllEqualityTerms(Parse * pParse,    /* Parsing context */
               WhereLevel * pLevel,    /* Which nested loop of the FROM 
we are coding */
               int bRev,        /* Reverse the order of IN operators */
-             int nExtraReg,    /* Number of extra registers to allocate */
-             enum field_type **res_type)
+             int nExtraReg)    /* Number of extra registers to allocate */
  {
      u16 nEq;        /* The number of == or IN constraints to code */
      u16 nSkip;        /* Number of left-most columns to skip */
@@ -669,9 +602,6 @@ codeAllEqualityTerms(Parse * pParse,    /* Parsing 
context */
      nReg = pLoop->nEq + nExtraReg;
      pParse->nMem += nReg;

-    enum field_type *type = sql_index_type_str(pParse->db, idx_def);
-    assert(type != NULL || pParse->db->mallocFailed);
-
      if (nSkip) {
          int iIdxCur = pLevel->iIdxCur;
          sqlVdbeAddOp1(v, (bRev ? OP_Last : OP_Rewind), iIdxCur);
@@ -714,17 +644,7 @@ codeAllEqualityTerms(Parse * pParse,    /* Parsing 
context */
                  sqlVdbeAddOp2(v, OP_SCopy, r1, regBase + j);
              }
          }
-        if (pTerm->eOperator & WO_IN) {
-            if (pTerm->pExpr->flags & EP_xIsSelect) {
-                /* No type ever needs to be (or should be) applied to a 
value
-                 * from the RHS of an "? IN (SELECT ...)" expression. The
-                 * sqlFindInIndex() routine has already ensured that the
-                 * type of the comparison has been applied to the value.
-                 */
-                if (type != NULL)
-                    type[j] = FIELD_TYPE_SCALAR;
-            }
-        } else if ((pTerm->eOperator & WO_ISNULL) == 0) {
+        if ((pTerm->eOperator & (WO_IN | WO_ISNULL)) == 0) {
              Expr *pRight = pTerm->pExpr->pRight;
              if (sqlExprCanBeNull(pRight)) {
                  sqlVdbeAddOp2(v, OP_IsNull, regBase + j,
@@ -733,7 +653,6 @@ codeAllEqualityTerms(Parse * pParse,    /* Parsing 
context */
              }
          }
      }
-    *res_type = type;
      return regBase;
  }

@@ -904,10 +823,6 @@ sqlWhereCodeOneLoopStart(WhereInfo * pWInfo,    /* 
Complete information about the W
          int iIdxCur;    /* The VDBE cursor for the index */
          int nExtraReg = 0;    /* Number of extra registers needed */
          int op;        /* Instruction opcode */
-        /* Types for start of range constraint. */
-        enum field_type *start_types;
-        /* Types for end of range constraint */
-        enum field_type *end_types = NULL;
          u8 bSeekPastNull = 0;    /* True to seek past initial nulls */
          u8 bStopAtNull = 0;    /* Add condition to terminate at NULLs */
          int force_integer_reg = -1;  /* If non-negative: number of
@@ -994,17 +909,7 @@ sqlWhereCodeOneLoopStart(WhereInfo * pWInfo,    /* 
Complete information about the W
           * and store the values of those terms in an array of registers
           * starting at regBase.
           */
-        regBase =
-            codeAllEqualityTerms(pParse, pLevel, bRev, nExtraReg,
-                     &start_types);
-        if (start_types != NULL && nTop) {
-            uint32_t len = 0;
-            for (enum field_type *tmp = &start_types[nEq];
-                 *tmp != field_type_MAX; tmp++, len++);
-            uint32_t sz = len * sizeof(enum field_type);
-            end_types = sqlDbMallocRaw(db, sz);
-            memcpy(end_types, &start_types[nEq], sz);
-        }
+        regBase = codeAllEqualityTerms(pParse, pLevel, bRev, nExtraReg);
          addrNxt = pLevel->addrNxt;

          testcase(pRangeStart && (pRangeStart->eOperator & WO_LE) != 0);
@@ -1029,10 +934,6 @@ sqlWhereCodeOneLoopStart(WhereInfo * pWInfo,    /* 
Complete information about the W
                  VdbeCoverage(v);
              }

-            if (start_types) {
-                expr_cmp_update_rhs_type(pRight, nBtm,
-                             &start_types[nEq]);
-            }
              nConstraint += nBtm;
              testcase(pRangeStart->wtFlags & TERM_VIRTUAL);
              if (sqlExprIsVector(pRight) == 0) {
@@ -1049,94 +950,6 @@ sqlWhereCodeOneLoopStart(WhereInfo * pWInfo,    /* 
Complete information about the W
          }
          struct index_def *idx_pk = space->index[0]->def;
          uint32_t pk_part_count = idx_pk->key_def->part_count;
-        /*
-         * Tarantool's iterator over integer fields doesn't
-         * tolerate floating point values. Hence, if term
-         * is equality comparison and value of operand is
-         * not integer, we can skip it since it always
-         * results in false: INT a == 0.5 -> false;
-         * It is done using OP_MustBeInt facilities.
-         * In case term is greater comparison (a > ?), we
-         * should notify OP_SeekGT to process truncation of
-         * floating point value: a > 0.5 -> a >= 1;
-         * It is done by setting P5 flag for OP_Seek*.
-         * It is worth mentioning that we do not need
-         * this step when it comes for less (<) comparison
-         * of nullable field. Key is NULL in this case:
-         * values are ordered as  NULL, ... NULL, min_value,
-         * so to fetch min value we pass NULL to GT iterator.
-         * The only exception is less comparison in
-         * conjunction with ORDER BY DESC clause:
-         * in such situation we use LE iterator and
-         * truncated value to compare. But then
-         * pRangeStart == NULL.
-         * This procedure is correct for compound index:
-         * only one comparison of less/greater type can be
-         * used at the same time. For instance,
-         * a < 1.5 AND b > 0.5 is handled by SeekGT using
-         * column a and fetching column b from tuple and
-         * OP_Le comparison.
-         *
-         * Note that OP_ApplyType, which is emitted before
-         * OP_Seek** doesn't truncate floating point to
-         * integer. That's why we need this routine.
-         * Also, note that terms are separated by OR
-         * predicates, so we consider term as sequence
-         * of AND'ed predicates.
-         */
-        size_t addrs_sz;
-        int *seek_addrs = region_alloc_array(&pParse->region,
-                             typeof(seek_addrs[0]), nEq,
-                             &addrs_sz);
-        if (seek_addrs == NULL) {
-            diag_set(OutOfMemory, addrs_sz, "region_alloc_array",
-                 "seek_addrs");
-            pParse->is_aborted = true;
-            return 0;
-        }
-        memset(seek_addrs, 0, addrs_sz);
-        for (int i = 0; i < nEq; i++) {
-            enum field_type type = idx_def->key_def->parts[i].type;
-            if (type == FIELD_TYPE_INTEGER ||
-                type == FIELD_TYPE_UNSIGNED) {
-                /*
-                 * OP_MustBeInt consider NULLs as
-                 * non-integer values, so firstly
-                 * check whether value is NULL or not.
-                 */
-                seek_addrs[i] = sqlVdbeAddOp1(v, OP_IsNull,
-                                  regBase);
-                sqlVdbeAddOp2(v, OP_MustBeInt, regBase + i,
-                          addrNxt);
-                start_types[i] = FIELD_TYPE_SCALAR;
-                /*
-                 * We need to notify column cache
-                 * that type of value may change
-                 * so we should fetch value from
-                 * tuple again rather then copy
-                 * from register.
-                 */
-                sql_expr_type_cache_change(pParse, regBase + i,
-                               1);
-            }
-        }
-        /* Inequality constraint comes always at the end of list. */
-        part_count = idx_def->key_def->part_count;
-        if (pRangeStart != NULL) {
-            /*
-             * nEq == 0 means that filter condition
-             * contains only inequality.
-             */
-            uint32_t ineq_idx = nEq == 0 ? 0 : nEq - 1;
-            assert(ineq_idx < part_count);
-            enum field_type ineq_type =
-                idx_def->key_def->parts[ineq_idx].type;
-            if (ineq_type == FIELD_TYPE_INTEGER ||
-                ineq_type == FIELD_TYPE_UNSIGNED)
-                force_integer_reg = regBase + nEq;
-        }
-        emit_apply_type(pParse, regBase, nConstraint - bSeekPastNull,
-                start_types);
          if (pLoop->nSkip > 0 && nConstraint == pLoop->nSkip) {
              /* The skip-scan logic inside the call to 
codeAllEqualityConstraints()
               * above has already left the cursor sitting on the 
correct row,
@@ -1146,10 +959,6 @@ sqlWhereCodeOneLoopStart(WhereInfo * pWInfo,    /* 
Complete information about the W
              op = aStartOp[(start_constraints << 2) +
                        (startEq << 1) + bRev];
              assert(op != 0);
-            for (uint32_t i = 0; i < nEq; ++i) {
-                if (seek_addrs[i] != 0)
-                    sqlVdbeJumpHere(v, seek_addrs[i]);
-            }
              sqlVdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase,
                           nConstraint);
              /* If this is Seek* opcode, and IPK is detected in the
@@ -1189,13 +998,6 @@ sqlWhereCodeOneLoopStart(WhereInfo * pWInfo,    /* 
Complete information about the W
                            addrNxt);
                  VdbeCoverage(v);
              }
-            if (end_types) {
-                expr_cmp_update_rhs_type(pRight, nTop, end_types);
-                emit_apply_type(pParse, regBase + nEq, nTop,
-                        end_types);
-            } else {
-                assert(pParse->db->mallocFailed);
-            }
              nConstraint += nTop;
              testcase(pRangeEnd->wtFlags & TERM_VIRTUAL);

@@ -1209,8 +1011,6 @@ sqlWhereCodeOneLoopStart(WhereInfo * pWInfo,    /* 
Complete information about the W
              endEq = 0;
              nConstraint++;
          }
-        sqlDbFree(db, start_types);
-        sqlDbFree(db, end_types);

          /* Top of the loop body */
          pLevel->p2 = sqlVdbeCurrentAddr(v);
diff --git a/test/sql-tap/gh-4230-del-impl-cast-str-to-num.test.lua 
b/test/sql-tap/gh-4230-del-impl-cast-str-to-num.test.lua
new file mode 100755
index 000000000..ef4127e0e
--- /dev/null
+++ b/test/sql-tap/gh-4230-del-impl-cast-str-to-num.test.lua
@@ -0,0 +1,78 @@
+#!/usr/bin/env tarantool
+test = require("sqltester")
+test:plan(8)
+
+--
+-- Make sure that there is no implicit cast between string and
+-- number.
+--
+test:do_catchsql_test(
+    "gh-4230-1",
+    [[
+        SELECT '1' > 0;
+    ]], {
+        1, "Type mismatch: can not convert 1 to numeric"
+    })
+
+test:do_catchsql_test(
+    "gh-4230-2",
+    [[
+        SELECT 0 > '1';
+    ]], {
+        1, "Type mismatch: can not convert 1 to numeric"
+    })
+
+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:finish_test()
diff --git a/test/sql-tap/identifier_case.test.lua 
b/test/sql-tap/identifier_case.test.lua
index 2a00626fc..1d56ffb44 100755
--- a/test/sql-tap/identifier_case.test.lua
+++ b/test/sql-tap/identifier_case.test.lua
@@ -242,11 +242,11 @@ data = {
      { 2,  [[ 'a' < 'b' collate "binary" ]], {0, {true}}},
      { 3,  [[ 'a' < 'b' collate 'binary' ]], {1, [[Syntax error at line 
1 near ''binary'']]}},
      { 4,  [[ 'a' < 'b' collate "unicode" ]], {0, {true}}},
-    { 5,  [[ 5 < 'b' collate "unicode" ]], {0, {true}}},
+    { 5,  [[ 5 < 'b' collate "unicode" ]], {1, "Type mismatch: can not 
convert b to numeric"}},
      { 6,  [[ 5 < 'b' collate unicode ]], {1,"Collation 'UNICODE' does 
not exist"}},
-    { 7,  [[ 5 < 'b' collate "unicode_ci" ]], {0, {true}}},
+    { 7,  [[ 5 < 'b' collate "unicode_ci" ]], {1, "Type mismatch: can 
not convert b to numeric"}},
      { 8,  [[ 5 < 'b' collate NONE ]], {1, "Collation 'NONE' does not 
exist"}},
-    { 9,  [[ 5 < 'b' collate "none" ]], {0, {true}}},
+    { 9,  [[ 5 < 'b' collate "none" ]], {1, "Type mismatch: can not 
convert b to numeric"}},
  }

  for _, row in ipairs(data) do
diff --git a/test/sql-tap/in1.test.lua b/test/sql-tap/in1.test.lua
index 570cc1779..e2f498889 100755
--- a/test/sql-tap/in1.test.lua
+++ b/test/sql-tap/in1.test.lua
@@ -637,12 +637,12 @@ test:do_test(
      "in-11.2",
      function()
          -- The '2' should be coerced into 2 because t6.b is NUMERIC
-        return test:execsql [[
+        return test:catchsql [[
              SELECT * FROM t6 WHERE b IN ('2');
          ]]
      end, {
          -- <in-11.2>
-        1, 2
+        1, "Type mismatch: can not convert 2 to numeric"
          -- </in-11.2>
      })

diff --git a/test/sql-tap/in4.test.lua b/test/sql-tap/in4.test.lua
index 33947d0ab..a494e846f 100755
--- a/test/sql-tap/in4.test.lua
+++ b/test/sql-tap/in4.test.lua
@@ -147,12 +147,13 @@ test:do_execsql_test(
          -- </in4-2.7>
      })

-test:do_execsql_test(
+test:do_catchsql_test(
      "in4-2.8",
      [[
          SELECT b FROM t2 WHERE a IN ('', '0.0.0', '2')
      ]], {
          -- <in4-2.8>
+        1, "Type mismatch: can not convert integer to text"
          -- </in4-2.8>
      })

diff --git a/test/sql-tap/insert3.test.lua b/test/sql-tap/insert3.test.lua
index b92bc508e..3276f0db2 100755
--- a/test/sql-tap/insert3.test.lua
+++ b/test/sql-tap/insert3.test.lua
@@ -59,7 +59,7 @@ test:do_execsql_test(
      [[
              CREATE TABLE log2(rowid INTEGER PRIMARY KEY AUTOINCREMENT, 
x TEXT UNIQUE,y INT );
              CREATE TRIGGER r2 BEFORE INSERT ON t1 FOR EACH ROW BEGIN
-              UPDATE log2 SET y=y+1 WHERE x=new.b;
+              UPDATE log2 SET y=y+1 WHERE x=CAST(new.b AS STRING);
                INSERT OR IGNORE INTO log2(x, y) VALUES(CAST(new.b AS 
STRING),1);
              END;
              INSERT INTO t1(a, b) VALUES('hi', 453);
diff --git a/test/sql-tap/intpkey.test.lua b/test/sql-tap/intpkey.test.lua
index 0db18ba91..bc3d701a7 100755
--- a/test/sql-tap/intpkey.test.lua
+++ b/test/sql-tap/intpkey.test.lua
@@ -1,6 +1,6 @@
  #!/usr/bin/env tarantool
  test = require("sqltester")
-test:plan(40)
+test:plan(39)

  --!./tcltestrunner.lua
  -- 2001 September 15
@@ -854,43 +854,33 @@ test:do_execsql_test(
          -- </intpkey-14.2>
      })

-test:do_execsql_test(
-    "intpkey-14.3",
-    [[
-        SELECT * FROM t3 WHERE a>'2';
-    ]], {
-        -- <intpkey-14.3>
-        3, 3, "3"
-        -- </intpkey-14.3>
-    })
-
-test:do_execsql_test(
+test:do_catchsql_test(
      "intpkey-14.4",
      [[
          SELECT * FROM t3 WHERE a<'2';
      ]], {
          -- <intpkey-14.4>
-        1, 1, "one"
+        1, "Type mismatch: can not convert text to integer"
          -- </intpkey-14.4>
      })

-test:do_execsql_test(
+test:do_catchsql_test(
      "intpkey-14.5",
      [[
          SELECT * FROM t3 WHERE a<c;
      ]], {
          -- <intpkey-14.5>
-        1, 1, "one"
+        1, "Type mismatch: can not convert one to numeric"
          -- </intpkey-14.5>
      })

-test:do_execsql_test(
+test:do_catchsql_test(
      "intpkey-14.6",
      [[
          SELECT * FROM t3 WHERE a=c;
      ]], {
          -- <intpkey-14.6>
-        2, 2, "2", 3, 3, "3"
+        1, "Type mismatch: can not convert one to numeric"
          -- </intpkey-14.6>
      })

diff --git a/test/sql-tap/join.test.lua b/test/sql-tap/join.test.lua
index 51e0ecb79..792302ab5 100755
--- a/test/sql-tap/join.test.lua
+++ b/test/sql-tap/join.test.lua
@@ -1028,22 +1028,23 @@ test:do_test(
          -- </join-11.8>
      })

-test:do_execsql_test(
+test:do_catchsql_test(
      "join-11.9",
      [[
          SELECT * FROM t1 NATURAL JOIN t2
      ]], {
          -- <join-11.9>
+        1, "Type mismatch: can not convert integer to text"
          -- </join-11.9>
      })

-test:do_execsql_test(
+test:do_catchsql_test(
      "join-11.10",
      [[
          SELECT * FROM t2 NATURAL JOIN t1
      ]], {
          -- <join-11.10>
-        1, "one", 2, "two"
+        1, "Type mismatch: can not convert 1 to numeric"
          -- </join-11.10>
      })

diff --git a/test/sql-tap/misc1.test.lua b/test/sql-tap/misc1.test.lua
index e0fe50bbe..3cef617f4 100755
--- a/test/sql-tap/misc1.test.lua
+++ b/test/sql-tap/misc1.test.lua
@@ -88,7 +88,7 @@ test:do_execsql_test(
  test:do_execsql_test(
      "misc1-1.4",
      [[
-        SELECT x75 FROM manycol WHERE x50=350
+        SELECT x75 FROM manycol WHERE x50='350'
      ]], {
          -- <misc1-1.4>
          "375"
@@ -98,7 +98,7 @@ test:do_execsql_test(
  test:do_execsql_test(
      "misc1-1.5",
      [[
-        SELECT x50 FROM manycol WHERE x99=599
+        SELECT x50 FROM manycol WHERE x99='599'
      ]], {
          -- <misc1-1.5>
          "550"
@@ -109,7 +109,7 @@ test:do_test(
      "misc1-1.6",
      function()
          test:execsql("CREATE INDEX manycol_idx1 ON manycol(x99)")
-        return test:execsql("SELECT x50 FROM manycol WHERE x99=899")
+        return test:execsql("SELECT x50 FROM manycol WHERE x99='899'")
      end, {
          -- <misc1-1.6>
          "850"
@@ -129,7 +129,7 @@ test:do_execsql_test(
  test:do_test(
      "misc1-1.8",
      function()
-        test:execsql("DELETE FROM manycol WHERE x98=1234")
+        test:execsql("DELETE FROM manycol WHERE x98='1234'")
          return test:execsql("SELECT count(*) FROM manycol")
      end, {
          -- <misc1-1.8>
@@ -140,7 +140,7 @@ test:do_test(
  test:do_test(
      "misc1-1.9",
      function()
-        test:execsql("DELETE FROM manycol WHERE x98=998")
+        test:execsql("DELETE FROM manycol WHERE x98='998'")
          return test:execsql("SELECT count(*) FROM manycol")
      end, {
          -- <misc1-1.9>
@@ -151,7 +151,7 @@ test:do_test(
  test:do_test(
      "misc1-1.10",
      function()
-        test:execsql("DELETE FROM manycol WHERE x99=500")
+        test:execsql("DELETE FROM manycol WHERE x99='500'")
          return test:execsql("SELECT count(*) FROM manycol")
      end, {
          -- <misc1-1.10>
@@ -162,7 +162,7 @@ test:do_test(
  test:do_test(
      "misc1-1.11",
      function()
-        test:execsql("DELETE FROM manycol WHERE x99=599")
+        test:execsql("DELETE FROM manycol WHERE x99='599'")
          return test:execsql("SELECT count(*) FROM manycol")
      end, {
          -- <misc1-1.11>
@@ -479,9 +479,9 @@ local where = ""
  test:do_test(
      "misc1-10.1",
      function()
-        where = "WHERE x0>=0"
+        where = "WHERE x0>='0'"
          for i = 1, 99, 1 do
-            where = where .. " AND x"..i.."<>0"
+            where = where .. " AND x"..i.."<>'0'"
          end
          return test:catchsql("SELECT count(*) FROM manycol "..where.."")
      end, {
@@ -496,7 +496,7 @@ test:do_test(
  test:do_test(
      "misc1-10.3",
      function()
-        where = string.gsub(where,"x0>=0", "x0=0")
+        where = string.gsub(where,"x0>='0'", "x0='0'")
          return test:catchsql("DELETE FROM manycol "..where.."")
      end, {
          -- <misc1-10.3>
@@ -520,7 +520,7 @@ test:do_execsql_test(
  test:do_execsql_test(
      "misc1-10.6",
      [[
-        SELECT x1 FROM manycol WHERE x0=100
+        SELECT x1 FROM manycol WHERE x0='100'
      ]], {
          -- <misc1-10.6>
          "101"
@@ -530,7 +530,7 @@ test:do_execsql_test(
  test:do_test(
      "misc1-10.7",
      function()
-        where = string.gsub(where, "x0=0", "x0=100")
+        where = string.gsub(where, "x0='0'", "x0='100'")
          return test:catchsql("UPDATE manycol SET x1=CAST(x1+1 AS 
STRING) "..where.."")
      end, {
          -- <misc1-10.7>
@@ -541,7 +541,7 @@ test:do_test(
  test:do_execsql_test(
      "misc1-10.8",
      [[
-        SELECT x1 FROM manycol WHERE x0=100
+        SELECT x1 FROM manycol WHERE x0='100'
      ]], {
          -- <misc1-10.8>
          "102"
@@ -563,7 +563,7 @@ test:do_execsql_test(
  test:do_execsql_test(
      "misc1-10.10",
      [[
-        SELECT x1 FROM manycol WHERE x0=100
+        SELECT x1 FROM manycol WHERE x0='100'
      ]], {
          -- <misc1-10.10>
          "103"
@@ -619,13 +619,13 @@ test:do_execsql_test(
          -- </misc1-12.1>
      })

-test:do_execsql_test(
+test:do_catchsql_test(
      "misc1-12.2",
      [[
          SELECT '0'==0.0
      ]], {
          -- <misc1-12.2>
-        true
+        1, "Type mismatch: can not convert 0 to numeric"
          -- </misc1-12.2>
      })

diff --git a/test/sql-tap/select1.test.lua b/test/sql-tap/select1.test.lua
index 9a969bf3c..f5a9b63fe 100755
--- a/test/sql-tap/select1.test.lua
+++ b/test/sql-tap/select1.test.lua
@@ -1912,7 +1912,7 @@ test:do_execsql_test(
  test:do_execsql_test(
          "select1-12.7",
          [[
-            SELECT * FROM t3 WHERE a=(SELECT 1);
+            SELECT * FROM t3 WHERE a=(SELECT '1');
          ]], {
              -- <select1-12.7>
              0, "1", "2"
@@ -1922,7 +1922,7 @@ test:do_execsql_test(
  test:do_execsql_test(
      "select1-12.8",
      [[
-        SELECT * FROM t3 WHERE a=(SELECT 2);
+        SELECT * FROM t3 WHERE a=(SELECT '2');
      ]], {
          -- <select1-12.8>

diff --git a/test/sql-tap/select7.test.lua b/test/sql-tap/select7.test.lua
index e1e43c557..0d1390fd6 100755
--- a/test/sql-tap/select7.test.lua
+++ b/test/sql-tap/select7.test.lua
@@ -256,7 +256,7 @@ test:do_execsql_test(
          DROP TABLE IF EXISTS t5;
          CREATE TABLE t5(a TEXT primary key, b INT);
          INSERT INTO t5 VALUES('123', 456);
-        SELECT typeof(a), a FROM t5 GROUP BY a HAVING a<b;
+        SELECT typeof(a), a FROM t5 GROUP BY a HAVING CAST(a AS INTEGER)<b;
      ]], {
          -- <select7-7.7>
          "string", "123"
diff --git a/test/sql-tap/subquery.test.lua b/test/sql-tap/subquery.test.lua
index e0771825e..bad702de9 100755
--- a/test/sql-tap/subquery.test.lua
+++ b/test/sql-tap/subquery.test.lua
@@ -284,13 +284,13 @@ test:do_execsql_test(
          -- </subquery-2.3.1>
      })

-test:do_execsql_test(
+test:do_catchsql_test(
      "subquery-2.3.2",
      [[
          SELECT a IN (10.0, 20) FROM t3;
      ]], {
          -- <subquery-2.3.2>
-        false
+        1, "Type mismatch: can not convert text to real"
          -- </subquery-2.3.2>
      })

diff --git a/test/sql-tap/tkt-9a8b09f8e6.test.lua 
b/test/sql-tap/tkt-9a8b09f8e6.test.lua
index 854ed774f..083a87b45 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
@@ -86,7 +86,7 @@ test:do_execsql_test(
  test:do_execsql_test(
      2.1,
      [[
-        SELECT x FROM t1 WHERE x IN (1);
+        SELECT x FROM t1 WHERE CAST(x AS INTEGER) IN (1);
      ]], {
          -- <2.1>
          "1"
@@ -96,7 +96,7 @@ test:do_execsql_test(
  test:do_execsql_test(
      2.2,
      [[
-        SELECT x FROM t1 WHERE x IN (1.0);
+        SELECT x FROM t1 WHERE CAST(x AS DOUBLE) IN (1);
      ]], {
          -- <2.2>
          "1"
@@ -126,7 +126,7 @@ test:do_execsql_test(
  test:do_execsql_test(
      2.5,
      [[
-        SELECT x FROM t1 WHERE 1 IN (x);
+        SELECT x FROM t1 WHERE CAST(1 AS STRING) IN (x);
      ]], {
          -- <2.5>
          "1"
@@ -136,10 +136,9 @@ test:do_execsql_test(
  test:do_execsql_test(
      2.6,
      [[
-        SELECT x FROM t1 WHERE 1.0 IN (x);
+        SELECT x FROM t1 WHERE CAST(1.0 AS STRING) IN (x);
      ]], {
          -- <2.6>
-        "1"
          -- </2.6>
      })

@@ -186,21 +185,13 @@ test:do_execsql_test(
  test:do_execsql_test(
      3.3,
      [[
-        SELECT x FROM t2 WHERE x IN ('1');
+        SELECT x FROM t2 WHERE CAST(x AS STRING) IN ('1');
      ]], {
          -- <3.3>
+        1
          -- </3.3>
      })

-test:do_execsql_test(
-    3.4,
-    [[
-        SELECT x FROM t2 WHERE x IN ('1');
-    ]], {
-        -- <3.4>
-        -- </3.4>
-    })
-
  test:do_execsql_test(
      3.5,
      [[
@@ -224,21 +215,13 @@ test:do_execsql_test(
  test:do_execsql_test(
      3.7,
      [[
-        SELECT x FROM t2 WHERE '1' IN (x);
+        SELECT x FROM t2 WHERE CAST('1' AS INTEGER) IN (x);
      ]], {
          -- <3.7>
+        1
          -- </3.7>
      })

-test:do_execsql_test(
-    3.8,
-    [[
-        SELECT x FROM t2 WHERE '1' IN (x);
-    ]], {
-        -- <3.8>
-        -- </3.8>
-    })
-
  test:do_execsql_test(
      4.1,
      [[
@@ -262,17 +245,16 @@ test:do_execsql_test(
  test:do_execsql_test(
      4.3,
      [[
-        SELECT x FROM t3 WHERE x IN ('1');
+        SELECT x FROM t3 WHERE CAST(x AS STRING) IN ('1');
      ]], {
          -- <4.3>
-        1.0
          -- </4.3>
      })

  test:do_execsql_test(
      4.4,
      [[
-        SELECT x FROM t3 WHERE x IN ('1.0');
+        SELECT x FROM t3 WHERE CAST(x AS STRING) IN ('1.0');
      ]], {
          -- <4.4>
          1.0
@@ -302,20 +284,20 @@ test:do_execsql_test(
  test:do_execsql_test(
      4.7,
      [[
-        SELECT x FROM t3 WHERE '1' IN (x);
+        SELECT x FROM t3 WHERE CAST('1' AS DOUBLE) IN (x);
      ]], {
          -- <4.7>
-        1
+        1.0
          -- </4.7>
      })

  test:do_execsql_test(
      4.8,
      [[
-        SELECT x FROM t3 WHERE '1.0' IN (x);
+        SELECT x FROM t3 WHERE CAST('1.0' AS DOUBLE) IN (x);
      ]], {
          -- <4.8>
-        1
+        1.0
          -- </4.8>
      })

@@ -342,20 +324,20 @@ test:do_execsql_test(
  test:do_execsql_test(
      5.3,
      [[
-        SELECT x FROM t4 WHERE x IN ('1');
+        SELECT x FROM t4 WHERE CAST(x AS STRING) IN ('1');
      ]], {
          -- <5.3>
-
+
          -- </5.3>
      })

  test:do_execsql_test(
      5.4,
      [[
-        SELECT x FROM t4 WHERE x IN ('1.0');
+        SELECT x FROM t4 WHERE CAST(x AS STRING) IN ('1.0');
      ]], {
          -- <5.4>
-
+
          -- </5.4>
      })

@@ -372,7 +354,7 @@ test:do_execsql_test(
  test:do_execsql_test(
      5.6,
      [[
-        SELECT x FROM t4 WHERE x IN ('1.11');
+        SELECT x FROM t4 WHERE CAST(x AS STRING) IN ('1.11');
      ]], {
          -- <5.6>
          1.11
@@ -402,20 +384,20 @@ test:do_execsql_test(
  test:do_execsql_test(
      5.9,
      [[
-        SELECT x FROM t4 WHERE '1' IN (x);
+        SELECT x FROM t4 WHERE CAST('1' AS DOUBLE) IN (x);
      ]], {
          -- <5.9>
-
+
          -- </5.9>
      })

  test:do_execsql_test(
      5.10,
      [[
-        SELECT x FROM t4 WHERE '1.0' IN (x);
+        SELECT x FROM t4 WHERE CAST('1.0' AS DOUBLE) IN (x);
      ]], {
          -- <5.10>
-
+
          -- </5.10>
      })

@@ -432,7 +414,7 @@ test:do_execsql_test(
  test:do_execsql_test(
      5.12,
      [[
-        SELECT x FROM t4 WHERE '1.11' IN (x);
+        SELECT x FROM t4 WHERE CAST('1.11' AS DOUBLE) IN (x);
      ]], {
          -- <5.12>
          1.11
@@ -462,7 +444,7 @@ test:do_execsql_test(
  test:do_execsql_test(
      6.3,
      [[
-        SELECT x, y FROM t5 WHERE x IN ('1');
+        SELECT x, y FROM t5 WHERE CAST(x AS STRING) IN ('1');
      ]], {
          -- <6.3>
          1, "one", 1, "two", 1, "three", 1.0, "four"
@@ -472,10 +454,10 @@ test:do_execsql_test(
  test:do_execsql_test(
      6.4,
      [[
-        SELECT x, y FROM t5 WHERE x IN ('1.0');
+        SELECT x, y FROM t5 WHERE CAST(x AS STRING) IN ('1.0');
      ]], {
          -- <6.4>
-        1, "one", 1, "two", 1, "three", 1.0, "four"
+
          -- </6.4>
      })

@@ -502,7 +484,7 @@ test:do_execsql_test(
  test:do_execsql_test(
      6.7,
      [[
-        SELECT x, y FROM t5 WHERE '1' IN (x);
+        SELECT x, y FROM t5 WHERE CAST('1' AS INTEGER) IN (x);
      ]], {
          -- <6.7>
          1, "one", 1, "two", 1, "three", 1.0, "four"
@@ -512,7 +494,7 @@ test:do_execsql_test(
  test:do_execsql_test(
      6.8,
      [[
-        SELECT x, y FROM t5 WHERE '1.0' IN (x);
+        SELECT x, y FROM t5 WHERE CAST('1.0' AS DOUBLE) IN (x);
      ]], {
          -- <6.8>
          1, "one", 1, "two", 1, "three", 1, "four"
diff --git a/test/sql-tap/tkt-f973c7ac31.test.lua 
b/test/sql-tap/tkt-f973c7ac31.test.lua
index 82bdb52f8..604a7e6bb 100755
--- a/test/sql-tap/tkt-f973c7ac31.test.lua
+++ b/test/sql-tap/tkt-f973c7ac31.test.lua
@@ -39,9 +39,8 @@ for tn, sql in ipairs(sqls) do
      test:do_execsql_test(
          "tkt-f973c7ac3-1."..tn..".1",
          [[
-            SELECT c1,c2 FROM t WHERE c1 = 5 AND c2>0 AND c2<='2' ORDER 
BY c2 DESC
+            SELECT c1,c2 FROM t WHERE c1 = 5 AND c2>0 AND CAST(c2 AS 
STRING)<='2' ORDER BY c2 DESC
          ]], {
-
          })

      test:do_execsql_test(
@@ -55,7 +54,7 @@ for tn, sql in ipairs(sqls) do
      test:do_execsql_test(
          "tkt-f973c7ac3-1."..tn..".3",
          [[
-            SELECT c1,c2 FROM t WHERE c1 = 5 AND c2>0 AND c2<='5' ORDER 
BY c2 DESC
+            SELECT c1,c2 FROM t WHERE c1 = 5 AND c2>0 AND CAST(c2 AS 
STRING)<='5' ORDER BY c2 DESC
          ]], {
              5, 5, 5, 4
          })
@@ -63,7 +62,7 @@ for tn, sql in ipairs(sqls) do
      test:do_execsql_test(
          "tkt-f973c7ac3-1."..tn..".4",
          [[
-            SELECT c1,c2 FROM t WHERE c1 = 5 AND c2>'0' AND c2<=5 ORDER 
BY c2 DESC
+            SELECT c1,c2 FROM t WHERE c1 = 5 AND CAST(c2 AS STRING)>'0' 
AND c2<=5 ORDER BY c2 DESC
          ]], {
              5, 5, 5, 4
          })
@@ -71,7 +70,7 @@ for tn, sql in ipairs(sqls) do
      test:do_execsql_test(
          "tkt-f973c7ac3-1."..tn..".5",
          [[
-            SELECT c1,c2 FROM t WHERE c1 = 5 AND c2>'0' AND c2<='5' 
ORDER BY c2 DESC
+            SELECT c1,c2 FROM t WHERE c1 = 5 AND CAST(c2 AS STRING)>'0' 
AND CAST(c2 AS STRING)<='5' ORDER BY c2 DESC
          ]], {
              5, 5, 5, 4
          })
@@ -79,9 +78,8 @@ for tn, sql in ipairs(sqls) do
      test:do_execsql_test(
          "tkt-f973c7ac3-1."..tn..".6",
          [[
-            SELECT c1,c2 FROM t WHERE c1 = 5 AND c2>0 AND c2<='2' ORDER 
BY c2 ASC
+            SELECT c1,c2 FROM t WHERE c1 = 5 AND c2>0 AND CAST(c2 AS 
STRING)<='2' ORDER BY c2 ASC
          ]], {
-
          })

      test:do_execsql_test(
@@ -95,7 +93,7 @@ for tn, sql in ipairs(sqls) do
      test:do_execsql_test(
          "tkt-f973c7ac3-1."..tn..".8",
          [[
-            SELECT c1,c2 FROM t WHERE c1 = 5 AND c2>0 AND c2<='5' ORDER 
BY c2 ASC
+            SELECT c1,c2 FROM t WHERE c1 = 5 AND c2>0 AND CAST(c2 AS 
STRING)<='5' ORDER BY c2 ASC
          ]], {
              5, 4, 5, 5
          })
@@ -103,7 +101,7 @@ for tn, sql in ipairs(sqls) do
      test:do_execsql_test(
          "tkt-f973c7ac3-1."..tn..".9",
          [[
-            SELECT c1,c2 FROM t WHERE c1 = 5 AND c2>'0' AND c2<=5 ORDER 
BY c2 ASC
+            SELECT c1,c2 FROM t WHERE c1 = 5 AND CAST(c2 AS STRING)>'0' 
AND c2<=5 ORDER BY c2 ASC
          ]], {
              5, 4, 5, 5
          })
@@ -111,7 +109,7 @@ for tn, sql in ipairs(sqls) do
      test:do_execsql_test(
          "tkt-f973c7ac3-1."..tn..".10",
          [[
-            SELECT c1,c2 FROM t WHERE c1 = 5 AND c2>'0' AND c2<='5' 
ORDER BY c2 ASC
+            SELECT c1,c2 FROM t WHERE c1 = 5 AND CAST(c2 AS STRING)>'0' 
AND CAST(c2 AS STRING)<='5' ORDER BY c2 ASC
          ]], {
              5, 4, 5, 5
          })
diff --git a/test/sql-tap/tkt3493.test.lua b/test/sql-tap/tkt3493.test.lua
index de77e61e9..82ba828d0 100755
--- a/test/sql-tap/tkt3493.test.lua
+++ b/test/sql-tap/tkt3493.test.lua
@@ -1,6 +1,6 @@
  #!/usr/bin/env tarantool
  test = require("sqltester")
-test:plan(26)
+test:plan(25)

  --!./tcltestrunner.lua
  -- 2008 October 13
@@ -45,7 +45,7 @@ test:do_execsql_test(
      [[
          SELECT
            CASE
-             WHEN B.val = 1 THEN 'XYZ'
+             WHEN B.val = '1' THEN 'XYZ'
               ELSE A.val
            END AS Col1
          FROM B
@@ -63,7 +63,7 @@ test:do_execsql_test(
      [[
          SELECT DISTINCT
            CASE
-             WHEN B.val = 1 THEN 'XYZ'
+             WHEN B.val = '1' THEN 'XYZ'
               ELSE A.val
            END AS Col1
          FROM B
@@ -79,7 +79,7 @@ test:do_execsql_test(
  test:do_execsql_test(
      "tkt3493-1.4",
      [[
-        SELECT b.val, CASE WHEN b.val = 1 THEN 'xyz' ELSE b.val END AS 
col1 FROM b;
+        SELECT b.val, CASE WHEN b.val = '1' THEN 'xyz' ELSE b.val END 
AS col1 FROM b;
      ]], {
          -- <tkt3493-1.4>
          "1", "xyz", "2", "2"
@@ -91,7 +91,7 @@ test:do_execsql_test(
      [[
          SELECT DISTINCT
            b.val,
-          CASE WHEN b.val = 1 THEN 'xyz' ELSE b.val END AS col1
+          CASE WHEN b.val = '1' THEN 'xyz' ELSE b.val END AS col1
          FROM b;
      ]], {
          -- <tkt3493-1.5>
@@ -126,23 +126,13 @@ test:do_execsql_test(
  test:do_execsql_test(
      "tkt3493-2.2.1",
      [[
-        SELECT a=123 FROM t1 GROUP BY a
+        SELECT a='123' FROM t1 GROUP BY a
      ]], {
          -- <tkt3493-2.2.1>
          true
          -- </tkt3493-2.2.1>
      })

-test:do_execsql_test(
-    "tkt3493-2.2.2",
-    [[
-        SELECT a=123 FROM t1
-    ]], {
-        -- <tkt3493-2.2.2>
-        true
-        -- </tkt3493-2.2.2>
-    })
-
  test:do_execsql_test(
      "tkt3493-2.2.3",
      [[
@@ -156,7 +146,7 @@ test:do_execsql_test(
  test:do_execsql_test(
      "tkt3493-2.2.4",
      [[
-        SELECT count(*), a=123 FROM t1
+        SELECT count(*), a='123' FROM t1
      ]], {
          -- <tkt3493-2.2.4>
          1, true
@@ -166,7 +156,7 @@ test:do_execsql_test(
  test:do_execsql_test(
      "tkt3493-2.2.5",
      [[
-        SELECT count(*), +a=123 FROM t1
+        SELECT count(*), +a='123' FROM t1
      ]], {
          -- <tkt3493-2.2.5>
          1, true
@@ -176,7 +166,7 @@ test:do_execsql_test(
  test:do_execsql_test(
      "tkt3493-2.3.3",
      [[
-        SELECT b='456' FROM t1 GROUP BY a
+        SELECT b = 456 FROM t1 GROUP BY a
      ]], {
          -- <tkt3493-2.3.3>
          true
@@ -186,7 +176,7 @@ test:do_execsql_test(
  test:do_execsql_test(
      "tkt3493-2.3.1",
      [[
-        SELECT b='456' FROM t1 GROUP BY b
+        SELECT b = 456 FROM t1 GROUP BY b
      ]], {
          -- <tkt3493-2.3.1>
          true
@@ -196,7 +186,7 @@ test:do_execsql_test(
  test:do_execsql_test(
      "tkt3493-2.3.2",
      [[
-        SELECT b='456' FROM t1
+        SELECT b = 456 FROM t1
      ]], {
          -- <tkt3493-2.3.2>
          true
@@ -206,7 +196,7 @@ test:do_execsql_test(
  test:do_execsql_test(
      "tkt3493-2.4.1",
      [[
-        SELECT typeof(a), a FROM t1 GROUP BY a HAVING a=123
+        SELECT typeof(a), a FROM t1 GROUP BY a HAVING a='123'
      ]], {
          -- <tkt3493-2.4.1>
          "string", "123"
@@ -216,7 +206,7 @@ test:do_execsql_test(
  test:do_execsql_test(
      "tkt3493-2.4.2",
      [[
-        SELECT typeof(a), a FROM t1 GROUP BY b HAVING a=123
+        SELECT typeof(a), a FROM t1 GROUP BY b HAVING a='123'
      ]], {
          -- <tkt3493-2.4.2>
          "string", "123"
@@ -226,7 +216,7 @@ test:do_execsql_test(
  test:do_execsql_test(
      "tkt3493-2.5.1",
      [[
-        SELECT typeof(b), b FROM t1 GROUP BY a HAVING b='456'
+        SELECT typeof(b), b FROM t1 GROUP BY a HAVING b=456
      ]], {
          -- <tkt3493-2.5.1>
          "integer", 456
@@ -236,7 +226,7 @@ test:do_execsql_test(
  test:do_execsql_test(
      "tkt3493-2.5.2",
      [[
-        SELECT typeof(b), b FROM t1 GROUP BY b HAVING b='456'
+        SELECT typeof(b), b FROM t1 GROUP BY b HAVING b=456
      ]], {
          -- <tkt3493-2.5.2>
          "integer", 456
diff --git a/test/sql-tap/transitive1.test.lua 
b/test/sql-tap/transitive1.test.lua
index 96895b4a7..cc7e066bf 100755
--- a/test/sql-tap/transitive1.test.lua
+++ b/test/sql-tap/transitive1.test.lua
@@ -63,7 +63,7 @@ test:do_execsql_test(
          INSERT INTO t2 VALUES(2, 20,20,'20');
          INSERT INTO t2 VALUES(3, 3,3,'3');

-        SELECT a,b,c FROM t2 WHERE a=b AND c=b AND c=20;
+        SELECT a,b,c FROM t2 WHERE a=b AND c=CAST(b AS STRING) AND c='20';
      ]], {
          -- <transitive1-200>
          20, 20, "20"
@@ -73,7 +73,7 @@ test:do_execsql_test(
  test:do_execsql_test(
      "transitive1-210",
      [[
-        SELECT a,b,c FROM t2 WHERE a=b AND c=b AND c>='20' ORDER BY +a;
+        SELECT a,b,c FROM t2 WHERE a=b AND c=CAST(b AS STRING) AND 
c>='20' ORDER BY +a;
      ]], {
          -- <transitive1-210>
          3, 3, "3", 20, 20, "20"
@@ -83,7 +83,7 @@ test:do_execsql_test(
  test:do_execsql_test(
      "transitive1-220",
      [[
-        SELECT a,b,c FROM t2 WHERE a=b AND c=b AND c<='20' ORDER BY +a;
+        SELECT a,b,c FROM t2 WHERE a=b AND c=CAST(b AS STRING) AND 
c<='20' ORDER BY +a;
      ]], {
          -- <transitive1-220>
          20, 20, "20", 100, 100, "100"
@@ -402,7 +402,7 @@ test:do_execsql_test(
      [[
          CREATE TABLE x(i INTEGER PRIMARY KEY, y TEXT);
          INSERT INTO x VALUES(10, '10');
-        SELECT * FROM x WHERE x.y>='1' AND x.y<'2' AND x.i=x.y;
+        SELECT * FROM x WHERE x.y>='1' AND x.y<'2' AND CAST(x.i AS 
STRING)=x.y;
      ]], {
          -- <transitive1-500>
          10, "10"
@@ -430,7 +430,7 @@ test:do_execsql_test(
      [[
          CREATE TABLE t3(i INTEGER PRIMARY KEY, t TEXT);
          INSERT INTO t3 VALUES(10, '10');
-        SELECT * FROM t3 WHERE i=t AND t = '10 ';
+        SELECT * FROM t3 WHERE CAST(i AS STRING)=t AND t = '10 ';
      ]], {
          -- <transitive1-520>

@@ -443,7 +443,7 @@ test:do_execsql_test(
          CREATE TABLE u1(x TEXT PRIMARY KEY, y INTEGER, z TEXT);
          CREATE INDEX i1 ON u1(x);
          INSERT INTO u1 VALUES('00013', 13, '013');
-        SELECT * FROM u1 WHERE x=y AND y=z AND z='013';
+        SELECT * FROM u1 WHERE CAST(x AS INTEGER)=y AND y=CAST(z AS 
INTEGER) AND z='013';
      ]], {
          -- <transitive1-530>
          "00013",13,"013"
diff --git a/test/sql-tap/where2.test.lua b/test/sql-tap/where2.test.lua
index f267be8e6..7348a855a 100755
--- a/test/sql-tap/where2.test.lua
+++ b/test/sql-tap/where2.test.lua
@@ -4,7 +4,7 @@ yaml = require("yaml")
  fio = require("fio")

  ffi = require("ffi")
-test:plan(74)
+test:plan(62)

  ffi.cdef[[
         int dup(int oldfd);
@@ -622,181 +622,12 @@ test:do_test(
          -- </where2-6.6>
      })

--- if X(356, "X!cmd", [=[["expr","[permutation] != 
\"no_optimization\""]]=])
--- then
-    -- Ticket #2249.  Make sure the OR optimization is not attempted if
-    -- comparisons between columns of different affinities are needed.
-    --
-    test:do_test(
-        "where2-6.7",
-        function()
-            test:execsql [[
-                CREATE TABLE t2249a(a TEXT PRIMARY KEY, x VARCHAR(100));
-                CREATE TABLE t2249b(b INTEGER PRIMARY KEY);
-                INSERT INTO t2249a(a) VALUES('0123');
-                INSERT INTO t2249b VALUES(123);
-            ]]
-            return queryplan([[
-    -- Because a is type TEXT and b is type INTEGER, both a and b
-    -- will attempt to convert to NUMERIC before the comparison.
-    -- They will thus compare equal.
-    --
-    SELECT b,a FROM t2249b CROSS JOIN t2249a WHERE a=b;
-  ]])
-        end, {
-            -- <where2-6.7>
-            123, '0123', "nosort", "T2249B", "*", "T2249A", "*"
-            -- </where2-6.7>
-        })
-
-    test:do_test(
-        "where2-6.9",
-        function()
-            return queryplan([[
-    -- The + operator doesn't affect RHS.
-    --
-    SELECT b,a FROM t2249b CROSS JOIN t2249a WHERE a=+b;
-  ]])
-        end, {
-            -- <where2-6.9>
-            123, "0123", "nosort", "T2249B", "*", "T2249A", "*"
-            -- </where2-6.9>
-        })
-
-    test:do_test(
-        "where2-6.9.2",
-        function()
-            -- The same thing but with the expression flipped around.
-            return queryplan([[
-    SELECT b,a FROM t2249b CROSS JOIN t2249a WHERE +b=a
-  ]])
-        end, {
-            -- <where2-6.9.2>
-            123, "0123","nosort", "T2249B", "*", "T2249A", "*"
-            -- </where2-6.9.2>
-        })
-
-    test:do_test(
-        "where2-6.10",
-        function()
-            return queryplan([[
-    SELECT b,a FROM t2249b CROSS JOIN t2249a WHERE +a=+b;
-  ]])
-        end, {
-            -- <where2-6.10>
-            123, "0123", "nosort", "T2249B", "*", "T2249A", "*"
-            -- </where2-6.10>
-        })
-
-    test:do_test(
-        "where2-6.11",
-        function()
-            -- This will not attempt the OR optimization because of the a=b
-            -- comparison.
-            return queryplan([[
-    SELECT b,a FROM t2249b CROSS JOIN t2249a WHERE a=b OR a='hello';
-  ]])
-        end, {
-            -- <where2-6.11>
-            123, '0123', "nosort", "T2249B", "*", "T2249A", "*"
-            -- </where2-6.11>
-        })
-
-    test:do_test(
-        "where2-6.11.2",
-        function()
-            -- Permutations of the expression terms.
-            return queryplan([[
-    SELECT b,a FROM t2249b CROSS JOIN t2249a WHERE b=a OR a='hello';
-  ]])
-        end, {
-            -- <where2-6.11.2>
-            123, '0123', "nosort", "T2249B", "*", "T2249A", "*"
-            -- </where2-6.11.2>
-        })
-
-    test:do_test(
-        "where2-6.11.3",
-        function()
-            -- Permutations of the expression terms.
-            return queryplan([[
-    SELECT b,a FROM t2249b CROSS JOIN t2249a WHERE 'hello'=a OR b=a;
-  ]])
-        end, {
-            -- <where2-6.11.3>
-            123, '0123', "nosort", "T2249B", "*", "T2249A", "*"
-            -- </where2-6.11.3>
-        })
-
-    test:do_test(
-        "where2-6.11.4",
-        function()
-            -- Permutations of the expression terms.
-            return queryplan([[
-    SELECT b,a FROM t2249b CROSS JOIN t2249a WHERE a='hello' OR b=a;
-  ]])
-        end, {
-            -- <where2-6.11.4>
-            123, '0123', "nosort", "T2249B", "*", "T2249A", "*"
-            -- </where2-6.11.4>
-        })
-
-    -- These tests are not run if subquery support is not included in the
-    -- build. This is because these tests test the "a = 1 OR a = 2" to
-    -- "a IN (1, 2)" optimisation transformation, which is not enabled if
-    -- subqueries and the IN operator is not available.
-    --
-    test:do_test(
-        "where2-6.12",
-        function()
-            return queryplan([[
-      SELECT b,a FROM t2249b CROSS JOIN t2249a WHERE a=+b OR a='hello';
-    ]])
-        end, {
-            -- <where2-6.12>
-            123, "0123", "nosort", "T2249B", "*", "T2249A", "*"
-            -- </where2-6.12>
-        })
-
-    test:do_test(
-        "where2-6.12.2",
-        function()
-            return queryplan([[
-      SELECT b,a FROM t2249b CROSS JOIN t2249a WHERE a='hello' OR +b=a;
-    ]])
-        end, {
-            -- <where2-6.12.2>
-            123, "0123", "nosort", "T2249B", "*", "T2249A", "*"
-            -- </where2-6.12.2>
-        })
-
-    test:do_test(
-        "where2-6.12.3",
-        function()
-            return queryplan([[
-      SELECT b,a FROM t2249b CROSS JOIN t2249a WHERE +b=a OR a='hello';
-    ]])
-        end, {
-            -- <where2-6.12.3>
-            123, "0123", "nosort", "T2249B", "*", "T2249A", "*"
-            -- </where2-6.12.3>
-        })
-
-    test:do_test(
-        "where2-6.13",
-        function()
-            -- The addition of +a on the second term disabled the OR 
optimization.
-            -- But we should still get the same empty-set result as in 
where2-6.9.
-            return queryplan([[
-      SELECT b,a FROM t2249b CROSS JOIN t2249a WHERE a=+b OR +a='hello';
-    ]])
-        end, {
-            -- <where2-6.13>
-            123, "0123", "nosort", "T2249B", "*", "T2249A", "*"
-            -- </where2-6.13>
-        })
-
-
+    test:execsql [[
+        CREATE TABLE t2249a(a TEXT PRIMARY KEY, x VARCHAR(100));
+        CREATE TABLE t2249b(b INTEGER PRIMARY KEY);
+        INSERT INTO t2249a(a) VALUES('0123');
+        INSERT INTO t2249b VALUES(123);
+    ]]

      -- Variations on the order of terms in a WHERE clause in order
      -- to make sure the OR optimizer can recognize them all.
diff --git a/test/sql-tap/where5.test.lua b/test/sql-tap/where5.test.lua
index 3aefcaca5..a93ba7854 100755
--- a/test/sql-tap/where5.test.lua
+++ b/test/sql-tap/where5.test.lua
@@ -34,7 +34,7 @@ test:do_test("where5-1.0", function()
          INSERT INTO t3 SELECT CAST(x AS INTEGER) FROM t1;
      ]]
      return test:execsql [[
-        SELECT * FROM t1 WHERE x<0
+        SELECT * FROM t1 WHERE CAST(x AS INTEGER)<0
      ]]
  end, {
      -- <where5-1.0>
@@ -43,7 +43,7 @@ end, {
  })

  test:do_execsql_test("where5-1.1", [[
-    SELECT * FROM t1 WHERE x<=0
+    SELECT * FROM t1 WHERE CAST(x AS INTEGER)<=0
  ]], {
      -- <where5-1.1>
      '-1', '0'
@@ -51,7 +51,7 @@ test:do_execsql_test("where5-1.1", [[
  })

  test:do_execsql_test("where5-1.2", [[
-    SELECT * FROM t1 WHERE x=0
+    SELECT * FROM t1 WHERE CAST(x AS INTEGER)=0
  ]], {
      -- <where5-1.2>
      '0'
@@ -59,7 +59,7 @@ test:do_execsql_test("where5-1.2", [[
  })

  test:do_execsql_test("where5-1.3", [[
-    SELECT * FROM t1 WHERE x>=0
+    SELECT * FROM t1 WHERE CAST(x AS INTEGER)>=0
  ]], {
      -- <where5-1.3>
      '0', '1'
@@ -67,7 +67,7 @@ test:do_execsql_test("where5-1.3", [[
  })

  test:do_execsql_test("where5-1.4", [[
-    SELECT * FROM t1 WHERE x>0
+    SELECT * FROM t1 WHERE CAST(x AS INTEGER)>0
  ]], {
      -- <where5-1.4>
      '1'
@@ -75,7 +75,7 @@ test:do_execsql_test("where5-1.4", [[
  })

  test:do_execsql_test("where5-1.5", [[
-    SELECT * FROM t1 WHERE x<>0
+    SELECT * FROM t1 WHERE CAST(x AS INTEGER)<>0
  ]], {
      -- <where5-1.5>
      '-1', '1'
diff --git a/test/sql/types.result b/test/sql/types.result
index 6b0f7a651..9099bcea4 100644
--- a/test/sql/types.result
+++ b/test/sql/types.result
@@ -339,12 +339,12 @@ box.execute("INSERT INTO tboolean VALUES (TRUE);")
  box.execute("SELECT * FROM tboolean WHERE s1 = x'44';")
  ---
  - null
-- 'Type mismatch: can not convert varbinary to boolean'
+- 'Type mismatch: can not convert boolean to varbinary'
  ...
  box.execute("SELECT * FROM tboolean WHERE s1 = 'abc';")
  ---
  - null
-- 'Type mismatch: can not convert abc to boolean'
+- 'Type mismatch: can not convert boolean to text'
  ...
  box.execute("SELECT * FROM tboolean WHERE s1 = 1;")
  ---
@@ -606,14 +606,6 @@ box.execute("SELECT 18446744073709551615.0 > 
18446744073709551615")
    rows:
    - [true]
  ...
-box.execute("SELECT 18446744073709551615 IN ('18446744073709551615', 
18446744073709551615.0)")
----
-- metadata:
-  - name: 18446744073709551615 IN ('18446744073709551615', 
18446744073709551615.0)
-    type: boolean
-  rows:
-  - [true]
-...
  box.execute("SELECT 1 LIMIT 18446744073709551615;")
  ---
  - metadata:
diff --git a/test/sql/types.test.lua b/test/sql/types.test.lua
index bd14b342d..f9603c60d 100644
--- a/test/sql/types.test.lua
+++ b/test/sql/types.test.lua
@@ -151,7 +151,6 @@ box.execute("SELECT 18446744073709551610 - 
18446744073709551615;")
  box.execute("SELECT 18446744073709551615 = null;")
  box.execute("SELECT 18446744073709551615 = 18446744073709551615.0;")
  box.execute("SELECT 18446744073709551615.0 > 18446744073709551615")
-box.execute("SELECT 18446744073709551615 IN ('18446744073709551615', 
18446744073709551615.0)")
  box.execute("SELECT 1 LIMIT 18446744073709551615;")
  box.execute("SELECT 1 LIMIT 1 OFFSET 18446744073709551614;")
  box.execute("SELECT CAST('18446744073' || '709551616' AS INTEGER);")




More information about the Tarantool-patches mailing list