From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from localhost (localhost [127.0.0.1]) by turing.freelists.org (Avenir Technologies Mail Multiplex) with ESMTP id 679F92899C for ; Mon, 3 Jun 2019 07:10:12 -0400 (EDT) Received: from turing.freelists.org ([127.0.0.1]) by localhost (turing.freelists.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id bmRCJ9UKJsPy for ; Mon, 3 Jun 2019 07:10:12 -0400 (EDT) Received: from smtpng1.m.smailru.net (smtpng1.m.smailru.net [94.100.181.251]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by turing.freelists.org (Avenir Technologies Mail Multiplex) with ESMTPS id 82B5929DEC for ; Mon, 3 Jun 2019 07:10:11 -0400 (EDT) From: Kirill Shcherbatov Subject: [tarantool-patches] [PATCH v1 1/1] sql: STRING and NUMBER aliases for TEXT and REAL Date: Mon, 3 Jun 2019 14:10:07 +0300 Message-Id: <123bb14cdd6e7ada7b8a12e591d524d53bf33b74.1559560173.git.kshcherbatov@tarantool.org> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 8bit Sender: tarantool-patches-bounce@freelists.org Errors-to: tarantool-patches-bounce@freelists.org Reply-To: tarantool-patches@freelists.org List-Help: List-Unsubscribe: List-software: Ecartis version 1.0.0 List-Id: tarantool-patches List-Subscribe: List-Owner: List-post: List-Archive: To: tarantool-patches@freelists.org, korablev@tarantool.org Cc: Kirill Shcherbatov On the one hand, Tarantool's SQL use TEXT and REAL type names to define string and numeric columns. On the other, TYPEOF('') = 'string' and TYPEOF(1e4) = 'number'. This follows native Tarantool core field types. This patch introduces STRING and NUMBER aliases for TEXT and REAL SQL types and makes them preferable. Closes #4192 --- Branch: http://github.com/tarantool/tarantool/tree/kshch/gh-4192-string-and-numbers-type-names Issue: https://github.com/tarantool/tarantool/issues/4192 extra/mkkeywordhash.c | 2 ++ src/box/lua/lua_sql.c | 4 +++ src/box/sql/delete.c | 2 +- src/box/sql/func.c | 8 ++--- src/box/sql/parse.y | 4 +-- src/box/sql/pragma.c | 2 +- src/box/sql/pragma.h | 34 +++++++++---------- src/box/sql/prepare.c | 10 +++--- src/box/sql/sqlLimit.h | 2 +- src/box/sql/vdbe.c | 14 ++++---- src/box/sql/vdbeapi.c | 4 +-- src/box/sql/vdbemem.c | 4 +-- test/sql-tap/e_expr.test.lua | 2 +- test/sql-tap/position.test.lua | 16 ++++----- test/sql/bind.result | 2 +- test/sql/iproto.result | 16 ++++----- test/sql/row-count.result | 2 +- test/sql/types.result | 60 ++++++++++++++++++++++++---------- test/sql/types.test.lua | 12 +++++++ 19 files changed, 122 insertions(+), 78 deletions(-) diff --git a/extra/mkkeywordhash.c b/extra/mkkeywordhash.c index 2ad74eddc..1b45bc2d5 100644 --- a/extra/mkkeywordhash.c +++ b/extra/mkkeywordhash.c @@ -265,6 +265,7 @@ static Keyword aKeywordTable[] = { { "RANK", "TK_STANDARD", RESERVED, true }, { "READS", "TK_STANDARD", RESERVED, true }, { "REAL", "TK_REAL", RESERVED, true }, + { "NUMBER", "TK_REAL", RESERVED, true }, { "REPEAT", "TK_STANDARD", RESERVED, true }, { "RESIGNAL", "TK_STANDARD", RESERVED, true }, { "RETURN", "TK_STANDARD", RESERVED, true }, @@ -282,6 +283,7 @@ static Keyword aKeywordTable[] = { { "WHENEVER", "TK_STANDARD", RESERVED, true }, { "WHILE", "TK_STANDARD", RESERVED, true }, { "TEXT", "TK_TEXT", RESERVED, true }, + { "STRING", "TK_TEXT", RESERVED, true }, { "TRUNCATE", "TK_TRUNCATE", ALWAYS, true }, { "TRIM", "TK_TRIM", ALWAYS, true }, { "LEADING", "TK_LEADING", ALWAYS, true }, diff --git a/src/box/lua/lua_sql.c b/src/box/lua/lua_sql.c index 36b75ff08..0623617c0 100644 --- a/src/box/lua/lua_sql.c +++ b/src/box/lua/lua_sql.c @@ -158,8 +158,12 @@ lbox_sql_create_function(struct lua_State *L) type = FIELD_TYPE_INTEGER; else if (strcmp(type_arg, "TEXT") == 0) type = FIELD_TYPE_STRING; + else if (strcmp(type_arg, "STRING") == 0) + type = FIELD_TYPE_STRING; else if (strcmp(type_arg, "FLOAT") == 0) type = FIELD_TYPE_NUMBER; + else if (strcmp(type_arg, "NUMBER") == 0) + type = FIELD_TYPE_NUMBER; else if (strcmp(type_arg, "NUM") == 0) type = FIELD_TYPE_NUMBER; else if (strcmp(type_arg, "BLOB") == 0) diff --git a/src/box/sql/delete.c b/src/box/sql/delete.c index a95b07155..356c88c50 100644 --- a/src/box/sql/delete.c +++ b/src/box/sql/delete.c @@ -585,7 +585,7 @@ sql_generate_index_key(struct Parse *parse, struct index *index, int cursor, * If the column type is NUMBER but the number * is an integer, then it might be stored in the * table as an integer (using a compact - * representation) then converted to REAL by an + * representation) then converted to NUMBER by an * OP_Realify opcode. But we are getting * ready to store this value back into an index, * where it should be converted by to INTEGER diff --git a/src/box/sql/func.c b/src/box/sql/func.c index bb7405e68..1704f278a 100644 --- a/src/box/sql/func.c +++ b/src/box/sql/func.c @@ -254,7 +254,7 @@ position_func(struct sql_context *context, int argc, struct Mem **argv) if (haystack_type != MP_STR && haystack_type != MP_BIN) inconsistent_type_arg = haystack; if (inconsistent_type_arg != NULL) { - diag_set(ClientError, ER_INCONSISTENT_TYPES, "TEXT or BLOB", + diag_set(ClientError, ER_INCONSISTENT_TYPES, "STRING or BLOB", mem_type_to_str(inconsistent_type_arg)); context->isError = SQL_TARANTOOL_ERROR; context->fErrorOrAux = 1; @@ -898,8 +898,8 @@ sql_strlike_ci(const char *zPattern, const char *zStr, unsigned int esc) * * are implemented as like(B,A). * - * Both arguments (A and B) must be of type TEXT. If one arguments - * is NULL then result is NULL as well. + * Both arguments (A and B) must be of type STRING. If one + * arguments is NULL then result is NULL as well. */ static void likeFunc(sql_context *context, int argc, sql_value **argv) @@ -917,7 +917,7 @@ likeFunc(sql_context *context, int argc, sql_value **argv) char *inconsistent_type = rhs_type != MP_STR ? mem_type_to_str(argv[0]) : mem_type_to_str(argv[1]); - diag_set(ClientError, ER_INCONSISTENT_TYPES, "TEXT", + diag_set(ClientError, ER_INCONSISTENT_TYPES, "STRING", inconsistent_type); context->fErrorOrAux = 1; context->isError = SQL_TARANTOOL_ERROR; diff --git a/src/box/sql/parse.y b/src/box/sql/parse.y index f241b8d52..282d33df6 100644 --- a/src/box/sql/parse.y +++ b/src/box/sql/parse.y @@ -1735,7 +1735,7 @@ wqlist(A) ::= wqlist(A) COMMA nm(X) eidlist_opt(Y) AS LP select(Z) RP. { ////////////////////////////// TYPE DECLARATION /////////////////////////////// %type typedef {struct type_def} -typedef(A) ::= TEXT . { A.type = FIELD_TYPE_STRING; } +typedef(A) ::= TEXT|STRING . { A.type = FIELD_TYPE_STRING; } typedef(A) ::= SCALAR . { A.type = FIELD_TYPE_SCALAR; } /** BOOL | BOOLEAN is not used due to possible bug in Lemon. */ typedef(A) ::= BOOL . { A.type = FIELD_TYPE_BOOLEAN; } @@ -1764,7 +1764,7 @@ typedef(A) ::= VARCHAR char_len(B) . { %type number_typedef {struct type_def} typedef(A) ::= number_typedef(A) . -number_typedef(A) ::= FLOAT_KW|REAL|DOUBLE . { A.type = FIELD_TYPE_NUMBER; } +number_typedef(A) ::= FLOAT_KW|REAL|NUMBER|DOUBLE . { A.type = FIELD_TYPE_NUMBER; } number_typedef(A) ::= INT|INTEGER_KW . { A.type = FIELD_TYPE_INTEGER; } /** diff --git a/src/box/sql/pragma.c b/src/box/sql/pragma.c index 53524b617..caccbe0c7 100644 --- a/src/box/sql/pragma.c +++ b/src/box/sql/pragma.c @@ -169,7 +169,7 @@ vdbe_emit_pragma_status(struct Parse *parse) sqlVdbeSetNumCols(v, 2); sqlVdbeSetColName(v, 0, COLNAME_NAME, "pragma_name", SQL_STATIC); - sqlVdbeSetColName(v, 0, COLNAME_DECLTYPE, "TEXT", SQL_STATIC); + sqlVdbeSetColName(v, 0, COLNAME_DECLTYPE, "STRING", SQL_STATIC); sqlVdbeSetColName(v, 1, COLNAME_NAME, "pragma_value", SQL_STATIC); sqlVdbeSetColName(v, 1, COLNAME_DECLTYPE, "INTEGER", SQL_STATIC); diff --git a/src/box/sql/pragma.h b/src/box/sql/pragma.h index aa7e7cd96..e0764df2e 100644 --- a/src/box/sql/pragma.h +++ b/src/box/sql/pragma.h @@ -33,20 +33,20 @@ static const char *const pragCName[] = { /* 0 */ "cid", /* 1 */ "INTEGER", /* 2 */ "name", - /* 3 */ "TEXT", + /* 3 */ "STRING", /* 4 */ "type", - /* 3 */ "TEXT", + /* 3 */ "STRING", /* 6 */ "notnull", /* 1 */ "INTEGER", /* 8 */ "dflt_value", - /* 9 */ "TEXT", + /* 9 */ "STRING", /* 10 */ "pk", /* 11 */ "INTEGER", /* Used by: stats */ /* 12 */ "table", - /* 13 */ "TEXT", + /* 13 */ "STRING", /* 14 */ "index", - /* 15 */ "TEXT", + /* 15 */ "STRING", /* 16 */ "width", /* 17 */ "INTEGER", /* 18 */ "height", @@ -57,42 +57,42 @@ static const char *const pragCName[] = { /* 22 */ "cid", /* 23 */ "INTEGER", /* 24 */ "name", - /* 25 */ "TEXT", + /* 25 */ "STRING", /* 26 */ "desc", /* 27 */ "INTEGER", /* 28 */ "coll", - /* 29 */ "TEXT", + /* 29 */ "STRING", /* 30 */ "type", - /* 31 */ "TEXT", + /* 31 */ "STRING", /* Used by: index_list */ /* 32 */ "seq", /* 33 */ "INTEGER", /* 34 */ "name", - /* 35 */ "TEXT", + /* 35 */ "STRING", /* 36 */ "unique", /* 37 */ "INTEGER", /* Used by: collation_list */ /* 38 */ "seq", /* 39 */ "INTEGER", /* 40 */ "name", - /* 41 */ "TEXT", + /* 41 */ "STRING", /* Used by: foreign_key_list */ /* 42 */ "id", /* 43 */ "INTEGER", /* 44 */ "seq", /* 45 */ "INTEGER", /* 46 */ "table", - /* 47 */ "TEXT", + /* 47 */ "STRING", /* 48 */ "from", - /* 49 */ "TEXT", + /* 49 */ "STRING", /* 50 */ "to", - /* 51 */ "TEXT", + /* 51 */ "STRING", /* 52 */ "on_update", - /* 53 */ "TEXT", + /* 53 */ "STRING", /* 54 */ "on_delete", - /* 55 */ "TEXT", + /* 55 */ "STRING", /* 56 */ "match", - /* 57 */ "TEXT", + /* 57 */ "STRING", /* Used by: case_sensitive_like */ /* 58 */ "case_sensitive_like", /* 59 */ "INTEGER", @@ -125,7 +125,7 @@ static const char *const pragCName[] = { /* 77 */ "INTEGER", /* Used by: sql_default_engine */ /* 78 */ "sql_default_engine", - /* 79 */ "TEXT", + /* 79 */ "STRING", /* Used by: sql_trace */ /* 80 */ "sql_trace", /* 81 */ "INTEGER", diff --git a/src/box/sql/prepare.c b/src/box/sql/prepare.c index 3df6b5c36..0d1a9a3d6 100644 --- a/src/box/sql/prepare.c +++ b/src/box/sql/prepare.c @@ -112,7 +112,7 @@ sqlPrepare(sql * db, /* Database handle. */ /* 0 */ "addr", /* 1 */ "INTEGER", /* 2 */ "opcode", - /* 3 */ "TEXT", + /* 3 */ "STRING", /* 4 */ "p1", /* 5 */ "INTEGER", /* 6 */ "p2", @@ -120,11 +120,11 @@ sqlPrepare(sql * db, /* Database handle. */ /* 8 */ "p3", /* 9 */ "INTEGER", /* 10 */ "p4", - /* 11 */ "TEXT", + /* 11 */ "STRING", /* 12 */ "p5", - /* 13 */ "TEXT", + /* 13 */ "STRING", /* 14 */ "comment", - /* 15 */ "TEXT", + /* 15 */ "STRING", /* 16 */ "selectid", /* 17 */ "INTEGER", /* 18 */ "order", @@ -132,7 +132,7 @@ sqlPrepare(sql * db, /* Database handle. */ /* 20 */ "from", /* 21 */ "INTEGER", /* 22 */ "detail", - /* 23 */ "TEXT", + /* 23 */ "STRING", }; int name_first, name_count; diff --git a/src/box/sql/sqlLimit.h b/src/box/sql/sqlLimit.h index 53dbe1505..3a7574927 100644 --- a/src/box/sql/sqlLimit.h +++ b/src/box/sql/sqlLimit.h @@ -45,7 +45,7 @@ enum { }; /* - * The maximum length of a TEXT or BLOB in bytes. This also + * The maximum length of a STRING or BLOB in bytes. This also * limits the size of a row in a table or index. * * The hard limit is the ability of a 32-bit signed integer diff --git a/src/box/sql/vdbe.c b/src/box/sql/vdbe.c index d083d3709..f371cd45c 100644 --- a/src/box/sql/vdbe.c +++ b/src/box/sql/vdbe.c @@ -343,7 +343,7 @@ mem_apply_type(struct Mem *record, enum field_type type) return sqlVdbeMemRealify(record); case FIELD_TYPE_STRING: /* - * Only attempt the conversion to TEXT if there is + * Only attempt the conversion to STRING if there is * an integer or real representation (BLOB and * NULL do not get converted). */ @@ -599,11 +599,11 @@ mem_type_to_str(const struct Mem *p) case MEM_Null: return "NULL"; case MEM_Str: - return "TEXT"; + return "STRING"; case MEM_Int: return "INTEGER"; case MEM_Real: - return "REAL"; + return "NUMBER"; case MEM_Blob: return "BLOB"; case MEM_Bool: @@ -1488,7 +1488,7 @@ case OP_ResultRow: { * to avoid a memcpy(). * * Concatenation operator accepts only arguments of string-like - * types (i.e. TEXT and BLOB). + * types (i.e. STRING and BLOB). */ case OP_Concat: { /* same as TK_CONCAT, in1, in2, out3 */ i64 nByte; @@ -1511,7 +1511,7 @@ case OP_Concat: { /* same as TK_CONCAT, in1, in2, out3 */ char *inconsistent_type = str_type_p1 == 0 ? mem_type_to_str(pIn1) : mem_type_to_str(pIn2); - diag_set(ClientError, ER_INCONSISTENT_TYPES, "TEXT or BLOB", + diag_set(ClientError, ER_INCONSISTENT_TYPES, "STRING or BLOB", inconsistent_type); rc = SQL_TARANTOOL_ERROR; goto abort_due_to_error; @@ -1983,11 +1983,11 @@ case OP_Realify: { /* in1 */ * Force the value in register P1 to be the type defined by P2. * *
    - *
  • TEXT + *
  • STRING *
  • BLOB *
  • NUMERIC *
  • INTEGER - *
  • REAL + *
  • NUMBER *
* * A NULL value is not changed by this routine. It remains NULL. diff --git a/src/box/sql/vdbeapi.c b/src/box/sql/vdbeapi.c index e480ae720..79bcdc077 100644 --- a/src/box/sql/vdbeapi.c +++ b/src/box/sql/vdbeapi.c @@ -1268,7 +1268,7 @@ sql_bind_type(struct Vdbe *v, uint32_t position, const char *type) } /* - * Bind a text or BLOB value. + * Bind a STRING or BLOB value. */ static int bindText(sql_stmt * pStmt, /* The statement to bind against */ @@ -1288,7 +1288,7 @@ bindText(sql_stmt * pStmt, /* The statement to bind against */ pVar = &p->aVar[i - 1]; rc = sqlVdbeMemSetStr(pVar, zData, nData, 1, xDel); if (rc == SQL_OK) - rc = sql_bind_type(p, i, "TEXT"); + rc = sql_bind_type(p, i, "STRING"); sqlError(p->db, rc); rc = sqlApiExit(p->db, rc); } diff --git a/src/box/sql/vdbemem.c b/src/box/sql/vdbemem.c index 08b649926..7185642b3 100644 --- a/src/box/sql/vdbemem.c +++ b/src/box/sql/vdbemem.c @@ -809,7 +809,7 @@ mem_set_bool(struct Mem *mem, bool value) /* * Delete any previous value and set the value stored in *pMem to val, - * manifest type REAL. + * manifest type NUMBER. */ void sqlVdbeMemSetDouble(Mem * pMem, double val) @@ -822,7 +822,7 @@ sqlVdbeMemSetDouble(Mem * pMem, double val) } /* - * Return true if the Mem object contains a TEXT or BLOB that is + * Return true if the Mem object contains a STRING or BLOB that is * too large - whose size exceeds SQL_MAX_LENGTH. */ int diff --git a/test/sql-tap/e_expr.test.lua b/test/sql-tap/e_expr.test.lua index 7b80651a8..30654cd19 100755 --- a/test/sql-tap/e_expr.test.lua +++ b/test/sql-tap/e_expr.test.lua @@ -3145,7 +3145,7 @@ do_expr_test("e_expr-31.2.3", [[ do_expr_test("e_expr-31.2.4", [[ CAST(9223372036854775809.0 AS INT) ]], "integer", 9223372036854775807LL) --- EVIDENCE-OF: R-09295-61337 Casting a TEXT or BLOB value into NUMERIC +-- EVIDENCE-OF: R-09295-61337 Casting a STRING or BLOB value into NUMERIC -- first does a forced conversion into REAL but then further converts the -- result into INTEGER if and only if the conversion from REAL to INTEGER -- is lossless and reversible. diff --git a/test/sql-tap/position.test.lua b/test/sql-tap/position.test.lua index 8c46d7b9e..c5c11c0c8 100755 --- a/test/sql-tap/position.test.lua +++ b/test/sql-tap/position.test.lua @@ -228,7 +228,7 @@ test:do_test( return test:catchsql "SELECT position(34, 12345);" end, { -- - 1, "Inconsistent types: expected TEXT or BLOB got INTEGER" + 1, "Inconsistent types: expected STRING or BLOB got INTEGER" -- }) @@ -238,7 +238,7 @@ test:do_test( return test:catchsql "SELECT position(34, 123456.78);" end, { -- - 1, "Inconsistent types: expected TEXT or BLOB got REAL" + 1, "Inconsistent types: expected STRING or BLOB got NUMBER" -- }) @@ -248,7 +248,7 @@ test:do_test( return test:catchsql "SELECT position(x'3334', 123456.78);" end, { -- - 1, "Inconsistent types: expected TEXT or BLOB got REAL" + 1, "Inconsistent types: expected STRING or BLOB got NUMBER" -- }) @@ -554,7 +554,7 @@ test:do_test( return test:catchsql("SELECT position('x', x'78c3a4e282ac79');") end, { -- - 1, "Inconsistent types: expected TEXT got BLOB" + 1, "Inconsistent types: expected STRING got BLOB" -- }) @@ -564,7 +564,7 @@ test:do_test( return test:catchsql "SELECT position('y', x'78c3a4e282ac79');" end, { -- - 1, "Inconsistent types: expected TEXT got BLOB" + 1, "Inconsistent types: expected STRING got BLOB" -- }) @@ -614,7 +614,7 @@ test:do_test( return test:catchsql "SELECT position(x'79', 'xä€y');" end, { -- - 1, "Inconsistent types: expected BLOB got TEXT" + 1, "Inconsistent types: expected BLOB got STRING" -- }) @@ -624,7 +624,7 @@ test:do_test( return test:catchsql "SELECT position(x'a4', 'xä€y');" end, { -- - 1, "Inconsistent types: expected BLOB got TEXT" + 1, "Inconsistent types: expected BLOB got STRING" -- }) @@ -634,7 +634,7 @@ test:do_test( return test:catchsql "SELECT position('y', x'78c3a4e282ac79');" end, { -- - 1, "Inconsistent types: expected TEXT got BLOB" + 1, "Inconsistent types: expected STRING got BLOB" -- }) diff --git a/test/sql/bind.result b/test/sql/bind.result index 076bf8319..e7f08b62e 100644 --- a/test/sql/bind.result +++ b/test/sql/bind.result @@ -170,7 +170,7 @@ execute('SELECT ?, ?, ?, ?, ?', {'abc', -123.456, msgpack.NULL, true, false}) --- - metadata: - name: '?' - type: TEXT + type: STRING - name: '?' type: NUMERIC - name: '?' diff --git a/test/sql/iproto.result b/test/sql/iproto.result index e734872b2..0aa5130a2 100644 --- a/test/sql/iproto.result +++ b/test/sql/iproto.result @@ -682,13 +682,13 @@ res.metadata - - name: cid type: INTEGER - name: name - type: TEXT + type: STRING - name: type - type: TEXT + type: STRING - name: notnull type: INTEGER - name: dflt_value - type: TEXT + type: STRING - name: pk type: INTEGER ... @@ -701,7 +701,7 @@ res.metadata - - name: addr type: INTEGER - name: opcode - type: TEXT + type: STRING - name: p1 type: INTEGER - name: p2 @@ -709,11 +709,11 @@ res.metadata - name: p3 type: INTEGER - name: p4 - type: TEXT + type: STRING - name: p5 - type: TEXT + type: STRING - name: comment - type: TEXT + type: STRING ... res = cn:execute("EXPLAIN QUERY PLAN SELECT COUNT(*) FROM t1") --- @@ -727,7 +727,7 @@ res.metadata - name: from type: INTEGER - name: detail - type: TEXT + type: STRING ... -- When pragma count_changes is on, statements INSERT, REPLACE and -- UPDATE returns number of changed columns. Make sure that this diff --git a/test/sql/row-count.result b/test/sql/row-count.result index da9b70e79..fd69d9735 100644 --- a/test/sql/row-count.result +++ b/test/sql/row-count.result @@ -301,7 +301,7 @@ box.execute("EXPLAIN QUERY PLAN INSERT INTO t1 VALUES ('b'), ('c'), ('d');") - name: from type: INTEGER - name: detail - type: TEXT + type: STRING rows: - [0, 0, 0, 'SCAN TABLE T2'] ... diff --git a/test/sql/types.result b/test/sql/types.result index a53d6f7ce..e1e195694 100644 --- a/test/sql/types.result +++ b/test/sql/types.result @@ -152,33 +152,33 @@ sp:drop() -- box.execute("SELECT 'abc' || 1;") --- -- error: 'Inconsistent types: expected TEXT or BLOB got INTEGER' +- error: 'Inconsistent types: expected STRING or BLOB got INTEGER' ... box.execute("SELECT 'abc' || 1.123;") --- -- error: 'Inconsistent types: expected TEXT or BLOB got REAL' +- error: 'Inconsistent types: expected STRING or BLOB got NUMBER' ... box.execute("SELECT 1 || 'abc';") --- -- error: 'Inconsistent types: expected TEXT or BLOB got INTEGER' +- error: 'Inconsistent types: expected STRING or BLOB got INTEGER' ... box.execute("SELECT 1.123 || 'abc';") --- -- error: 'Inconsistent types: expected TEXT or BLOB got REAL' +- error: 'Inconsistent types: expected STRING or BLOB got NUMBER' ... box.execute("SELECt 'a' || 'b' || 1;") --- -- error: 'Inconsistent types: expected TEXT or BLOB got INTEGER' +- error: 'Inconsistent types: expected STRING or BLOB got INTEGER' ... -- What is more, they must be of the same type. -- box.execute("SELECT 'abc' || randomblob(5);") --- -- error: 'Inconsistent types: expected TEXT got BLOB' +- error: 'Inconsistent types: expected STRING got BLOB' ... box.execute("SELECT randomblob(5) || 'x';") --- -- error: 'Inconsistent types: expected BLOB got TEXT' +- error: 'Inconsistent types: expected BLOB got STRING' ... -- Result of BLOBs concatenation must be BLOB. -- @@ -202,15 +202,15 @@ box.execute("INSERT INTO t1 VALUES (randomblob(5));") ... box.execute("SELECT * FROM t1 WHERE s LIKE 'blob';") --- -- error: 'Inconsistent types: expected TEXT got BLOB' +- error: 'Inconsistent types: expected STRING got BLOB' ... box.execute("SELECT * FROM t1 WHERE 'blob' LIKE s;") --- -- error: 'Inconsistent types: expected TEXT got BLOB' +- error: 'Inconsistent types: expected STRING got BLOB' ... box.execute("SELECT * FROM t1 WHERE 'blob' LIKE x'0000';") --- -- error: 'Inconsistent types: expected TEXT got BLOB' +- error: 'Inconsistent types: expected STRING got BLOB' ... box.execute("SELECT s LIKE NULL FROM t1;") --- @@ -230,11 +230,11 @@ box.execute("INSERT INTO t1 VALUES (1);") ... box.execute("SELECT * FROM t1 WHERE s LIKE 'int';") --- -- error: 'Inconsistent types: expected TEXT got INTEGER' +- error: 'Inconsistent types: expected STRING got INTEGER' ... box.execute("SELECT * FROM t1 WHERE 'int' LIKE 4;") --- -- error: 'Inconsistent types: expected TEXT got INTEGER' +- error: 'Inconsistent types: expected STRING got INTEGER' ... box.execute("SELECT NULL LIKE s FROM t1;") --- @@ -359,11 +359,11 @@ box.execute("SELECT 1 = true;") ... box.execute("SELECT 'abc' = true;") --- -- error: 'Type mismatch: can not convert TEXT to boolean' +- error: 'Type mismatch: can not convert STRING to boolean' ... box.execute("SELECT 1.123 > true;") --- -- error: 'Type mismatch: can not convert REAL to boolean' +- error: 'Type mismatch: can not convert NUMBER to boolean' ... box.execute("SELECT true IN (1, 'abc', true)") --- @@ -391,7 +391,7 @@ box.execute("SELECT 1 LIMIT 1 OFFSET true;") ... box.execute("SELECT 'abc' || true;") --- -- error: 'Inconsistent types: expected TEXT or BLOB got BOOLEAN' +- error: 'Inconsistent types: expected STRING or BLOB got BOOLEAN' ... -- Boolean can take part in arithmetic operations. -- @@ -892,11 +892,11 @@ box.execute("INSERT INTO t1 VALUES (3, 'abc'), (4, 12.5);") ... box.execute("SELECT s FROM t1 WHERE s = true;") --- -- error: 'Type mismatch: can not convert TEXT to boolean' +- error: 'Type mismatch: can not convert STRING to boolean' ... box.execute("SELECT s FROM t1 WHERE s < true;") --- -- error: 'Type mismatch: can not convert TEXT to boolean' +- error: 'Type mismatch: can not convert STRING to boolean' ... box.execute("SELECT s FROM t1 WHERE s IN (true, 1, 'abcd')") --- @@ -963,3 +963,29 @@ box.execute('SELECT ?', {true}) rows: - [true] ... +-- +-- gh-4192: Introduce STRING and NUMBER aliases for TEXT and +-- REAL types. +-- +box.execute("CREATE TABLE t1 (id STRING PRIMARY KEY);") +--- +- row_count: 1 +... +box.execute("SELECT * FROM t1").metadata[1].type == 'string' +--- +- true +... +box.execute("CREATE TABLE t2 (id NUMBER PRIMARY KEY);") +--- +- row_count: 1 +... +box.execute("SELECT * FROM t2").metadata[1].type == 'number' +--- +- true +... +box.space.T1:drop() +--- +... +box.space.T2:drop() +--- +... diff --git a/test/sql/types.test.lua b/test/sql/types.test.lua index ae1a0ab72..b9c411088 100644 --- a/test/sql/types.test.lua +++ b/test/sql/types.test.lua @@ -234,3 +234,15 @@ box.execute('SELECT \'9223372036854\' + 1;') -- Fix BOOLEAN bindings. box.execute('SELECT ?', {true}) + + +-- +-- gh-4192: Introduce STRING and NUMBER aliases for TEXT and +-- REAL types. +-- +box.execute("CREATE TABLE t1 (id STRING PRIMARY KEY);") +box.execute("SELECT * FROM t1").metadata[1].type == 'string' +box.execute("CREATE TABLE t2 (id NUMBER PRIMARY KEY);") +box.execute("SELECT * FROM t2").metadata[1].type == 'number' +box.space.T1:drop() +box.space.T2:drop() -- 2.21.0