From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from smtp55.i.mail.ru (smtp55.i.mail.ru [217.69.128.35]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dev.tarantool.org (Postfix) with ESMTPS id 9297446970F for ; Thu, 21 Nov 2019 01:58:16 +0300 (MSK) From: Roman Khabibov Message-Id: <62BA0501-2422-430E-8A60-87DDE1CBB473@tarantool.org> Content-Type: multipart/alternative; boundary="Apple-Mail=_17CB3347-326E-4006-91FC-8A9F0EC2B57C" Mime-Version: 1.0 (Mac OS X Mail 13.0 \(3594.4.19\)) Date: Thu, 21 Nov 2019 01:58:09 +0300 In-Reply-To: <20191108110117.GA82024@tarantool.org> References: <20191006210514.49639-1-roman.habibov@tarantool.org> <20191014154750.GA21135@tarantool.org> <20191108110117.GA82024@tarantool.org> Subject: Re: [Tarantool-patches] [tarantool-patches] [PATCH] sql: print line and column number in error message List-Id: Tarantool development patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: tarantool-patches@dev.tarantool.org --Apple-Mail=_17CB3347-326E-4006-91FC-8A9F0EC2B57C Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=utf-8 Hi! Thanks for the review. > On Nov 8, 2019, at 14:01, Nikita Pettik = wrote: >=20 > On 23 Oct 13:40, Roman Khabibov wrote: >> Hi! Thanks for the review. >>=20 >>> On Oct 14, 2019, at 18:47, Nikita Pettik = wrote: >>>=20 >>> On 07 Oct 00:05, Roman Khabibov wrote: >>>> Count the number of rows and columns during query parsing. This is >>>> to make it easier for the user to find errors in multiline >>>> queries. >>>>=20 >>>> Closes #2611 >>>>=20 >>>> # Please enter the commit message for your changes. Lines starting >>>=20 >>> ? >> Oops. >=20 > GitLab/Travis statuses are negative. Please check CI results before > sending patch on the review. Now, every test is passed on my local machine. =20 >>>> diff --git a/src/box/errcode.h b/src/box/errcode.h >>>> index d5d396d87..36e5c179f 100644 >>>> --- a/src/box/errcode.h >>>> +++ b/src/box/errcode.h >>>> @@ -235,9 +235,9 @@ struct errcode_record { >>>> /*180 */_(ER_SQL_STACK_OVERFLOW, "Failed to parse SQL = statement: parser stack limit reached") \ >>>> /*181 */_(ER_SQL_SELECT_WILDCARD, "Failed to expand '*' in = SELECT statement without FROM clause") \ >>>> /*182 */_(ER_SQL_STATEMENT_EMPTY, "Failed to execute an = empty SQL statement") \ >>>> - /*183 */_(ER_SQL_KEYWORD_IS_RESERVED, "Keyword '%.*s' is = reserved. Please use double quotes if '%.*s' is an identifier.") \ >>>> - /*184 */_(ER_SQL_UNRECOGNIZED_SYNTAX, "Syntax error near = '%.*s'") \ >>>> - /*185 */_(ER_SQL_UNKNOWN_TOKEN, "Syntax error: = unrecognized token: '%.*s'") \ >>>> + /*183 */_(ER_SQL_KEYWORD_IS_RESERVED, "Keyword '%.*s' on line = %d at character %d is reserved. Please use double quotes if '%.*s' is an = identifier.") \ >>>> + /*184 */_(ER_SQL_UNRECOGNIZED_SYNTAX, "Syntax error on line %d = at character %d near '%.*s'") \ >>>> + /*185 */_(ER_SQL_UNKNOWN_TOKEN, "Syntax error: on line = %d at character %d unrecognized token: '%.*s'") \ >>>> /*186 */_(ER_SQL_PARSER_GENERIC, "%s") \ >>>=20 >>> What about other syntax related errors like ER_SQL_PARSER_GENERIC, >>> ER_SQL_SYNTAX? Please use the same pattern for all errors: >>>=20 >>> "On line %d at/near position %d ..." OR >>> "Syntax error on line %d at column %d: =E2=80=A6=E2=80=9D >> Unfortunately, I can print line count and position only during the = process >> of tokenizing. Outside of the parse.y and tokenize.c we will just = print the >> last symbol position of a query, because this process is assumed to = be >> completed, as I understood. >=20 > For example look at sqlSrcListAppendFromTerm(): there we set = ER_SQL_SYNTAX. > But it is called only from parse.y. Thus, it is possible to set = correct > line and position. Please, check all other errors and introduce = position > where it is possible. This function is used on select.c:4525. Consider some cases with syntax errors from functions, that used in = parse.y only: 1) build.c sql_add_autoincrement() tarantool> CREATE TABLE t11_7 (i INT AUTOINCREMENT, a INT AUTOINCREMENT = , PRIMARY KEY(a, i)); --- - 'Syntax error on line 1 at column 83 in CREATE TABLE: Table must = feature at most one AUTOINCREMENT field' ... tarantool> CREATE TABLE t11_7 (i INT AUTOINCREMENT, a INT AUTOINCREMENT = , PRIMARY KEY(a, i)); --- - 'Syntax error on line 1 at column 76 in CREATE TABLE: Table must = feature at most one AUTOINCREMENT field' The error line and position depends on whitespaces or linefeeds after = last AUTOINCREMENT keyword, because at the moment of calling sql_add_autoincrement() the = last parsed token was =E2=80=98,=E2=80=99. That looks weird. 2) select.c sqlJoinType() tarantool> SELECT * FROM t1 INNER OUTER JOIN t2 ; --- - null - 'Syntax erroron line 1 at column 35: unknown or unsupported join type: = INNER OUTER' ... tarantool> SELECT * FROM t1 INNER OUTER JOIN t2; --- - null - 'Syntax erroron line 1 at column 39: unknown or unsupported join type: = INNER OUTER' ... The same problem. As I understood, we can print error line/pos if incorrect token is last = parsed. Therefore, we need to find the occurrences of = diag_set(ClientError, =E2=80=A6), where incorrect token is last parsed. = I didn=E2=80=99t find. So, I decided to print in parse.y and tokenize.c only. > Also, taking into account my comment below, you don't need two = versions > (with and without position) of the same error. >=20 >>>> diff --git a/test/sql/checks.result b/test/sql/checks.result >>>> index 50347bc3a..4ecab9ad4 100644 >>>> --- a/test/sql/checks.result >>>> +++ b/test/sql/checks.result >>>> @@ -39,8 +39,8 @@ _ =3D box.space.test:create_index('pk') >>>> -- Invalid expression test. >>>> box.space._ck_constraint:insert({513, 'CK_CONSTRAINT_01', false, = 'SQL', 'X><5'}) >>>> --- >>>> -- error: 'Failed to create check constraint ''CK_CONSTRAINT_01'': = Syntax error near >>>> - ''<''' >>>> +- error: 'Failed to create check constraint ''CK_CONSTRAINT_01'': = Syntax error on >>>> + line 1 at character 10 near ''<''' >>>=20 >>> There's parse_only flag in struct Parse. You can use it to calculate >>> correct position in expression. >>=20 >> diff --git a/src/box/sql/parse.y b/src/box/sql/parse.y >> index ed59a875a..7546271d8 100644 >> --- a/src/box/sql/parse.y >> +++ b/src/box/sql/parse.y >> @@ -33,10 +33,21 @@ >> UNUSED_PARAMETER(yymajor); /* Silence some compiler warnings */ >> assert( TOKEN.z[0] ); /* The tokenizer always gives us a token */ >> if (yypParser->is_fallback_failed && TOKEN.isReserved) { >> - diag_set(ClientError, ER_SQL_KEYWORD_IS_RESERVED, TOKEN.n, = TOKEN.z, >> - TOKEN.n, TOKEN.z); >> + if (!pParse->parse_only) { >> + diag_set(ClientError, ER_SQL_KEYWORD_IS_RESERVED_WITH_POS, >> + pParse->line_count, pParse->line_pos, TOKEN.n, = TOKEN.z, TOKEN.n, >> + TOKEN.z); >> + } else { >> + diag_set(ClientError, ER_SQL_KEYWORD_IS_RESERVED, TOKEN.n, = TOKEN.z, >> + TOKEN.n, TOKEN.z); >> + } >=20 > Firstly (and obviously), you can introduce wrapper around this = if-else: > parser_diag_set() and provide covering comment. diff --git a/src/box/sql/parse.y b/src/box/sql/parse.y index 1d0c95fac..b2660635b 100644 --- a/src/box/sql/parse.y +++ b/src/box/sql/parse.y @@ -33,10 +33,11 @@ UNUSED_PARAMETER(yymajor); /* Silence some compiler warnings */ assert( TOKEN.z[0] ); /* The tokenizer always gives us a token */ if (yypParser->is_fallback_failed && TOKEN.isReserved) { - diag_set(ClientError, ER_SQL_KEYWORD_IS_RESERVED, TOKEN.n, TOKEN.z, - TOKEN.n, TOKEN.z); + parser_diag_set(pParse, ER_SQL_KEYWORD_IS_RESERVED, TOKEN.n, = TOKEN.z, + TOKEN.n, TOKEN.z); } else { - diag_set(ClientError, ER_SQL_UNRECOGNIZED_SYNTAX, TOKEN.n, = TOKEN.z); + parser_diag_set(pParse, ER_SQL_UNRECOGNIZED_SYNTAX, TOKEN.n, = TOKEN.z, 0, + NULL); } pParse->is_aborted =3D true; } @@ -115,6 +116,35 @@ static void disableLookaside(Parse *pParse){ pParse->db->lookaside.bDisable++; } =20 +void parser_diag_set(struct Parse *parser, uint32_t errcode, uint32_t = len_1, + const char *str_1, uint32_t len_2, + const char *str_2) { + const char *add =3D tt_sprintf(" on line %d at column %d", + parser->line_count, = parser->line_pos); + switch (errcode) { + case ER_SQL_SYNTAX: + assert (str_1 !=3D NULL && str_2 !=3D NULL); + diag_set(ClientError, errcode, !parser->parse_only ? add : "", = str_1, + str_2); + break; + case ER_SQL_KEYWORD_IS_RESERVED: + assert(str_1 !=3D NULL && str_2 !=3D NULL); + diag_set(ClientError, errcode, !parser->parse_only ? add : "", = len_1, str_1, + len_2, str_2); + break; + case ER_SQL_UNRECOGNIZED_SYNTAX: + case ER_SQL_UNKNOWN_TOKEN: + assert (str_1 !=3D NULL); + diag_set(ClientError, errcode, !parser->parse_only ? add : "", = len_1, + str_1); + break; + case ER_SQL_PARSER_GENERIC: + assert (str_1 !=3D NULL); + diag_set(ClientError, errcode, !parser->parse_only ? add : "", = str_1); + break; + } +} + } // end %include > Secondly, you can avoid > using different error patterns substracting from offset length("SELECT = ") > (or whatever string is added to the intial query). For instance, you = may > set offset to the negative value from very beggining of parsing = process. I think that it is better to print not error line/offset in lua queries, = which uses sql parser.=20 E. g., what we need to print in this query (wrong expression is 'X><5')? tuple =3D {513, 'CK_CONSTRAINT_01', false, 'SQL', 'X><5', true} box.space._ck_constraint:insert(tuple) commit 797e9b7a3f33ddc307b045d836f15fe3e78dbc8e Author: Roman Khabibov Date: Sat Sep 28 20:16:45 2019 +0300 sql: print line and column number in error message =20 Count the number of rows and columns during query parsing. This is to make it easier for the user to find errors in multiline queries. =20 Closes #2611 diff --git a/extra/addopcodes.sh b/extra/addopcodes.sh index c25f1e48e..cb6c84725 100755 --- a/extra/addopcodes.sh +++ b/extra/addopcodes.sh @@ -50,6 +50,7 @@ extras=3D" \ ASTERISK \ SPAN \ ANALYZE \ + LINEFEED \ SPACE \ ILLEGAL \ " diff --git a/src/box/errcode.h b/src/box/errcode.h index c660b1c70..46f10d157 100644 --- a/src/box/errcode.h +++ b/src/box/errcode.h @@ -231,14 +231,14 @@ struct errcode_record { /*176 */_(ER_SQL_CANT_RESOLVE_FIELD, "Can=E2=80=99t resolve = field '%s'") \ /*177 */_(ER_INDEX_EXISTS_IN_SPACE, "Index '%s' already = exists in space '%s'") \ /*178 */_(ER_INCONSISTENT_TYPES, "Inconsistent types: = expected %s got %s") \ - /*179 */_(ER_SQL_SYNTAX, "Syntax error in %s: = %s") \ + /*179 */_(ER_SQL_SYNTAX, "Syntax error%s in %s: = %s") \ /*180 */_(ER_SQL_STACK_OVERFLOW, "Failed to parse SQL = statement: parser stack limit reached") \ /*181 */_(ER_SQL_SELECT_WILDCARD, "Failed to expand '*' in = SELECT statement without FROM clause") \ /*182 */_(ER_SQL_STATEMENT_EMPTY, "Failed to execute an = empty SQL statement") \ - /*183 */_(ER_SQL_KEYWORD_IS_RESERVED, "Keyword '%.*s' is = reserved. Please use double quotes if '%.*s' is an identifier.") \ - /*184 */_(ER_SQL_UNRECOGNIZED_SYNTAX, "Syntax error near = '%.*s'") \ - /*185 */_(ER_SQL_UNKNOWN_TOKEN, "Syntax error: = unrecognized token: '%.*s'") \ - /*186 */_(ER_SQL_PARSER_GENERIC, "%s") \ + /*183 */_(ER_SQL_KEYWORD_IS_RESERVED, "Syntax error%s: keyword = '%.*s' is reserved. Please use double quotes if '%.*s' is an = identifier.") \ + /*184 */_(ER_SQL_UNRECOGNIZED_SYNTAX, "Syntax error%s near = '%.*s'") \ + /*185 */_(ER_SQL_UNKNOWN_TOKEN, "Syntax error%s = unrecognized token: '%.*s'") \ + /*186 */_(ER_SQL_PARSER_GENERIC, "Syntax error%s: %s") \ /*187 */_(ER_SQL_ANALYZE_ARGUMENT, "ANALYZE statement = argument %s is not a base table") \ /*188 */_(ER_SQL_COLUMN_COUNT_MAX, "Failed to create space = '%s': space column count %d exceeds the limit (%d)") \ /*189 */_(ER_HEX_LITERAL_MAX, "Hex literal %s%s length = %d exceeds the supported limit (%d)") \ diff --git a/src/box/sql/build.c b/src/box/sql/build.c index 51cd7ce63..24a8a816a 100644 --- a/src/box/sql/build.c +++ b/src/box/sql/build.c @@ -2920,7 +2920,7 @@ sqlSrcListAppendFromTerm(Parse * pParse, /* = Parsing context */ struct SrcList_item *pItem; sql *db =3D pParse->db; if (!p && (pOn || pUsing)) { - diag_set(ClientError, ER_SQL_SYNTAX, "FROM clause", + diag_set(ClientError, ER_SQL_SYNTAX, "", "FROM clause", "a JOIN clause is required before ON and = USING"); pParse->is_aborted =3D true; goto append_from_error; @@ -3117,10 +3117,10 @@ sqlWithAdd(Parse * pParse, /* Parsing = context */ } if (pWith !=3D NULL) { int i; - const char *err =3D "Ambiguous table name in WITH query: = %s"; + const char *err =3D "ambiguous table name in WITH query: = %s"; for (i =3D 0; i < pWith->nCte; i++) { if (strcmp(name, pWith->a[i].zName) =3D=3D 0) { - diag_set(ClientError, = ER_SQL_PARSER_GENERIC, + diag_set(ClientError, = ER_SQL_PARSER_GENERIC, "", tt_sprintf(err, name)); pParse->is_aborted =3D true; } @@ -3208,8 +3208,8 @@ int sql_add_autoincrement(struct Parse *parse_context, uint32_t fieldno) { if (parse_context->create_table_def.has_autoinc) { - diag_set(ClientError, ER_SQL_SYNTAX, "CREATE TABLE", = "Table " - "must feature at most one AUTOINCREMENT = field"); + diag_set(ClientError, ER_SQL_SYNTAX, "", "CREATE TABLE", + "table must feature at most one AUTOINCREMENT = field"); parse_context->is_aborted =3D true; return -1; } diff --git a/src/box/sql/expr.c b/src/box/sql/expr.c index 648b7170e..f0ed748c4 100644 --- a/src/box/sql/expr.c +++ b/src/box/sql/expr.c @@ -231,7 +231,7 @@ check_collate_arg(struct Parse *parse, struct Expr = *expr) left =3D left->pLeft; enum field_type type =3D sql_expr_type(left); if (type !=3D FIELD_TYPE_STRING && type !=3D FIELD_TYPE_SCALAR) = { - diag_set(ClientError, ER_SQL_PARSER_GENERIC, + diag_set(ClientError, ER_SQL_PARSER_GENERIC, "", "COLLATE clause can't be used with non-string " "arguments"); parse->is_aborted =3D true; @@ -1246,8 +1246,8 @@ sqlExprAssignVarNumber(Parse * pParse, Expr * = pExpr, u32 n) testcase(i =3D=3D SQL_BIND_PARAMETER_MAX - 1); testcase(i =3D=3D SQL_BIND_PARAMETER_MAX); if (is_neg || i < 1) { - diag_set(ClientError, = ER_SQL_PARSER_GENERIC, - "Index of binding slots must = start "\ + diag_set(ClientError, = ER_SQL_PARSER_GENERIC, "", + "index of binding slots must = start "\ "from 1"); pParse->is_aborted =3D true; return; @@ -1836,7 +1836,7 @@ sqlExprListAppendVector(Parse * pParse, /* = Parsing context */ && pColumns->nId !=3D (n =3D sqlExprVectorSize(pExpr))) { const char *err =3D tt_sprintf("%d columns assigned %d = values", pColumns->nId, n); - diag_set(ClientError, ER_SQL_PARSER_GENERIC, err); + diag_set(ClientError, ER_SQL_PARSER_GENERIC, "", err); pParse->is_aborted =3D true; goto vector_append_error; } @@ -3963,7 +3963,7 @@ sqlExprCodeTarget(Parse * pParse, Expr * pExpr, = int target) if (pInfo =3D=3D 0) { assert(!ExprHasProperty(pExpr, = EP_IntValue)); const char *err =3D "misuse of = aggregate: %s()"; - diag_set(ClientError, = ER_SQL_PARSER_GENERIC, + diag_set(ClientError, = ER_SQL_PARSER_GENERIC, "", tt_sprintf(err, = pExpr->u.zToken)); pParse->is_aborted =3D true; } else { @@ -4184,7 +4184,7 @@ sqlExprCodeTarget(Parse * pParse, Expr * pExpr, = int target) ) { const char *err =3D "%d columns assigned %d values"; - diag_set(ClientError, = ER_SQL_PARSER_GENERIC, + diag_set(ClientError, = ER_SQL_PARSER_GENERIC, "", tt_sprintf(err, pExpr->iTable, = n)); pParse->is_aborted =3D true; } @@ -4281,7 +4281,7 @@ sqlExprCodeTarget(Parse * pParse, Expr * pExpr, = int target) } =20 case TK_VECTOR:{ - diag_set(ClientError, ER_SQL_PARSER_GENERIC, + diag_set(ClientError, ER_SQL_PARSER_GENERIC, "", "row value misused"); pParse->is_aborted =3D true; break; @@ -4383,8 +4383,9 @@ sqlExprCodeTarget(Parse * pParse, Expr * pExpr, = int target) } case TK_RAISE: if (pParse->triggered_space =3D=3D NULL) { - diag_set(ClientError, ER_SQL_PARSER_GENERIC, = "RAISE() "\ - "may only be used within a = trigger-program"); + diag_set(ClientError, ER_SQL_PARSER_GENERIC, "", = "RAISE" + "() may only be used within a " + "trigger-program"); pParse->is_aborted =3D true; return 0; } diff --git a/src/box/sql/insert.c b/src/box/sql/insert.c index 70504c800..63360fa3c 100644 --- a/src/box/sql/insert.c +++ b/src/box/sql/insert.c @@ -383,7 +383,7 @@ sqlInsert(Parse * pParse, /* Parser context */ if (bit_test(used_columns, j)) { const char *err =3D "table id list: = duplicate "\ "column name %s"; - diag_set(ClientError, = ER_SQL_PARSER_GENERIC, + diag_set(ClientError, = ER_SQL_PARSER_GENERIC, "", tt_sprintf(err, = pColumn->a[i].zName)); pParse->is_aborted =3D true; goto insert_cleanup; @@ -500,13 +500,13 @@ sqlInsert(Parse * pParse, /* Parser context */ "table %s has %d columns but %d values were = supplied"; err =3D tt_sprintf(err, pTabList->a[0].zName, space_def->field_count, nColumn); - diag_set(ClientError, ER_SQL_PARSER_GENERIC, err); + diag_set(ClientError, ER_SQL_PARSER_GENERIC, "", err); pParse->is_aborted =3D true; goto insert_cleanup; } if (pColumn !=3D 0 && nColumn !=3D pColumn->nId) { const char *err =3D "%d values for %d columns"; - diag_set(ClientError, ER_SQL_PARSER_GENERIC, + diag_set(ClientError, ER_SQL_PARSER_GENERIC, "", tt_sprintf(err, nColumn, pColumn->nId)); pParse->is_aborted =3D true; goto insert_cleanup; diff --git a/src/box/sql/parse.y b/src/box/sql/parse.y index 1d0c95fac..b2660635b 100644 --- a/src/box/sql/parse.y +++ b/src/box/sql/parse.y @@ -33,10 +33,11 @@ UNUSED_PARAMETER(yymajor); /* Silence some compiler warnings */ assert( TOKEN.z[0] ); /* The tokenizer always gives us a token */ if (yypParser->is_fallback_failed && TOKEN.isReserved) { - diag_set(ClientError, ER_SQL_KEYWORD_IS_RESERVED, TOKEN.n, TOKEN.z, - TOKEN.n, TOKEN.z); + parser_diag_set(pParse, ER_SQL_KEYWORD_IS_RESERVED, TOKEN.n, = TOKEN.z, + TOKEN.n, TOKEN.z); } else { - diag_set(ClientError, ER_SQL_UNRECOGNIZED_SYNTAX, TOKEN.n, = TOKEN.z); + parser_diag_set(pParse, ER_SQL_UNRECOGNIZED_SYNTAX, TOKEN.n, = TOKEN.z, 0, + NULL); } pParse->is_aborted =3D true; } @@ -115,6 +116,35 @@ static void disableLookaside(Parse *pParse){ pParse->db->lookaside.bDisable++; } =20 +void parser_diag_set(struct Parse *parser, uint32_t errcode, uint32_t = len_1, + const char *str_1, uint32_t len_2, + const char *str_2) { + const char *add =3D tt_sprintf(" on line %d at column %d", + parser->line_count, = parser->line_pos); + switch (errcode) { + case ER_SQL_SYNTAX: + assert (str_1 !=3D NULL && str_2 !=3D NULL); + diag_set(ClientError, errcode, !parser->parse_only ? add : "", = str_1, + str_2); + break; + case ER_SQL_KEYWORD_IS_RESERVED: + assert(str_1 !=3D NULL && str_2 !=3D NULL); + diag_set(ClientError, errcode, !parser->parse_only ? add : "", = len_1, str_1, + len_2, str_2); + break; + case ER_SQL_UNRECOGNIZED_SYNTAX: + case ER_SQL_UNKNOWN_TOKEN: + assert (str_1 !=3D NULL); + diag_set(ClientError, errcode, !parser->parse_only ? add : "", = len_1, + str_1); + break; + case ER_SQL_PARSER_GENERIC: + assert (str_1 !=3D NULL); + diag_set(ClientError, errcode, !parser->parse_only ? add : "", = str_1); + break; + } +} + } // end %include =20 // Input is a single SQL command @@ -274,7 +304,7 @@ columnname(A) ::=3D nm(A) typedef(Y). = {sqlAddColumn(pParse,&A,&Y);} %type nm {Token} nm(A) ::=3D id(A). { if(A.isReserved) { - diag_set(ClientError, ER_SQL_KEYWORD_IS_RESERVED, A.n, A.z, A.n, = A.z); + parser_diag_set(pParse, ER_SQL_KEYWORD_IS_RESERVED, A.n, A.z, A.n, = A.z); pParse->is_aborted =3D true; } } @@ -1076,15 +1106,15 @@ expr(A) ::=3D VARIABLE(X). { Token t =3D X; if (pParse->parse_only) { spanSet(&A, &t, &t); - diag_set(ClientError, ER_SQL_PARSER_GENERIC, - "bindings are not allowed in DDL"); + parser_diag_set(pParse, ER_SQL_PARSER_GENERIC, 0, "bindings are not = allowed" + " in DDL", 0, NULL); pParse->is_aborted =3D true; A.pExpr =3D NULL; } else if (!(X.z[0]=3D=3D'#' && sqlIsdigit(X.z[1]))) { u32 n =3D X.n; spanExpr(&A, pParse, TK_VARIABLE, X); if (A.pExpr->u.zToken[0] =3D=3D '?' && n > 1) { - diag_set(ClientError, ER_SQL_UNRECOGNIZED_SYNTAX, t.n, t.z); + parser_diag_set(pParse, ER_SQL_UNRECOGNIZED_SYNTAX, t.n, t.z, 0, = NULL); pParse->is_aborted =3D true; } else { sqlExprAssignVarNumber(pParse, A.pExpr, n); @@ -1092,7 +1122,7 @@ expr(A) ::=3D VARIABLE(X). { }else{ assert( t.n>=3D2 ); spanSet(&A, &t, &t); - diag_set(ClientError, ER_SQL_UNRECOGNIZED_SYNTAX, t.n, t.z); + parser_diag_set(pParse, ER_SQL_UNRECOGNIZED_SYNTAX, t.n, t.z, 0, = NULL); pParse->is_aborted =3D true; A.pExpr =3D NULL; } @@ -1608,8 +1638,9 @@ trigger_event(A) ::=3D UPDATE(X). {A.a =3D = @X; /*A-overwrites-X*/ A.b =3D 0;} trigger_event(A) ::=3D UPDATE OF idlist(X).{A.a =3D TK_UPDATE; A.b =3D = X;} =20 foreach_clause ::=3D . { - diag_set(ClientError, ER_SQL_PARSER_GENERIC, "FOR EACH STATEMENT " - "triggers are not implemented, please supply FOR EACH ROW = clause"); + parser_diag_set(pParse, ER_SQL_PARSER_GENERIC, 0, "FOR EACH STATEMENT = " + "triggers are not implemented, please supply FOR EACH = ROW " + "clause", 0, NULL); pParse->is_aborted =3D true; } foreach_clause ::=3D FOR EACH ROW. @@ -1639,8 +1670,9 @@ trigger_cmd_list(A) ::=3D trigger_cmd(A) SEMI. { trnm(A) ::=3D nm(A). trnm(A) ::=3D nm DOT nm(X). { A =3D X; - diag_set(ClientError, ER_SQL_PARSER_GENERIC, "qualified table names = are not "\ - "allowed on INSERT, UPDATE, and DELETE statements within = triggers"); + parser_diag_set(pParse, ER_SQL_PARSER_GENERIC, 0, "qualified table = names are " + "not allowed on INSERT, UPDATE, and DELETE statements = within " + "triggers", 0, NULL); pParse->is_aborted =3D true; } =20 @@ -1650,14 +1682,15 @@ trnm(A) ::=3D nm DOT nm(X). { // tridxby ::=3D . tridxby ::=3D INDEXED BY nm. { - diag_set(ClientError, ER_SQL_SYNTAX, "trigger body", "the INDEXED BY = clause "\ - "is not allowed on UPDATE or DELETE statements within = triggers"); + parser_diag_set(pParse, ER_SQL_SYNTAX, 0, "trigger body", 0, "the = INDEXED BY " + "clause is not allowed on UPDATE or DELETE statements = within " + "triggers"); pParse->is_aborted =3D true; } tridxby ::=3D NOT INDEXED. { - diag_set(ClientError, ER_SQL_SYNTAX, "trigger body", "the NOT INDEXED = "\ - "clause is not allowed on UPDATE or DELETE statements within = "\ - "triggers"); + parser_diag_set(pParse, ER_SQL_SYNTAX, 0, "trigger body", 0, "the NOT = INDEXED " + "clause is not allowed on UPDATE or DELETE statements = within " + "triggers"); pParse->is_aborted =3D true; } =20 diff --git a/src/box/sql/prepare.c b/src/box/sql/prepare.c index 0ecc676e2..df9a7ca22 100644 --- a/src/box/sql/prepare.c +++ b/src/box/sql/prepare.c @@ -243,6 +243,8 @@ sql_parser_create(struct Parse *parser, struct sql = *db, uint32_t sql_flags) memset(parser, 0, sizeof(struct Parse)); parser->db =3D db; parser->sql_flags =3D sql_flags; + parser->line_count =3D 1; + parser->line_pos =3D 1; region_create(&parser->region, &cord()->slabc); } =20 diff --git a/src/box/sql/resolve.c b/src/box/sql/resolve.c index 6f625dc18..40c93dbf1 100644 --- a/src/box/sql/resolve.c +++ b/src/box/sql/resolve.c @@ -382,6 +382,7 @@ lookupName(Parse * pParse, /* The parsing context = */ && ExprHasProperty(pOrig, = EP_Agg)) { diag_set(ClientError, = ER_SQL_PARSER_GENERIC, + "", tt_sprintf(err, = zAs)); pParse->is_aborted =3D = true; return WRC_Abort; @@ -389,6 +390,7 @@ lookupName(Parse * pParse, /* The parsing context = */ if (sqlExprVectorSize(pOrig) !=3D = 1) { diag_set(ClientError, = ER_SQL_PARSER_GENERIC, + "", "row value = misused"); pParse->is_aborted =3D = true; return WRC_Abort; @@ -424,7 +426,7 @@ lookupName(Parse * pParse, /* The parsing context = */ } else { err =3D tt_sprintf("ambiguous column name: %s", = zCol); } - diag_set(ClientError, ER_SQL_PARSER_GENERIC, err); + diag_set(ClientError, ER_SQL_PARSER_GENERIC, "", err); pParse->is_aborted =3D true; pTopNC->nErr++; } @@ -606,7 +608,7 @@ resolveExprStep(Walker * pWalker, Expr * pExpr) return WRC_Abort; } if (!func->def->exports.sql) { - diag_set(ClientError, = ER_SQL_PARSER_GENERIC, + diag_set(ClientError, = ER_SQL_PARSER_GENERIC, "", tt_sprintf("function %.*s() is = not " "available in SQL", nId, zId)); @@ -661,7 +663,8 @@ resolveExprStep(Walker * pWalker, Expr * pExpr) const char *err =3D tt_sprintf("misuse of aggregate = "\ "function %.*s()", = nId, zId); - diag_set(ClientError, = ER_SQL_PARSER_GENERIC, err); + diag_set(ClientError, = ER_SQL_PARSER_GENERIC, "", + err); pParse->is_aborted =3D true; pNC->nErr++; is_agg =3D 0; @@ -917,13 +920,14 @@ resolveCompoundOrderBy(Parse * pParse, /* = Parsing context. Leave error messages if (sqlExprIsInteger(pE, &iCol)) { if (iCol <=3D 0 || iCol > pEList->nExpr) = { const char *err =3D - "Error at ORDER BY in = place "\ + "error at ORDER BY in = place "\ "%d: term out of range - = "\ "should be between 1 and = %d"; err =3D tt_sprintf(err, i + 1, pEList->nExpr); diag_set(ClientError, - ER_SQL_PARSER_GENERIC, = err); + ER_SQL_PARSER_GENERIC, = "", + err); pParse->is_aborted =3D true; return 1; } @@ -973,10 +977,10 @@ resolveCompoundOrderBy(Parse * pParse, /* = Parsing context. Leave error messages } for (i =3D 0; i < pOrderBy->nExpr; i++) { if (pOrderBy->a[i].done =3D=3D 0) { - const char *err =3D "Error at ORDER BY in place = %d: "\ + const char *err =3D "error at ORDER BY in place = %d: "\ "term does not match any = column in "\ "the result set"; - diag_set(ClientError, ER_SQL_PARSER_GENERIC, + diag_set(ClientError, ER_SQL_PARSER_GENERIC, "", tt_sprintf(err, i + 1)); pParse->is_aborted =3D true; return 1; @@ -1023,12 +1027,12 @@ sqlResolveOrderGroupBy(Parse * pParse, /* = Parsing context. Leave error messages for (i =3D 0, pItem =3D pOrderBy->a; i < pOrderBy->nExpr; i++, = pItem++) { if (pItem->u.x.iOrderByCol) { if (pItem->u.x.iOrderByCol > pEList->nExpr) { - const char *err =3D "Error at %s BY in = place "\ + const char *err =3D "error at %s BY in = place "\ "%d: term out of range = - "\ "should be between 1 = and %d"; err =3D tt_sprintf(err, zType, i + 1, pEList->nExpr); - diag_set(ClientError, = ER_SQL_PARSER_GENERIC, + diag_set(ClientError, = ER_SQL_PARSER_GENERIC, "", err); pParse->is_aborted =3D true; return 1; @@ -1094,11 +1098,11 @@ resolveOrderGroupBy(NameContext * pNC, /* The = name context of the SELECT stateme * order-by term to a copy of the result-set = expression */ if (iCol < 1 || iCol > 0xffff) { - const char *err =3D "Error at %s BY in = place "\ + const char *err =3D "error at %s BY in = place "\ "%d: term out of range = - "\ "should be between 1 = and %d"; err =3D tt_sprintf(err, zType, i + 1, = nResult); - diag_set(ClientError, = ER_SQL_PARSER_GENERIC, + diag_set(ClientError, = ER_SQL_PARSER_GENERIC, "", err); pParse->is_aborted =3D true; return 1; @@ -1387,7 +1391,7 @@ resolveSelectStep(Walker * pWalker, Select * p) i++, pItem++) { if (ExprHasProperty(pItem->pExpr, = EP_Agg)) { diag_set(ClientError, - ER_SQL_PARSER_GENERIC, + ER_SQL_PARSER_GENERIC, = "", err_msg); pParse->is_aborted =3D true; return WRC_Abort; @@ -1400,7 +1404,7 @@ resolveSelectStep(Walker * pWalker, Select * p) */ if (p->pNext && p->pEList->nExpr !=3D = p->pNext->pEList->nExpr) { if (p->pNext->selFlags & SF_Values) { - diag_set(ClientError, = ER_SQL_PARSER_GENERIC, + diag_set(ClientError, = ER_SQL_PARSER_GENERIC, "", "all VALUES must have the same = "\ "number of terms"); } else { @@ -1410,7 +1414,7 @@ resolveSelectStep(Walker * pWalker, Select * p) "result columns"; const char *op =3D = sql_select_op_name(p->pNext->op); - diag_set(ClientError, = ER_SQL_PARSER_GENERIC, + diag_set(ClientError, = ER_SQL_PARSER_GENERIC, "", tt_sprintf(err, op)); } pParse->is_aborted =3D true; diff --git a/src/box/sql/select.c b/src/box/sql/select.c index 8f93edd16..0371a73c6 100644 --- a/src/box/sql/select.c +++ b/src/box/sql/select.c @@ -451,7 +451,7 @@ sqlJoinType(Parse * pParse, Token * pA, Token * pB, = Token * pC) "%.*s %.*s %.*s", pA->n, pA->z, = pB->n, pB->z, pC->n, pC->z); } - diag_set(ClientError, ER_SQL_PARSER_GENERIC, err); + diag_set(ClientError, ER_SQL_PARSER_GENERIC, "", err); pParse->is_aborted =3D true; jointype =3D JT_INNER; } else if ((jointype & JT_OUTER) !=3D 0 @@ -640,7 +640,7 @@ sqlProcessJoin(Parse * pParse, Select * p) */ if (pRight->fg.jointype & JT_NATURAL) { if (pRight->pOn || pRight->pUsing) { - diag_set(ClientError, = ER_SQL_PARSER_GENERIC, + diag_set(ClientError, = ER_SQL_PARSER_GENERIC, "", "a NATURAL join may not have " "an ON or USING clause"); pParse->is_aborted =3D true; @@ -664,7 +664,7 @@ sqlProcessJoin(Parse * pParse, Select * p) /* Disallow both ON and USING clauses in the same join */ if (pRight->pOn && pRight->pUsing) { - diag_set(ClientError, ER_SQL_PARSER_GENERIC, + diag_set(ClientError, ER_SQL_PARSER_GENERIC, "", "cannot have both ON and USING clauses = in "\ "the same join"); pParse->is_aborted =3D true; @@ -709,7 +709,7 @@ sqlProcessJoin(Parse * pParse, Select * p) ) { err =3D tt_sprintf(err, zName); diag_set(ClientError, - ER_SQL_PARSER_GENERIC, = err); + ER_SQL_PARSER_GENERIC, = "", err); pParse->is_aborted =3D true; return 1; } @@ -2115,7 +2115,7 @@ computeLimitRegisters(Parse * pParse, Select * p, = int iBreak) if((p->pLimit->flags & EP_Collate) !=3D 0 || (p->pOffset !=3D NULL && (p->pOffset->flags & EP_Collate) !=3D 0)) { - diag_set(ClientError, = ER_SQL_UNRECOGNIZED_SYNTAX, + diag_set(ClientError, = ER_SQL_UNRECOGNIZED_SYNTAX, "", sizeof("COLLATE"), "COLLATE"); pParse->is_aborted =3D true; return; @@ -2618,7 +2618,7 @@ multiSelect(Parse * pParse, /* Parsing = context */ const char *err_msg =3D tt_sprintf("ORDER BY clause should come after %s = not "\ "before", sql_select_op_name(p->op)); - diag_set(ClientError, ER_SQL_PARSER_GENERIC, err_msg); + diag_set(ClientError, ER_SQL_PARSER_GENERIC, "", = err_msg); pParse->is_aborted =3D true; rc =3D 1; goto multi_select_end; @@ -2627,7 +2627,7 @@ multiSelect(Parse * pParse, /* Parsing = context */ const char *err_msg =3D tt_sprintf("LIMIT clause should come after %s = not "\ "before", sql_select_op_name(p->op)); - diag_set(ClientError, ER_SQL_PARSER_GENERIC, err_msg); + diag_set(ClientError, ER_SQL_PARSER_GENERIC, "", = err_msg); pParse->is_aborted =3D true; rc =3D 1; goto multi_select_end; @@ -4642,14 +4642,14 @@ withExpand(Walker * pWalker, struct SrcList_item = *pFrom) * In this case, proceed. */ if (pCte->zCteErr) { - diag_set(ClientError, ER_SQL_PARSER_GENERIC, + diag_set(ClientError, ER_SQL_PARSER_GENERIC, "", tt_sprintf(pCte->zCteErr, = pCte->zName)); pParse->is_aborted =3D true; return -1; } if (pFrom->fg.isTabFunc) { const char *err =3D "'%s' is not a function"; - diag_set(ClientError, ER_SQL_PARSER_GENERIC, + diag_set(ClientError, ER_SQL_PARSER_GENERIC, "", tt_sprintf(err, pFrom->zName)); pParse->is_aborted =3D true; return -1; @@ -4688,7 +4688,8 @@ withExpand(Walker * pWalker, struct SrcList_item = *pFrom) const char *err_msg =3D tt_sprintf("multiple references to = recursive "\ "table: %s", pCte->zName); - diag_set(ClientError, ER_SQL_PARSER_GENERIC, = err_msg); + diag_set(ClientError, ER_SQL_PARSER_GENERIC, "", + err_msg); pParse->is_aborted =3D true; return -1; } @@ -4710,7 +4711,8 @@ withExpand(Walker * pWalker, struct SrcList_item = *pFrom) "for %d columns", pCte->zName, = pEList->nExpr, pCte->pCols->nExpr); - diag_set(ClientError, = ER_SQL_PARSER_GENERIC, err_msg); + diag_set(ClientError, = ER_SQL_PARSER_GENERIC, "", + err_msg); pParse->is_aborted =3D true; pParse->pWith =3D pSavedWith; return -1; @@ -4865,7 +4867,7 @@ selectExpander(Walker * pWalker, Select * p) const char *err =3D tt_sprintf("'%s' is not a = function", pFrom->zName); - diag_set(ClientError, = ER_SQL_PARSER_GENERIC, + diag_set(ClientError, = ER_SQL_PARSER_GENERIC, "", err); pParse->is_aborted =3D true; return WRC_Abort; @@ -5285,7 +5287,7 @@ resetAccumulator(Parse * pParse, AggInfo * = pAggInfo) Expr *pE =3D pFunc->pExpr; assert(!ExprHasProperty(pE, EP_xIsSelect)); if (pE->x.pList =3D=3D 0 || pE->x.pList->nExpr = !=3D 1) { - diag_set(ClientError, = ER_SQL_PARSER_GENERIC, + diag_set(ClientError, = ER_SQL_PARSER_GENERIC, "", "DISTINCT aggregates must have = "\ "exactly one argument"); pParse->is_aborted =3D true; diff --git a/src/box/sql/sqlInt.h b/src/box/sql/sqlInt.h index 2594b73e0..df821a26b 100644 --- a/src/box/sql/sqlInt.h +++ b/src/box/sql/sqlInt.h @@ -2181,6 +2181,10 @@ struct Parse { = ***********************************************************************/ =20 Token sLastToken; /* The last token parsed */ + /** The line counter. */ + uint32_t line_count; + /** The position in a line. */ + uint32_t line_pos; ynVar nVar; /* Number of '?' variables seen in the = SQL so far */ u8 explain; /* True if the EXPLAIN flag is found on = the query */ int nHeight; /* Expression tree height of current = sub-select */ @@ -4467,4 +4471,16 @@ int sql_fieldno_by_name(struct Parse *parse_context, struct Expr = *field_name, uint32_t *fieldno); =20 +/** + * Call diag_set() with or without error line and offset. + * + * @param parser Parser. + * @param len String length. + * @param str_1 Ptr to first string. + * @param str_2 Ptr to second string. + */ +void +parser_diag_set(struct Parse *parser, uint32_t errcode, uint32_t len_1, + const char *str_1, uint32_t len_2, const char *str_2); + #endif /* sqlINT_H */ diff --git a/src/box/sql/tokenize.c b/src/box/sql/tokenize.c index 9fa069d09..1e44c4312 100644 --- a/src/box/sql/tokenize.c +++ b/src/box/sql/tokenize.c @@ -82,10 +82,11 @@ #define CC_TILDA 25 /* '~' */ #define CC_DOT 26 /* '.' */ #define CC_ILLEGAL 27 /* Illegal character */ +#define CC_LINEFEED 28 /* '\n' */ =20 static const char sql_ascii_class[] =3D { /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xa xb xc xd xe xf */ -/* 0x */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 7, 7, 7, 7, 7, 27, 27, +/* 0x */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 7, 28, 7, 7, 7, 27, 27, /* 1x */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, = 27, /* 2x */ 7, 15, 9, 5, 4, 22, 24, 8, 17, 18, 21, 20, 23, 11, 26, 16, /* 3x */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 19, 12, 14, 13, 6, @@ -192,12 +193,24 @@ sql_token(const char *z, int *type, bool = *is_reserved) i =3D 1 + sql_skip_spaces(z+1); *type =3D TK_SPACE; return i; + case CC_LINEFEED: + *type =3D TK_LINEFEED; + return 1; case CC_MINUS: + /* + * Ignore single-line comment started with "--" + * till the end of parsing string or next line. + */ if (z[1] =3D=3D '-') { - for (i =3D 2; (c =3D z[i]) !=3D 0 && c !=3D = '\n'; i++) { + for (i =3D 2; true; i++) { + if (z[i] =3D=3D '\0') { + *type =3D TK_SPACE; + return i; + } else if (z[i] =3D=3D '\n') { + *type =3D TK_LINEFEED; + return ++i; + } } - *type =3D TK_SPACE; - return i; } *type =3D TK_MINUS; return 1; @@ -499,12 +512,16 @@ sqlRunParser(Parse * pParse, const char *zSql) assert(tokenType =3D=3D TK_SPACE || tokenType =3D=3D TK_ILLEGAL); if (tokenType =3D=3D TK_ILLEGAL) { - diag_set(ClientError, = ER_SQL_UNKNOWN_TOKEN, + parser_diag_set(pParse, = ER_SQL_UNKNOWN_TOKEN, pParse->sLastToken.n, - pParse->sLastToken.z); + pParse->sLastToken.z, 0, NULL); pParse->is_aborted =3D true; break; } + } else if (tokenType =3D=3D TK_LINEFEED) { + pParse->line_count++; + pParse->line_pos =3D 1; + continue; } else { sqlParser(pEngine, tokenType, = pParse->sLastToken, pParse); @@ -512,6 +529,7 @@ sqlRunParser(Parse * pParse, const char *zSql) if (pParse->is_aborted || db->mallocFailed) break; } + pParse->line_pos +=3D pParse->sLastToken.n; } pParse->zTail =3D &zSql[i]; sqlParserFree(pEngine, sql_free); diff --git a/src/box/sql/trigger.c b/src/box/sql/trigger.c index 0c387bc3b..283e67f53 100644 --- a/src/box/sql/trigger.c +++ b/src/box/sql/trigger.c @@ -595,8 +595,8 @@ codeTriggerProgram(Parse * pParse, /* The parser = context */ sqlSubProgramsRemaining--; =20 if (sqlSubProgramsRemaining =3D=3D 0) { - diag_set(ClientError, ER_SQL_PARSER_GENERIC, "Maximum = number "\ - "of chained trigger activations exceeded."); + diag_set(ClientError, ER_SQL_PARSER_GENERIC, "", = "maximum " + "number of chained trigger activations = exceeded."); pParse->is_aborted =3D true; } =20 diff --git a/src/box/sql/update.c b/src/box/sql/update.c index 6d69b7252..7d46e3cee 100644 --- a/src/box/sql/update.c +++ b/src/box/sql/update.c @@ -156,7 +156,7 @@ sqlUpdate(Parse * pParse, /* The parser = context */ err =3D tt_sprintf(err, = pChanges->a[i].zName); diag_set(ClientError, - ER_SQL_PARSER_GENERIC, + ER_SQL_PARSER_GENERIC, = "", err); pParse->is_aborted =3D true; goto update_cleanup; diff --git a/test/box/function1.result b/test/box/function1.result index b91d63c51..a1020471d 100644 --- a/test/box/function1.result +++ b/test/box/function1.result @@ -387,7 +387,7 @@ test_run:cmd("setopt delimiter ''"); box.execute('SELECT "function1.divide"()') --- - null -- function function1.divide() is not available in SQL +- 'Syntax error: function function1.divide() is not available in SQL' ... box.func["function1.divide"]:drop() --- diff --git a/test/sql-tap/alter2.test.lua b/test/sql-tap/alter2.test.lua index e0bd60727..9f53ab86a 100755 --- a/test/sql-tap/alter2.test.lua +++ b/test/sql-tap/alter2.test.lua @@ -223,7 +223,7 @@ test:do_catchsql_test( ALTER TABLE child ADD CONSTRAINT fk FOREIGN KEY REFERENCES = child(id); ]], { -- - 1, "Keyword 'REFERENCES' is reserved. Please use double quotes = if 'REFERENCES' is an identifier." + 1, "Syntax error on line 1 at column 57: keyword 'REFERENCES' = is reserved. Please use double quotes if 'REFERENCES' is an identifier." -- }) =20 @@ -233,7 +233,7 @@ test:do_catchsql_test( ALTER TABLE child ADD CONSTRAINT fk () FOREIGN KEY REFERENCES = child(id); ]], { -- - 1, "Syntax error near '('" + 1, "Syntax error on line 1 at column 45 near '('" -- }) =20 diff --git a/test/sql-tap/autoinc.test.lua = b/test/sql-tap/autoinc.test.lua index 39e47966b..a7745f390 100755 --- a/test/sql-tap/autoinc.test.lua +++ b/test/sql-tap/autoinc.test.lua @@ -880,7 +880,7 @@ test:do_catchsql_test( [[ CREATE TABLE t11_7 (i INT AUTOINCREMENT, a INT AUTOINCREMENT, = PRIMARY KEY(a, i)); ]], { - 1, "Syntax error in CREATE TABLE: Table must feature at most = one AUTOINCREMENT field" + 1, "Syntax error in CREATE TABLE: table must feature at most = one AUTOINCREMENT field" }) =20 test:do_catchsql_test( @@ -888,7 +888,7 @@ test:do_catchsql_test( [[ CREATE TABLE t11_8 (i INT, a INT, PRIMARY KEY(a AUTOINCREMENT, = i AUTOINCREMENT)); ]], { - 1, "Syntax error in CREATE TABLE: Table must feature at most = one AUTOINCREMENT field" + 1, "Syntax error in CREATE TABLE: table must feature at most = one AUTOINCREMENT field" }) =20 test:do_catchsql_test( diff --git a/test/sql-tap/blob.test.lua b/test/sql-tap/blob.test.lua index 2b5c7a9ca..e5d88eef9 100755 --- a/test/sql-tap/blob.test.lua +++ b/test/sql-tap/blob.test.lua @@ -72,7 +72,7 @@ test:do_catchsql_test( SELECT X'01020k304', 100 ]], { -- - 1, [[Syntax error: unrecognized token: 'X'01020k304'']] + 1, [[Syntax error on line 1 at column 16 unrecognized token: = 'X'01020k304'']] -- }) =20 @@ -81,7 +81,7 @@ test:do_catchsql_test( [[ SELECT X'01020, 100]], { -- - 1, [[Syntax error: unrecognized token: 'X'01020, 100']] + 1, [[Syntax error on line 1 at column 16 unrecognized token: = 'X'01020, 100']] -- }) =20 @@ -91,7 +91,7 @@ test:do_catchsql_test( SELECT X'01020 100' ]], { -- - 1, [[Syntax error: unrecognized token: 'X'01020 100'']] + 1, [[Syntax error on line 1 at column 16 unrecognized token: = 'X'01020 100'']] -- }) =20 @@ -101,7 +101,7 @@ test:do_catchsql_test( SELECT X'01001' ]], { -- - 1, [[Syntax error: unrecognized token: 'X'01001'']] + 1, [[Syntax error on line 1 at column 16 unrecognized token: = 'X'01001'']] -- }) =20 @@ -111,7 +111,7 @@ test:do_catchsql_test( SELECT x'012/45' ]], { -- - 1, [[Syntax error: unrecognized token: 'x'012/45'']] + 1, [[Syntax error on line 1 at column 16 unrecognized token: = 'x'012/45'']] -- }) =20 @@ -121,7 +121,7 @@ test:do_catchsql_test( SELECT x'012:45' ]], { -- - 1, [[Syntax error: unrecognized token: 'x'012:45'']] + 1, [[Syntax error on line 1 at column 16 unrecognized token: = 'x'012:45'']] -- }) =20 @@ -131,7 +131,7 @@ test:do_catchsql_test( SELECT x'012@45' ]], { -- - 1, [[Syntax error: unrecognized token: 'x'012@45'']] + 1, [[Syntax error on line 1 at column 16 unrecognized token: = 'x'012@45'']] -- }) =20 @@ -141,7 +141,7 @@ test:do_catchsql_test( SELECT x'012G45' ]], { -- - 1, [[Syntax error: unrecognized token: 'x'012G45'']] + 1, [[Syntax error on line 1 at column 16 unrecognized token: = 'x'012G45'']] -- }) =20 @@ -151,7 +151,7 @@ test:do_catchsql_test( SELECT x'012`45' ]], { -- - 1, [[Syntax error: unrecognized token: 'x'012`45'']] + 1, [[Syntax error on line 1 at column 16 unrecognized token: = 'x'012`45'']] -- }) =20 @@ -161,7 +161,7 @@ test:do_catchsql_test( SELECT x'012g45' ]], { -- - 1, [[Syntax error: unrecognized token: 'x'012g45'']] + 1, [[Syntax error on line 1 at column 16 unrecognized token: = 'x'012g45'']] -- }) =20 diff --git a/test/sql-tap/check.test.lua b/test/sql-tap/check.test.lua index c9b60bbf5..c0b1554de 100755 --- a/test/sql-tap/check.test.lua +++ b/test/sql-tap/check.test.lua @@ -282,7 +282,7 @@ test:do_catchsql_test( ); ]], { -- - 1,"Syntax error near ','" + 1,"Syntax error on line 2 at column 77 near ','" -- }) =20 @@ -296,7 +296,7 @@ test:do_catchsql_test( ); ]], { -- - 1,"Syntax error near ','" + 1,"Syntax error on line 3 at column 23 near ','" -- }) =20 @@ -517,7 +517,7 @@ test:do_catchsql_test( ); ]], { -- - 1, "Failed to create check constraint 'ck_unnamed_T5_1': = bindings are not allowed in DDL" + 1, "Failed to create check constraint 'ck_unnamed_T5_1': Syntax = error: bindings are not allowed in DDL" -- }) =20 @@ -529,7 +529,7 @@ test:do_catchsql_test( ); ]], { -- - 1, "Failed to create check constraint 'ck_unnamed_T5_1': = bindings are not allowed in DDL" + 1, "Failed to create check constraint 'ck_unnamed_T5_1': Syntax = error: bindings are not allowed in DDL" -- }) =20 @@ -783,7 +783,7 @@ test:do_catchsql_test( ON CONFLICT REPLACE) ]], { -- <9.1> - 1, "Keyword 'ON' is reserved. Please use double quotes if 'ON' = is an identifier." + 1, "Syntax error on line 2 at column 9: keyword 'ON' is = reserved. Please use double quotes if 'ON' is an identifier." -- }) =20 @@ -794,7 +794,7 @@ test:do_catchsql_test( ON CONFLICT ABORT) ]], { -- <9.2> - 1, "Keyword 'ON' is reserved. Please use double quotes if 'ON' = is an identifier." + 1, "Syntax error on line 2 at column 9: keyword 'ON' is = reserved. Please use double quotes if 'ON' is an identifier." -- }) =20 @@ -805,7 +805,7 @@ test:do_catchsql_test( ON CONFLICT ROLLBACK) ]], { -- <9.3> - 1, "Keyword 'ON' is reserved. Please use double quotes if 'ON' = is an identifier." + 1, "Syntax error on line 2 at column 9: keyword 'ON' is = reserved. Please use double quotes if 'ON' is an identifier." -- }) =20 diff --git a/test/sql-tap/collation.test.lua = b/test/sql-tap/collation.test.lua index f7099b222..b76a334b7 100755 --- a/test/sql-tap/collation.test.lua +++ b/test/sql-tap/collation.test.lua @@ -551,28 +551,28 @@ test:do_execsql_test( test:do_catchsql_test( "collation-2.7.1", 'SELECT one COLLATE "binary" FROM test1', - {1, "COLLATE clause can't be used with non-string arguments"}) + {1, "Syntax error: COLLATE clause can't be used with non-string = arguments"}) =20 test:do_catchsql_test( "collation-2.7.2", 'SELECT one COLLATE "unicode_ci" FROM test1', - {1, "COLLATE clause can't be used with non-string arguments"}) + {1, "Syntax error: COLLATE clause can't be used with non-string = arguments"}) =20 test:do_catchsql_test( "collation-2.7.3", 'SELECT two COLLATE "binary" FROM test1', - {1, "COLLATE clause can't be used with non-string arguments"}) + {1, "Syntax error: COLLATE clause can't be used with non-string = arguments"}) =20 =20 test:do_catchsql_test( "collation-2.7.4", 'SELECT (one + two) COLLATE "binary" FROM test1', - {1, "COLLATE clause can't be used with non-string arguments"}) + {1, "Syntax error: COLLATE clause can't be used with non-string = arguments"}) =20 test:do_catchsql_test( "collation-2.7.5", 'SELECT (SELECT one FROM test1) COLLATE "binary"', - {1, "COLLATE clause can't be used with non-string arguments"}) + {1, "Syntax error: COLLATE clause can't be used with non-string = arguments"}) =20 test:do_execsql_test( "collation-2.7.6", @@ -582,32 +582,32 @@ test:do_execsql_test( test:do_catchsql_test( "collation-2.7.7", 'SELECT RANDOM() COLLATE "binary"', - {1, "COLLATE clause can't be used with non-string arguments"}) + {1, "Syntax error: COLLATE clause can't be used with non-string = arguments"}) =20 test:do_catchsql_test( "collation-2.7.8", 'SELECT LENGTH(\'A\') COLLATE "binary"', - {1, "COLLATE clause can't be used with non-string arguments"}) + {1, "Syntax error: COLLATE clause can't be used with non-string = arguments"}) =20 test:do_catchsql_test( "collation-2.7.9", 'SELECT TRUE COLLATE "unicode"', - {1, "COLLATE clause can't be used with non-string arguments"}) + {1, "Syntax error: COLLATE clause can't be used with non-string = arguments"}) =20 test:do_catchsql_test( "collation-2.7.10", 'SELECT NOT TRUE COLLATE "unicode"', - {1, "COLLATE clause can't be used with non-string arguments"}) + {1, "Syntax error: COLLATE clause can't be used with non-string = arguments"}) =20 test:do_catchsql_test( "collation-2.7.11", 'SELECT TRUE AND TRUE COLLATE "unicode"', - {1, "COLLATE clause can't be used with non-string arguments"}) + {1, "Syntax error: COLLATE clause can't be used with non-string = arguments"}) =20 test:do_catchsql_test( "collation-2.7.12", 'SELECT 1 | 1 COLLATE "unicode"', - {1, "COLLATE clause can't be used with non-string arguments"}) + {1, "Syntax error: COLLATE clause can't be used with non-string = arguments"}) =20 test:do_execsql_test( "collation-2.7.14", diff --git a/test/sql-tap/count.test.lua b/test/sql-tap/count.test.lua index cf5bfccdd..354a464a4 100755 --- a/test/sql-tap/count.test.lua +++ b/test/sql-tap/count.test.lua @@ -128,7 +128,7 @@ test:do_catchsql_test( SELECT count(DISTINCT *) FROM t2 ]], { -- - 1, [[Syntax error near '*']] + 1, [[Syntax error on line 1 at column 31 near '*']] -- }) =20 @@ -156,7 +156,7 @@ test:do_catchsql_test( SELECT count(DISTINCT) FROM t2 ]], { -- - 1, "DISTINCT aggregates must have exactly one argument" + 1, "Syntax error: DISTINCT aggregates must have exactly one = argument" -- }) =20 @@ -290,7 +290,7 @@ test:do_catchsql_test( SELECT count(DISTINCT) FROM t6 GROUP BY x; ]], { -- - 1, "DISTINCT aggregates must have exactly one argument" + 1, "Syntax error: DISTINCT aggregates must have exactly one = argument" -- }) =20 diff --git a/test/sql-tap/default.test.lua = b/test/sql-tap/default.test.lua index f2a5db071..9feca0df1 100755 --- a/test/sql-tap/default.test.lua +++ b/test/sql-tap/default.test.lua @@ -224,7 +224,7 @@ test:do_catchsql_test( CREATE TABLE t6(id INTEGER PRIMARY KEY, b TEXT DEFAULT id); ]], { -- - 1, "Syntax error near 'id'" + 1, "Syntax error on line 1 at column 64 near 'id'" -- }) =20 @@ -234,7 +234,7 @@ test:do_catchsql_test( CREATE TABLE t6(id INTEGER PRIMARY KEY, b TEXT DEFAULT "id"); ]], { -- - 1, "Syntax error near '\"id\"'" + 1, "Syntax error on line 1 at column 64 near '\"id\"'" -- }) =20 diff --git a/test/sql-tap/distinctagg.test.lua = b/test/sql-tap/distinctagg.test.lua index 5454bf0ed..8e0042f77 100755 --- a/test/sql-tap/distinctagg.test.lua +++ b/test/sql-tap/distinctagg.test.lua @@ -75,7 +75,7 @@ test:do_catchsql_test( SELECT count(distinct) FROM t1; ]], { -- - 1, "DISTINCT aggregates must have exactly one argument" + 1, "Syntax error: DISTINCT aggregates must have exactly one = argument" -- }) =20 @@ -85,7 +85,7 @@ test:do_catchsql_test( SELECT group_concat(distinct a,b) FROM t1; ]], { -- - 1, "DISTINCT aggregates must have exactly one argument" + 1, "Syntax error: DISTINCT aggregates must have exactly one = argument" -- }) =20 diff --git a/test/sql-tap/e_select1.test.lua = b/test/sql-tap/e_select1.test.lua index a0a671644..0d9b29453 100755 --- a/test/sql-tap/e_select1.test.lua +++ b/test/sql-tap/e_select1.test.lua @@ -95,7 +95,7 @@ test:do_catchsql_test( SELECT count(*) FROM t1, t2 ON (t1.a=3Dt2.a) USING (a) ]], { -- - 1, "cannot have both ON and USING clauses in the same join" + 1, "Syntax error: cannot have both ON and USING clauses in the = same join" -- }) =20 @@ -105,7 +105,7 @@ test:do_catchsql_test( SELECT count(*) FROM t1, t2 USING (a) ON (t1.a=3Dt2.a) ]], { -- - 1, [[Keyword 'ON' is reserved. Please use double quotes if 'ON' = is an identifier.]] + 1, [[Syntax error on line 1 at column 47: keyword 'ON' is = reserved. Please use double quotes if 'ON' is an identifier.]] -- }) =20 @@ -643,7 +643,7 @@ for tn, sql in ipairs(data) do string.format([[ %s ]], sql), { - 1, "a NATURAL join may not have an ON or USING clause" + 1, "Syntax error: a NATURAL join may not have an ON or = USING clause" }) =20 end @@ -805,9 +805,9 @@ test:do_select_tests( -- FROM clause. -- data =3D { - {"1.1", "SELECT a, b, c FROM z1 WHERE *", "Syntax error near = '*'"}, - {"1.2", "SELECT a, b, c FROM z1 GROUP BY *", "Syntax error near = '*'"}, - {"1.3", "SELECT 1 + * FROM z1", "Syntax error near '*'"}, + {"1.1", "SELECT a, b, c FROM z1 WHERE *", "Syntax error on line 1 = at column 30 near '*'"}, + {"1.2", "SELECT a, b, c FROM z1 GROUP BY *", "Syntax error on line = 1 at column 33 near '*'"}, + {"1.3", "SELECT 1 + * FROM z1", "Syntax error on line 1 at column = 12 near '*'"}, {"1.4", "SELECT * + 1 FROM z1", "Failed to expand '*' in SELECT = statement without FROM clause"}, {"2.1", "SELECT *", "Failed to expand '*' in SELECT statement = without FROM clause"}, {"2.2", "SELECT * WHERE 1", "Failed to expand '*' in SELECT = statement without FROM clause"}, @@ -1064,7 +1064,7 @@ data =3D { for _, val in ipairs(data) do local tn =3D val[1] local select =3D val[2] - local res =3D {1, "aggregate functions are not allowed in the GROUP = BY clause"} + local res =3D {1, "Syntax error: aggregate functions are not = allowed in the GROUP BY clause"} test:do_catchsql_test( "e_select-4."..tn, select, res) @@ -1341,7 +1341,7 @@ for tn, val in ipairs(data) do local sql =3D val[1] local subst =3D val[2] local label =3D "e_select-7.1."..tn - local error =3D string.format("SELECTs to the left and right of %s = do not have the same number of result columns", subst) + local error =3D string.format("Syntax error: SELECTs to the left = and right of %s do not have the same number of result columns", subst) test:do_catchsql_test( label, sql, @@ -1380,7 +1380,7 @@ for _, val in ipairs(data) do local op1 =3D val[3] local op2 =3D val[4] local label =3D "e_select-7.2."..tn - local error =3D string.format("%s clause should come after %s not = before", op1, op2) + local error =3D string.format("Syntax error: %s clause should come = after %s not before", op1, op2) test:do_catchsql_test( label, select, @@ -1853,13 +1853,13 @@ test:do_catchsql_test( "e_select-8.7.1.1", "SELECT x FROM d1 UNION ALL SELECT a FROM d2 ORDER BY x*z", { - 1, "Error at ORDER BY in place 1: term does not match any = column in the result set"}) + 1, "Syntax error: error at ORDER BY in place 1: term does not = match any column in the result set"}) =20 test:do_catchsql_test( "e_select-8.7.1.2", "SELECT x,z FROM d1 UNION ALL SELECT a,b FROM d2 ORDER BY x, x/z", { - 1, "Error at ORDER BY in place 2: term does not match any = column in the result set"}) + 1, "Syntax error: error at ORDER BY in place 2: term does not = match any column in the result set"}) =20 test:do_select_tests( "e_select-8.7.2", @@ -2088,7 +2088,7 @@ for _, val in ipairs({{1, "SELECT a FROM d5 UNION = SELECT c FROM d6 ORDER BY a+1" "e_select-8.14."..tn, select, { - 1, string.format("Error at ORDER BY in place %s: term does = not match any column in the result set", err_param)}) + 1, string.format("Syntax error: error at ORDER BY in place = %s: term does not match any column in the result set", err_param)}) end -- EVIDENCE-OF: R-03407-11483 Each term of the ORDER BY clause is -- processed separately and may be matched against result columns from diff --git a/test/sql-tap/func.test.lua b/test/sql-tap/func.test.lua index 4574ddfeb..10651be15 100755 --- a/test/sql-tap/func.test.lua +++ b/test/sql-tap/func.test.lua @@ -1882,7 +1882,7 @@ test:do_catchsql_test( SELECT trim(1,2,3) ]], { -- - 1, "Syntax error near ','" + 1, "Syntax error on line 1 at column 22 near ','" -- }) =20 @@ -2228,7 +2228,7 @@ test:do_catchsql_test( SELECT TRIM(FROM 'xyxzy'); ]], { -- - 1, "Syntax error near 'FROM'" + 1, "Syntax error on line 1 at column 21 near 'FROM'" -- }) =20 diff --git a/test/sql-tap/gh-3307-xfer-optimization-issue.test.lua = b/test/sql-tap/gh-3307-xfer-optimization-issue.test.lua index bb8a4989e..5e8061424 100755 --- a/test/sql-tap/gh-3307-xfer-optimization-issue.test.lua +++ b/test/sql-tap/gh-3307-xfer-optimization-issue.test.lua @@ -85,7 +85,7 @@ test:do_catchsql_xfer_test( INSERT INTO t2 SELECT * FROM t1; ]], { -- - 1, "table T2 has 2 columns but 3 values were supplied" + 1, "Syntax error: table T2 has 2 columns but 3 values were = supplied" -- }, { exp_xfer_count =3D 0 diff --git a/test/sql-tap/gh2168-temp-tables.test.lua = b/test/sql-tap/gh2168-temp-tables.test.lua index 3b29c9ed2..8012cf135 100755 --- a/test/sql-tap/gh2168-temp-tables.test.lua +++ b/test/sql-tap/gh2168-temp-tables.test.lua @@ -1,6 +1,6 @@ #!/usr/bin/env tarantool test =3D require("sqltester") -test:plan(2) +test:plan(3) =20 test:do_catchsql_test( "trigger2-10.1", @@ -8,23 +8,32 @@ test:do_catchsql_test( CREATE TEMP TABLE tmp1 (id INTEGER PRIMARY KEY); ]], { -- - 1, "Syntax error near 'TEMP'" + 1, "Syntax error on line 1 at column 10 near 'TEMP'" -- }); =20 -- TEMP triggers are removed now, check it -test:do_catchsql_test( - "trigger2-10.1", + +test:do_execsql_test( + "trigger2-10.2", [[ CREATE TABLE t1 (id INTEGER PRIMARY KEY); + ]], { + -- + -- +}); + +test:do_catchsql_test( + "trigger2-10.3", + [[ CREATE TEMP TRIGGER ttmp1 BEFORE UPDATE ON t1 BEGIN SELECT 1; END; ]], { - -- - 1, "Syntax error near 'TEMP'" - -- + -- + 1, "Syntax error on line 1 at column 10 near 'TEMP'" + -- }); =20 =20 diff --git a/test/sql-tap/gh2250-trigger-chain-limit.test.lua = b/test/sql-tap/gh2250-trigger-chain-limit.test.lua index 0a8a6c58d..62cc78566 100755 --- a/test/sql-tap/gh2250-trigger-chain-limit.test.lua +++ b/test/sql-tap/gh2250-trigger-chain-limit.test.lua @@ -81,7 +81,7 @@ for _, table_count in ipairs({30, 31}) do function() return true end, - table_count <=3D 30 or msg =3D=3D 'Maximum number = of chained trigger activations exceeded.') + table_count <=3D 30 or msg =3D=3D 'Syntax error: = maximum number of chained trigger activations exceeded.') end =20 -- Exceed check for UPDATE diff --git a/test/sql-tap/identifier_case.test.lua = b/test/sql-tap/identifier_case.test.lua index 65ed9aea1..3d70e7457 100755 --- a/test/sql-tap/identifier_case.test.lua +++ b/test/sql-tap/identifier_case.test.lua @@ -240,7 +240,7 @@ test:do_catchsql_test( data =3D { { 1, [[ 'a' < 'b' collate binary ]], {1, "Collation 'BINARY' does = not exist"}}, { 2, [[ 'a' < 'b' collate "binary" ]], {0, {true}}}, - { 3, [[ 'a' < 'b' collate 'binary' ]], {1, [[Syntax error near = ''binary'']]}}, + { 3, [[ 'a' < 'b' collate 'binary' ]], {1, [[Syntax error on line = 1 at column 43 near ''binary'']]}}, { 4, [[ 'a' < 'b' collate "unicode" ]], {0, {true}}}, { 5, [[ 5 < 'b' collate "unicode" ]], {0, {true}}}, { 6, [[ 5 < 'b' collate unicode ]], {1,"Collation 'UNICODE' does = not exist"}}, diff --git a/test/sql-tap/in1.test.lua b/test/sql-tap/in1.test.lua index 570cc1779..9001e6cee 100755 --- a/test/sql-tap/in1.test.lua +++ b/test/sql-tap/in1.test.lua @@ -725,7 +725,7 @@ test:do_catchsql_test( ); ]], { -- - 1, "SELECTs to the left and right of UNION ALL do not have the = same number of result columns" + 1, "Syntax error: SELECTs to the left and right of UNION ALL do = not have the same number of result columns" -- }) =20 @@ -737,7 +737,7 @@ test:do_catchsql_test( ); ]], { -- - 1, "SELECTs to the left and right of UNION do not have the same = number of result columns" + 1, "Syntax error: SELECTs to the left and right of UNION do not = have the same number of result columns" -- }) =20 @@ -749,7 +749,7 @@ test:do_catchsql_test( ); ]], { -- - 1, "SELECTs to the left and right of EXCEPT do not have the = same number of result columns" + 1, "Syntax error: SELECTs to the left and right of EXCEPT do = not have the same number of result columns" -- }) =20 @@ -761,7 +761,7 @@ test:do_catchsql_test( ); ]], { -- - 1, "SELECTs to the left and right of INTERSECT do not have the = same number of result columns" + 1, "Syntax error: SELECTs to the left and right of INTERSECT do = not have the same number of result columns" -- }) =20 @@ -775,7 +775,7 @@ test:do_catchsql_test( ); ]], { -- - 1, "SELECTs to the left and right of UNION ALL do not have the = same number of result columns" + 1, "Syntax error: SELECTs to the left and right of UNION ALL do = not have the same number of result columns" -- }) =20 @@ -787,7 +787,7 @@ test:do_catchsql_test( ); ]], { -- - 1, "SELECTs to the left and right of UNION do not have the same = number of result columns" + 1, "Syntax error: SELECTs to the left and right of UNION do not = have the same number of result columns" -- }) =20 @@ -799,7 +799,7 @@ test:do_catchsql_test( ); ]], { -- - 1, "SELECTs to the left and right of EXCEPT do not have the = same number of result columns" + 1, "Syntax error: SELECTs to the left and right of EXCEPT do = not have the same number of result columns" -- }) =20 @@ -811,7 +811,7 @@ test:do_catchsql_test( ); ]], { -- - 1, "SELECTs to the left and right of INTERSECT do not have the = same number of result columns" + 1, "Syntax error: SELECTs to the left and right of INTERSECT do = not have the same number of result columns" -- }) =20 @@ -835,7 +835,7 @@ test:do_catchsql_test( ); ]], { -- - 1, "SELECTs to the left and right of UNION ALL do not have the = same number of result columns" + 1, "Syntax error: SELECTs to the left and right of UNION ALL do = not have the same number of result columns" -- }) =20 diff --git a/test/sql-tap/index-info.test.lua = b/test/sql-tap/index-info.test.lua index a5ed9a98e..46c64ba68 100755 --- a/test/sql-tap/index-info.test.lua +++ b/test/sql-tap/index-info.test.lua @@ -26,7 +26,7 @@ test:do_catchsql_test( "index-info-1.2", "PRAGMA index_info =3D t1.a;", { - 1, "Syntax error near '.'", + 1, "Syntax error on line 1 at column 23 near '.'", }) =20 -- Case: single column index with an integer column. diff --git a/test/sql-tap/index1.test.lua b/test/sql-tap/index1.test.lua index 16209715d..7b8523555 100755 --- a/test/sql-tap/index1.test.lua +++ b/test/sql-tap/index1.test.lua @@ -994,7 +994,7 @@ test:do_catchsql_test( CREATE INDEX temp.i21 ON t6(c); ]], { -- - 1, "Syntax error near '.'" + 1, "Syntax error on line 1 at column 26 near '.'" -- }) =20 diff --git a/test/sql-tap/index7.test.lua b/test/sql-tap/index7.test.lua index ca5cb1910..340a5a963 100755 --- a/test/sql-tap/index7.test.lua +++ b/test/sql-tap/index7.test.lua @@ -1,6 +1,6 @@ #!/usr/bin/env tarantool test =3D require("sqltester") -test:plan(11) +test:plan(12) =20 --!./tcltestrunner.lua -- 2013-11-04 @@ -286,13 +286,18 @@ test:do_eqp_test( -- gh-2165 Currently, Tarantool lacks support of partial indexes, -- so temporary we removed processing of their syntax from parser. -- -test:do_catchsql_test( +test:do_execsql_test( "index7-7.1", [[ CREATE TABLE t1 (a INTEGER PRIMARY KEY, b INTEGER); + ]]) + +test:do_catchsql_test( + "index7-7.1", + [[ CREATE UNIQUE INDEX i ON t1 (a) WHERE a =3D 3; ]], { - 1, "Keyword 'WHERE' is reserved. Please use double quotes if = 'WHERE' is an identifier." + 1, "Syntax error on line 1 at column 41: keyword 'WHERE' is = reserved. Please use double quotes if 'WHERE' is an identifier." }) =20 -- Currently, when a user tries to create index (or primary key, diff --git a/test/sql-tap/insert1.test.lua = b/test/sql-tap/insert1.test.lua index d28baf11a..6a1078fa4 100755 --- a/test/sql-tap/insert1.test.lua +++ b/test/sql-tap/insert1.test.lua @@ -43,7 +43,7 @@ test:do_test("insert-1.3", function() return test:catchsql "INSERT INTO test1 VALUES(1,2)" end, { -- - 1, "table TEST1 has 3 columns but 2 values were supplied" + 1, "Syntax error: table TEST1 has 3 columns but 2 values were = supplied" -- }) =20 @@ -51,7 +51,7 @@ test:do_catchsql_test("insert-1.3b", [[ INSERT INTO test1 VALUES(1,2,3,4) ]], { -- - 1, "table TEST1 has 3 columns but 4 values were supplied" + 1, "Syntax error: table TEST1 has 3 columns but 4 values were = supplied" -- }) =20 @@ -59,7 +59,7 @@ test:do_catchsql_test("insert-1.3c", [[ INSERT INTO test1(one,two) VALUES(1,2,3,4) ]], { -- - 1, "4 values for 2 columns" + 1, "Syntax error: 4 values for 2 columns" -- }) =20 @@ -67,7 +67,7 @@ test:do_catchsql_test("insert-1.3d", [[ INSERT INTO test1(one,two) VALUES(1) ]], { -- - 1, "1 values for 2 columns" + 1, "Syntax error: 1 values for 2 columns" -- }) =20 @@ -470,7 +470,7 @@ test:do_execsql_test("insert-4.7", [[ INSERT INTO t10 VALUES(11,12,13), (14,15), (16,17,28); ]], { -- - 1, "all VALUES must have the same number of terms" + 1, "Syntax error: all VALUES must have the same number of terms" -- }) =20 @@ -519,14 +519,14 @@ test:do_catchsql_test( [[ insert into test(a, a, b) values(1, 1, 1) ]], - {1, "table id list: duplicate column name A"}) + {1, "Syntax error: table id list: duplicate column name A"}) =20 test:do_catchsql_test( "insert-13.2", [[ insert into test(a, b, b) values(1, 1, 1) ]], - {1, "table id list: duplicate column name B"}) + {1, "Syntax error: table id list: duplicate column name B"}) =20 test:do_execsql_test( "insert-13.3", diff --git a/test/sql-tap/join.test.lua b/test/sql-tap/join.test.lua index ac7d32b84..ad7ca9745 100755 --- a/test/sql-tap/join.test.lua +++ b/test/sql-tap/join.test.lua @@ -520,7 +520,7 @@ test:do_catchsql_test( SELECT * FROM t1 NATURAL JOIN t2 ON t1.a=3Dt2.b; ]], { -- - 1, "a NATURAL join may not have an ON or USING clause" + 1, "Syntax error: a NATURAL join may not have an ON or USING = clause" -- }) =20 @@ -530,7 +530,7 @@ test:do_catchsql_test( SELECT * FROM t1 NATURAL JOIN t2 USING(b); ]], { -- - 1, "a NATURAL join may not have an ON or USING clause" + 1, "Syntax error: a NATURAL join may not have an ON or USING = clause" -- }) =20 @@ -540,7 +540,7 @@ test:do_catchsql_test( SELECT * FROM t1 JOIN t2 ON t1.a=3Dt2.b USING(b); ]], { -- - 1, "cannot have both ON and USING clauses in the same join" + 1, "Syntax error: cannot have both ON and USING clauses in the = same join" -- }) =20 @@ -550,7 +550,7 @@ test:do_catchsql_test( SELECT * FROM t1 JOIN t2 USING(a); ]], { -- - 1, "cannot join using column A - column not present in both = tables" + 1, "Syntax error: cannot join using column A - column not = present in both tables" -- }) =20 @@ -560,7 +560,7 @@ test:do_catchsql_test( SELECT * FROM t1 JOIN t2 USING(d); ]], { -- - 1, "cannot join using column D - column not present in both = tables" + 1, "Syntax error: cannot join using column D - column not = present in both tables" -- }) =20 @@ -590,7 +590,7 @@ test:do_catchsql_test( SELECT * FROM t1 INNER OUTER JOIN t2; ]], { -- - 1, "unknown or unsupported join type: INNER OUTER" + 1, "Syntax error: unknown or unsupported join type: INNER = OUTER" -- }) =20 @@ -600,7 +600,7 @@ test:do_catchsql_test( SELECT * FROM t1 INNER OUTER CROSS JOIN t2; ]], { -- - 1, "unknown or unsupported join type: INNER OUTER CROSS" + 1, "Syntax error: unknown or unsupported join type: INNER OUTER = CROSS" -- }) =20 @@ -610,7 +610,7 @@ test:do_catchsql_test( SELECT * FROM t1 OUTER NATURAL INNER JOIN t2; ]], { -- - 1, "unknown or unsupported join type: OUTER NATURAL INNER" + 1, "Syntax error: unknown or unsupported join type: OUTER = NATURAL INNER" -- }) =20 @@ -620,7 +620,7 @@ test:do_catchsql_test( SELECT * FROM t1 LEFT BOGUS JOIN t2; ]], { -- - 1, "unknown or unsupported join type: LEFT BOGUS" + 1, "Syntax error: unknown or unsupported join type: LEFT BOGUS" -- }) =20 @@ -630,7 +630,7 @@ test:do_catchsql_test( SELECT * FROM t1 INNER BOGUS CROSS JOIN t2; ]], { -- - 1, "unknown or unsupported join type: INNER BOGUS CROSS" + 1, "Syntax error: unknown or unsupported join type: INNER BOGUS = CROSS" -- }) =20 @@ -640,7 +640,7 @@ test:do_catchsql_test( SELECT * FROM t1 NATURAL AWK SED JOIN t2; ]], { -- - 1, "unknown or unsupported join type: NATURAL AWK SED" + 1, "Syntax error: unknown or unsupported join type: NATURAL AWK = SED" -- }) =20 diff --git a/test/sql-tap/keyword1.test.lua = b/test/sql-tap/keyword1.test.lua index 571e1dcbe..71548a46f 100755 --- a/test/sql-tap/keyword1.test.lua +++ b/test/sql-tap/keyword1.test.lua @@ -240,11 +240,25 @@ end =20 for _, kw in ipairs(bannedkws) do query =3D 'CREATE TABLE '..kw..'(a INT PRIMARY KEY);' - test:do_catchsql_test( + if kw =3D=3D 'end' or kw =3D=3D 'match' or kw =3D=3D 'release' or = kw =3D=3D 'rename' or + kw =3D=3D 'replace' or kw =3D=3D 'binary' or kw =3D=3D = 'character' or + kw =3D=3D 'smallint' then + test:do_catchsql_test( "bannedkw1-"..kw..".1", query, { - 1, "Keyword '"..kw.."' is reserved. Please use double = quotes if '"..kw.."' is an identifier." + 1, "Syntax error on line 1 at column "..14 + = string.len(kw).. + ": keyword '"..kw.."' is reserved. Please use double quotes = if '" + ..kw.."' is an identifier." }) + else + test:do_catchsql_test( + "bannedkw1-"..kw..".1", + query, { + 1, "Syntax error on line 1 at column 14: keyword '"..kw.. + "' is reserved. Please use double quotes if '"..kw.. + "' is an identifier." + }) + end end =20 =20 diff --git a/test/sql-tap/limit.test.lua b/test/sql-tap/limit.test.lua index 870233942..b4b39e324 100755 --- a/test/sql-tap/limit.test.lua +++ b/test/sql-tap/limit.test.lua @@ -684,7 +684,7 @@ test:do_catchsql_test( SELECT * FROM t7 LIMIT 3 ]], { -- - 1, "LIMIT clause should come after UNION not before" + 1, "Syntax error: LIMIT clause should come after UNION not = before" -- }) =20 diff --git a/test/sql-tap/misc1.test.lua b/test/sql-tap/misc1.test.lua index b84093e3c..ae7829ff8 100755 --- a/test/sql-tap/misc1.test.lua +++ b/test/sql-tap/misc1.test.lua @@ -1,6 +1,6 @@ #!/usr/bin/env tarantool test =3D require("sqltester") -test:plan(58) +test:plan(59) =20 --!./tcltestrunner.lua -- 2001 September 15. @@ -262,17 +262,26 @@ test:do_execsql_test( -- before executing a command. Thus if "WHERE" is misspelled on an = UPDATE, -- the user won't accidently update every record. -- -test:do_catchsql_test( - "misc1-5.1", + +test:do_execsql_test( + "misc1-5.1.1", [[ CREATE TABLE t3(a INT primary key,b INT ); INSERT INTO t3 VALUES(1,2); INSERT INTO t3 VALUES(3,4); + ]], { + -- + -- + }) + +test:do_catchsql_test( + "misc1-5.1.2", + [[ UPDATE t3 SET a=3D0 WHEREwww b=3D2; ]], { - -- - 1, [[Syntax error near 'WHEREwww']] - -- + -- + 1, [[Syntax error on line 1 at column 27 near 'WHEREwww']] + -- }) =20 test:do_execsql_test( @@ -1037,7 +1046,7 @@ test:do_catchsql_test( select''like''like''like#0; ]], { -- - 1, [[Syntax error near '#0']] + 1, [[Syntax error on line 1 at column 35 near '#0']] -- }) =20 @@ -1047,7 +1056,7 @@ test:do_catchsql_test( VALUES(0,0x0MATCH#0; ]], { -- - 1, [[Syntax error near '#0']] + 1, [[Syntax error on line 1 at column 28 near '#0']] -- }) =20 diff --git a/test/sql-tap/misc5.test.lua b/test/sql-tap/misc5.test.lua index 5f98f21f6..33ad8c3bb 100755 --- a/test/sql-tap/misc5.test.lua +++ b/test/sql-tap/misc5.test.lua @@ -347,7 +347,7 @@ test:do_catchsql_test( SELECT 123abc ]], { -- - 1, [[Syntax error: unrecognized token: '123abc']] + 1, [[Syntax error on line 1 at column 16 unrecognized token: = '123abc']] -- }) =20 @@ -357,7 +357,7 @@ test:do_catchsql_test( SELECT 1*123.4e5ghi; ]], { -- - 1, [[Syntax error: unrecognized token: '123.4e5ghi']] + 1, [[Syntax error on line 1 at column 18 unrecognized token: = '123.4e5ghi']] -- }) =20 diff --git a/test/sql-tap/null.test.lua b/test/sql-tap/null.test.lua index de4d5033d..aa3367dba 100755 --- a/test/sql-tap/null.test.lua +++ b/test/sql-tap/null.test.lua @@ -295,7 +295,7 @@ test:do_catchsql_test( select b from t1 union select c from t1 order by t1.a; ]], { -- - 1, "Error at ORDER BY in place 1: term does not match any = column in the result set" + 1, "Syntax error: error at ORDER BY in place 1: term does not = match any column in the result set" -- }) =20 @@ -305,7 +305,7 @@ test:do_catchsql_test( select b from t1 union select c from t1 order by t1.a; ]], { -- - 1, "Error at ORDER BY in place 1: term does not match any = column in the result set" + 1, "Syntax error: error at ORDER BY in place 1: term does not = match any column in the result set" -- }) =20 @@ -517,7 +517,7 @@ test:do_catchsql_test( ]], { -- - 1, "Syntax error near '1'" + 1, "Syntax error on line 1 at column 29 near '1'" -- }) =20 @@ -528,7 +528,7 @@ test:do_catchsql_test( ]], { -- - 1, "Syntax error near '1'" + 1, "Syntax error on line 1 at column 33 near '1'" -- }) =20 @@ -539,7 +539,7 @@ test:do_catchsql_test( ]], { -- - 1, "Syntax error near '1'" + 1, "Syntax error on line 1 at column 32 near '1'" -- }) =20 @@ -550,7 +550,7 @@ test:do_catchsql_test( ]], { -- - 1, "Syntax error near '1'" + 1, "Syntax error on line 1 at column 36 near '1'" -- }) =20 diff --git a/test/sql-tap/pragma.test.lua b/test/sql-tap/pragma.test.lua index b3821dcf7..fcd3c2e0b 100755 --- a/test/sql-tap/pragma.test.lua +++ b/test/sql-tap/pragma.test.lua @@ -43,7 +43,7 @@ test:do_catchsql_test( [[ pragma sql_default_engine 'memtx'; ]], { - 1, "Syntax error near ''memtx''" + 1, "Syntax error on line 1 at column 29 near ''memtx''" }) =20 test:do_catchsql_test( @@ -51,7 +51,7 @@ test:do_catchsql_test( [[ pragma sql_default_engine 1; ]], { - 1, "Syntax error near '1'" + 1, "Syntax error on line 1 at column 29 near '1'" }) =20 -- diff --git a/test/sql-tap/resolver01.test.lua = b/test/sql-tap/resolver01.test.lua index 315c892ac..21390dfe0 100755 --- a/test/sql-tap/resolver01.test.lua +++ b/test/sql-tap/resolver01.test.lua @@ -48,7 +48,7 @@ test:do_catchsql_test( SELECT 1 AS yy FROM t1, t2 ORDER BY y; ]], { -- - 1, "ambiguous column name: Y" + 1, "Syntax error: ambiguous column name: Y" -- }) =20 @@ -119,7 +119,7 @@ test:do_catchsql_test( SELECT 2 AS yy FROM t1, t2 ORDER BY y; ]], { -- - 1, "ambiguous column name: Y" + 1, "Syntax error: ambiguous column name: Y" -- }) =20 @@ -176,7 +176,7 @@ test:do_catchsql_test( SELECT 3 AS y FROM t1, t2 ORDER BY +y; ]], { -- - 1, "ambiguous column name: Y" + 1, "Syntax error: ambiguous column name: Y" -- }) =20 @@ -186,7 +186,7 @@ test:do_catchsql_test( SELECT 2 AS yy FROM t1, t2 ORDER BY +y; ]], { -- - 1, "ambiguous column name: Y" + 1, "Syntax error: ambiguous column name: Y" -- }) =20 diff --git a/test/sql-tap/select1.test.lua = b/test/sql-tap/select1.test.lua index 4bbfbd67b..de3d5bd1f 100755 --- a/test/sql-tap/select1.test.lua +++ b/test/sql-tap/select1.test.lua @@ -539,7 +539,7 @@ test:do_catchsql_test( SELECT SUM(min(f1)) FROM test1 ]], { -- - 1, "misuse of aggregate function MIN()" + 1, "Syntax error: misuse of aggregate function MIN()" -- }) =20 @@ -551,7 +551,7 @@ test:do_catchsql_test( SELECT min(f1) AS m FROM test1 GROUP BY f1 HAVING max(m+5)<10 ]], { -- - 1, "misuse of aliased aggregate M" + 1, "Syntax error: misuse of aliased aggregate M" -- }) =20 @@ -563,7 +563,7 @@ test:do_catchsql_test( HAVING max(m+5)<10 ]], { -- - 1, "misuse of aliased aggregate M" + 1, "Syntax error: misuse of aliased aggregate M" -- }) =20 @@ -577,7 +577,7 @@ test:do_catchsql_test( -- catchsql { -- SELECT count(a) AS cn FROM tkt2526 GROUP BY a HAVING cn - 1, "misuse of aggregate function COUNT()" + 1, "Syntax error: misuse of aggregate function COUNT()" -- }) =20 @@ -733,7 +733,7 @@ test:do_catchsql_test( SELECT f1 FROM test1 ORDER BY min(f1) ]], { -- - 1, "misuse of aggregate: MIN()" + 1, "Syntax error: misuse of aggregate: MIN()" -- }) =20 @@ -743,7 +743,7 @@ test:do_catchsql_test( INSERT INTO test1(f1) SELECT f1 FROM test1 ORDER BY min(f1); ]], { -- - 1, "misuse of aggregate: MIN()" + 1, "Syntax error: misuse of aggregate: MIN()" -- }) =20 @@ -840,7 +840,7 @@ test:do_catchsql_test( SELECT * FROM t5 ORDER BY 3; ]], { -- - 1, "Error at ORDER BY in place 1: term out of range - should be = between 1 and 2" + 1, "Syntax error: error at ORDER BY in place 1: term out of = range - should be between 1 and 2" -- }) =20 @@ -850,7 +850,7 @@ test:do_catchsql_test( SELECT * FROM t5 ORDER BY -1; ]], { -- - 1, "Error at ORDER BY in place 1: term out of range - should be = between 1 and 2" + 1, "Syntax error: error at ORDER BY in place 1: term out of = range - should be between 1 and 2" -- }) =20 @@ -1080,7 +1080,7 @@ test:do_catchsql2_test( [[SELECT A.f1, f1 FROM test1 as A, test1 as B=20 ORDER BY f2]], { -- - 1, "ambiguous column name: F1" + 1, "Syntax error: ambiguous column name: F1" -- }) =20 @@ -1089,7 +1089,7 @@ test:do_catchsql2_test( [[SELECT A.f1, B.f1 FROM test1 as A, test1 as B=20 ORDER BY f2]], { -- - 1, "ambiguous column name: F2" + 1, "Syntax error: ambiguous column name: F2" -- }) =20 @@ -1098,7 +1098,7 @@ test:do_catchsql2_test( [[SELECT A.f1, f1 FROM test1 as A, test1 as A=20 ORDER BY f2]], { -- - 1, "ambiguous column name: A.F1" + 1, "Syntax error: ambiguous column name: A.F1" -- }) =20 @@ -1334,7 +1334,7 @@ test:do_catchsql2_test( ORDER BY f2+101; ]], { -- - 1, "Error at ORDER BY in place 1: term does not match any = column in the result set" + 1, "Syntax error: error at ORDER BY in place 1: term does = not match any column in the result set" -- }) =20 @@ -1406,7 +1406,7 @@ test:do_catchsql_test( SELECT f1 FROM test1 WHERE f2=3D; ]], { -- - 1, [[Syntax error near ';']] + 1, [[Syntax error on line 1 at column 39 near ';']] -- }) =20 @@ -1416,7 +1416,7 @@ test:do_catchsql_test( SELECT f1 FROM test1 UNION SELECT WHERE; ]], { -- - 1, [[Keyword 'WHERE' is reserved. Please use double quotes = if 'WHERE' is an identifier.]] + 1, [[Syntax error on line 1 at column 47: keyword 'WHERE' = is reserved. Please use double quotes if 'WHERE' is an identifier.]] -- }) =20 @@ -1428,7 +1428,7 @@ test:do_catchsql_test( [[ SELECT f1 FROM test1 as "hi", test2 as]], { -- - 1, [[Keyword 'as' is reserved. Please use double quotes if 'as' = is an identifier.]] + 1, [[Syntax error on line 1 at column 47: keyword 'as' is = reserved. Please use double quotes if 'as' is an identifier.]] -- }) =20 @@ -1438,7 +1438,7 @@ test:do_catchsql_test( SELECT f1 FROM test1 ORDER BY; ]], { -- - 1, [[Syntax error near ';']] + 1, [[Syntax error on line 1 at column 38 near ';']] -- }) =20 @@ -1448,7 +1448,7 @@ test:do_catchsql_test( SELECT f1 FROM test1 ORDER BY f1 desc, f2 where; ]], { -- - 1, [[Keyword 'where' is reserved. Please use double quotes if = 'where' is an identifier.]] + 1, [[Syntax error on line 1 at column 51: keyword 'where' is = reserved. Please use double quotes if 'where' is an identifier.]] -- }) =20 @@ -1458,7 +1458,7 @@ test:do_catchsql_test( SELECT count(f1,f2 FROM test1; ]], { -- - 1, [[Keyword 'FROM' is reserved. Please use double quotes if = 'FROM' is an identifier.]] + 1, [[Syntax error on line 1 at column 28: keyword 'FROM' is = reserved. Please use double quotes if 'FROM' is an identifier.]] -- }) =20 @@ -1468,7 +1468,7 @@ test:do_catchsql_test( SELECT count(f1,f2+) FROM test1; ]], { -- - 1, [[Syntax error near ')']] + 1, [[Syntax error on line 1 at column 28 near ')']] -- }) =20 @@ -1478,7 +1478,7 @@ test:do_catchsql_test( SELECT f1 FROM test1 ORDER BY f2, f1+; ]], { -- - 1, [[Syntax error near ';']] + 1, [[Syntax error on line 1 at column 46 near ';']] -- }) =20 @@ -1488,7 +1488,7 @@ test:do_catchsql_test( SELECT f1 FROM test1 LIMIT 5+3 OFFSET 11 ORDER BY f2; ]], { -- - 1, [[Keyword 'ORDER' is reserved. Please use double quotes if = 'ORDER' is an identifier.]] + 1, [[Syntax error on line 1 at column 50: keyword 'ORDER' is = reserved. Please use double quotes if 'ORDER' is an identifier.]] -- }) =20 diff --git a/test/sql-tap/select3.test.lua = b/test/sql-tap/select3.test.lua index 19f853dc7..9cfe2ef08 100755 --- a/test/sql-tap/select3.test.lua +++ b/test/sql-tap/select3.test.lua @@ -157,7 +157,7 @@ test:do_catchsql_test("select3-2.10", [[ SELECT log, count(*) FROM t1 GROUP BY 0 ORDER BY log; ]], { -- - 1, "Error at GROUP BY in place 1: term out of range - should be = between 1 and 2" + 1, "Syntax error: error at GROUP BY in place 1: term out of range - = should be between 1 and 2" -- }) =20 @@ -165,7 +165,7 @@ test:do_catchsql_test("select3-2.11", [[ SELECT log, count(*) FROM t1 GROUP BY 3 ORDER BY log; ]], { -- - 1, "Error at GROUP BY in place 1: term out of range - should be = between 1 and 2" + 1, "Syntax error: error at GROUP BY in place 1: term out of range - = should be between 1 and 2" -- }) =20 @@ -182,7 +182,7 @@ test:do_catchsql_test("select3-2.13", [[ SELECT log, count(*) FROM t1 GROUP BY ORDER BY log; ]], { -- - 1, [[Keyword 'ORDER' is reserved. Please use double quotes if 'ORDER' = is an identifier.]] + 1, [[Syntax error on line 1 at column 41: keyword 'ORDER' is = reserved. Please use double quotes if 'ORDER' is an identifier.]] -- }) =20 @@ -190,7 +190,7 @@ test:do_catchsql_test("select3-2.14", [[ SELECT log, count(*) FROM t1 GROUP BY; ]], { -- - 1, [[Syntax error near ';']] + 1, [[Syntax error on line 1 at column 40 near ';']] -- }) =20 diff --git a/test/sql-tap/select4.test.lua = b/test/sql-tap/select4.test.lua index 23cf1bf1b..808e616e6 100755 --- a/test/sql-tap/select4.test.lua +++ b/test/sql-tap/select4.test.lua @@ -160,7 +160,7 @@ test:do_catchsql_test( ORDER BY log; ]], { -- - 1, "ORDER BY clause should come after UNION ALL not before" + 1, "Syntax error: ORDER BY clause should come after UNION ALL = not before" -- }) =20 @@ -171,7 +171,7 @@ test:do_catchsql_test( SELECT 0 UNION SELECT 0 ORDER BY 1); ]], { -- - 1, "ORDER BY clause should come after UNION not before" + 1, "Syntax error: ORDER BY clause should come after UNION not = before" -- }) =20 @@ -214,7 +214,7 @@ test:do_catchsql_test( ORDER BY log; ]], { -- - 1, "ORDER BY clause should come after UNION not before" + 1, "Syntax error: ORDER BY clause should come after UNION not = before" -- }) =20 @@ -224,7 +224,7 @@ test:do_catchsql_test( SELECT 0 ORDER BY (SELECT 0) UNION SELECT 0; ]], { -- - 1, "ORDER BY clause should come after UNION not before" + 1, "Syntax error: ORDER BY clause should come after UNION not = before" -- }) =20 @@ -299,7 +299,7 @@ test:do_catchsql_test( ORDER BY log; ]], { -- - 1, "ORDER BY clause should come after EXCEPT not before" + 1, "Syntax error: ORDER BY clause should come after EXCEPT not = before" -- }) =20 @@ -379,7 +379,7 @@ test:do_catchsql_test( ORDER BY log; ]], { -- - 1, "ORDER BY clause should come after INTERSECT not before" + 1, "Syntax error: ORDER BY clause should come after INTERSECT = not before" -- }) =20 @@ -396,7 +396,7 @@ test:do_catchsql_test( ); ]], { -- - 1, "ORDER BY clause should come after INTERSECT not before" + 1, "Syntax error: ORDER BY clause should come after INTERSECT = not before" -- }) =20 @@ -450,7 +450,7 @@ test:do_catchsql_test( ORDER BY "xyzzy"; ]], { -- - 1, "Error at ORDER BY in place 1: term does not match any = column in the result set" + 1, "Syntax error: error at ORDER BY in place 1: term does not = match any column in the result set" -- }) =20 @@ -463,7 +463,7 @@ test:do_catchsql_test( ORDER BY "xyzzy"; ]], { -- - 1, "Error at ORDER BY in place 1: term does not match any = column in the result set" + 1, "Syntax error: error at ORDER BY in place 1: term does not = match any column in the result set" -- }) =20 @@ -515,7 +515,7 @@ test:do_catchsql_test( ORDER BY 2; ]], { -- - 1, "Error at ORDER BY in place 1: term out of range - should be = between 1 and 1" + 1, "Syntax error: error at ORDER BY in place 1: term out of = range - should be between 1 and 1" -- }) =20 @@ -567,7 +567,7 @@ test:do_catchsql_test( ORDER BY log; ]], { -- - 1, "SELECTs to the left and right of UNION ALL do not have the = same number of result columns" + 1, "Syntax error: SELECTs to the left and right of UNION ALL do = not have the same number of result columns" -- }) =20 @@ -577,7 +577,7 @@ test:do_catchsql_test( SELECT 1 UNION SELECT 2, 3 UNION SELECT 4, 5 ORDER BY 1; ]], { -- - 1, "SELECTs to the left and right of UNION do not have the same = number of result columns" + 1, "Syntax error: SELECTs to the left and right of UNION do not = have the same number of result columns" -- }) =20 @@ -1075,7 +1075,7 @@ test:do_catchsql_test( SELECT x FROM t2 ]], { -- - 1, "SELECTs to the left and right of UNION do not have the same = number of result columns" + 1, "Syntax error: SELECTs to the left and right of UNION do not = have the same number of result columns" -- }) =20 @@ -1087,7 +1087,7 @@ test:do_catchsql_test( SELECT = x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x FROM t2 ]], { -- - 1, "SELECTs to the left and right of UNION do not have the same = number of result columns" + 1, "Syntax error: SELECTs to the left and right of UNION do not = have the same number of result columns" -- }) =20 @@ -1099,7 +1099,7 @@ test:do_catchsql_test( SELECT x FROM t2 ]], { -- - 1, "SELECTs to the left and right of UNION ALL do not have the = same number of result columns" + 1, "Syntax error: SELECTs to the left and right of UNION ALL do = not have the same number of result columns" -- }) =20 @@ -1111,7 +1111,7 @@ test:do_catchsql_test( SELECT = x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x FROM t2 ]], { -- - 1, "SELECTs to the left and right of UNION ALL do not have the = same number of result columns" + 1, "Syntax error: SELECTs to the left and right of UNION ALL do = not have the same number of result columns" -- }) =20 @@ -1123,7 +1123,7 @@ test:do_catchsql_test( SELECT x FROM t2 ]], { -- - 1, "SELECTs to the left and right of EXCEPT do not have the = same number of result columns" + 1, "Syntax error: SELECTs to the left and right of EXCEPT do = not have the same number of result columns" -- }) =20 @@ -1135,7 +1135,7 @@ test:do_catchsql_test( SELECT = x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x FROM t2 ]], { -- - 1, "SELECTs to the left and right of EXCEPT do not have the = same number of result columns" + 1, "Syntax error: SELECTs to the left and right of EXCEPT do = not have the same number of result columns" -- }) =20 @@ -1147,7 +1147,7 @@ test:do_catchsql_test( SELECT x FROM t2 ]], { -- - 1, "SELECTs to the left and right of INTERSECT do not have the = same number of result columns" + 1, "Syntax error: SELECTs to the left and right of INTERSECT do = not have the same number of result columns" -- }) =20 @@ -1159,7 +1159,7 @@ test:do_catchsql_test( SELECT = x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x FROM t2 ]], { -- - 1, "SELECTs to the left and right of INTERSECT do not have the = same number of result columns" + 1, "Syntax error: SELECTs to the left and right of INTERSECT do = not have the same number of result columns" -- }) =20 @@ -1177,7 +1177,7 @@ test:do_catchsql_test( SELECT = x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x FROM t2 ]], { -- - 1, "SELECTs to the left and right of INTERSECT do not have the = same number of result columns" + 1, "Syntax error: SELECTs to the left and right of INTERSECT do = not have the same number of result columns" -- }) =20 @@ -1195,7 +1195,7 @@ test:do_catchsql_test( SELECT x FROM t2 ]], { -- - 1, "SELECTs to the left and right of EXCEPT do not have the = same number of result columns" + 1, "Syntax error: SELECTs to the left and right of EXCEPT do = not have the same number of result columns" -- }) =20 @@ -1213,7 +1213,7 @@ test:do_catchsql_test( SELECT x FROM t2 ]], { -- - 1, "SELECTs to the left and right of UNION ALL do not have the = same number of result columns" + 1, "Syntax error: SELECTs to the left and right of UNION ALL do = not have the same number of result columns" -- }) =20 @@ -1231,7 +1231,7 @@ test:do_catchsql_test( SELECT x FROM t2 ]], { -- - 1, "SELECTs to the left and right of UNION do not have the same = number of result columns" + 1, "Syntax error: SELECTs to the left and right of UNION do not = have the same number of result columns" -- }) =20 @@ -1249,7 +1249,7 @@ test:do_catchsql_test( SELECT x FROM t2 ]], { -- - 1, "SELECTs to the left and right of UNION do not have the same = number of result columns" + 1, "Syntax error: SELECTs to the left and right of UNION do not = have the same number of result columns" -- }) =20 @@ -1259,7 +1259,7 @@ test:do_catchsql_test( INSERT INTO t2(rowid) VALUES(2) UNION SELECT 3,4 UNION SELECT = 5,6 ORDER BY 1; ]], { -- - 1, "SELECTs to the left and right of UNION do not have the same = number of result columns" + 1, "Syntax error: SELECTs to the left and right of UNION do not = have the same number of result columns" -- }) =20 @@ -1268,7 +1268,7 @@ test:do_catchsql_test( -- catchsql { -- SELECT 1 UNION SELECT 2,3 UNION SELECT 4,5 ORDER BY 1; -- } db2 --- } {1 {SELECTs to the left and right of UNION do not have the same = number of result columns}} +-- } {1 {Syntax error: SELECTs to the left and right of UNION do not = have the same number of result columns}} =20 =20 -- ifcapable compound diff --git a/test/sql-tap/select6.test.lua = b/test/sql-tap/select6.test.lua index c9960dc29..9871509c3 100755 --- a/test/sql-tap/select6.test.lua +++ b/test/sql-tap/select6.test.lua @@ -905,7 +905,7 @@ test:do_execsql_test( CREATE TABLE k(o INT primary key); ]]) =20 -err =3D { 1, "SELECTs to the left and right of UNION ALL do not have = the same number of result columns" } +err =3D { 1, "Syntax error: SELECTs to the left and right of UNION ALL = do not have the same number of result columns" } test:do_execsql_test( 10.2, [[ diff --git a/test/sql-tap/select7.test.lua = b/test/sql-tap/select7.test.lua index fec5d7a41..66ffca055 100755 --- a/test/sql-tap/select7.test.lua +++ b/test/sql-tap/select7.test.lua @@ -278,7 +278,7 @@ test:do_catchsql_test( ) WHERE y=3D1 ]], { -- <8.1> - 1, "SELECTs to the left and right of UNION do not have the same = number of result columns" + 1, "Syntax error: SELECTs to the left and right of UNION do not = have the same number of result columns" -- }) =20 @@ -289,7 +289,7 @@ test:do_catchsql_test( EXPLAIN QUERY PLAN SELECT * FROM v0 WHERE x=3D'0' OR y; ]], { -- <8.2> - 1, "SELECTs to the left and right of UNION do not have the same = number of result columns" + 1, "Syntax error: SELECTs to the left and right of UNION do not = have the same number of result columns" -- }) =20 diff --git a/test/sql-tap/selectE.test.lua = b/test/sql-tap/selectE.test.lua index 32c3d6a06..0ab48acf7 100755 --- a/test/sql-tap/selectE.test.lua +++ b/test/sql-tap/selectE.test.lua @@ -141,7 +141,7 @@ test:do_catchsql_test( SELECT 1 EXCEPT SELECT 2 ORDER BY 1 COLLATE "unicode_ci" EXCEPT = SELECT 3; ]], { -- - 1, "ORDER BY clause should come after EXCEPT not before" + 1, "Syntax error: ORDER BY clause should come after EXCEPT not = before" -- }) =20 diff --git a/test/sql-tap/sql-errors.test.lua = b/test/sql-tap/sql-errors.test.lua index b16337682..4aceaa54e 100755 --- a/test/sql-tap/sql-errors.test.lua +++ b/test/sql-tap/sql-errors.test.lua @@ -17,7 +17,7 @@ test:do_catchsql_test( ANALYZE v0; ]], { -- - 1,"Syntax error near 'ANALYZE'" + 1,"Syntax error on line 1 at column 3 near 'ANALYZE'" -- }) =20 @@ -422,7 +422,7 @@ test:do_catchsql_test( CREATE TRIGGER r0 AFTER INSERT ON t0 FOR EACH ROW BEGIN = INSERT INTO t0.i VALUES (2); END; ]], { -- - 1,"qualified table names are not allowed on INSERT, = UPDATE, and DELETE statements within triggers" + 1,"Syntax error on line 1 at column 76: qualified table = names are not allowed on INSERT, UPDATE, and DELETE statements within = triggers" -- }) =20 @@ -432,7 +432,7 @@ test:do_catchsql_test( UPDATE t0 SET (i, a) =3D (100,1,1); ]], { -- - 1,"2 columns assigned 3 values" + 1,"Syntax error: 2 columns assigned 3 values" -- }) =20 @@ -442,7 +442,7 @@ test:do_catchsql_test( SELECT * FROM t0(); ]], { -- - 1,"'T0' is not a function" + 1,"Syntax error: 'T0' is not a function" -- }) =20 @@ -452,7 +452,7 @@ test:do_catchsql_test( SELECT $0; ]], { -- - 1,"Index of binding slots must start from 1" + 1,"Syntax error: index of binding slots must start from = 1" -- }) =20 @@ -472,7 +472,7 @@ test:do_catchsql_test( SELECT (1, 2); ]], { -- - 1,"row value misused" + 1,"Syntax error: row value misused" -- }) =20 @@ -482,7 +482,7 @@ test:do_catchsql_test( SELECT (i,a) AS m FROM t0 WHERE m < 1; ]], { -- - 1,"row value misused" + 1,"Syntax error: row value misused" -- }) =20 @@ -522,7 +522,7 @@ test:do_catchsql_test( DROP TABLE IF EXISTS END; ]], { -- - 1, "Keyword 'END' is reserved. Please use double quotes = if 'END' is an identifier." + 1, "Syntax error on line 1 at column 27: keyword 'END' = is reserved. Please use double quotes if 'END' is an identifier." -- }) =20 diff --git a/test/sql-tap/start-transaction.test.lua = b/test/sql-tap/start-transaction.test.lua index c5703d438..b2cd9a1b9 100755 --- a/test/sql-tap/start-transaction.test.lua +++ b/test/sql-tap/start-transaction.test.lua @@ -21,7 +21,7 @@ test:do_catchsql_test( COMMIT; ]], { -- - 1, "Syntax error near 'BEGIN'" + 1, "Syntax error on line 2 at column 3 near 'BEGIN'" -- }) =20 @@ -46,7 +46,7 @@ test:do_catchsql_test( COMMIT; ]], { -- - 1, "Syntax error near 'BEGIN'" + 1, "Syntax error on line 2 at column 3 near 'BEGIN'" -- }) =20 @@ -94,7 +94,7 @@ test:do_catchsql_test( COMMIT TRANSACTION; ]], { -- - 1, "Keyword 'TRANSACTION' is reserved. Please use double = quotes if 'TRANSACTION' is an identifier." + 1, "Syntax error on line 2 at column 10: keyword = 'TRANSACTION' is reserved. Please use double quotes if 'TRANSACTION' is = an identifier." -- }) =20 @@ -119,7 +119,7 @@ test:do_catchsql_test( END; ]], { -- - 1, "Keyword 'END' is reserved. Please use double quotes = if 'END' is an identifier." + 1, "Syntax error on line 2 at column 3: keyword 'END' is = reserved. Please use double quotes if 'END' is an identifier." -- }) =20 @@ -144,7 +144,7 @@ test:do_catchsql_test( END TRANSACTION; ]], { -- - 1, "Keyword 'END' is reserved. Please use double quotes = if 'END' is an identifier." + 1, "Syntax error on line 2 at column 3: keyword 'END' is = reserved. Please use double quotes if 'END' is an identifier." -- }) =20 @@ -193,7 +193,7 @@ test:do_catchsql_test( COMMIT; ]], { -- - 1, "Keyword 'TRANSACTION' is reserved. Please use double = quotes if 'TRANSACTION' is an identifier." + 1, "Syntax error on line 2 at column 13: keyword = 'TRANSACTION' is reserved. Please use double quotes if 'TRANSACTION' is = an identifier." -- }) =20 @@ -246,7 +246,7 @@ test:do_catchsql_test( COMMIT; ]], { -- - 1, "Keyword 'TRANSACTION' is reserved. Please use double = quotes if 'TRANSACTION' is an identifier." + 1, "Syntax error on line 2 at column 13: keyword = 'TRANSACTION' is reserved. Please use double quotes if 'TRANSACTION' is = an identifier." -- }) =20 diff --git a/test/sql-tap/subquery.test.lua = b/test/sql-tap/subquery.test.lua index 6bedf5879..dd90a9f73 100755 --- a/test/sql-tap/subquery.test.lua +++ b/test/sql-tap/subquery.test.lua @@ -614,7 +614,7 @@ test:do_catchsql_test( SELECT max((SELECT count(x) FROM t35b)) FROM t35a; ]], { -- - 1, "misuse of aggregate: COUNT()" + 1, "Syntax error: misuse of aggregate: COUNT()" -- }) =20 @@ -624,7 +624,7 @@ test:do_catchsql_test( SELECT max((SELECT count(x) FROM t35b)) FROM t35a; ]], { -- - 1, "misuse of aggregate: COUNT()" + 1, "Syntax error: misuse of aggregate: COUNT()" -- }) =20 @@ -634,7 +634,7 @@ test:do_catchsql_test( SELECT max((SELECT a FROM (SELECT count(x) AS a FROM t35b))) = FROM t35a; ]], { -- - 1, "misuse of aggregate: COUNT()" + 1, "Syntax error: misuse of aggregate: COUNT()" -- }) =20 @@ -951,7 +951,7 @@ test:do_catchsql_test( SELECT * FROM table1); ]], { -- - 1, 'ORDER BY clause should come after UNION ALL not = before' + 1, 'Syntax error: ORDER BY clause should come after = UNION ALL not before' -- }) =20 @@ -975,7 +975,7 @@ test:do_catchsql_test( SELECT * FROM table1); ]], { -- - 1, 'ORDER BY clause should come after UNION ALL not = before' + 1, 'Syntax error: ORDER BY clause should come after UNION = ALL not before' -- }) =20 diff --git a/test/sql-tap/table.test.lua b/test/sql-tap/table.test.lua index e17b4a2c1..4616a82a6 100755 --- a/test/sql-tap/table.test.lua +++ b/test/sql-tap/table.test.lua @@ -620,7 +620,7 @@ test:do_catchsql_test( CREATE TEMP TABLE t1(a INTEGER PRIMARY KEY, b = VARCHAR(10)); ]], { -- - 1, "Syntax error near 'TEMP'" + 1, "Syntax error on line 1 at column 10 near 'TEMP'" -- }) =20 @@ -630,7 +630,7 @@ test:do_catchsql_test( CREATE TEMPORARY TABLE t1(a INTEGER PRIMARY KEY, b = VARCHAR(10)); ]], { -- - 1, "Syntax error near 'TEMPORARY'" + 1, "Syntax error on line 1 at column 10 near 'TEMPORARY'" -- }) =20 @@ -1257,7 +1257,7 @@ test:do_catchsql_test( ); ]], { -- - 1,"Keyword 'CONSTRAINT' is reserved. Please use double quotes = if 'CONSTRAINT' is an identifier." + 1,"Syntax error on line 3 at column 28: keyword 'CONSTRAINT' is = reserved. Please use double quotes if 'CONSTRAINT' is an identifier." -- }) =20 @@ -1322,7 +1322,7 @@ test:do_catchsql_test( ); ]], { -- - 1,"Keyword 'CONSTRAINT' is reserved. Please use double quotes = if 'CONSTRAINT' is an identifier." + 1,"Syntax error on line 3 at column 37: keyword 'CONSTRAINT' is = reserved. Please use double quotes if 'CONSTRAINT' is an identifier." -- }) =20 @@ -1336,7 +1336,7 @@ test:do_catchsql_test( ); ]], { -- - 1,"Keyword 'CONSTRAINT' is reserved. Please use double quotes = if 'CONSTRAINT' is an identifier." + 1,"Syntax error on line 3 at column 37: keyword 'CONSTRAINT' is = reserved. Please use double quotes if 'CONSTRAINT' is an identifier." -- }) =20 diff --git a/test/sql-tap/tkt1514.test.lua = b/test/sql-tap/tkt1514.test.lua index 685c916a8..95f1d2dec 100755 --- a/test/sql-tap/tkt1514.test.lua +++ b/test/sql-tap/tkt1514.test.lua @@ -27,7 +27,7 @@ test:do_catchsql_test( SELECT a FROM t1 WHERE max(b)<10 GROUP BY a; ]], { -- - 1, "misuse of aggregate: MAX()" + 1, "Syntax error: misuse of aggregate: MAX()" -- }) =20 diff --git a/test/sql-tap/tkt2822.test.lua = b/test/sql-tap/tkt2822.test.lua index 86674aeac..800dee74b 100755 --- a/test/sql-tap/tkt2822.test.lua +++ b/test/sql-tap/tkt2822.test.lua @@ -200,7 +200,7 @@ test:do_catchsql_test( SELECT a, b, c FROM t1 UNION ALL SELECT a, b, c FROM t2 ORDER = BY x ]], { -- - 1, "Error at ORDER BY in place 1: term does not match any = column in the result set" + 1, "Syntax error: error at ORDER BY in place 1: term does not = match any column in the result set" -- }) =20 @@ -298,7 +298,7 @@ test:do_test( ]] end, { -- - 1, "Error at ORDER BY in place 1: term out of range - should be = between 1 and 25" + 1, "Syntax error: error at ORDER BY in place 1: term out of = range - should be between 1 and 25" -- }) =20 @@ -308,7 +308,7 @@ test:do_catchsql_test( SELECT * FROM t7 ORDER BY 1, 0; ]], { -- - 1, "Error at ORDER BY in place 2: term out of range - should be = between 1 and 25" + 1, "Syntax error: error at ORDER BY in place 2: term out of = range - should be between 1 and 25" -- }) =20 @@ -318,7 +318,7 @@ test:do_catchsql_test( SELECT * FROM t7 ORDER BY 1, 26; ]], { -- - 1, "Error at ORDER BY in place 2: term out of range - should be = between 1 and 25" + 1, "Syntax error: error at ORDER BY in place 2: term out of = range - should be between 1 and 25" -- }) =20 @@ -328,7 +328,7 @@ test:do_catchsql_test( SELECT * FROM t7 ORDER BY 1, 65536; ]], { -- - 1, "Error at ORDER BY in place 2: term out of range - should be = between 1 and 25" + 1, "Syntax error: error at ORDER BY in place 2: term out of = range - should be between 1 and 25" -- }) =20 @@ -338,7 +338,7 @@ test:do_catchsql_test( SELECT * FROM t7 ORDER BY 1, 2, 0; ]], { -- - 1, "Error at ORDER BY in place 3: term out of range - should be = between 1 and 25" + 1, "Syntax error: error at ORDER BY in place 3: term out of = range - should be between 1 and 25" -- }) =20 @@ -348,7 +348,7 @@ test:do_catchsql_test( SELECT * FROM t7 ORDER BY 1, 2, 3, 0; ]], { -- - 1, "Error at ORDER BY in place 4: term out of range - should be = between 1 and 25" + 1, "Syntax error: error at ORDER BY in place 4: term out of = range - should be between 1 and 25" -- }) =20 @@ -358,7 +358,7 @@ test:do_catchsql_test( SELECT * FROM t7 ORDER BY 1, 2, 3, 4, 5, 6, 7, 8, 0; ]], { -- - 1, "Error at ORDER BY in place 9: term out of range - should be = between 1 and 25" + 1, "Syntax error: error at ORDER BY in place 9: term out of = range - should be between 1 and 25" -- }) =20 @@ -368,7 +368,7 @@ test:do_catchsql_test( SELECT * FROM t7 ORDER BY 1, 2, 3, 4, 5, 6, 7, 8, 9, 0; ]], { -- - 1, "Error at ORDER BY in place 10: term out of range - should = be between 1 and 25" + 1, "Syntax error: error at ORDER BY in place 10: term out of = range - should be between 1 and 25" -- }) =20 @@ -378,7 +378,7 @@ test:do_catchsql_test( SELECT * FROM t7 ORDER BY 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0; ]], { -- - 1, "Error at ORDER BY in place 11: term out of range - should = be between 1 and 25" + 1, "Syntax error: error at ORDER BY in place 11: term out of = range - should be between 1 and 25" -- }) =20 @@ -388,7 +388,7 @@ test:do_catchsql_test( SELECT * FROM t7 ORDER BY 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 0; ]], { -- - 1, "Error at ORDER BY in place 12: term out of range - should = be between 1 and 25" + 1, "Syntax error: error at ORDER BY in place 12: term out of = range - should be between 1 and 25" -- }) =20 @@ -398,7 +398,7 @@ test:do_catchsql_test( SELECT * FROM t7 ORDER BY 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, = 13, 0; ]], { -- - 1, "Error at ORDER BY in place 13: term out of range - should = be between 1 and 25" + 1, "Syntax error: error at ORDER BY in place 13: term out of = range - should be between 1 and 25" -- }) =20 @@ -409,7 +409,7 @@ test:do_catchsql_test( 11,12,13,14,15,16,17,18,19, 0 ]], { -- - 1, "Error at ORDER BY in place 20: term out of range - should = be between 1 and 25" + 1, "Syntax error: error at ORDER BY in place 20: term out of = range - should be between 1 and 25" -- }) =20 @@ -420,7 +420,7 @@ test:do_catchsql_test( 11,12,13,14,15,16,17,18,19, 20, 0 ]], { -- - 1, "Error at ORDER BY in place 21: term out of range - should = be between 1 and 25" + 1, "Syntax error: error at ORDER BY in place 21: term out of = range - should be between 1 and 25" -- }) =20 @@ -431,7 +431,7 @@ test:do_catchsql_test( 11,12,13,14,15,16,17,18,19, 20, 21, 0 ]], { -- - 1, "Error at ORDER BY in place 22: term out of range - should = be between 1 and 25" + 1, "Syntax error: error at ORDER BY in place 22: term out of = range - should be between 1 and 25" -- }) =20 diff --git a/test/sql-tap/tkt3508.test.lua = b/test/sql-tap/tkt3508.test.lua index 643cf6f54..520a13057 100755 --- a/test/sql-tap/tkt3508.test.lua +++ b/test/sql-tap/tkt3508.test.lua @@ -39,7 +39,7 @@ test:do_catchsql_test( from modificationsTmp where c > 1 group by SUBSTRATE_HPRD_ID; ]], { -- - 1, "misuse of aggregate: COUNT()" + 1, "Syntax error: misuse of aggregate: COUNT()" -- }) =20 diff --git a/test/sql-tap/tokenize.test.lua = b/test/sql-tap/tokenize.test.lua index b1a097e23..eb11eb8a4 100755 --- a/test/sql-tap/tokenize.test.lua +++ b/test/sql-tap/tokenize.test.lua @@ -1,6 +1,6 @@ #!/usr/bin/env tarantool test =3D require("sqltester") -test:plan(14) +test:plan(16) =20 --!./tcltestrunner.lua -- 2008 July 7 @@ -26,7 +26,7 @@ test:do_catchsql_test( SELECT 1.0e+ ]], { -- - 1, [[Syntax error: unrecognized token: '1.0e']] + 1, [[Syntax error on line 1 at column 16 unrecognized token: = '1.0e']] -- }) =20 @@ -36,7 +36,7 @@ test:do_catchsql_test( SELECT 1.0E+ ]], { -- - 1, [[Syntax error: unrecognized token: '1.0E']] + 1, [[Syntax error on line 1 at column 16 unrecognized token: = '1.0E']] -- }) =20 @@ -46,7 +46,7 @@ test:do_catchsql_test( SELECT 1.0e- ]], { -- - 1, [[Syntax error: unrecognized token: '1.0e']] + 1, [[Syntax error on line 1 at column 16 unrecognized token: = '1.0e']] -- }) =20 @@ -56,7 +56,7 @@ test:do_catchsql_test( SELECT 1.0E- ]], { -- - 1, [[Syntax error: unrecognized token: '1.0E']] + 1, [[Syntax error on line 1 at column 16 unrecognized token: = '1.0E']] -- }) =20 @@ -66,7 +66,7 @@ test:do_catchsql_test( SELECT 1.0e+/ ]], { -- - 1, [[Syntax error: unrecognized token: '1.0e']] + 1, [[Syntax error on line 1 at column 16 unrecognized token: = '1.0e']] -- }) =20 @@ -76,7 +76,7 @@ test:do_catchsql_test( SELECT 1.0E+: ]], { -- - 1, [[Syntax error: unrecognized token: '1.0E']] + 1, [[Syntax error on line 1 at column 16 unrecognized token: = '1.0E']] -- }) =20 @@ -86,7 +86,7 @@ test:do_catchsql_test( SELECT 1.0e-: ]], { -- - 1, [[Syntax error: unrecognized token: '1.0e']] + 1, [[Syntax error on line 1 at column 16 unrecognized token: = '1.0e']] -- }) =20 @@ -96,7 +96,7 @@ test:do_catchsql_test( SELECT 1.0E-/ ]], { -- - 1, [[Syntax error: unrecognized token: '1.0E']] + 1, [[Syntax error on line 1 at column 16 unrecognized token: = '1.0E']] -- }) =20 @@ -106,7 +106,7 @@ test:do_catchsql_test( SELECT 1.0F+5 ]], { -- - 1, [[Syntax error: unrecognized token: '1.0F']] + 1, [[Syntax error on line 1 at column 16 unrecognized token: = '1.0F']] -- }) =20 @@ -116,7 +116,7 @@ test:do_catchsql_test( SELECT 1.0d-10 ]], { -- - 1, [[Syntax error: unrecognized token: '1.0d']] + 1, [[Syntax error on line 1 at column 16 unrecognized token: = '1.0d']] -- }) =20 @@ -126,7 +126,7 @@ test:do_catchsql_test( SELECT 1.0e,5 ]], { -- - 1, [[Syntax error: unrecognized token: '1.0e']] + 1, [[Syntax error on line 1 at column 16 unrecognized token: = '1.0e']] -- }) =20 @@ -136,7 +136,7 @@ test:do_catchsql_test( SELECT 1.0E.10 ]], { -- - 1, [[Syntax error: unrecognized token: '1.0E']] + 1, [[Syntax error on line 1 at column 16 unrecognized token: = '1.0E']] -- }) =20 @@ -145,7 +145,7 @@ test:do_catchsql_test( [[ SELECT 1, 2 /*]], { -- - 1, [[Syntax error near '*']] + 1, [[Syntax error on line 1 at column 22 near '*']] -- }) =20 @@ -159,6 +159,29 @@ test:do_catchsql_test( -- }) =20 +-- +--gh-2611 Check the correct parsing of single-line comments. +-- +test:do_execsql_test( + "tokenize-3.1", + [[ + SELECT 1 + -- 1 + 1. + 1 + ]], { + -- + 2 + -- + }) =20 +test:do_catchsql_test( + "tokenize-3.2", + [[ + SELECT 1 + -- Syntax error. + * + ]], { + -- + 1,"Syntax error on line 2 at column 9 near '*'" + -- + }) =20 test:finish_test() diff --git a/test/sql-tap/trigger1.test.lua = b/test/sql-tap/trigger1.test.lua index bc02d6236..73e6bd5a0 100755 --- a/test/sql-tap/trigger1.test.lua +++ b/test/sql-tap/trigger1.test.lua @@ -74,7 +74,7 @@ test:do_catchsql_test( END; ]], { -- - 1, [[Syntax error near 'STATEMENT']] + 1, [[Syntax error on line 1 at column 51 near 'STATEMENT']] -- }) =20 @@ -307,7 +307,7 @@ test:do_catchsql_test( END; ]], { -- - 1, [[Syntax error near ';']] + 1, [[Syntax error on line 3 at column 24 near ';']] -- }) =20 @@ -321,7 +321,7 @@ test:do_catchsql_test( END; ]], { -- - 1, [[Syntax error near ';']] + 1, [[Syntax error on line 4 at column 24 near ';']] -- }) =20 @@ -744,7 +744,7 @@ test:do_catchsql_test( SELECT raise(abort,'message'); ]], { -- - 1, "RAISE() may only be used within a trigger-program" + 1, "Syntax error: RAISE() may only be used within a = trigger-program" -- }) =20 @@ -823,7 +823,7 @@ test:do_catchsql_test( END; ]], { -- - 1, "Syntax error in trigger body: the NOT INDEXED clause is not = allowed on UPDATE or DELETE statements within triggers" + 1, "Syntax error on line 2 at column 34 in trigger body: the = NOT INDEXED clause is not allowed on UPDATE or DELETE statements within = triggers" -- }) =20 @@ -835,7 +835,7 @@ test:do_catchsql_test( END; ]], { -- - 1, "Syntax error in trigger body: the INDEXED BY clause is not = allowed on UPDATE or DELETE statements within triggers" + 1, "Syntax error on line 2 at column 38 in trigger body: the = INDEXED BY clause is not allowed on UPDATE or DELETE statements within = triggers" -- }) =20 @@ -847,7 +847,7 @@ test:do_catchsql_test( END; ]], { -- - 1, "Syntax error in trigger body: the NOT INDEXED clause is not = allowed on UPDATE or DELETE statements within triggers" + 1, "Syntax error on line 2 at column 39 in trigger body: the = NOT INDEXED clause is not allowed on UPDATE or DELETE statements within = triggers" -- }) =20 @@ -859,7 +859,7 @@ test:do_catchsql_test( END; ]], { -- - 1, "Syntax error in trigger body: the INDEXED BY clause is not = allowed on UPDATE or DELETE statements within triggers" + 1, "Syntax error on line 2 at column 43 in trigger body: the = INDEXED BY clause is not allowed on UPDATE or DELETE statements within = triggers" -- }) =20 diff --git a/test/sql-tap/update.test.lua b/test/sql-tap/update.test.lua index 07e4e43d9..152dee9bb 100755 --- a/test/sql-tap/update.test.lua +++ b/test/sql-tap/update.test.lua @@ -1123,7 +1123,7 @@ test:do_catchsql_test( [[ update test set a =3D 2, a =3D 3; ]], - {1, "set id list: duplicate column name A"}) + {1, "Syntax error: set id list: duplicate column name A"}) =20 test:do_execsql_test( "insert-15.2", diff --git a/test/sql-tap/view.test.lua b/test/sql-tap/view.test.lua index 6234f863e..d094eec0a 100755 --- a/test/sql-tap/view.test.lua +++ b/test/sql-tap/view.test.lua @@ -293,7 +293,7 @@ test:do_catchsql_test( CREATE VIEW v1err(x,y DESC,z) AS SELECT a, b+c, c-b FROM t1; ]], { -- - 1, [[Keyword 'DESC' is reserved. Please use double quotes if = 'DESC' is an identifier.]] + 1, [[Syntax error on line 1 at column 31: keyword 'DESC' is = reserved. Please use double quotes if 'DESC' is an identifier.]] -- }) =20 diff --git a/test/sql-tap/with1.test.lua b/test/sql-tap/with1.test.lua index f82b73e63..f0d3c31a1 100755 --- a/test/sql-tap/with1.test.lua +++ b/test/sql-tap/with1.test.lua @@ -123,7 +123,7 @@ test:do_catchsql_test(3.1, [[ SELECT * FROM tmp1; ]], { -- <3.1> - 1, "circular reference: TMP1" + 1, "Syntax error: circular reference: TMP1" -- }) =20 @@ -134,7 +134,7 @@ test:do_catchsql_test(3.2, [[ SELECT * FROM tmp; ]], { -- <3.2> - 1, "Ambiguous table name in WITH query: TMP" + 1, "Syntax error: ambiguous table name in WITH query: TMP" -- }) =20 @@ -178,7 +178,7 @@ test:do_catchsql_test(3.6, [[ SELECT * FROM tmp; ]], { -- <3.6> - 1, [[Keyword 'SELECT' is reserved. Please use double quotes if = 'SELECT' is an identifier.]] + 1, [[Syntax error on line 2 at column 3: keyword 'SELECT' is = reserved. Please use double quotes if 'SELECT' is an identifier.]] -- }) =20 @@ -334,7 +334,7 @@ test:do_catchsql_test("5.6.1", [[ SELECT * FROM i; ]], { -- <5.6.1> - 1, "table I has 1 values for 2 columns" + 1, "Syntax error: table I has 1 values for 2 columns" -- }) =20 @@ -343,7 +343,7 @@ test:do_catchsql_test("5.6.2", [[ SELECT * FROM i; ]], { -- <5.6.2> - 1, "table I has 2 values for 1 columns" + 1, "Syntax error: table I has 2 values for 1 columns" -- }) =20 @@ -353,7 +353,7 @@ test:do_catchsql_test("5.6.3", [[ SELECT * FROM i; ]], { -- <5.6.3> - 1, "table I has 2 values for 1 columns" + 1, "Syntax error: table I has 2 values for 1 columns" -- }) =20 @@ -362,7 +362,7 @@ test:do_catchsql_test("5.6.4", [[ SELECT * FROM i; ]], { -- <5.6.4> - 1, "table I has 2 values for 1 columns" + 1, "Syntax error: table I has 2 values for 1 columns" -- }) =20 @@ -371,7 +371,7 @@ test:do_catchsql_test("5.6.5", [[ SELECT * FROM i; ]], { -- <5.6.5> - 1, "SELECTs to the left and right of UNION ALL do not have the same = number of result columns" + 1, "Syntax error: SELECTs to the left and right of UNION ALL do not = have the same number of result columns" -- }) =20 @@ -380,7 +380,7 @@ test:do_catchsql_test("5.6.6", [[ SELECT * FROM i; ]], { -- <5.6.6> - 1, "SELECTs to the left and right of UNION ALL do not have the same = number of result columns" + 1, "Syntax error: SELECTs to the left and right of UNION ALL do not = have the same number of result columns" -- }) =20 @@ -389,7 +389,7 @@ test:do_catchsql_test("5.6.7", [[ SELECT * FROM i; ]], { -- <5.6.7> - 1, "table I has 2 values for 1 columns" + 1, "Syntax error: table I has 2 values for 1 columns" -- }) =20 @@ -501,7 +501,7 @@ test:do_catchsql_test(7.4, [[ SELECT id FROM t; ]], { -- <7.4> - 1, "recursive reference in a subquery: T" + 1, "Syntax error: recursive reference in a subquery: T" -- }) =20 @@ -514,7 +514,7 @@ test:do_catchsql_test(7.5, [[ SELECT id FROM t; ]], { -- <7.5> - 1, "multiple recursive references: T" + 1, "Syntax error: multiple recursive references: T" -- }) =20 @@ -527,7 +527,7 @@ test:do_catchsql_test(7.6, [[ SELECT id FROM t; ]], { -- <7.6> - 1, "circular reference: T" + 1, "Syntax error: circular reference: T" -- }) =20 @@ -782,7 +782,7 @@ test:do_catchsql_test("10.7.1", [[ SELECT * FROM t ]], { -- <10.7.1> - 1, "Error at ORDER BY in place 1: term does not match any column in = the result set" + 1, "Syntax error: error at ORDER BY in place 1: term does not match = any column in the result set" -- }) =20 @@ -1036,7 +1036,7 @@ test:do_catchsql_test(13.3, [[ SELECT i FROM c; ]], { -- <13.3> - 1, "table C has 1 values for 2 columns" + 1, "Syntax error: table C has 1 values for 2 columns" -- }) =20 diff --git a/test/sql-tap/with2.test.lua b/test/sql-tap/with2.test.lua index 8c7f9f2d9..2b6edf72c 100755 --- a/test/sql-tap/with2.test.lua +++ b/test/sql-tap/with2.test.lua @@ -215,7 +215,7 @@ test:do_catchsql_test(1.16, [[ SELECT * FROM t4; ]], { -- <1.16> - 1, "multiple references to recursive table: T4" + 1, "Syntax error: multiple references to recursive table: T4" -- }) =20 @@ -258,7 +258,7 @@ test:do_catchsql_test(3.1, [[ SELECT * FROM i; ]], { -- <3.1> - 1, "circular reference: I" + 1, "Syntax error: circular reference: I" -- }) =20 @@ -270,7 +270,7 @@ test:do_catchsql_test(3.2, [[ SELECT * FROM i; ]], { -- <3.2> - 1, "circular reference: I" + 1, "Syntax error: circular reference: I" -- }) =20 @@ -281,7 +281,7 @@ test:do_catchsql_test(3.3, [[ SELECT * FROM i; ]], { -- <3.3> - 1, "circular reference: I" + 1, "Syntax error: circular reference: I" -- }) =20 @@ -292,7 +292,7 @@ test:do_catchsql_test(3.4, [[ SELECT * FROM j; ]], { -- <3.4> - 1, "circular reference: J" + 1, "Syntax error: circular reference: J" -- }) =20 @@ -305,7 +305,7 @@ test:do_catchsql_test(3.5, [[ SELECT * FROM i; ]], { -- <3.5> - 1, "circular reference: I" + 1, "Syntax error: circular reference: I" -- }) =20 @@ -317,7 +317,7 @@ test:do_catchsql_test(4.1, [[ SELECT * FROM x; ]], { -- <4.1> - 1, [[Syntax error near ')']] + 1, [[Syntax error on line 1 at column 12 near ')']] -- }) =20 @@ -519,7 +519,7 @@ test:do_catchsql_test(6.2, [[ INSERT INTO t2 VALUES(1, 2,); ]], { -- <6.2> - 1, [[Syntax error near ')']] + 1, [[Syntax error on line 2 at column 32 near ')']] -- }) =20 @@ -528,7 +528,7 @@ test:do_catchsql_test("6.3.1", [[ INSERT INTO t2 SELECT a, b, FROM t1; ]], { -- <6.3> - 1, [[Keyword 'FROM' is reserved. Please use double quotes if 'FROM' = is an identifier.]] + 1, [[Syntax error on line 2 at column 33: keyword 'FROM' is = reserved. Please use double quotes if 'FROM' is an identifier.]] -- }) =20 @@ -546,7 +546,7 @@ test:do_catchsql_test(6.4, [[ INSERT INTO t2 SELECT a, b, FROM t1 a a a; ]], { -- <6.4> - 1, [[Keyword 'FROM' is reserved. Please use double quotes if 'FROM' = is an identifier.]] + 1, [[Syntax error on line 2 at column 33: keyword 'FROM' is = reserved. Please use double quotes if 'FROM' is an identifier.]] -- }) =20 @@ -555,7 +555,7 @@ test:do_catchsql_test(6.5, [[ DELETE FROM t2 WHERE; ]], { -- <6.5> - 1, [[Syntax error near ';']] + 1, [[Syntax error on line 2 at column 25 near ';']] -- }) =20 @@ -563,7 +563,7 @@ test:do_catchsql_test(6.6, [[ WITH x AS (SELECT * FROM t1) DELETE FROM t2 WHERE ]], { -- <6.6> - 1, "Syntax error near '\n'" + 1, "Syntax error on line 2 at column 1 near '\n'" -- }) =20 @@ -571,7 +571,7 @@ test:do_catchsql_test(6.7, [[ WITH x AS (SELECT * FROM t1) DELETE FROM t2 WHRE 1; ]], { -- <6.7> - 1, "Syntax error near 'WHRE'" + 1, "Syntax error on line 1 at column 49 near 'WHRE'" -- }) =20 @@ -579,7 +579,7 @@ test:do_catchsql_test(6.8, [[ WITH x AS (SELECT * FROM t1) UPDATE t2 SET a =3D 10, b =3D ; ]], { -- <6.8> - 1, "Syntax error near ';'" + 1, "Syntax error on line 1 at column 60 near ';'" -- }) =20 @@ -587,7 +587,7 @@ test:do_catchsql_test(6.9, [[ WITH x AS (SELECT * FROM t1) UPDATE t2 SET a =3D 10, b =3D 1 WHERE = a=3D=3D=3Db; ]], { -- <6.9> - 1, "Syntax error near '=3D'" + 1, "Syntax error on line 1 at column 71 near '=3D'" -- }) =20 diff --git a/test/sql/checks.result b/test/sql/checks.result index a952b2b70..7ad06a14d 100644 --- a/test/sql/checks.result +++ b/test/sql/checks.result @@ -160,7 +160,7 @@ box.execute("DROP TABLE t1") box.execute("CREATE TABLE first (id NUMBER PRIMARY KEY CHECK(id < 5), a = INT CONSTRAINT ONE CHECK(a >< 5));") --- - null -- Syntax error near '<' +- Syntax error on line 1 at column 88 near '<' ... box.space.FIRST =3D=3D nil --- @@ -290,8 +290,8 @@ box.execute("DROP TABLE w2;") box.execute("CREATE TABLE t5(x INT PRIMARY KEY, y INT, CHECK( x*y < ? = ));") --- - null -- 'Failed to create check constraint ''ck_unnamed_T5_1'': bindings are = not allowed - in DDL' +- 'Failed to create check constraint ''ck_unnamed_T5_1'': Syntax error: = bindings are + not allowed in DDL' ... -- Test trim CK constraint code correctness. box.execute("CREATE TABLE t1(x TEXT PRIMARY KEY CHECK(x LIKE '1 = a'))") diff --git a/test/sql/engine.result b/test/sql/engine.result index 3ee93ad19..58b9dacb1 100644 --- a/test/sql/engine.result +++ b/test/sql/engine.result @@ -104,12 +104,12 @@ box.space.T2_MEMTX:drop() box.execute("CREATE TABLE t1_vinyl (id INT PRIMARY KEY) WITH ENGINE =3D = VINYL") --- - null -- Syntax error near 'VINYL' +- Syntax error on line 1 at column 58 near 'VINYL' ... box.execute("CREATE TABLE t1_vinyl (id INT PRIMARY KEY) WITH ENGINE =3D = vinyl") --- - null -- Syntax error near 'vinyl' +- Syntax error on line 1 at column 58 near 'vinyl' ... box.execute("CREATE TABLE t1_vinyl (id INT PRIMARY KEY) WITH ENGINE =3D = 'VINYL'") --- @@ -119,7 +119,7 @@ box.execute("CREATE TABLE t1_vinyl (id INT PRIMARY = KEY) WITH ENGINE =3D 'VINYL'") box.execute("CREATE TABLE t1_vinyl (id INT PRIMARY KEY) WITH ENGINE =3D = \"vinyl\"") --- - null -- Syntax error near '"vinyl"' +- Syntax error on line 1 at column 58 near '"vinyl"' ... -- Make sure that wrong engine name is handled properly. -- diff --git a/test/sql/foreign-keys.result b/test/sql/foreign-keys.result index 29538e816..f17234904 100644 --- a/test/sql/foreign-keys.result +++ b/test/sql/foreign-keys.result @@ -396,22 +396,26 @@ box.execute('CREATE TABLE t1 (id INT PRIMARY = KEY);') box.execute('CREATE TABLE t2 (id INT PRIMARY KEY REFERENCES t2 ON = DELETE CASCADE ON DELETE RESTRICT);') --- - null -- Keyword 'DELETE' is reserved. Please use double quotes if 'DELETE' is = an identifier. +- 'Syntax error on line 1 at column 72: keyword ''DELETE'' is reserved. = Please use + double quotes if ''DELETE'' is an identifier.' ... box.execute('CREATE TABLE t2 (id INT PRIMARY KEY REFERENCES t2 ON = DELETE CASCADE ON DELETE CASCADE);') --- - null -- Keyword 'DELETE' is reserved. Please use double quotes if 'DELETE' is = an identifier. +- 'Syntax error on line 1 at column 72: keyword ''DELETE'' is reserved. = Please use + double quotes if ''DELETE'' is an identifier.' ... box.execute('CREATE TABLE t2 (id INT PRIMARY KEY REFERENCES t2 ON = DELETE CASCADE ON UPDATE RESTRICT ON DELETE RESTRICT);') --- - null -- Keyword 'ON' is reserved. Please use double quotes if 'ON' is an = identifier. +- 'Syntax error on line 1 at column 88: keyword ''ON'' is reserved. = Please use double + quotes if ''ON'' is an identifier.' ... box.execute('CREATE TABLE t2 (id INT PRIMARY KEY REFERENCES t2 ON = DELETE CASCADE MATCH FULL);') --- - null -- Keyword 'MATCH' is reserved. Please use double quotes if 'MATCH' is = an identifier. +- 'Syntax error on line 1 at column 69: keyword ''MATCH'' is reserved. = Please use + double quotes if ''MATCH'' is an identifier.' ... box.space.T1:drop() --- diff --git a/test/sql/gh-3888-values-blob-assert.result = b/test/sql/gh-3888-values-blob-assert.result index 4b8e7ede6..f20598e4a 100644 --- a/test/sql/gh-3888-values-blob-assert.result +++ b/test/sql/gh-3888-values-blob-assert.result @@ -18,23 +18,23 @@ box.execute('pragma = sql_default_engine=3D\''..engine..'\'') box.execute('VALUES(scalar)') --- - null -- Syntax error near 'scalar' +- Syntax error on line 1 at column 8 near 'scalar' ... box.execute('VALUES(float)') --- - null -- Syntax error near 'float' +- Syntax error on line 1 at column 8 near 'float' ... -- check 'SELECT' against typedef keywords (should fail) box.execute('SELECT scalar') --- - null -- Syntax error near 'scalar' +- Syntax error on line 1 at column 8 near 'scalar' ... box.execute('SELECT float') --- - null -- Syntax error near 'float' +- Syntax error on line 1 at column 8 near 'float' ... -- check 'VALUES' against ID (should fail) box.execute('VALUES(TheColumnName)') diff --git a/test/sql/iproto.result b/test/sql/iproto.result index 67acd0ac1..fb2772605 100644 --- a/test/sql/iproto.result +++ b/test/sql/iproto.result @@ -106,7 +106,7 @@ cn:execute('insert into not_existing_table values = ("kek")') ... cn:execute('insert qwerty gjsdjq q qwd qmq;; q;qwd;') --- -- error: Syntax error near 'qwerty' +- error: Syntax error on line 1 at column 8 near 'qwerty' ... -- Empty result. cn:execute('select id as identifier from test where a =3D 5;') @@ -119,7 +119,7 @@ cn:execute('select id as identifier from test where = a =3D 5;') -- netbox API errors. cn:execute(100) --- -- error: Syntax error near '100' +- error: Syntax error on line 1 at column 1 near '100' ... cn:execute('select 1', nil, {dry_run =3D true}) --- @@ -352,11 +352,11 @@ cn:execute('drop table if exists test3') -- cn:execute('select ?1, ?2, ?3', {1, 2, 3}) --- -- error: Syntax error near '?1' +- error: Syntax error on line 1 at column 10 near '?1' ... cn:execute('select $name, $name2', {1, 2}) --- -- error: Index of binding slots must start from 1 +- error: 'Syntax error: index of binding slots must start from 1' ... parameters =3D {} --- diff --git a/test/sql/misc.result b/test/sql/misc.result index a157ddbc1..82b86f574 100644 --- a/test/sql/misc.result +++ b/test/sql/misc.result @@ -20,12 +20,14 @@ box.execute('select 1;') box.execute('select 1; select 2;') --- - null -- Keyword 'select' is reserved. Please use double quotes if 'select' is = an identifier. +- 'Syntax error on line 1 at column 11: keyword ''select'' is reserved. = Please use + double quotes if ''select'' is an identifier.' ... box.execute('create table t1 (id INT primary key); select 100;') --- - null -- Keyword 'select' is reserved. Please use double quotes if 'select' is = an identifier. +- 'Syntax error on line 1 at column 39: keyword ''select'' is reserved. = Please use + double quotes if ''select'' is an identifier.' ... box.space.t1 =3D=3D nil --- @@ -56,17 +58,20 @@ box.execute('\n\n\n\t\t\t ') box.execute('CREATE TABLE test (id INTEGER PRIMARY KEY, b INTEGER = CONSTRAINT c1 NULL)') --- - null -- Keyword 'NULL' is reserved. Please use double quotes if 'NULL' is an = identifier. +- 'Syntax error on line 1 at column 68: keyword ''NULL'' is reserved. = Please use double + quotes if ''NULL'' is an identifier.' ... box.execute('CREATE TABLE test (id INTEGER PRIMARY KEY, b INTEGER = CONSTRAINT c1 DEFAULT 300)') --- - null -- Keyword 'DEFAULT' is reserved. Please use double quotes if 'DEFAULT' = is an identifier. +- 'Syntax error on line 1 at column 68: keyword ''DEFAULT'' is = reserved. Please use + double quotes if ''DEFAULT'' is an identifier.' ... box.execute('CREATE TABLE test (id INTEGER PRIMARY KEY, b TEXT = CONSTRAINT c1 COLLATE "binary")') --- - null -- Keyword 'COLLATE' is reserved. Please use double quotes if 'COLLATE' = is an identifier. +- 'Syntax error on line 1 at column 65: keyword ''COLLATE'' is = reserved. Please use + double quotes if ''COLLATE'' is an identifier.' ... -- Make sure that type of literals in meta complies with its real -- type. For instance, typeof(0.5) is number, not integer. diff --git a/test/sql/on-conflict.result b/test/sql/on-conflict.result index 6851e217e..328656ea1 100644 --- a/test/sql/on-conflict.result +++ b/test/sql/on-conflict.result @@ -15,44 +15,52 @@ box.execute('pragma = sql_default_engine=3D\''..engine..'\'') box.execute("CREATE TABLE t (id INTEGER PRIMARY KEY, v INTEGER UNIQUE = ON CONFLICT ABORT)") --- - null -- Keyword 'ON' is reserved. Please use double quotes if 'ON' is an = identifier. +- 'Syntax error on line 1 at column 58: keyword ''ON'' is reserved. = Please use double + quotes if ''ON'' is an identifier.' ... box.execute("CREATE TABLE q (id INTEGER PRIMARY KEY, v INTEGER UNIQUE = ON CONFLICT FAIL)") --- - null -- Keyword 'ON' is reserved. Please use double quotes if 'ON' is an = identifier. +- 'Syntax error on line 1 at column 58: keyword ''ON'' is reserved. = Please use double + quotes if ''ON'' is an identifier.' ... box.execute("CREATE TABLE p (id INTEGER PRIMARY KEY, v INTEGER UNIQUE = ON CONFLICT IGNORE)") --- - null -- Keyword 'ON' is reserved. Please use double quotes if 'ON' is an = identifier. +- 'Syntax error on line 1 at column 58: keyword ''ON'' is reserved. = Please use double + quotes if ''ON'' is an identifier.' ... box.execute("CREATE TABLE g (id INTEGER PRIMARY KEY, v INTEGER UNIQUE = ON CONFLICT REPLACE)") --- - null -- Keyword 'ON' is reserved. Please use double quotes if 'ON' is an = identifier. +- 'Syntax error on line 1 at column 58: keyword ''ON'' is reserved. = Please use double + quotes if ''ON'' is an identifier.' ... box.execute("CREATE TABLE e (id INTEGER PRIMARY KEY ON CONFLICT = REPLACE, v INTEGER)") --- - null -- Keyword 'ON' is reserved. Please use double quotes if 'ON' is an = identifier. +- 'Syntax error on line 1 at column 40: keyword ''ON'' is reserved. = Please use double + quotes if ''ON'' is an identifier.' ... box.execute("CREATE TABLE t1(a INT PRIMARY KEY ON CONFLICT REPLACE)") --- - null -- Keyword 'ON' is reserved. Please use double quotes if 'ON' is an = identifier. +- 'Syntax error on line 1 at column 35: keyword ''ON'' is reserved. = Please use double + quotes if ''ON'' is an identifier.' ... box.execute("CREATE TABLE t2(a INT PRIMARY KEY ON CONFLICT IGNORE)") --- - null -- Keyword 'ON' is reserved. Please use double quotes if 'ON' is an = identifier. +- 'Syntax error on line 1 at column 35: keyword ''ON'' is reserved. = Please use double + quotes if ''ON'' is an identifier.' ... -- CHECK constraint is illegal with REPLACE option. -- box.execute("CREATE TABLE t (id INTEGER PRIMARY KEY, a INTEGER CHECK (a = > 5) ON CONFLICT REPLACE);") --- - null -- Keyword 'ON' is reserved. Please use double quotes if 'ON' is an = identifier. +- 'Syntax error on line 1 at column 65: keyword ''ON'' is reserved. = Please use double + quotes if ''ON'' is an identifier.' ... -- -- gh-3473: Primary key can't be declared with NULL. diff --git a/test/sql/triggers.result b/test/sql/triggers.result index 9dfe981a0..f11f7617f 100644 --- a/test/sql/triggers.result +++ b/test/sql/triggers.result @@ -487,14 +487,14 @@ space_id =3D box.space.T1.id box.execute("CREATE TRIGGER tr1 AFTER INSERT ON t1 FOR EACH ROW WHEN = new.a =3D ? BEGIN SELECT 1; END;") --- - null -- bindings are not allowed in DDL +- 'Syntax error: bindings are not allowed in DDL' ... tuple =3D {"TR1", space_id, {sql =3D [[CREATE TRIGGER tr1 AFTER INSERT = ON t1 FOR EACH ROW WHEN new.a =3D ? BEGIN SELECT 1; END;]]}} --- ... box.space._trigger:insert(tuple) --- -- error: bindings are not allowed in DDL +- error: 'Syntax error: bindings are not allowed in DDL' ... box.execute("DROP TABLE t1;") --- @@ -513,7 +513,8 @@ space_id =3D box.space.T1.id box.execute("CREATE TRIGGER tr1 AFTER INSERT ON t1 BEGIN ; END;") --- - null -- FOR EACH STATEMENT triggers are not implemented, please supply FOR = EACH ROW clause +- 'Syntax error on line 1 at column 39: FOR EACH STATEMENT triggers are = not implemented, + please supply FOR EACH ROW clause' ... box.execute("DROP TABLE t1;") --- diff --git a/test/sql/types.result b/test/sql/types.result index 1ad52e8c7..d824d22f7 100644 --- a/test/sql/types.result +++ b/test/sql/types.result @@ -9,27 +9,30 @@ test_run =3D env.new() box.execute("CREATE TABLE t1 (id PRIMARY KEY);") --- - null -- Keyword 'PRIMARY' is reserved. Please use double quotes if 'PRIMARY' = is an identifier. +- 'Syntax error on line 1 at column 21: keyword ''PRIMARY'' is = reserved. Please use + double quotes if ''PRIMARY'' is an identifier.' ... box.execute("CREATE TABLE t1 (a, id INT PRIMARY KEY);") --- - null -- Syntax error near ',' +- Syntax error on line 1 at column 19 near ',' ... box.execute("CREATE TABLE t1 (id PRIMARY KEY, a INT);") --- - null -- Keyword 'PRIMARY' is reserved. Please use double quotes if 'PRIMARY' = is an identifier. +- 'Syntax error on line 1 at column 21: keyword ''PRIMARY'' is = reserved. Please use + double quotes if ''PRIMARY'' is an identifier.' ... box.execute("CREATE TABLE t1 (id INT PRIMARY KEY, a);") --- - null -- Syntax error near ')' +- Syntax error on line 1 at column 39 near ')' ... box.execute("CREATE TABLE t1 (id INT PRIMARY KEY, a INT, b UNIQUE);") --- - null -- Keyword 'UNIQUE' is reserved. Please use double quotes if 'UNIQUE' is = an identifier. +- 'Syntax error on line 1 at column 47: keyword ''UNIQUE'' is reserved. = Please use + double quotes if ''UNIQUE'' is an identifier.' ... -- gh-3104: real type is stored in space format. -- --Apple-Mail=_17CB3347-326E-4006-91FC-8A9F0EC2B57C Content-Transfer-Encoding: quoted-printable Content-Type: text/html; charset=utf-8 Hi! Thanks for the = review.

On Nov 8, 2019, at 14:01, Nikita Pettik <korablev@tarantool.org> wrote:

On 23 Oct 13:40, Roman Khabibov wrote:
Hi! = Thanks for the review.

On Oct 14, 2019, at 18:47, Nikita Pettik <korablev@tarantool.org> wrote:

On 07 Oct 00:05, Roman Khabibov wrote:
Count the number of rows = and columns during query parsing. This is
to make it = easier for the user to find errors in multiline
queries.

Closes #2611

# = Please enter the commit message for your changes. Lines starting

?
Oops.

GitLab/Travis statuses are negative. Please check CI results = before
sending patch on the review.
Now, every test is passed on my local = machine.
 
diff --git a/src/box/errcode.h b/src/box/errcode.h
index d5d396d87..36e5c179f 100644
--- = a/src/box/errcode.h
+++ b/src/box/errcode.h
@@= -235,9 +235,9 @@ struct errcode_record {
/*180 = */_(ER_SQL_STACK_OVERFLOW, "Failed to parse SQL statement: = parser stack limit reached") \
/*181 = */_(ER_SQL_SELECT_WILDCARD, "Failed to expand '*' in SELECT = statement without FROM clause") \
/*182 = */_(ER_SQL_STATEMENT_EMPTY, "Failed to execute an empty SQL = statement") \
- /*183 = */_(ER_SQL_KEYWORD_IS_RESERVED, "Keyword '%.*s' is reserved. = Please use double quotes if '%.*s' is an identifier.") \
- = /*184 */_(ER_SQL_UNRECOGNIZED_SYNTAX, "Syntax error near '%.*s'") \
- = /*185 */_(ER_SQL_UNKNOWN_TOKEN, "Syntax error: unrecognized = token: '%.*s'") \
+ /*183 = */_(ER_SQL_KEYWORD_IS_RESERVED, "Keyword '%.*s' on line %d at = character %d is reserved. Please use double quotes if '%.*s' is an = identifier.") \
+ /*184 = */_(ER_SQL_UNRECOGNIZED_SYNTAX, "Syntax error on line %d at = character %d near '%.*s'") \
+ /*185 = */_(ER_SQL_UNKNOWN_TOKEN, "Syntax error: on line %d at = character %d unrecognized token: '%.*s'") \
/*186 = */_(ER_SQL_PARSER_GENERIC, "%s") \

What about other syntax related = errors like ER_SQL_PARSER_GENERIC,
ER_SQL_SYNTAX? Please = use the same pattern for all errors:

"On = line %d at/near position %d ..." OR
"Syntax error on line = %d at column %d: =E2=80=A6=E2=80=9D
Unfortunately, I can print line count and = position only during the process
of tokenizing. Outside of = the parse.y and tokenize.c we will just print the
last = symbol position of a query, because this process is assumed to be
completed, as I understood.

For example look at sqlSrcListAppendFromTerm(): there we set = ER_SQL_SYNTAX.
But it is called only from parse.y. Thus, = it is possible to set correct
line and position. Please, = check all other errors and introduce position
where it is = possible.
This function is used on = select.c:4525.

Consider some cases with syntax errors from functions, that = used in parse.y only:
1) = build.c sql_add_autoincrement()

tarantool> CREATE TABLE t11_7 (i INT AUTOINCREMENT, a INT = AUTOINCREMENT                =       , PRIMARY KEY(a, i));
---
- 'Syntax error on line 1 at = column 83 in CREATE TABLE: Table must feature at most = one
  = AUTOINCREMENT field'
...

tarantool> CREATE TABLE t11_7 (i INT AUTOINCREMENT, a INT = AUTOINCREMENT               = , PRIMARY KEY(a, i));
---
- = 'Syntax error on line 1 at column 76 in CREATE TABLE: Table must feature = at most one
  = AUTOINCREMENT field'

The error line and position depends on = whitespaces or linefeeds after last AUTOINCREMENT
keyword, because at the moment of calling = sql_add_autoincrement() the last parsed token was =E2=80=98,=E2=80=99.
That looks weird.

2) select.c sqlJoinType()

tarantool> SELECT * FROM t1 INNER = OUTER JOIN t2     ;
---
- null
- 'Syntax erroron line 1 at column 35: = unknown or unsupported join type: INNER OUTER'
...

tarantool> SELECT * FROM t1 INNER OUTER JOIN     = t2;
---
- null
- 'Syntax erroron line 1 at column 39: = unknown or unsupported join type: INNER OUTER'
...
The same problem.
As I understood, we can print error line/pos if incorrect = token is last parsed. Therefore, we need to find the occurrences of = diag_set(ClientError, =E2=80=A6), where incorrect token is last parsed. = I didn=E2=80=99t find. So, I decided to
print in = parse.y and tokenize.c only.

Also, taking into account my comment below, you don't need = two versions
(with and without position) of the same = error.

diff --git = a/test/sql/checks.result b/test/sql/checks.result
index = 50347bc3a..4ecab9ad4 100644
--- = a/test/sql/checks.result
+++ b/test/sql/checks.result
@@ -39,8 +39,8 @@ _ =3D box.space.test:create_index('pk')
-- Invalid expression test.
box.space._ck_constraint:insert({513, 'CK_CONSTRAINT_01', = false, 'SQL', 'X><5'})
---
-- error: = 'Failed to create check constraint ''CK_CONSTRAINT_01'': Syntax error = near
-    ''<'''
+- error: = 'Failed to create check constraint ''CK_CONSTRAINT_01'': Syntax error = on
+    line 1 at character 10 near ''<'''

There's parse_only flag in struct = Parse. You can use it to calculate
correct position in = expression.

diff --git = a/src/box/sql/parse.y b/src/box/sql/parse.y
index = ed59a875a..7546271d8 100644
--- a/src/box/sql/parse.y
+++ b/src/box/sql/parse.y
@@ -33,10 +33,21 = @@
  UNUSED_PARAMETER(yymajor);  /* Silence some = compiler warnings */
  assert( TOKEN.z[0] );  /* = The tokenizer always gives us a token */
  if = (yypParser->is_fallback_failed && TOKEN.isReserved) {
-    diag_set(ClientError, = ER_SQL_KEYWORD_IS_RESERVED, TOKEN.n, TOKEN.z,
-   =           TOKEN.n, TOKEN.z);
+ =    if (!pParse->parse_only) {
+     =  diag_set(ClientError, ER_SQL_KEYWORD_IS_RESERVED_WITH_POS,
+               = pParse->line_count, pParse->line_pos, TOKEN.n, TOKEN.z, = TOKEN.n,
+             =   TOKEN.z);
+    } else {
+ =      diag_set(ClientError, ER_SQL_KEYWORD_IS_RESERVED, = TOKEN.n, TOKEN.z,
+           =     TOKEN.n, TOKEN.z);
+    }

Firstly (and obviously), you can = introduce wrapper around this if-else:
parser_diag_set() = and provide covering comment.
diff --git = a/src/box/sql/parse.y b/src/box/sql/parse.y
index 1d0c95fac..b2660635b = 100644
--- = a/src/box/sql/parse.y
+++ b/src/box/sql/parse.y
@@ -33,10 +33,11 @@
  =  UNUSED_PARAMETER(yymajor);  /* Silence some compiler warnings = */
  =  assert( TOKEN.z[0] );  /* The tokenizer always gives us a = token */
   if (yypParser->is_fallback_failed && = TOKEN.isReserved) {
-    diag_set(ClientError, = ER_SQL_KEYWORD_IS_RESERVED, TOKEN.n, TOKEN.z,
-         =     TOKEN.n, TOKEN.z);
+    parser_diag_set(pParse, = ER_SQL_KEYWORD_IS_RESERVED, TOKEN.n, TOKEN.z,
+         =            TOKEN.n, = TOKEN.z);
   } else {
-    diag_set(ClientError, = ER_SQL_UNRECOGNIZED_SYNTAX, TOKEN.n, TOKEN.z);
+   =  parser_diag_set(pParse, ER_SQL_UNRECOGNIZED_SYNTAX, TOKEN.n, = TOKEN.z, 0,
+ =                   =  NULL);
   }
   pParse->is_aborted =3D = true;
 }
@@ -115,6 +116,35 @@ static void disableLookaside(Parse = *pParse){
  =  pParse->db->lookaside.bDisable++;
 }
 
+void parser_diag_set(struct = Parse *parser, uint32_t errcode, uint32_t len_1,
+         =                   =  const char *str_1, uint32_t len_2,
+             =                const char = *str_2) {
+ =  const char *add =3D tt_sprintf(" on line %d at column = %d",
+ =                     =               =  parser->line_count, parser->line_pos);
+  switch (errcode) = {
+ =  case ER_SQL_SYNTAX:
+    assert (str_1 !=3D NULL && str_2 !=3D = NULL);
+ =    diag_set(ClientError, errcode, !parser->parse_only ? add = : "", str_1,
+=             str_2);
+   =  break;
+=  case ER_SQL_KEYWORD_IS_RESERVED:
+    assert(str_1 !=3D NULL = && str_2 !=3D NULL);
+    diag_set(ClientError, errcode, = !parser->parse_only ? add : "", len_1, str_1,
+         =     len_2, str_2);
+    break;
+  case = ER_SQL_UNRECOGNIZED_SYNTAX:
+  case = ER_SQL_UNKNOWN_TOKEN:
+    assert (str_1 !=3D NULL);
+   =  diag_set(ClientError, errcode, !parser->parse_only ? add : "", = len_1,
+ =             str_1);
+   =  break;
+=  case ER_SQL_PARSER_GENERIC:
+    assert (str_1 !=3D = NULL);
+ =    diag_set(ClientError, errcode, !parser->parse_only ? add = : "", str_1);
+    break;
+  }
+}
+
 } // end %include

Secondly, you can avoid
using different error = patterns substracting from offset length("SELECT ")
(or = whatever string is added to the intial query). For instance, you may
set offset to the negative value from very beggining of = parsing process.
I think that it is better to = print not error line/offset in lua queries, which uses sql = parser. 
E. g., what we need to print in this = query (wrong expression is 'X><5')?

tuple =3D {513, = 'CK_CONSTRAINT_01', false, 'SQL', 'X><5', = true}
box.space._ck_constraint:insert(tuple)

commit = 797e9b7a3f33ddc307b045d836f15fe3e78dbc8e
Author: Roman Khabibov <roman.habibov@tarantool.org>
Date:   Sat Sep 28 = 20:16:45 2019 +0300

    sql: print line and column = number in error message
    
    Count the number of rows and = columns during query parsing. This is
    to make it easier for the user = to find errors in multiline
    queries.
  =   
    Closes #2611

diff --git = a/extra/addopcodes.sh b/extra/addopcodes.sh
index c25f1e48e..cb6c84725 = 100755
--- = a/extra/addopcodes.sh
+++ b/extra/addopcodes.sh
@@ -50,6 +50,7 @@ extras=3D"     =        \
     ASTERISK     =    \
     SPAN           =  \
 =    ANALYZE         \
+    LINEFEED =        \
     SPACE       =     \
     ILLEGAL         = \
 "
diff --git a/src/box/errcode.h = b/src/box/errcode.h
index c660b1c70..46f10d157 100644
--- = a/src/box/errcode.h
+++ b/src/box/errcode.h
@@ -231,14 +231,14 @@ struct errcode_record = {
  /*176 = */_(ER_SQL_CANT_RESOLVE_FIELD, "Can=E2=80=99t resolve field = '%s'") \
 = /*177 */_(ER_INDEX_EXISTS_IN_SPACE, "Index = '%s' already exists in space '%s'") \
  /*178 = */_(ER_INCONSISTENT_TYPES, "Inconsistent types: expected %s = got %s") \
- = /*179 */_(ER_SQL_SYNTAX, "Syntax error in %s: %s") = \
+ /*179 = */_(ER_SQL_SYNTAX, "Syntax error%s in %s: = %s") \
 = /*180 */_(ER_SQL_STACK_OVERFLOW, "Failed = to parse SQL statement: parser stack limit reached") \
  /*181 = */_(ER_SQL_SELECT_WILDCARD, "Failed to expand '*' in SELECT = statement without FROM clause") \
  /*182 = */_(ER_SQL_STATEMENT_EMPTY, "Failed to execute an empty SQL = statement") \
- = /*183 */_(ER_SQL_KEYWORD_IS_RESERVED, "Keyword '%.*s' is reserved. = Please use double quotes if '%.*s' is an identifier.") = \
- /*184 = */_(ER_SQL_UNRECOGNIZED_SYNTAX, "Syntax error near '%.*s'") = \
- /*185 = */_(ER_SQL_UNKNOWN_TOKEN, "Syntax error: = unrecognized token: '%.*s'") \
- /*186 = */_(ER_SQL_PARSER_GENERIC, "%s") \
+ /*183 = */_(ER_SQL_KEYWORD_IS_RESERVED, "Syntax error%s: keyword '%.*s' = is reserved. Please use double quotes if '%.*s' is an identifier.") = \
+ /*184 = */_(ER_SQL_UNRECOGNIZED_SYNTAX, "Syntax error%s near '%.*s'") = \
+ /*185 = */_(ER_SQL_UNKNOWN_TOKEN, "Syntax error%s = unrecognized token: '%.*s'") \
+ /*186 = */_(ER_SQL_PARSER_GENERIC, "Syntax error%s: %s") = \
  /*187 = */_(ER_SQL_ANALYZE_ARGUMENT, "ANALYZE statement argument %s is = not a base table") \
 = /*188 */_(ER_SQL_COLUMN_COUNT_MAX, "Failed = to create space '%s': space column count %d exceeds the limit (%d)") = \
  /*189 = */_(ER_HEX_LITERAL_MAX, "Hex literal %s%s length = %d exceeds the supported limit (%d)") \
diff --git a/src/box/sql/build.c = b/src/box/sql/build.c
index 51cd7ce63..24a8a816a 100644
--- = a/src/box/sql/build.c
+++ b/src/box/sql/build.c
@@ -2920,7 +2920,7 @@ = sqlSrcListAppendFromTerm(Parse * pParse, /* Parsing context = */
  struct = SrcList_item *pItem;
 = sql *db =3D pParse->db;
  if (!p = && (pOn || pUsing)) {
- diag_set(ClientError, = ER_SQL_SYNTAX, "FROM clause",
+ diag_set(ClientError, = ER_SQL_SYNTAX, "", "FROM clause",
  "a JOIN clause = is required before ON and USING");
  pParse->is_aborted =3D = true;
 = goto append_from_error;
@@ -3117,10 +3117,10 @@ = sqlWithAdd(Parse * pParse, /* Parsing context = */
  = }
 = if (pWith !=3D NULL) {
  int i;
- const char *err =3D = "Ambiguous table name in WITH query: %s";
+ const char *err =3D = "ambiguous table name in WITH query: %s";
  = for (i =3D 0; i < pWith->nCte; i++) {
  = if (strcmp(name, pWith->a[i].zName) =3D=3D 0) = {
- = diag_set(ClientError, ER_SQL_PARSER_GENERIC,
+ = diag_set(ClientError, ER_SQL_PARSER_GENERIC, "",
  = tt_sprintf(err, name));
  = pParse->is_aborted =3D true;
  = }
@@ = -3208,8 +3208,8 @@ int
 sql_add_autoincrement(struct Parse *parse_context, = uint32_t fieldno)
 {
 = if (parse_context->create_table_def.has_autoinc) = {
- = diag_set(ClientError, ER_SQL_SYNTAX, "CREATE TABLE", "Table = "
- = "must feature at most one AUTOINCREMENT = field");
+ = diag_set(ClientError, ER_SQL_SYNTAX, "", "CREATE = TABLE",
+ = "table must feature at most one AUTOINCREMENT = field");
 = parse_context->is_aborted =3D = true;
 = return -1;
  }
diff --git a/src/box/sql/expr.c = b/src/box/sql/expr.c
index 648b7170e..f0ed748c4 100644
--- = a/src/box/sql/expr.c
+++ b/src/box/sql/expr.c
@@ -231,7 +231,7 @@ check_collate_arg(struct = Parse *parse, struct Expr *expr)
  left =3D = left->pLeft;
 = enum field_type type =3D = sql_expr_type(left);
 = if (type !=3D FIELD_TYPE_STRING && type !=3D = FIELD_TYPE_SCALAR) {
- = diag_set(ClientError, ER_SQL_PARSER_GENERIC,
+ diag_set(ClientError, = ER_SQL_PARSER_GENERIC, "",
  "COLLATE clause = can't be used with non-string "
  = "arguments");
 = parse->is_aborted =3D true;
@@ -1246,8 +1246,8 @@ = sqlExprAssignVarNumber(Parse * pParse, Expr * pExpr, u32 = n)
  = testcase(i =3D=3D SQL_BIND_PARAMETER_MAX - 1);
  = testcase(i =3D=3D SQL_BIND_PARAMETER_MAX);
  = if (is_neg || i < 1) {
- = diag_set(ClientError, ER_SQL_PARSER_GENERIC,
- = "Index of binding slots must start "\
+ = diag_set(ClientError, ER_SQL_PARSER_GENERIC, "",
+ = "index of binding slots must start "\
  = "from 1");
 = pParse->is_aborted =3D = true;
 = return;
@@ -1836,7 +1836,7 @@ = sqlExprListAppendVector(Parse * pParse, /* Parsing context = */
    =  && pColumns->nId !=3D (n =3D sqlExprVectorSize(pExpr))) = {
  = const char *err =3D tt_sprintf("%d columns assigned %d = values",
 =     = pColumns->nId, n);
- = diag_set(ClientError, ER_SQL_PARSER_GENERIC, = err);
+ = diag_set(ClientError, ER_SQL_PARSER_GENERIC, "", = err);
 = pParse->is_aborted =3D true;
  = goto vector_append_error;
  }
@@ -3963,7 +3963,7 @@ sqlExprCodeTarget(Parse = * pParse, Expr * pExpr, int target)
  if (pInfo =3D=3D = 0) {
 = assert(!ExprHasProperty(pExpr, = EP_IntValue));
 = const char *err =3D "misuse of = aggregate: %s()";
- = diag_set(ClientError, = ER_SQL_PARSER_GENERIC,
+ = diag_set(ClientError, ER_SQL_PARSER_GENERIC, = "",
 = tt_sprintf(err, = pExpr->u.zToken));
 = pParse->is_aborted =3D = true;
 = } else {
@@ -4184,7 +4184,7 @@ sqlExprCodeTarget(Parse = * pParse, Expr * pExpr, int target)
     ) = {
  = const char *err =3D
  = "%d columns assigned %d values";
- = diag_set(ClientError, ER_SQL_PARSER_GENERIC,
+ = diag_set(ClientError, ER_SQL_PARSER_GENERIC, "",
  = tt_sprintf(err, pExpr->iTable, n));
  = pParse->is_aborted =3D true;
  = }
@@ = -4281,7 +4281,7 @@ sqlExprCodeTarget(Parse * pParse, Expr * pExpr, int = target)
 = }
 
 = case TK_VECTOR:{
- = diag_set(ClientError, ER_SQL_PARSER_GENERIC,
+ = diag_set(ClientError, ER_SQL_PARSER_GENERIC, "",
  = "row value misused");
  = pParse->is_aborted =3D true;
  = break;
@@ -4383,8 +4383,9 @@ sqlExprCodeTarget(Parse * pParse, Expr = * pExpr, int target)
 = }
 = case TK_RAISE:
  if = (pParse->triggered_space =3D=3D NULL) {
- = diag_set(ClientError, ER_SQL_PARSER_GENERIC, "RAISE() = "\
- = "may only be used within a trigger-program");
+ = diag_set(ClientError, ER_SQL_PARSER_GENERIC, "", = "RAISE"
+ = "() may only be used within a "
+ = "trigger-program");
 = pParse->is_aborted =3D = true;
 = return 0;
  }
diff --git = a/src/box/sql/insert.c b/src/box/sql/insert.c
index 70504c800..63360fa3c = 100644
--- = a/src/box/sql/insert.c
+++ b/src/box/sql/insert.c
@@ -383,7 +383,7 @@ sqlInsert(Parse * = pParse, = /* Parser context */
  if = (bit_test(used_columns, j)) {
  const = char *err =3D "table id list: duplicate "\
  =  "column name %s";
- = diag_set(ClientError, ER_SQL_PARSER_GENERIC,
+ = diag_set(ClientError, ER_SQL_PARSER_GENERIC, "",
  = tt_sprintf(err, = pColumn->a[i].zName));
  = pParse->is_aborted =3D true;
  goto = insert_cleanup;
@@ -500,13 +500,13 @@ sqlInsert(Parse * pParse, /* Parser = context */
 = "table %s has %d columns but %d values = were supplied";
 = err =3D tt_sprintf(err, = pTabList->a[0].zName,
 = space_def->field_count, = nColumn);
- = diag_set(ClientError, ER_SQL_PARSER_GENERIC, = err);
+ = diag_set(ClientError, ER_SQL_PARSER_GENERIC, "", = err);
 = pParse->is_aborted =3D true;
  = goto insert_cleanup;
  }
  if (pColumn !=3D 0 && = nColumn !=3D pColumn->nId) {
  const char *err =3D "%d = values for %d columns";
- = diag_set(ClientError, ER_SQL_PARSER_GENERIC,
+ diag_set(ClientError, = ER_SQL_PARSER_GENERIC, "",
  tt_sprintf(err, = nColumn, pColumn->nId));
  pParse->is_aborted =3D = true;
 = goto insert_cleanup;
diff --git = a/src/box/sql/parse.y b/src/box/sql/parse.y
index 1d0c95fac..b2660635b = 100644
--- = a/src/box/sql/parse.y
+++ b/src/box/sql/parse.y
@@ -33,10 +33,11 @@
  =  UNUSED_PARAMETER(yymajor);  /* Silence some compiler warnings = */
  =  assert( TOKEN.z[0] );  /* The tokenizer always gives us a = token */
   if (yypParser->is_fallback_failed && = TOKEN.isReserved) {
-    diag_set(ClientError, = ER_SQL_KEYWORD_IS_RESERVED, TOKEN.n, TOKEN.z,
-         =     TOKEN.n, TOKEN.z);
+    parser_diag_set(pParse, = ER_SQL_KEYWORD_IS_RESERVED, TOKEN.n, TOKEN.z,
+         =            TOKEN.n, = TOKEN.z);
   } else {
-    diag_set(ClientError, = ER_SQL_UNRECOGNIZED_SYNTAX, TOKEN.n, TOKEN.z);
+   =  parser_diag_set(pParse, ER_SQL_UNRECOGNIZED_SYNTAX, TOKEN.n, = TOKEN.z, 0,
+ =                   =  NULL);
   }
   pParse->is_aborted =3D = true;
 }
@@ -115,6 +116,35 @@ static void disableLookaside(Parse = *pParse){
  =  pParse->db->lookaside.bDisable++;
 }
 
+void parser_diag_set(struct = Parse *parser, uint32_t errcode, uint32_t len_1,
+         =                   =  const char *str_1, uint32_t len_2,
+             =                const char = *str_2) {
+ =  const char *add =3D tt_sprintf(" on line %d at column = %d",
+ =                     =               =  parser->line_count, parser->line_pos);
+  switch (errcode) = {
+ =  case ER_SQL_SYNTAX:
+    assert (str_1 !=3D NULL && str_2 !=3D = NULL);
+ =    diag_set(ClientError, errcode, !parser->parse_only ? add = : "", str_1,
+=             str_2);
+   =  break;
+=  case ER_SQL_KEYWORD_IS_RESERVED:
+    assert(str_1 !=3D NULL = && str_2 !=3D NULL);
+    diag_set(ClientError, errcode, = !parser->parse_only ? add : "", len_1, str_1,
+         =     len_2, str_2);
+    break;
+  case = ER_SQL_UNRECOGNIZED_SYNTAX:
+  case = ER_SQL_UNKNOWN_TOKEN:
+    assert (str_1 !=3D NULL);
+   =  diag_set(ClientError, errcode, !parser->parse_only ? add : "", = len_1,
+ =             str_1);
+   =  break;
+=  case ER_SQL_PARSER_GENERIC:
+    assert (str_1 !=3D = NULL);
+ =    diag_set(ClientError, errcode, !parser->parse_only ? add = : "", str_1);
+    break;
+  }
+}
+
 } // end %include
 
 // Input is a single = SQL command
@@= -274,7 +304,7 @@ columnname(A) ::=3D nm(A) typedef(Y). = {sqlAddColumn(pParse,&A,&Y);}
 %type nm {Token}
 nm(A) ::=3D id(A). = {
  =  if(A.isReserved) {
-    diag_set(ClientError, = ER_SQL_KEYWORD_IS_RESERVED, A.n, A.z, A.n, A.z);
+   =  parser_diag_set(pParse, ER_SQL_KEYWORD_IS_RESERVED, A.n, A.z, A.n, = A.z);
  =    pParse->is_aborted =3D true;
  =  }
 }
@@ -1076,15 +1106,15 @@ expr(A) ::=3D VARIABLE(X).   =   {
   Token t =3D X;
   if (pParse->parse_only) = {
  =    spanSet(&A, &t, &t);
-   =  diag_set(ClientError, ER_SQL_PARSER_GENERIC,
-         =     "bindings are not allowed in DDL");
+   =  parser_diag_set(pParse, ER_SQL_PARSER_GENERIC, 0, "bindings are = not allowed"
+=                    " = in DDL", 0, NULL);
     pParse->is_aborted =3D = true;
  =    A.pExpr =3D NULL;
   } else if (!(X.z[0]=3D=3D'#' = && sqlIsdigit(X.z[1]))) {
     u32 n =3D = X.n;
  =    spanExpr(&A, pParse, TK_VARIABLE, X);
     if = (A.pExpr->u.zToken[0] =3D=3D '?' && n > 1) = {
-   =    diag_set(ClientError, ER_SQL_UNRECOGNIZED_SYNTAX, t.n, = t.z);
+ =      parser_diag_set(pParse, ER_SQL_UNRECOGNIZED_SYNTAX, = t.n, t.z, 0, NULL);
       pParse->is_aborted =3D = true;
  =    } else {
       sqlExprAssignVarNumber(pParse, = A.pExpr, n);
@@ -1092,7 +1122,7 @@ expr(A) ::=3D VARIABLE(X).   =   {
   }else{
     assert( t.n>=3D2 = );
  =    spanSet(&A, &t, &t);
-   =  diag_set(ClientError, ER_SQL_UNRECOGNIZED_SYNTAX, t.n, = t.z);
+ =    parser_diag_set(pParse, ER_SQL_UNRECOGNIZED_SYNTAX, t.n, = t.z, 0, NULL);
     pParse->is_aborted =3D = true;
  =    A.pExpr =3D NULL;
   }
@@ -1608,8 +1638,9 @@ trigger_event(A) ::=3D = UPDATE(X).          {A.a =3D @X; = /*A-overwrites-X*/ A.b =3D 0;}
 trigger_event(A) ::=3D UPDATE OF = idlist(X).{A.a =3D TK_UPDATE; A.b =3D X;}
 
 foreach_clause ::=3D . = {
- =  diag_set(ClientError, ER_SQL_PARSER_GENERIC, "FOR EACH STATEMENT = "
-   =     "triggers are not implemented, please supply FOR EACH ROW = clause");
+ =  parser_diag_set(pParse, ER_SQL_PARSER_GENERIC, 0, "FOR EACH = STATEMENT "
+ =                  "triggers = are not implemented, please supply FOR EACH ROW "
+         =          "clause", 0, NULL);
  =  pParse->is_aborted =3D true;
 }
 foreach_clause ::=3D FOR EACH = ROW.
@@ = -1639,8 +1670,9 @@ trigger_cmd_list(A) ::=3D trigger_cmd(A) SEMI. = {
 trnm(A) ::=3D nm(A).
 trnm(A) ::=3D nm DOT nm(X). = {
  =  A =3D X;
-  diag_set(ClientError, ER_SQL_PARSER_GENERIC, = "qualified table names are not "\
-           "allowed = on INSERT, UPDATE, and DELETE statements within = triggers");
+ =  parser_diag_set(pParse, ER_SQL_PARSER_GENERIC, 0, "qualified table = names are "
+ =                  "not = allowed on INSERT, UPDATE, and DELETE statements within = "
+   =                "triggers", 0, = NULL);
  =  pParse->is_aborted =3D true;
 }
 
@@ -1650,14 +1682,15 @@ trnm(A) ::=3D nm DOT = nm(X). {
 //
 tridxby ::=3D .
 tridxby ::=3D INDEXED BY nm. = {
- =  diag_set(ClientError, ER_SQL_SYNTAX, "trigger body", "the INDEXED = BY clause "\
-=           "is not allowed on UPDATE or DELETE = statements within triggers");
+  parser_diag_set(pParse, ER_SQL_SYNTAX, = 0, "trigger body", 0, "the INDEXED BY "
+             =      "clause is not allowed on UPDATE or DELETE = statements within "
+                 =  "triggers");
   pParse->is_aborted =3D true;
 }
 tridxby ::=3D NOT = INDEXED. {
- =  diag_set(ClientError, ER_SQL_SYNTAX, "trigger body", "the NOT = INDEXED "\
- =           "clause is not allowed on UPDATE or = DELETE statements within "\
-           = "triggers");
+=  parser_diag_set(pParse, ER_SQL_SYNTAX, 0, "trigger body", 0, "the = NOT INDEXED "
+                 =  "clause is not allowed on UPDATE or DELETE statements within = "
+   =               =  "triggers");
   pParse->is_aborted =3D true;
 }
 
diff --git = a/src/box/sql/prepare.c b/src/box/sql/prepare.c
index 0ecc676e2..df9a7ca22 = 100644
--- = a/src/box/sql/prepare.c
+++ b/src/box/sql/prepare.c
@@ -243,6 +243,8 @@ sql_parser_create(struct = Parse *parser, struct sql *db, uint32_t sql_flags)
  = memset(parser, 0, sizeof(struct Parse));
  = parser->db =3D db;
  parser->sql_flags =3D = sql_flags;
+ = parser->line_count =3D 1;
+ parser->line_pos =3D = 1;
  = region_create(&parser->region, = &cord()->slabc);
 }
 
diff --git a/src/box/sql/resolve.c = b/src/box/sql/resolve.c
index 6f625dc18..40c93dbf1 100644
--- = a/src/box/sql/resolve.c
+++ b/src/box/sql/resolve.c
@@ -382,6 +382,7 @@ lookupName(Parse * = pParse, = /* The parsing context */
  =    && ExprHasProperty(pOrig, EP_Agg)) = {
  = diag_set(ClientError,
  = ER_SQL_PARSER_GENERIC,
+ = "",
 = = tt_sprintf(err, zAs));
 = = pParse->is_aborted =3D true;
  = return WRC_Abort;
@@ -389,6 +390,7 @@ lookupName(Parse * pParse, /* The = parsing context */
 = if = (sqlExprVectorSize(pOrig) !=3D 1) {
  = diag_set(ClientError,
  = ER_SQL_PARSER_GENERIC,
+ = "",
 = "row = value misused");
 = = pParse->is_aborted =3D true;
  = return WRC_Abort;
@@ -424,7 +426,7 @@ lookupName(Parse * pParse, /* The = parsing context */
 = } else {
  err =3D = tt_sprintf("ambiguous column name: %s", zCol);
  = }
- = diag_set(ClientError, ER_SQL_PARSER_GENERIC, = err);
+ = diag_set(ClientError, ER_SQL_PARSER_GENERIC, "", = err);
 = pParse->is_aborted =3D true;
  = pTopNC->nErr++;
  }
@@ -606,7 +608,7 @@ resolveExprStep(Walker * = pWalker, Expr * pExpr)
 = return = WRC_Abort;
 = }
  if = (!func->def->exports.sql) {
- = diag_set(ClientError, ER_SQL_PARSER_GENERIC,
+ = diag_set(ClientError, ER_SQL_PARSER_GENERIC, "",
  = tt_sprintf("function %.*s() is not "
  =    "available in = SQL",
 =     = nId, zId));
@@= -661,7 +663,8 @@ resolveExprStep(Walker * pWalker, Expr * = pExpr)
 = const char *err = =3D
 = tt_sprintf("misuse of = aggregate "\
 =   "function = %.*s()", nId, zId);
- = diag_set(ClientError, ER_SQL_PARSER_GENERIC, = err);
+ = diag_set(ClientError, ER_SQL_PARSER_GENERIC, "",
+ = err);
 = pParse->is_aborted =3D = true;
 = pNC->nErr++;
  = is_agg =3D 0;
@@ -917,13 +920,14 @@ resolveCompoundOrderBy(Parse * = pParse, = /* Parsing context.  Leave error messages
  = if (sqlExprIsInteger(pE, &iCol)) {
  = if (iCol <=3D 0 || iCol > pEList->nExpr) = {
  = const char *err =3D
- = "Error at ORDER BY in place "\
+ = "error at ORDER BY in place "\
  = "%d: term out of range - "\
  = "should be between 1 and %d";
  = err =3D tt_sprintf(err, i + 1,
  = pEList->nExpr);
  = diag_set(ClientError,
- = ER_SQL_PARSER_GENERIC, err);
+ = ER_SQL_PARSER_GENERIC, "",
+ = err);
 = pParse->is_aborted =3D = true;
 = return = 1;
  = }
@@ = -973,10 +977,10 @@ resolveCompoundOrderBy(Parse * pParse, /* = Parsing context.  Leave error messages
  = }
 = for (i =3D 0; i < pOrderBy->nExpr; i++) = {
  = if (pOrderBy->a[i].done =3D=3D 0) {
- const char *err =3D= "Error at ORDER BY in place %d: "\
+ const char *err =3D= "error at ORDER BY in place %d: "\
  =  "term does not match any column in "\
  =  "the result set";
- = diag_set(ClientError, ER_SQL_PARSER_GENERIC,
+ = diag_set(ClientError, ER_SQL_PARSER_GENERIC, "",
  = tt_sprintf(err, i + 1));
  = pParse->is_aborted =3D true;
  return = 1;
@@ = -1023,12 +1027,12 @@ sqlResolveOrderGroupBy(Parse * pParse, /* = Parsing context.  Leave error messages
  for (i =3D = 0, pItem =3D pOrderBy->a; i < pOrderBy->nExpr; i++, pItem++) = {
  = if (pItem->u.x.iOrderByCol) {
  if = (pItem->u.x.iOrderByCol > pEList->nExpr) {
- const = char *err =3D "Error at %s BY in place "\
+ const = char *err =3D "error at %s BY in place "\
  =  "%d: term out of range - = "\
  =  "should be between 1 and = %d";
 = err =3D tt_sprintf(err, zType, i = + 1,
 = = pEList->nExpr);
- = diag_set(ClientError, = ER_SQL_PARSER_GENERIC,
+ = diag_set(ClientError, ER_SQL_PARSER_GENERIC, = "",
 = err);
  = pParse->is_aborted =3D true;
  return = 1;
@@ = -1094,11 +1098,11 @@ resolveOrderGroupBy(NameContext * pNC, /* The = name context of the SELECT stateme
  * order-by term = to a copy of the result-set expression
  = */
  = if (iCol < 1 || iCol > 0xffff) {
- const = char *err =3D "Error at %s BY in place "\
+ const = char *err =3D "error at %s BY in place "\
  =  "%d: term out of range - = "\
  =  "should be between 1 and = %d";
 = err =3D tt_sprintf(err, zType, i = + 1, nResult);
- = diag_set(ClientError, = ER_SQL_PARSER_GENERIC,
+ = diag_set(ClientError, ER_SQL_PARSER_GENERIC, = "",
 = err);
  = pParse->is_aborted =3D true;
  return = 1;
@@ = -1387,7 +1391,7 @@ resolveSelectStep(Walker * pWalker, Select * = p)
  =     i++, pItem++) {
  if = (ExprHasProperty(pItem->pExpr, EP_Agg)) {
  = diag_set(ClientError,
- = ER_SQL_PARSER_GENERIC,
+ = ER_SQL_PARSER_GENERIC, "",
  = err_msg);
 = pParse->is_aborted =3D = true;
 = return = WRC_Abort;
@@ = -1400,7 +1404,7 @@ resolveSelectStep(Walker * pWalker, Select * = p)
  = */
  = if (p->pNext && p->pEList->nExpr !=3D = p->pNext->pEList->nExpr) {
  if = (p->pNext->selFlags & SF_Values) {
- = diag_set(ClientError, ER_SQL_PARSER_GENERIC,
+ = diag_set(ClientError, ER_SQL_PARSER_GENERIC, "",
  = "all VALUES must have the same "\
  = "number of terms");
  } else = {
@@ -1410,7 = +1414,7 @@ resolveSelectStep(Walker * pWalker, Select * = p)
  = "result columns";
  const = char *op =3D
 = = sql_select_op_name(p->pNext->op);
- = diag_set(ClientError, ER_SQL_PARSER_GENERIC,
+ = diag_set(ClientError, ER_SQL_PARSER_GENERIC, "",
  = tt_sprintf(err, op));
  = }
 = pParse->is_aborted =3D = true;
diff = --git a/src/box/sql/select.c b/src/box/sql/select.c
index 8f93edd16..0371a73c6 = 100644
--- = a/src/box/sql/select.c
+++ b/src/box/sql/select.c
@@ -451,7 +451,7 @@ sqlJoinType(Parse * = pParse, Token * pA, Token * pB, Token * pC)
  = "%.*s %.*s %.*s", pA->n, pA->z, = pB->n,
 = pB->z, pC->n, = pC->z);
 = }
- = diag_set(ClientError, ER_SQL_PARSER_GENERIC, = err);
+ = diag_set(ClientError, ER_SQL_PARSER_GENERIC, "", = err);
 = pParse->is_aborted =3D true;
  = jointype =3D JT_INNER;
  } else if ((jointype & = JT_OUTER) !=3D 0
@@ -640,7 +640,7 @@ sqlProcessJoin(Parse * pParse, Select * = p)
  = */
  = if (pRight->fg.jointype & JT_NATURAL) {
  = if (pRight->pOn || pRight->pUsing) {
- = diag_set(ClientError, ER_SQL_PARSER_GENERIC,
+ = diag_set(ClientError, ER_SQL_PARSER_GENERIC, "",
  = "a NATURAL join may not have "
  = "an ON or USING clause");
  = pParse->is_aborted =3D true;
@@ -664,7 +664,7 @@ sqlProcessJoin(Parse * = pParse, Select * p)
 = /* Disallow both ON and USING clauses in the same = join
 = */
  if (pRight->pOn = && pRight->pUsing) {
- = diag_set(ClientError, ER_SQL_PARSER_GENERIC,
+ = diag_set(ClientError, ER_SQL_PARSER_GENERIC, "",
  = "cannot have both ON and USING clauses in "\
  = "the same join");
  = pParse->is_aborted =3D true;
@@ -709,7 +709,7 @@ sqlProcessJoin(Parse * = pParse, Select * p)
 =    ) = {
  = err =3D tt_sprintf(err, zName);
  = diag_set(ClientError,
- = ER_SQL_PARSER_GENERIC, err);
+ = ER_SQL_PARSER_GENERIC, "", err);
  = pParse->is_aborted =3D true;
  = return 1;
 = }
@@ -2115,7 +2115,7 @@ = computeLimitRegisters(Parse * pParse, Select * p, int = iBreak)
 = if((p->pLimit->flags & EP_Collate) !=3D = 0 ||
 =   (p->pOffset !=3D NULL = &&
 =   (p->pOffset->flags & = EP_Collate) !=3D 0)) {
- = diag_set(ClientError, = ER_SQL_UNRECOGNIZED_SYNTAX,
+ = diag_set(ClientError, ER_SQL_UNRECOGNIZED_SYNTAX, = "",
 = sizeof("COLLATE"), = "COLLATE");
 = pParse->is_aborted =3D = true;
 = return;
@@ -2618,7 +2618,7 @@ multiSelect(Parse * = pParse, = /* Parsing context */
  const char *err_msg = =3D
 = tt_sprintf("ORDER BY clause should come = after %s not "\
 =   "before", = sql_select_op_name(p->op));
- diag_set(ClientError, = ER_SQL_PARSER_GENERIC, err_msg);
+ diag_set(ClientError, = ER_SQL_PARSER_GENERIC, "", err_msg);
  pParse->is_aborted =3D = true;
 = rc =3D 1;
  goto = multi_select_end;
@@ -2627,7 +2627,7 @@ multiSelect(Parse * pParse, /* = Parsing context */
 = const char *err_msg =3D
  = tt_sprintf("LIMIT clause should come after %s not = "\
  =   "before", sql_select_op_name(p->op));
- diag_set(ClientError, = ER_SQL_PARSER_GENERIC, err_msg);
+ diag_set(ClientError, = ER_SQL_PARSER_GENERIC, "", err_msg);
  pParse->is_aborted =3D = true;
 = rc =3D 1;
  goto = multi_select_end;
@@ -4642,14 +4642,14 @@ withExpand(Walker * pWalker, struct = SrcList_item *pFrom)
 = * In this case, proceed.
  = */
  = if (pCte->zCteErr) {
- = diag_set(ClientError, ER_SQL_PARSER_GENERIC,
+ = diag_set(ClientError, ER_SQL_PARSER_GENERIC, "",
  = tt_sprintf(pCte->zCteErr, pCte->zName));
  = pParse->is_aborted =3D true;
  return = -1;
 = }
 = if (pFrom->fg.isTabFunc) {
  = const char *err =3D "'%s' is not a function";
- = diag_set(ClientError, ER_SQL_PARSER_GENERIC,
+ = diag_set(ClientError, ER_SQL_PARSER_GENERIC, "",
  = tt_sprintf(err, pFrom->zName));
  = pParse->is_aborted =3D true;
  return = -1;
@@ = -4688,7 +4688,8 @@ withExpand(Walker * pWalker, struct SrcList_item = *pFrom)
 = const char *err_msg =3D
  = tt_sprintf("multiple references to recursive "\
  =   "table: %s", pCte->zName);
- = diag_set(ClientError, ER_SQL_PARSER_GENERIC, = err_msg);
+ = diag_set(ClientError, ER_SQL_PARSER_GENERIC, = "",
+ = err_msg);
 = pParse->is_aborted =3D = true;
 = return -1;
  = }
@@ = -4710,7 +4711,8 @@ withExpand(Walker * pWalker, struct SrcList_item = *pFrom)
 =   "for %d = columns",
 =   = pCte->zName, pEList->nExpr,
  =   pCte->pCols->nExpr);
- = diag_set(ClientError, ER_SQL_PARSER_GENERIC, = err_msg);
+ = diag_set(ClientError, ER_SQL_PARSER_GENERIC, = "",
+ = err_msg);
  = pParse->is_aborted =3D true;
  = pParse->pWith =3D pSavedWith;
  return = -1;
@@ = -4865,7 +4867,7 @@ selectExpander(Walker * pWalker, Select * = p)
  = const char *err =3D
  = tt_sprintf("'%s' is not a function",
  =   pFrom->zName);
- = diag_set(ClientError, ER_SQL_PARSER_GENERIC,
+ = diag_set(ClientError, ER_SQL_PARSER_GENERIC, "",
  = err);
 = pParse->is_aborted =3D = true;
 = return = WRC_Abort;
@@ = -5285,7 +5287,7 @@ resetAccumulator(Parse * pParse, AggInfo * = pAggInfo)
 = Expr *pE =3D = pFunc->pExpr;
 = assert(!ExprHasProperty(pE, = EP_xIsSelect));
 = if (pE->x.pList =3D=3D 0 || = pE->x.pList->nExpr !=3D 1) {
- = diag_set(ClientError, ER_SQL_PARSER_GENERIC,
+ = diag_set(ClientError, ER_SQL_PARSER_GENERIC, "",
  = "DISTINCT aggregates must have "\
  = "exactly one argument");
  = pParse->is_aborted =3D true;
diff --git a/src/box/sql/sqlInt.h = b/src/box/sql/sqlInt.h
index 2594b73e0..df821a26b 100644
--- = a/src/box/sql/sqlInt.h
+++ b/src/box/sql/sqlInt.h
@@ -2181,6 +2181,10 @@ struct Parse = {
  =  ********************************************************************= ***/
 
 = Token sLastToken; /* The last token parsed = */
+ /** The = line counter. */
+ = uint32_t line_count;
+ /** The position in a line. = */
+ uint32_t = line_pos;
 = ynVar nVar; /* Number of '?' = variables seen in the SQL so far */
  u8 explain; = /* True if the EXPLAIN flag is found on the query = */
  int = nHeight; = /* Expression tree height of current sub-select = */
@@ = -4467,4 +4471,16 @@ int
 sql_fieldno_by_name(struct Parse *parse_context, struct = Expr *field_name,
 =    uint32_t = *fieldno);
 
+/**
+ * Call diag_set() with or without error line and = offset.
+ = *
+ * @param = parser Parser.
+ * @param len    String length.
+ * @param str_1  Ptr to = first string.
+ * @param str_2  Ptr to second string.
+ */
+void
+parser_diag_set(struct Parse = *parser, uint32_t errcode, uint32_t len_1,
+ const char *str_1, = uint32_t len_2, const char *str_2);
+
 #endif /* = sqlINT_H */
diff --git a/src/box/sql/tokenize.c = b/src/box/sql/tokenize.c
index 9fa069d09..1e44c4312 100644
--- = a/src/box/sql/tokenize.c
+++ b/src/box/sql/tokenize.c
@@ -82,10 +82,11 @@
 #define CC_TILDA   =   25 = /* '~' */
 #define CC_DOT       26 = /* '.' */
 #define CC_ILLEGAL   27 = /* Illegal character */
+#define CC_LINEFEED  28 = /* '\n' */
 
 static const char sql_ascii_class[] =3D = {
 /* =       x0  x1  x2  x3  x4  x5 =  x6  x7  x8 x9  xa xb  xc xd xe  xf = */
-/* 0x */ = 27, 27, 27, 27, 27, 27, 27, 27, 27, 7,  7, 7, 7, 7, 27, = 27,
+/* 0x = */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 7, 28, 7, 7, 7, 27, = 27,
 /* = 1x */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, = 27,
 /* = 2x */ 7, 15, 9, 5, 4, 22, 24, 8, 17, 18, 21, 20, 23, 11, 26, = 16,
 /* = 3x */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 19, 12, 14, 13, = 6,
@@ = -192,12 +193,24 @@ sql_token(const char *z, int *type, bool = *is_reserved)
 = i =3D 1 + sql_skip_spaces(z+1);
  = *type =3D TK_SPACE;
  return = i;
+ case = CC_LINEFEED:
+ = *type =3D TK_LINEFEED;
+ return = 1;
  case = CC_MINUS:
+ = /*
+ = * Ignore single-line comment started with "--"
+ * till the end of = parsing string or next line.
+ */
  = if (z[1] =3D=3D '-') {
- for (i =3D 2; (c = =3D z[i]) !=3D 0 && c !=3D '\n'; i++) {
+ for (i =3D 2; = true; i++) {
+ = if (z[i] =3D=3D '\0') {
+ = *type =3D TK_SPACE;
+ = return i;
+ = } else if (z[i] =3D=3D '\n') {
+ = *type =3D TK_LINEFEED;
+ = return ++i;
+ = }
 = }
- *type =3D = TK_SPACE;
- = return i;
 = }
 = *type =3D TK_MINUS;
  = return 1;
@@ -499,12 +512,16 @@ sqlRunParser(Parse * pParse, const char = *zSql)
 = assert(tokenType =3D=3D = TK_SPACE
 =       || tokenType =3D=3D = TK_ILLEGAL);
 = if (tokenType =3D=3D TK_ILLEGAL) = {
- = diag_set(ClientError, ER_SQL_UNKNOWN_TOKEN,
+ = parser_diag_set(pParse, ER_SQL_UNKNOWN_TOKEN,
  = pParse->sLastToken.n,
- = pParse->sLastToken.z);
+ = pParse->sLastToken.z, 0, = NULL);
 = pParse->is_aborted =3D = true;
 = break;
  = }
+ = } else if (tokenType =3D=3D TK_LINEFEED) {
+ = pParse->line_count++;
+ = pParse->line_pos =3D 1;
+ = continue;
 = } else {
  = sqlParser(pEngine, tokenType, = pParse->sLastToken,
 =     =  pParse);
@@ -512,6 +529,7 @@ sqlRunParser(Parse * pParse, const char = *zSql)
 = if (pParse->is_aborted || = db->mallocFailed)
 = break;
  = }
+ = pParse->line_pos +=3D = pParse->sLastToken.n;
 = }
 = pParse->zTail =3D &zSql[i];
  = sqlParserFree(pEngine, sql_free);
diff --git a/src/box/sql/trigger.c = b/src/box/sql/trigger.c
index 0c387bc3b..283e67f53 100644
--- = a/src/box/sql/trigger.c
+++ b/src/box/sql/trigger.c
@@ -595,8 +595,8 @@ codeTriggerProgram(Parse * = pParse, = /* The parser context */
  = sqlSubProgramsRemaining--;
 
  if (sqlSubProgramsRemaining =3D=3D = 0) {
- = diag_set(ClientError, ER_SQL_PARSER_GENERIC, "Maximum number = "\
- = "of chained trigger activations exceeded.");
+ diag_set(ClientError, = ER_SQL_PARSER_GENERIC, "", "maximum "
+ "number of = chained trigger activations exceeded.");
  pParse->is_aborted =3D = true;
 = }
 
diff --git a/src/box/sql/update.c = b/src/box/sql/update.c
index 6d69b7252..7d46e3cee 100644
--- = a/src/box/sql/update.c
+++ b/src/box/sql/update.c
@@ -156,7 +156,7 @@ sqlUpdate(Parse * = pParse, = /* The parser context */
  = err =3D tt_sprintf(err,
  = pChanges->a[i].zName);
  = diag_set(ClientError,
- = ER_SQL_PARSER_GENERIC,
+ = ER_SQL_PARSER_GENERIC, "",
  = err);
 = pParse->is_aborted =3D = true;
 = goto = update_cleanup;
diff --git a/test/box/function1.result = b/test/box/function1.result
index b91d63c51..a1020471d = 100644
--- = a/test/box/function1.result
+++ = b/test/box/function1.result
@@ -387,7 +387,7 @@ test_run:cmd("setopt = delimiter ''");
 box.execute('SELECT = "function1.divide"()')
 ---
 - null
-- function function1.divide() is not available in = SQL
+- = 'Syntax error: function function1.divide() is not available in = SQL'
 ...
 box.func["function1.divide"]:drop()
 ---
diff --git = a/test/sql-tap/alter2.test.lua = b/test/sql-tap/alter2.test.lua
index e0bd60727..9f53ab86a = 100755
--- = a/test/sql-tap/alter2.test.lua
+++ = b/test/sql-tap/alter2.test.lua
@@ -223,7 +223,7 @@ = test:do_catchsql_test(
         ALTER TABLE child ADD = CONSTRAINT fk FOREIGN KEY REFERENCES child(id);
     ]], = {
  =        -- <alter2-4.1>
-       =  1, "Keyword 'REFERENCES' is reserved. Please use double quotes if = 'REFERENCES' is an identifier."
+        1, "Syntax error = on line 1 at column 57: keyword 'REFERENCES' is reserved. Please use = double quotes if 'REFERENCES' is an identifier."
        =  -- </alter2-4.1>
     })
 
@@ -233,7 +233,7 @@ = test:do_catchsql_test(
         ALTER TABLE child ADD = CONSTRAINT fk () FOREIGN KEY REFERENCES child(id);
     ]], = {
  =        -- <alter2-4.1>
-       =  1, "Syntax error near '('"
+        1, "Syntax error = on line 1 at column 45 near '('"
         -- = </alter2-4.2>
     })
 
diff --git a/test/sql-tap/autoinc.test.lua = b/test/sql-tap/autoinc.test.lua
index 39e47966b..a7745f390 = 100755
--- = a/test/sql-tap/autoinc.test.lua
+++ = b/test/sql-tap/autoinc.test.lua
@@ -880,7 +880,7 @@ = test:do_catchsql_test(
     [[
         CREATE TABLE = t11_7 (i INT AUTOINCREMENT, a INT AUTOINCREMENT, PRIMARY KEY(a, = i));
  =    ]], {
-        1, "Syntax error in CREATE = TABLE: Table must feature at most one AUTOINCREMENT = field"
+ =        1, "Syntax error in CREATE TABLE: table must = feature at most one AUTOINCREMENT field"
     })
 
 test:do_catchsql_test(
@@ -888,7 +888,7 @@ = test:do_catchsql_test(
     [[
         CREATE TABLE = t11_8 (i INT, a INT, PRIMARY KEY(a AUTOINCREMENT, i = AUTOINCREMENT));
     ]], {
-        1, "Syntax error = in CREATE TABLE: Table must feature at most one AUTOINCREMENT = field"
+ =        1, "Syntax error in CREATE TABLE: table must = feature at most one AUTOINCREMENT field"
     })
 
 test:do_catchsql_test(
diff --git a/test/sql-tap/blob.test.lua = b/test/sql-tap/blob.test.lua
index 2b5c7a9ca..e5d88eef9 = 100755
--- = a/test/sql-tap/blob.test.lua
+++ = b/test/sql-tap/blob.test.lua
@@ -72,7 +72,7 @@ = test:do_catchsql_test(
         SELECT X'01020k304', = 100
  =    ]], {
         -- = <blob-1.4>
-        1, [[Syntax error: unrecognized = token: 'X'01020k304'']]
+        1, [[Syntax error on line 1 at = column 16 unrecognized token: 'X'01020k304'']]
        =  -- </blob-1.4>
     })
 
@@ -81,7 +81,7 @@ = test:do_catchsql_test(
     [[
         SELECT = X'01020, 100]], {
         -- = <blob-1.5>
-        1, [[Syntax error: unrecognized = token: 'X'01020, 100']]
+        1, [[Syntax error on line 1 at = column 16 unrecognized token: 'X'01020, 100']]
        =  -- </blob-1.5>
     })
 
@@ -91,7 +91,7 @@ = test:do_catchsql_test(
         SELECT X'01020 = 100'
  =    ]], {
         -- = <blob-1.6>
-        1, [[Syntax error: unrecognized = token: 'X'01020 100'']]
+        1, [[Syntax error on line 1 at = column 16 unrecognized token: 'X'01020 100'']]
        =  -- </blob-1.6>
     })
 
@@ -101,7 +101,7 @@ = test:do_catchsql_test(
         SELECT = X'01001'
     ]], {
         -- = <blob-1.7>
-        1, [[Syntax error: unrecognized = token: 'X'01001'']]
+        1, [[Syntax error on line 1 at = column 16 unrecognized token: 'X'01001'']]
        =  -- </blob-1.7>
     })
 
@@ -111,7 +111,7 @@ = test:do_catchsql_test(
         SELECT = x'012/45'
     ]], {
         -- = <blob-1.8>
-        1, [[Syntax error: unrecognized = token: 'x'012/45'']]
+        1, [[Syntax error on line 1 at = column 16 unrecognized token: 'x'012/45'']]
        =  -- </blob-1.8>
     })
 
@@ -121,7 +121,7 @@ = test:do_catchsql_test(
         SELECT = x'012:45'
     ]], {
         -- = <blob-1.9>
-        1, [[Syntax error: unrecognized = token: 'x'012:45'']]
+        1, [[Syntax error on line 1 at = column 16 unrecognized token: 'x'012:45'']]
        =  -- </blob-1.9>
     })
 
@@ -131,7 +131,7 @@ = test:do_catchsql_test(
         SELECT = x'012@45'
     ]], {
         -- = <blob-1.10>
-        1, [[Syntax error: unrecognized = token: 'x'012@45'']]
+        1, [[Syntax error on line 1 at = column 16 unrecognized token: 'x'012@45'']]
        =  -- </blob-1.10>
     })
 
@@ -141,7 +141,7 @@ = test:do_catchsql_test(
         SELECT = x'012G45'
     ]], {
         -- = <blob-1.11>
-        1, [[Syntax error: unrecognized = token: 'x'012G45'']]
+        1, [[Syntax error on line 1 at = column 16 unrecognized token: 'x'012G45'']]
        =  -- </blob-1.11>
     })
 
@@ -151,7 +151,7 @@ = test:do_catchsql_test(
         SELECT = x'012`45'
     ]], {
         -- = <blob-1.12>
-        1, [[Syntax error: unrecognized = token: 'x'012`45'']]
+        1, [[Syntax error on line 1 at = column 16 unrecognized token: 'x'012`45'']]
        =  -- </blob-1.12>
     })
 
@@ -161,7 +161,7 @@ = test:do_catchsql_test(
         SELECT = x'012g45'
     ]], {
         -- = <blob-1.13>
-        1, [[Syntax error: unrecognized = token: 'x'012g45'']]
+        1, [[Syntax error on line 1 at = column 16 unrecognized token: 'x'012g45'']]
        =  -- </blob-1.13>
     })
 
diff --git = a/test/sql-tap/check.test.lua = b/test/sql-tap/check.test.lua
index c9b60bbf5..c0b1554de = 100755
--- = a/test/sql-tap/check.test.lua
+++ = b/test/sql-tap/check.test.lua
@@ -282,7 +282,7 @@ = test:do_catchsql_test(
         );
     ]], = {
  =        -- <check-2.10>
-       =  1,"Syntax error near ','"
+        1,"Syntax error = on line 2 at column 77 near ','"
         -- = </check-2.10>
     })
 
@@ -296,7 +296,7 @@ = test:do_catchsql_test(
         );
     ]], = {
  =        -- <check-2.10>
-       =  1,"Syntax error near ','"
+        1,"Syntax error = on line 3 at column 23 near ','"
         -- = </check-2.10>
     })
 
@@ -517,7 +517,7 @@ = test:do_catchsql_test(
         );
     ]], = {
  =        -- <check-5.1>
-       =  1, "Failed to create check constraint 'ck_unnamed_T5_1': bindings = are not allowed in DDL"
+        1, "Failed to create check = constraint 'ck_unnamed_T5_1': Syntax error: bindings are not allowed in = DDL"
  =        -- </check-5.1>
    =  })
 
@@ -529,7 +529,7 @@ test:do_catchsql_test(
        =  );
     ]], {
         -- = <check-5.2>
-        1, "Failed to create check = constraint 'ck_unnamed_T5_1': bindings are not allowed in = DDL"
+ =        1, "Failed to create check constraint = 'ck_unnamed_T5_1': Syntax error: bindings are not allowed in = DDL"
  =        -- </check-5.2>
    =  })
 
@@ -783,7 +783,7 @@ test:do_catchsql_test(
        =  ON CONFLICT REPLACE)
     ]], {
        =  -- <9.1>
-        1, "Keyword 'ON' is reserved. = Please use double quotes if 'ON' is an identifier."
+       =  1, "Syntax error on line 2 at column 9: keyword 'ON' is reserved. = Please use double quotes if 'ON' is an identifier."
        =  -- </9.1>
     })
 
@@ -794,7 +794,7 @@ = test:do_catchsql_test(
         ON CONFLICT = ABORT)
  =    ]], {
         -- = <9.2>
- =        1, "Keyword 'ON' is reserved. Please use = double quotes if 'ON' is an identifier."
+        1, "Syntax error = on line 2 at column 9: keyword 'ON' is reserved. Please use double = quotes if 'ON' is an identifier."
         -- = </9.2>
     })
 
@@ -805,7 +805,7 @@ = test:do_catchsql_test(
         ON CONFLICT = ROLLBACK)
     ]], {
         -- = <9.3>
- =        1, "Keyword 'ON' is reserved. Please use = double quotes if 'ON' is an identifier."
+        1, "Syntax error = on line 2 at column 9: keyword 'ON' is reserved. Please use double = quotes if 'ON' is an identifier."
         -- = </9.3>
     })
 
diff --git a/test/sql-tap/collation.test.lua = b/test/sql-tap/collation.test.lua
index f7099b222..b76a334b7 = 100755
--- = a/test/sql-tap/collation.test.lua
+++ = b/test/sql-tap/collation.test.lua
@@ -551,28 +551,28 @@ = test:do_execsql_test(
 test:do_catchsql_test(
    =  "collation-2.7.1",
     'SELECT one COLLATE "binary" FROM = test1',
- =    {1, "COLLATE clause can't be used with non-string = arguments"})
+=    {1, "Syntax error: COLLATE clause can't be used with = non-string arguments"})
 
 test:do_catchsql_test(
    =  "collation-2.7.2",
     'SELECT one COLLATE "unicode_ci" FROM = test1',
- =    {1, "COLLATE clause can't be used with non-string = arguments"})
+=    {1, "Syntax error: COLLATE clause can't be used with = non-string arguments"})
 
 test:do_catchsql_test(
    =  "collation-2.7.3",
     'SELECT two COLLATE "binary" FROM = test1',
- =    {1, "COLLATE clause can't be used with non-string = arguments"})
+=    {1, "Syntax error: COLLATE clause can't be used with = non-string arguments"})
 
 
 test:do_catchsql_test(
    =  "collation-2.7.4",
     'SELECT (one + two) COLLATE "binary" FROM = test1',
- =    {1, "COLLATE clause can't be used with non-string = arguments"})
+=    {1, "Syntax error: COLLATE clause can't be used with = non-string arguments"})
 
 test:do_catchsql_test(
    =  "collation-2.7.5",
     'SELECT (SELECT one FROM test1) COLLATE = "binary"',
- =    {1, "COLLATE clause can't be used with non-string = arguments"})
+=    {1, "Syntax error: COLLATE clause can't be used with = non-string arguments"})
 
 test:do_execsql_test(
    =  "collation-2.7.6",
@@ -582,32 +582,32 @@ test:do_execsql_test(
 test:do_catchsql_test(
    =  "collation-2.7.7",
     'SELECT RANDOM() COLLATE = "binary"',
- =    {1, "COLLATE clause can't be used with non-string = arguments"})
+=    {1, "Syntax error: COLLATE clause can't be used with = non-string arguments"})
 
 test:do_catchsql_test(
    =  "collation-2.7.8",
     'SELECT LENGTH(\'A\') COLLATE = "binary"',
- =    {1, "COLLATE clause can't be used with non-string = arguments"})
+=    {1, "Syntax error: COLLATE clause can't be used with = non-string arguments"})
 
 test:do_catchsql_test(
    =  "collation-2.7.9",
     'SELECT TRUE COLLATE = "unicode"',
- =    {1, "COLLATE clause can't be used with non-string = arguments"})
+=    {1, "Syntax error: COLLATE clause can't be used with = non-string arguments"})
 
 test:do_catchsql_test(
    =  "collation-2.7.10",
     'SELECT NOT TRUE COLLATE = "unicode"',
- =    {1, "COLLATE clause can't be used with non-string = arguments"})
+=    {1, "Syntax error: COLLATE clause can't be used with = non-string arguments"})
 
 test:do_catchsql_test(
    =  "collation-2.7.11",
     'SELECT TRUE AND TRUE COLLATE = "unicode"',
- =    {1, "COLLATE clause can't be used with non-string = arguments"})
+=    {1, "Syntax error: COLLATE clause can't be used with = non-string arguments"})
 
 test:do_catchsql_test(
    =  "collation-2.7.12",
     'SELECT 1 | 1 COLLATE = "unicode"',
- =    {1, "COLLATE clause can't be used with non-string = arguments"})
+=    {1, "Syntax error: COLLATE clause can't be used with = non-string arguments"})
 
 test:do_execsql_test(
    =  "collation-2.7.14",
diff --git a/test/sql-tap/count.test.lua = b/test/sql-tap/count.test.lua
index cf5bfccdd..354a464a4 = 100755
--- = a/test/sql-tap/count.test.lua
+++ = b/test/sql-tap/count.test.lua
@@ -128,7 +128,7 @@ = test:do_catchsql_test(
         SELECT count(DISTINCT *) = FROM t2
 =    ]], {
         -- = <count-2.2>
-        1, [[Syntax error near = '*']]
+ =        1, [[Syntax error on line 1 at column 31 near = '*']]
  =        -- </count-2.2>
    =  })
 
@@ -156,7 +156,7 @@ test:do_catchsql_test(
        =  SELECT count(DISTINCT) FROM t2
     ]], {
        =  -- <count-2.6>
-        1, "DISTINCT = aggregates must have exactly one argument"
+       =  1, "Syntax error: DISTINCT aggregates must have exactly one = argument"
         -- = </count-2.6>
     })
 
@@ -290,7 +290,7 @@ = test:do_catchsql_test(
         SELECT count(DISTINCT) FROM = t6 GROUP BY x;
     ]], {
         -- = <count-6.1>
-        1, "DISTINCT aggregates must = have exactly one argument"
+        1, "Syntax error: = DISTINCT aggregates must have exactly one argument"
        =  -- </count-6.1>
     })
 
diff --git = a/test/sql-tap/default.test.lua = b/test/sql-tap/default.test.lua
index f2a5db071..9feca0df1 = 100755
--- = a/test/sql-tap/default.test.lua
+++ = b/test/sql-tap/default.test.lua
@@ -224,7 +224,7 @@ = test:do_catchsql_test(
         CREATE TABLE t6(id INTEGER = PRIMARY KEY, b TEXT DEFAULT id);
     ]], {
     -- = <default-5.2>
-    1, "Syntax error near 'id'"
+    1, "Syntax = error on line 1 at column 64 near 'id'"
     -- = </default-5.2>
 })
 
@@ -234,7 +234,7 @@ test:do_catchsql_test(
        =  CREATE TABLE t6(id INTEGER PRIMARY KEY, b TEXT DEFAULT = "id");
  =    ]], {
     -- <default-5.3>
-    1, "Syntax = error near '\"id\"'"
+    1, "Syntax error on line 1 at column 64 near = '\"id\"'"
     -- </default-5.3>
 })
 
diff --git = a/test/sql-tap/distinctagg.test.lua = b/test/sql-tap/distinctagg.test.lua
index 5454bf0ed..8e0042f77 = 100755
--- = a/test/sql-tap/distinctagg.test.lua
+++ = b/test/sql-tap/distinctagg.test.lua
@@ -75,7 +75,7 @@ = test:do_catchsql_test(
         SELECT count(distinct) FROM = t1;
  =    ]], {
         -- = <distinctagg-2.1>
-        1, "DISTINCT aggregates must = have exactly one argument"
+        1, "Syntax error: = DISTINCT aggregates must have exactly one argument"
        =  -- </distinctagg-2.1>
     })
 
@@ -85,7 +85,7 @@ = test:do_catchsql_test(
         SELECT = group_concat(distinct a,b) FROM t1;
     ]], {
        =  -- <distinctagg-2.2>
-        1, "DISTINCT = aggregates must have exactly one argument"
+       =  1, "Syntax error: DISTINCT aggregates must have exactly one = argument"
         -- = </distinctagg-2.2>
     })
 
diff --git a/test/sql-tap/e_select1.test.lua = b/test/sql-tap/e_select1.test.lua
index a0a671644..0d9b29453 = 100755
--- = a/test/sql-tap/e_select1.test.lua
+++ = b/test/sql-tap/e_select1.test.lua
@@ -95,7 +95,7 @@ = test:do_catchsql_test(
         SELECT count(*) FROM t1, t2 = ON (t1.a=3Dt2.a) USING (a)
     ]], {
        =  -- <e_select-0.1.4>
-        1, "cannot have = both ON and USING clauses in the same join"
+       =  1, "Syntax error: cannot have both ON and USING clauses in the = same join"
         -- = </e_select-0.1.4>
     })
 
@@ -105,7 +105,7 @@ = test:do_catchsql_test(
         SELECT count(*) FROM t1, t2 = USING (a) ON (t1.a=3Dt2.a)
     ]], {
        =  -- <e_select-0.1.5>
-        1, [[Keyword 'ON' = is reserved. Please use double quotes if 'ON' is an = identifier.]]
+        1, [[Syntax error on line 1 at = column 47: keyword 'ON' is reserved. Please use double quotes if 'ON' is = an identifier.]]
         -- = </e_select-0.1.5>
     })
 
@@ -643,7 +643,7 @@ for tn, sql in = ipairs(data) do
 string.format([[
            =  %s
         ]], sql), = {
-   =          1, "a NATURAL join may not have an ON = or USING clause"
+            1, "Syntax error: = a NATURAL join may not have an ON or USING clause"
        =  })
 
 end
@@ -805,9 +805,9 @@ test:do_select_tests(
 -- FROM = clause.
 --
 data =3D {
-    {"1.1", "SELECT a, b, c FROM z1 = WHERE *",  "Syntax error near '*'"},
-    {"1.2", = "SELECT a, b, c FROM z1 GROUP BY *", "Syntax error near = '*'"},
- =    {"1.3", "SELECT 1 + * FROM z1",  "Syntax error near = '*'"},
+ =    {"1.1", "SELECT a, b, c FROM z1 WHERE *",  "Syntax = error on line 1 at column 30 near '*'"},
+    {"1.2", "SELECT a, b, c FROM = z1 GROUP BY *", "Syntax error on line 1 at column 33 near = '*'"},
+ =    {"1.3", "SELECT 1 + * FROM z1",  "Syntax error on line = 1 at column 12 near '*'"},
     {"1.4", "SELECT * + 1 FROM = z1", "Failed to expand '*' in SELECT statement without FROM = clause"},
     {"2.1", "SELECT *", "Failed to expand '*' = in SELECT statement without FROM clause"},
     {"2.2", = "SELECT * WHERE 1", "Failed to expand '*' in SELECT statement without = FROM clause"},
@@ -1064,7 +1064,7 @@ data =3D {
 for _, val in = ipairs(data) do
     local tn =3D val[1]
     local = select =3D val[2]
-    local res =3D {1, "aggregate functions are not = allowed in the GROUP BY clause"}
+    local res =3D {1, "Syntax = error: aggregate functions are not allowed in the GROUP BY = clause"}
     test:do_catchsql_test(
        =  "e_select-4."..tn,
         select, = res)
@@ = -1341,7 +1341,7 @@ for tn, val in ipairs(data) do
     local sql = =3D val[1]
     local subst =3D val[2]
     local = label =3D "e_select-7.1."..tn
-    local error =3D = string.format("SELECTs to the left and right of %s do not have the same = number of result columns", subst)
+    local error =3D = string.format("Syntax error: SELECTs to the left and right of %s do not = have the same number of result columns", subst)
    =  test:do_catchsql_test(
        =  label,
         sql,
@@ -1380,7 +1380,7 @@ for _, = val in ipairs(data) do
     local op1 =3D val[3]
     local op2 = =3D val[4]
     local label =3D = "e_select-7.2."..tn
-    local error =3D string.format("%s clause = should come after %s not before", op1, op2)
+    local error =3D = string.format("Syntax error: %s clause should come after %s not before", = op1, op2)
     test:do_catchsql_test(
        =  label,
         select,
@@ -1853,13 +1853,13 @@ = test:do_catchsql_test(
     "e_select-8.7.1.1",
     "SELECT x = FROM d1 UNION ALL SELECT a FROM d2 ORDER BY x*z",
    =  {
- =        1, "Error at ORDER BY in place 1: term does = not match any column in the result set"})
+       =  1, "Syntax error: error at ORDER BY in place 1: term does not = match any column in the result set"})
 
 test:do_catchsql_test(
    =  "e_select-8.7.1.2",
     "SELECT x,z FROM d1 UNION ALL SELECT a,b = FROM d2 ORDER BY x, x/z",
     {
-        1, "Error at = ORDER BY in place 2: term does not match any column in the result = set"})
+ =        1, "Syntax error: error at ORDER BY in place = 2: term does not match any column in the result set"})
 
 test:do_select_tests(
    =  "e_select-8.7.2",
@@ -2088,7 +2088,7 @@ for _, val in ipairs({{1, "SELECT a = FROM d5 UNION SELECT c FROM d6 ORDER BY a+1"
        =  "e_select-8.14."..tn,
        =  select,
         {
-         =    1, string.format("Error at ORDER BY in place %s: term does = not match any column in the result set", err_param)})
+         =    1, string.format("Syntax error: error at ORDER BY in place = %s: term does not match any column in the result set", = err_param)})
 end
 -- EVIDENCE-OF: R-03407-11483 Each term of the ORDER BY = clause is
 -- processed separately and may be matched against = result columns from
diff --git a/test/sql-tap/func.test.lua = b/test/sql-tap/func.test.lua
index 4574ddfeb..10651be15 = 100755
--- = a/test/sql-tap/func.test.lua
+++ = b/test/sql-tap/func.test.lua
@@ -1882,7 +1882,7 @@ = test:do_catchsql_test(
         SELECT = trim(1,2,3)
     ]], {
         -- = <func-22.1>
-        1, "Syntax error near = ','"
+ =        1, "Syntax error on line 1 at column 22 near = ','"
  =        -- </func-22.1>
    =  })
 
@@ -2228,7 +2228,7 @@ test:do_catchsql_test(
        =  SELECT TRIM(FROM 'xyxzy');
     ]], {
        =  -- <func-22.38>
-        1, "Syntax error = near 'FROM'"
+=        1, "Syntax error on line 1 at column 21 near = 'FROM'"
 =        -- </func-22.38>
    =  })
 
diff --git = a/test/sql-tap/gh-3307-xfer-optimization-issue.test.lua = b/test/sql-tap/gh-3307-xfer-optimization-issue.test.lua
index bb8a4989e..5e8061424 = 100755
--- = a/test/sql-tap/gh-3307-xfer-optimization-issue.test.lua
+++ = b/test/sql-tap/gh-3307-xfer-optimization-issue.test.lua
@@ -85,7 +85,7 @@ = test:do_catchsql_xfer_test(
         INSERT INTO = t2 SELECT * FROM t1;
     ]], {
         -- = <xfer-optimization-1.5>
-        1, "table T2 has = 2 columns but 3 values were supplied"
+        1, "Syntax error: = table T2 has 2 columns but 3 values were supplied"
        =  -- <xfer-optimization-1.5>
     }, {
        =  exp_xfer_count =3D 0
diff --git = a/test/sql-tap/gh2168-temp-tables.test.lua = b/test/sql-tap/gh2168-temp-tables.test.lua
index 3b29c9ed2..8012cf135 = 100755
--- = a/test/sql-tap/gh2168-temp-tables.test.lua
+++ = b/test/sql-tap/gh2168-temp-tables.test.lua
@@ -1,6 +1,6 = @@
 #!/usr/bin/env tarantool
 test =3D = require("sqltester")
-test:plan(2)
+test:plan(3)
 
 test:do_catchsql_test(
  "trigger2-10.1",
@@ -8,23 +8,32 @@ = test:do_catchsql_test(
 = CREATE TEMP TABLE tmp1 (id INTEGER PRIMARY = KEY);
 = ]], {
 = -- <trigger2-10.1>
- 1, "Syntax error near = 'TEMP'"
+ 1, = "Syntax error on line 1 at column 10 near 'TEMP'"
  = -- <trigger2-10.1>
 });
 
 -- TEMP triggers are removed now, check = it
-test:do_catchsql_test(
- "trigger2-10.1",
+
+test:do_execsql_test(
+ "trigger2-10.2",
  = [[
 = CREATE TABLE t1 (id INTEGER PRIMARY = KEY);
+ ]], = {
+ = -- <trigger2-10.2>
+ -- = <trigger2-10.2>
+});
+
+test:do_catchsql_test(
+ "trigger2-10.3",
+ [[
  = CREATE TEMP TRIGGER ttmp1 BEFORE UPDATE ON t1
  = BEGIN
 = SELECT 1;
  END;
  ]], = {
- = -- <trigger2-10.1>
- 1, "Syntax error near = 'TEMP'"
- = -- <trigger2-10.1>
+ -- = <trigger2-10.3>
+ = 1, "Syntax error on line 1 at column 10 near = 'TEMP'"
+ = -- <trigger2-10.3>
 });
 
 
diff --git = a/test/sql-tap/gh2250-trigger-chain-limit.test.lua = b/test/sql-tap/gh2250-trigger-chain-limit.test.lua
index 0a8a6c58d..62cc78566 = 100755
--- = a/test/sql-tap/gh2250-trigger-chain-limit.test.lua
+++ = b/test/sql-tap/gh2250-trigger-chain-limit.test.lua
@@ -81,7 +81,7 @@ for _, = table_count in ipairs({30, 31}) do
            =           function()
        =                   return = true
  =                     = end,
- =                     = table_count <=3D 30 or msg =3D=3D 'Maximum number of chained trigger = activations exceeded.')
+                 =     table_count <=3D 30 or msg =3D=3D 'Syntax error: = maximum number of chained trigger activations = exceeded.')
     end
 
     -- Exceed check for = UPDATE
diff = --git a/test/sql-tap/identifier_case.test.lua = b/test/sql-tap/identifier_case.test.lua
index 65ed9aea1..3d70e7457 = 100755
--- = a/test/sql-tap/identifier_case.test.lua
+++ = b/test/sql-tap/identifier_case.test.lua
@@ -240,7 +240,7 @@ = test:do_catchsql_test(
 data =3D {
     { 1,  [[ 'a' < 'b' = collate binary ]], {1, "Collation 'BINARY' does not = exist"}},
     { 2,  [[ 'a' < 'b' collate = "binary" ]], {0, {true}}},
-    { 3,  [[ 'a' < 'b' = collate 'binary' ]], {1, [[Syntax error near = ''binary'']]}},
+    { 3,  [[ 'a' < 'b' collate 'binary' = ]], {1, [[Syntax error on line 1 at column 43 near = ''binary'']]}},
     { 4,  [[ 'a' < 'b' collate = "unicode" ]], {0, {true}}},
     { 5,  [[ 5 < 'b' = collate "unicode" ]], {0, {true}}},
     { 6,  [[ 5 < 'b' = collate unicode ]], {1,"Collation 'UNICODE' does not = exist"}},
diff= --git a/test/sql-tap/in1.test.lua = b/test/sql-tap/in1.test.lua
index 570cc1779..9001e6cee = 100755
--- = a/test/sql-tap/in1.test.lua
+++ = b/test/sql-tap/in1.test.lua
@@ -725,7 +725,7 @@ = test:do_catchsql_test(
         );
     ]], = {
  =        -- <in-12.6>
-       =  1, "SELECTs to the left and right of UNION ALL do not have the = same number of result columns"
+        1, "Syntax error: = SELECTs to the left and right of UNION ALL do not have the same number = of result columns"
         -- = </in-12.6>
     })
 
@@ -737,7 +737,7 @@ = test:do_catchsql_test(
         );
     ]], = {
  =        -- <in-12.7>
-       =  1, "SELECTs to the left and right of UNION do not have the same = number of result columns"
+        1, "Syntax error: SELECTs to = the left and right of UNION do not have the same number of result = columns"
         -- = </in-12.7>
     })
 
@@ -749,7 +749,7 @@ = test:do_catchsql_test(
         );
     ]], = {
  =        -- <in-12.8>
-       =  1, "SELECTs to the left and right of EXCEPT do not have the same = number of result columns"
+        1, "Syntax error: SELECTs to = the left and right of EXCEPT do not have the same number of result = columns"
         -- = </in-12.8>
     })
 
@@ -761,7 +761,7 @@ = test:do_catchsql_test(
         );
     ]], = {
  =        -- <in-12.9>
-       =  1, "SELECTs to the left and right of INTERSECT do not have the = same number of result columns"
+        1, "Syntax error: = SELECTs to the left and right of INTERSECT do not have the same number = of result columns"
         -- = </in-12.9>
     })
 
@@ -775,7 +775,7 @@ = test:do_catchsql_test(
         );
     ]], = {
  =        -- <in-12.10>
-       =  1, "SELECTs to the left and right of UNION ALL do not have the = same number of result columns"
+        1, "Syntax error: = SELECTs to the left and right of UNION ALL do not have the same number = of result columns"
         -- = </in-12.10>
     })
 
@@ -787,7 +787,7 @@ = test:do_catchsql_test(
         );
     ]], = {
  =        -- <in-12.11>
-       =  1, "SELECTs to the left and right of UNION do not have the same = number of result columns"
+        1, "Syntax error: SELECTs to = the left and right of UNION do not have the same number of result = columns"
         -- = </in-12.11>
     })
 
@@ -799,7 +799,7 @@ = test:do_catchsql_test(
         );
     ]], = {
  =        -- <in-12.12>
-       =  1, "SELECTs to the left and right of EXCEPT do not have the same = number of result columns"
+        1, "Syntax error: SELECTs to = the left and right of EXCEPT do not have the same number of result = columns"
         -- = </in-12.12>
     })
 
@@ -811,7 +811,7 @@ = test:do_catchsql_test(
         );
     ]], = {
  =        -- <in-12.13>
-       =  1, "SELECTs to the left and right of INTERSECT do not have the = same number of result columns"
+        1, "Syntax error: = SELECTs to the left and right of INTERSECT do not have the same number = of result columns"
         -- = </in-12.13>
     })
 
@@ -835,7 +835,7 @@ = test:do_catchsql_test(
         );
     ]], = {
  =        -- <in-12.15>
-       =  1, "SELECTs to the left and right of UNION ALL do not have the = same number of result columns"
+        1, "Syntax error: = SELECTs to the left and right of UNION ALL do not have the same number = of result columns"
         -- = </in-12.15>
     })
 
diff --git a/test/sql-tap/index-info.test.lua = b/test/sql-tap/index-info.test.lua
index a5ed9a98e..46c64ba68 = 100755
--- = a/test/sql-tap/index-info.test.lua
+++ = b/test/sql-tap/index-info.test.lua
@@ -26,7 +26,7 @@ = test:do_catchsql_test(
     "index-info-1.2",
     "PRAGMA = index_info =3D t1.a;",
     {
-        1, "Syntax error = near '.'",
+ =        1, "Syntax error on line 1 at column 23 near = '.'",
  =    })
 
 -- Case: single column index with an integer = column.
diff = --git a/test/sql-tap/index1.test.lua = b/test/sql-tap/index1.test.lua
index 16209715d..7b8523555 = 100755
--- = a/test/sql-tap/index1.test.lua
+++ = b/test/sql-tap/index1.test.lua
@@ -994,7 +994,7 @@ = test:do_catchsql_test(
         CREATE INDEX temp.i21 ON = t6(c);
  =    ]], {
         -- = <index-21.1>
-        1, "Syntax error near = '.'"
+ =        1, "Syntax error on line 1 at column 26 near = '.'"
  =        -- </index-21.1>
    =  })
 
diff --git a/test/sql-tap/index7.test.lua = b/test/sql-tap/index7.test.lua
index ca5cb1910..340a5a963 = 100755
--- = a/test/sql-tap/index7.test.lua
+++ = b/test/sql-tap/index7.test.lua
@@ -1,6 +1,6 @@
 #!/usr/bin/env = tarantool
 test =3D require("sqltester")
-test:plan(11)
+test:plan(12)
 
 --!./tcltestrunner.lua
 -- 2013-11-04
@@ -286,13 +286,18 @@ = test:do_eqp_test(
 -- gh-2165 Currently, Tarantool lacks support of = partial indexes,
 -- so temporary we removed processing of their syntax = from parser.
 --
-test:do_catchsql_test(
+test:do_execsql_test(
    =  "index7-7.1",
     [[
         CREATE TABLE = t1 (a INTEGER PRIMARY KEY, b INTEGER);
+    ]])
+
+test:do_catchsql_test(
+    "index7-7.1",
+   =  [[
         CREATE UNIQUE INDEX i ON t1 = (a) WHERE a =3D 3;
     ]], {
-        1, "Keyword = 'WHERE' is reserved. Please use double quotes if 'WHERE' is an = identifier."
+=        1, "Syntax error on line 1 at column 41: = keyword 'WHERE' is reserved. Please use double quotes if 'WHERE' is an = identifier."
     })
 
 -- Currently, when a user tries to = create index (or primary key,
diff --git a/test/sql-tap/insert1.test.lua = b/test/sql-tap/insert1.test.lua
index d28baf11a..6a1078fa4 = 100755
--- = a/test/sql-tap/insert1.test.lua
+++ = b/test/sql-tap/insert1.test.lua
@@ -43,7 +43,7 @@ test:do_test("insert-1.3", = function()
   return test:catchsql "INSERT INTO test1 = VALUES(1,2)"
 end, {
   -- <insert-1.3>
-  1, "table TEST1 has 3 = columns but 2 values were supplied"
+  1, "Syntax error: table TEST1 has 3 = columns but 2 values were supplied"
   -- = </insert-1.3>
 })
 
@@ -51,7 +51,7 @@ test:do_catchsql_test("insert-1.3b", = [[
  =  INSERT INTO test1 VALUES(1,2,3,4)
 ]], {
   -- = <insert-1.3b>
-  1, "table TEST1 has 3 columns but 4 values were = supplied"
+ =  1, "Syntax error: table TEST1 has 3 columns but 4 values were = supplied"
   -- </insert-1.3b>
 })
 
@@ -59,7 +59,7 @@ = test:do_catchsql_test("insert-1.3c", [[
   INSERT INTO test1(one,two) = VALUES(1,2,3,4)
 ]], {
   -- <insert-1.3c>
-  1, "4 values for 2 = columns"
+ =  1, "Syntax error: 4 values for 2 columns"
   -- = </insert-1.3c>
 })
 
@@ -67,7 +67,7 @@ test:do_catchsql_test("insert-1.3d", = [[
  =  INSERT INTO test1(one,two) VALUES(1)
 ]], {
   -- = <insert-1.3d>
-  1, "1 values for 2 columns"
+  1, "Syntax error: 1 = values for 2 columns"
   -- </insert-1.3d>
 })
 
@@ -470,7 +470,7 @@ = test:do_execsql_test("insert-4.7", [[
     INSERT INTO t10 = VALUES(11,12,13), (14,15), (16,17,28);
   ]], {
     -- = <insert-10.2>
-    1, "all VALUES must have the same number of = terms"
+ =    1, "Syntax error: all VALUES must have the same number of = terms"
  =    -- </insert-10.2>
   })
 
@@ -519,14 +519,14 @@ = test:do_catchsql_test(
     [[
         insert into = test(a, a, b) values(1, 1, 1)
     ]],
-    {1, "table id = list: duplicate column name A"})
+    {1, "Syntax error: table id = list: duplicate column name A"})
 
 test:do_catchsql_test(
    =  "insert-13.2",
     [[
         insert into = test(a, b, b) values(1, 1, 1)
     ]],
-    {1, "table id = list: duplicate column name B"})
+    {1, "Syntax error: table id = list: duplicate column name B"})
 
 test:do_execsql_test(
    =  "insert-13.3",
diff --git a/test/sql-tap/join.test.lua = b/test/sql-tap/join.test.lua
index ac7d32b84..ad7ca9745 = 100755
--- = a/test/sql-tap/join.test.lua
+++ = b/test/sql-tap/join.test.lua
@@ -520,7 +520,7 @@ = test:do_catchsql_test(
         SELECT * FROM t1 NATURAL = JOIN t2 ON t1.a=3Dt2.b;
     ]], {
         -- = <join-3.1>
-        1, "a NATURAL join may not have = an ON or USING clause"
+        1, "Syntax error: a NATURAL join = may not have an ON or USING clause"
         -- = </join-3.1>
     })
 
@@ -530,7 +530,7 @@ = test:do_catchsql_test(
         SELECT * FROM t1 NATURAL = JOIN t2 USING(b);
     ]], {
         -- = <join-3.2>
-        1, "a NATURAL join may not have = an ON or USING clause"
+        1, "Syntax error: a NATURAL join = may not have an ON or USING clause"
         -- = </join-3.2>
     })
 
@@ -540,7 +540,7 @@ = test:do_catchsql_test(
         SELECT * FROM t1 JOIN t2 ON = t1.a=3Dt2.b USING(b);
     ]], {
         -- = <join-3.3>
-        1, "cannot have both ON and = USING clauses in the same join"
+        1, "Syntax error: = cannot have both ON and USING clauses in the same join"
        =  -- </join-3.3>
     })
 
@@ -550,7 +550,7 @@ = test:do_catchsql_test(
         SELECT * FROM t1 JOIN t2 = USING(a);
     ]], {
         -- = <join-3.4.1>
-        1, "cannot join using column A - = column not present in both tables"
+        1, "Syntax error: = cannot join using column A - column not present in both = tables"
 =        -- </join-3.4.1>
    =  })
 
@@ -560,7 +560,7 @@ test:do_catchsql_test(
        =  SELECT * FROM t1 JOIN t2 USING(d);
     ]], {
        =  -- <join-3.4.2>
-        1, "cannot join = using column D - column not present in both tables"
+       =  1, "Syntax error: cannot join using column D - column not present = in both tables"
         -- = </join-3.4.2>
     })
 
@@ -590,7 +590,7 @@ = test:do_catchsql_test(
         SELECT * FROM t1 INNER = OUTER JOIN t2;
     ]], {
         -- = <join-3.7>
-        1, "unknown or unsupported join = type: INNER OUTER"
+        1, "Syntax error: unknown or = unsupported join type: INNER OUTER"
         -- = </join-3.7>
     })
 
@@ -600,7 +600,7 @@ = test:do_catchsql_test(
         SELECT * FROM t1 INNER = OUTER CROSS JOIN t2;
     ]], {
         -- = <join-3.8>
-        1, "unknown or unsupported join = type: INNER OUTER CROSS"
+        1, "Syntax error: unknown or = unsupported join type: INNER OUTER CROSS"
        =  -- </join-3.8>
     })
 
@@ -610,7 +610,7 @@ = test:do_catchsql_test(
         SELECT * FROM t1 OUTER = NATURAL INNER JOIN t2;
     ]], {
         -- = <join-3.9>
-        1, "unknown or unsupported join = type: OUTER NATURAL INNER"
+        1, "Syntax error: = unknown or unsupported join type: OUTER NATURAL INNER"
        =  -- </join-3.9>
     })
 
@@ -620,7 +620,7 @@ = test:do_catchsql_test(
         SELECT * FROM t1 LEFT BOGUS = JOIN t2;
     ]], {
         -- = <join-3.10>
-        1, "unknown or unsupported join = type: LEFT BOGUS"
+        1, "Syntax error: unknown or = unsupported join type: LEFT BOGUS"
         -- = </join-3.10>
     })
 
@@ -630,7 +630,7 @@ = test:do_catchsql_test(
         SELECT * FROM t1 INNER = BOGUS CROSS JOIN t2;
     ]], {
         -- = <join-3.11>
-        1, "unknown or unsupported join = type: INNER BOGUS CROSS"
+        1, "Syntax error: unknown or = unsupported join type: INNER BOGUS CROSS"
        =  -- </join-3.11>
     })
 
@@ -640,7 +640,7 @@ = test:do_catchsql_test(
         SELECT * FROM t1 NATURAL = AWK SED JOIN t2;
     ]], {
         -- = <join-3.12>
-        1, "unknown or unsupported join = type: NATURAL AWK SED"
+        1, "Syntax error: unknown or = unsupported join type: NATURAL AWK SED"
         -- = </join-3.12>
     })
 
diff --git a/test/sql-tap/keyword1.test.lua = b/test/sql-tap/keyword1.test.lua
index 571e1dcbe..71548a46f = 100755
--- = a/test/sql-tap/keyword1.test.lua
+++ = b/test/sql-tap/keyword1.test.lua
@@ -240,11 +240,25 @@ end
 
 for _, kw in = ipairs(bannedkws) do
     query =3D 'CREATE TABLE '..kw..'(a INT = PRIMARY KEY);'
-    test:do_catchsql_test(
+    if kw =3D=3D = 'end' or kw =3D=3D 'match' or kw =3D=3D 'release' or kw =3D=3D 'rename' = or
+   =     kw =3D=3D 'replace' or kw =3D=3D 'binary' or kw =3D=3D = 'character' or
+       kw =3D=3D 'smallint' = then
+ =        test:do_catchsql_test(
        =  "bannedkw1-"..kw..".1",
         query, = {
-   =          1, "Keyword '"..kw.."' is reserved. = Please use double quotes if '"..kw.."' is an = identifier."
+=            1, "Syntax error on line 1 at = column "..14 + string.len(kw)..
+            ": = keyword '"..kw.."' is reserved. Please use double quotes if = '"
+   =          ..kw.."' is an = identifier."
         })
+   =  else
+ =        test:do_catchsql_test(
+       =  "bannedkw1-"..kw..".1",
+        query, = {
+   =          1, "Syntax error on line 1 at column = 14: keyword '"..kw..
+            "' is reserved. = Please use double quotes if '"..kw..
+            "' = is an identifier."
+        })
+   =  end
 end
 
 
diff --git a/test/sql-tap/limit.test.lua = b/test/sql-tap/limit.test.lua
index 870233942..b4b39e324 = 100755
--- = a/test/sql-tap/limit.test.lua
+++ = b/test/sql-tap/limit.test.lua
@@ -684,7 +684,7 @@ = test:do_catchsql_test(
         SELECT * FROM t7 LIMIT = 3
  =    ]], {
         -- = <limit-9.5>
-        1, "LIMIT clause should come = after UNION not before"
+        1, "Syntax error: LIMIT clause = should come after UNION not before"
         -- = </limit-9.5>
     })
 
diff --git a/test/sql-tap/misc1.test.lua = b/test/sql-tap/misc1.test.lua
index b84093e3c..ae7829ff8 = 100755
--- = a/test/sql-tap/misc1.test.lua
+++ = b/test/sql-tap/misc1.test.lua
@@ -1,6 +1,6 @@
 #!/usr/bin/env = tarantool
 test =3D require("sqltester")
-test:plan(58)
+test:plan(59)
 
 --!./tcltestrunner.lua
 -- 2001 September 15.
@@ -262,17 +262,26 @@ = test:do_execsql_test(
 -- before executing a command.  Thus if "WHERE" is = misspelled on an UPDATE,
 -- the user won't accidently update every = record.
 --
-test:do_catchsql_test(
-    "misc1-5.1",
+
+test:do_execsql_test(
+    "misc1-5.1.1",
    =  [[
         CREATE TABLE t3(a  INT = primary key,b INT );
         INSERT INTO t3 = VALUES(1,2);
         INSERT INTO t3 = VALUES(3,4);
+=    ]], {
+        -- = <misc1-5.1.1>
+        -- = </misc1-5.1.1>
+    })
+
+test:do_catchsql_test(
+   =  "misc1-5.1.2",
+    [[
         UPDATE t3 = SET a=3D0 WHEREwww b=3D2;
     ]], {
-        -- = <misc1-5.1>
-        1, [[Syntax error near = 'WHEREwww']]
-=        -- </misc1-5.1>
+       =  -- <misc1-5.1.2>
+        1, [[Syntax error = on line 1 at column 27 near 'WHEREwww']]
+        -- = </misc1-5.1.2>
     })
 
 test:do_execsql_test(
@@ -1037,7 +1046,7 @@ = test:do_catchsql_test(
        =  select''like''like''like#0;
     ]], {
        =  -- <misc1-21.1>
-        1, [[Syntax error = near '#0']]
+ =        1, [[Syntax error on line 1 at column 35 near = '#0']]
  =        -- </misc1-21.1>
    =  })
 
@@ -1047,7 +1056,7 @@ test:do_catchsql_test(
        =  VALUES(0,0x0MATCH#0;
     ]], {
        =  -- <misc1-21.2>
-        1, [[Syntax error = near '#0']]
+ =        1, [[Syntax error on line 1 at column 28 near = '#0']]
  =        -- </misc1-21.2>
    =  })
 
diff --git a/test/sql-tap/misc5.test.lua = b/test/sql-tap/misc5.test.lua
index 5f98f21f6..33ad8c3bb = 100755
--- = a/test/sql-tap/misc5.test.lua
+++ = b/test/sql-tap/misc5.test.lua
@@ -347,7 +347,7 @@ = test:do_catchsql_test(
         SELECT = 123abc
  =    ]], {
         -- = <misc5-10.1>
-        1, [[Syntax error: unrecognized = token: '123abc']]
+        1, [[Syntax error on line 1 at = column 16 unrecognized token: '123abc']]
         -- = </misc5-10.1>
     })
 
@@ -357,7 +357,7 @@ = test:do_catchsql_test(
         SELECT = 1*123.4e5ghi;
     ]], {
         -- = <misc5-10.2>
-        1, [[Syntax error: unrecognized = token: '123.4e5ghi']]
+        1, [[Syntax error on line 1 at = column 18 unrecognized token: '123.4e5ghi']]
        =  -- </misc5-10.2>
     })
 
diff --git = a/test/sql-tap/null.test.lua = b/test/sql-tap/null.test.lua
index de4d5033d..aa3367dba = 100755
--- = a/test/sql-tap/null.test.lua
+++ = b/test/sql-tap/null.test.lua
@@ -295,7 +295,7 @@ = test:do_catchsql_test(
         select b from t1 union = select c from t1 order by t1.a;
     ]], {
        =  -- <null-6.5>
-        1, "Error at ORDER BY in place = 1: term does not match any column in the result set"
+       =  1, "Syntax error: error at ORDER BY in place 1: term does not = match any column in the result set"
         -- = </null-6.5>
     })
 
@@ -305,7 +305,7 @@ = test:do_catchsql_test(
         select b from t1 union = select c from t1 order by t1.a;
     ]], {
        =  -- <null-6.6>
-        1, "Error at ORDER BY in place = 1: term does not match any column in the result set"
+       =  1, "Syntax error: error at ORDER BY in place 1: term does not = match any column in the result set"
         -- = </null-6.6>
     })
 
@@ -517,7 +517,7 @@ = test:do_catchsql_test(
     ]],
     {
     -- = <index-1.3>
-    1, "Syntax error near '1'"
+    1, "Syntax = error on line 1 at column 29 near '1'"
     -- = <index-1.3>
     })
 
@@ -528,7 +528,7 @@ = test:do_catchsql_test(
     ]],
     {
     -- = <index-1.3>
-    1, "Syntax error near '1'"
+    1, "Syntax = error on line 1 at column 33 near '1'"
     -- = <index-1.3>
     })
 
@@ -539,7 +539,7 @@ = test:do_catchsql_test(
     ]],
     {
     -- = <index-1.3>
-    1, "Syntax error near '1'"
+    1, "Syntax = error on line 1 at column 32 near '1'"
     -- = <index-1.3>
     })
 
@@ -550,7 +550,7 @@ = test:do_catchsql_test(
     ]],
     {
     -- = <index-1.3>
-    1, "Syntax error near '1'"
+    1, "Syntax = error on line 1 at column 36 near '1'"
     -- = <index-1.3>
     })
 
diff --git a/test/sql-tap/pragma.test.lua = b/test/sql-tap/pragma.test.lua
index b3821dcf7..fcd3c2e0b = 100755
--- = a/test/sql-tap/pragma.test.lua
+++ = b/test/sql-tap/pragma.test.lua
@@ -43,7 +43,7 @@ = test:do_catchsql_test(
 = [[
 = pragma sql_default_engine = 'memtx';
 = ]], {
- = 1, "Syntax error near ''memtx''"
+ 1, "Syntax error on line 1 at = column 29 near ''memtx''"
 })
 
 test:do_catchsql_test(
@@ -51,7 +51,7 @@ = test:do_catchsql_test(
 = [[
 = pragma sql_default_engine 1;
  ]], = {
- 1, = "Syntax error near '1'"
+ = 1, "Syntax error on line 1 at column 29 near = '1'"
 })
 
 --
diff --git a/test/sql-tap/resolver01.test.lua = b/test/sql-tap/resolver01.test.lua
index 315c892ac..21390dfe0 = 100755
--- = a/test/sql-tap/resolver01.test.lua
+++ = b/test/sql-tap/resolver01.test.lua
@@ -48,7 +48,7 @@ = test:do_catchsql_test(
         SELECT 1 AS yy FROM t1, t2 = ORDER BY y;
     ]], {
         -- = <resolver01-1.2>
-        1, "ambiguous column name: = Y"
+   =      1, "Syntax error: ambiguous column name: = Y"
  =        -- </resolver01-1.2>
    =  })
 
@@ -119,7 +119,7 @@ test:do_catchsql_test(
        =  SELECT 2 AS yy FROM t1, t2 ORDER BY y;
     ]], = {
  =        -- <resolver01-2.2>
-       =  1, "ambiguous column name: Y"
+        1, "Syntax error: = ambiguous column name: Y"
         -- = </resolver01-2.2>
     })
 
@@ -176,7 +176,7 @@ = test:do_catchsql_test(
         SELECT 3 AS y FROM t1, t2 = ORDER BY +y;
     ]], {
         -- = <resolver01-3.1>
-        1, "ambiguous column name: = Y"
+   =      1, "Syntax error: ambiguous column name: = Y"
  =        -- </resolver01-3.1>
    =  })
 
@@ -186,7 +186,7 @@ test:do_catchsql_test(
        =  SELECT 2 AS yy FROM t1, t2 ORDER BY +y;
     ]], = {
  =        -- <resolver01-3.2>
-       =  1, "ambiguous column name: Y"
+        1, "Syntax error: = ambiguous column name: Y"
         -- = </resolver01-3.2>
     })
 
diff --git a/test/sql-tap/select1.test.lua = b/test/sql-tap/select1.test.lua
index 4bbfbd67b..de3d5bd1f = 100755
--- = a/test/sql-tap/select1.test.lua
+++ = b/test/sql-tap/select1.test.lua
@@ -539,7 +539,7 @@ = test:do_catchsql_test(
         SELECT SUM(min(f1)) FROM = test1
  =    ]], {
         -- = <select1-2.20>
-        1, "misuse of aggregate function = MIN()"
+ =        1, "Syntax error: misuse of aggregate = function MIN()"
         -- = </select1-2.20>
     })
 
@@ -551,7 +551,7 @@ = test:do_catchsql_test(
         SELECT min(f1) AS m FROM = test1 GROUP BY f1 HAVING max(m+5)<10
     ]], {
        =  -- <select1-2.21>
-        1, "misuse of = aliased aggregate M"
+        1, "Syntax error: misuse of = aliased aggregate M"
         -- = </select1-2.21>
     })
 
@@ -563,7 +563,7 @@ = test:do_catchsql_test(
         HAVING = max(m+5)<10
     ]], {
         -- = <select1-2.22>
-        1, "misuse of aliased aggregate = M"
+   =      1, "Syntax error: misuse of aliased aggregate = M"
  =        -- </select1-2.22>
    =  })
 
@@ -577,7 +577,7 @@ test:do_catchsql_test(
 --   catchsql = {
 -- =     SELECT count(a) AS cn FROM tkt2526 GROUP BY a HAVING = cn<max(cn)
 --   }
--- } {1 {misuse of aliased aggregate = cn}}
+-- } = {1 {Syntax error: misuse of aliased aggregate cn}}
 -- WHERE clause = expressions
 --
 test:do_catchsql_test(
@@ -691,7 +691,7 @@ = test:do_catchsql_test(
         SELECT f1 FROM test1 WHERE = count(f1,f2)!=3D11
     ]], {
         -- = <select1-3.9>
-        1, "misuse of aggregate function = COUNT()"
+ =        1, "Syntax error: misuse of aggregate = function COUNT()"
         -- = </select1-3.9>
     })
 
@@ -733,7 +733,7 @@ = test:do_catchsql_test(
         SELECT f1 FROM test1 ORDER = BY min(f1)
     ]], {
         -- = <select1-4.4>
-        1, "misuse of aggregate: = MIN()"
+ =        1, "Syntax error: misuse of aggregate: = MIN()"
  =        -- </select1-4.4>
    =  })
 
@@ -743,7 +743,7 @@ test:do_catchsql_test(
        =  INSERT INTO test1(f1) SELECT f1 FROM test1 ORDER BY = min(f1);
     ]], {
         -- = <select1-4.5>
-        1, "misuse of aggregate: = MIN()"
+ =        1, "Syntax error: misuse of aggregate: = MIN()"
  =        -- </select1-4.5>
    =  })
 
@@ -840,7 +840,7 @@ test:do_catchsql_test(
        =  SELECT * FROM t5 ORDER BY 3;
     ]], {
        =  -- <select1-4.10.1>
-        1, "Error at = ORDER BY in place 1: term out of range - should be between 1 and = 2"
+   =      1, "Syntax error: error at ORDER BY in place 1: term = out of range - should be between 1 and 2"
        =  -- </select1-4.10.1>
     })
 
@@ -850,7 +850,7 @@ = test:do_catchsql_test(
         SELECT * FROM t5 ORDER BY = -1;
  =    ]], {
         -- = <select1-4.10.2>
-        1, "Error at ORDER BY in place = 1: term out of range - should be between 1 and 2"
+       =  1, "Syntax error: error at ORDER BY in place 1: term out of range = - should be between 1 and 2"
         -- = </select1-4.10.2>
     })
 
@@ -1080,7 +1080,7 @@ = test:do_catchsql2_test(
     [[SELECT A.f1, f1 FROM test1 as A, test1 = as B 
          ORDER BY f2]], = {
  =        -- <select1-6.8>
-       =  1, "ambiguous column name: F1"
+        1, "Syntax error: = ambiguous column name: F1"
         -- = </select1-6.8>
     })
 
@@ -1089,7 +1089,7 @@ = test:do_catchsql2_test(
     [[SELECT A.f1, B.f1 FROM test1 as A, = test1 as B 
          ORDER BY f2]], = {
  =        -- <select1-6.8b>
-       =  1, "ambiguous column name: F2"
+        1, "Syntax error: = ambiguous column name: F2"
         -- = </select1-6.8b>
     })
 
@@ -1098,7 +1098,7 @@ = test:do_catchsql2_test(
     [[SELECT A.f1, f1 FROM test1 as A, test1 = as A 
          ORDER BY f2]], = {
  =        -- <select1-6.8c>
-       =  1, "ambiguous column name: A.F1"
+        1, "Syntax error: = ambiguous column name: A.F1"
         -- = </select1-6.8c>
     })
 
@@ -1334,7 +1334,7 @@ = test:do_catchsql2_test(
             ORDER BY = f2+101;
 =        ]], {
            =  -- <select1-6.11>
-            1, = "Error at ORDER BY in place 1: term does not match any column in the = result set"
+ =            1, "Syntax error: error at = ORDER BY in place 1: term does not match any column in the result = set"
  =            -- = </select1-6.11>
         })
 
@@ -1406,7 +1406,7 @@ = test:do_catchsql_test(
         SELECT f1 FROM test1 WHERE = f2=3D;
  =    ]], {
         -- = <select1-7.1>
-        1, [[Syntax error near = ';']]
+ =        1, [[Syntax error on line 1 at column 39 near = ';']]
  =        -- </select1-7.1>
    =  })
 
@@ -1416,7 +1416,7 @@ test:do_catchsql_test(
        =      SELECT f1 FROM test1 UNION SELECT = WHERE;
  =        ]], {
            =  -- <select1-7.2>
-            1, = [[Keyword 'WHERE' is reserved. Please use double quotes if 'WHERE' is an = identifier.]]
+            1, [[Syntax error = on line 1 at column 47: keyword 'WHERE' is reserved. Please use double = quotes if 'WHERE' is an identifier.]]
            =  -- </select1-7.2>
        =  })
 
@@ -1428,7 +1428,7 @@ test:do_catchsql_test(
    =  [[
         SELECT f1 FROM test1 as = "hi", test2 as]], {
         -- = <select1-7.3>
-        1, [[Keyword 'as' is reserved. = Please use double quotes if 'as' is an identifier.]]
+       =  1, [[Syntax error on line 1 at column 47: keyword 'as' is = reserved. Please use double quotes if 'as' is an = identifier.]]
         -- = </select1-7.3>
     })
 
@@ -1438,7 +1438,7 @@ = test:do_catchsql_test(
         SELECT f1 FROM test1 ORDER = BY;
  =    ]], {
         -- = <select1-7.4>
-        1, [[Syntax error near = ';']]
+ =        1, [[Syntax error on line 1 at column 38 near = ';']]
  =        -- </select1-7.4>
    =  })
 
@@ -1448,7 +1448,7 @@ test:do_catchsql_test(
        =  SELECT f1 FROM test1 ORDER BY f1 desc, f2 where;
     ]], = {
  =        -- <select1-7.5>
-       =  1, [[Keyword 'where' is reserved. Please use double quotes if = 'where' is an identifier.]]
+        1, [[Syntax error = on line 1 at column 51: keyword 'where' is reserved. Please use double = quotes if 'where' is an identifier.]]
         -- = </select1-7.5>
     })
 
@@ -1458,7 +1458,7 @@ = test:do_catchsql_test(
         SELECT count(f1,f2 FROM = test1;
  =    ]], {
         -- = <select1-7.6>
-        1, [[Keyword 'FROM' is reserved. = Please use double quotes if 'FROM' is an identifier.]]
+       =  1, [[Syntax error on line 1 at column 28: keyword 'FROM' is = reserved. Please use double quotes if 'FROM' is an = identifier.]]
         -- = </select1-7.6>
     })
 
@@ -1468,7 +1468,7 @@ = test:do_catchsql_test(
         SELECT count(f1,f2+) FROM = test1;
  =    ]], {
         -- = <select1-7.7>
-        1, [[Syntax error near = ')']]
+ =        1, [[Syntax error on line 1 at column 28 near = ')']]
  =        -- </select1-7.7>
    =  })
 
@@ -1478,7 +1478,7 @@ test:do_catchsql_test(
        =  SELECT f1 FROM test1 ORDER BY f2, f1+;
     ]], = {
  =        -- <select1-7.8>
-       =  1, [[Syntax error near ';']]
+        1, [[Syntax error = on line 1 at column 46 near ';']]
         -- = </select1-7.8>
     })
 
@@ -1488,7 +1488,7 @@ = test:do_catchsql_test(
         SELECT f1 FROM test1 LIMIT = 5+3 OFFSET 11 ORDER BY f2;
     ]], {
        =  -- <select1-7.9>
-        1, [[Keyword = 'ORDER' is reserved. Please use double quotes if 'ORDER' is an = identifier.]]
+        1, [[Syntax error on line 1 at = column 50: keyword 'ORDER' is reserved. Please use double quotes if = 'ORDER' is an identifier.]]
         -- = </select1-7.9>
     })
 
diff --git a/test/sql-tap/select3.test.lua = b/test/sql-tap/select3.test.lua
index 19f853dc7..9cfe2ef08 = 100755
--- = a/test/sql-tap/select3.test.lua
+++ = b/test/sql-tap/select3.test.lua
@@ -157,7 +157,7 @@ = test:do_catchsql_test("select3-2.10", [[
   SELECT log, count(*) FROM t1 = GROUP BY 0 ORDER BY log;
 ]], {
   -- <select3-2.10>
-  1, "Error at GROUP BY = in place 1: term out of range - should be between 1 and = 2"
+ =  1, "Syntax error: error at GROUP BY in place 1: term out of range = - should be between 1 and 2"
   -- = </select3-2.10>
 })
 
@@ -165,7 +165,7 @@ test:do_catchsql_test("select3-2.11", = [[
  =  SELECT log, count(*) FROM t1 GROUP BY 3 ORDER BY = log;
 ]],= {
  =  -- <select3-2.11>
-  1, "Error at GROUP BY in place 1: term = out of range - should be between 1 and 2"
+  1, "Syntax error: = error at GROUP BY in place 1: term out of range - should be between 1 = and 2"
  =  -- </select3-2.11>
 })
 
@@ -182,7 +182,7 @@ = test:do_catchsql_test("select3-2.13", [[
   SELECT log, count(*) FROM t1 = GROUP BY ORDER BY log;
 ]], {
   -- <select3-2.13>
-  1, [[Keyword 'ORDER' = is reserved. Please use double quotes if 'ORDER' is an = identifier.]]
+  1, [[Syntax error on line 1 at column 41: keyword = 'ORDER' is reserved. Please use double quotes if 'ORDER' is an = identifier.]]
   -- </select3-2.13>
 })
 
@@ -190,7 +190,7 @@ = test:do_catchsql_test("select3-2.14", [[
   SELECT log, count(*) FROM t1 = GROUP BY;
 ]], {
   -- <select3-2.14>
-  1, [[Syntax error = near ';']]
+ =  1, [[Syntax error on line 1 at column 40 near = ';']]
  =  -- </select3-2.14>
 })
 
diff --git a/test/sql-tap/select4.test.lua = b/test/sql-tap/select4.test.lua
index 23cf1bf1b..808e616e6 = 100755
--- = a/test/sql-tap/select4.test.lua
+++ = b/test/sql-tap/select4.test.lua
@@ -160,7 +160,7 @@ = test:do_catchsql_test(
         ORDER BY = log;
  =    ]], {
         -- = <select4-1.3>
-        1, "ORDER BY clause should come = after UNION ALL not before"
+        1, "Syntax error: = ORDER BY clause should come after UNION ALL not before"
        =  -- </select4-1.3>
     })
 
@@ -171,7 +171,7 @@ = test:do_catchsql_test(
                =  SELECT 0 UNION SELECT 0 ORDER BY 1);
     ]], = {
  =        -- <select4-1.4>
-       =  1, "ORDER BY clause should come after UNION not = before"
+ =        1, "Syntax error: ORDER BY clause should come = after UNION not before"
         -- = </select4-1.4>
     })
 
@@ -214,7 +214,7 @@ = test:do_catchsql_test(
         ORDER BY = log;
  =    ]], {
         -- = <select4-2.3>
-        1, "ORDER BY clause should come = after UNION not before"
+        1, "Syntax error: ORDER BY = clause should come after UNION not before"
        =  -- </select4-2.3>
     })
 
@@ -224,7 +224,7 @@ = test:do_catchsql_test(
         SELECT 0 ORDER BY (SELECT = 0) UNION SELECT 0;
     ]], {
         -- = <select4-2.4>
-        1, "ORDER BY clause should come = after UNION not before"
+        1, "Syntax error: ORDER BY = clause should come after UNION not before"
        =  -- </select4-2.4>
     })
 
@@ -299,7 +299,7 @@ = test:do_catchsql_test(
         ORDER BY = log;
  =    ]], {
         -- = <select4-3.3>
-        1, "ORDER BY clause should come = after EXCEPT not before"
+        1, "Syntax error: ORDER BY = clause should come after EXCEPT not before"
        =  -- </select4-3.3>
     })
 
@@ -379,7 +379,7 @@ = test:do_catchsql_test(
         ORDER BY = log;
  =    ]], {
         -- = <select4-4.3>
-        1, "ORDER BY clause should come = after INTERSECT not before"
+        1, "Syntax error: = ORDER BY clause should come after INTERSECT not before"
        =  -- </select4-4.3>
     })
 
@@ -396,7 +396,7 @@ = test:do_catchsql_test(
         );
     ]], = {
  =        -- <select4-4.4>
-       =  1, "ORDER BY clause should come after INTERSECT not = before"
+ =        1, "Syntax error: ORDER BY clause should come = after INTERSECT not before"
         -- = </select4-4.4>
     })
 
@@ -450,7 +450,7 @@ = test:do_catchsql_test(
         ORDER BY = "xyzzy";
     ]], {
         -- = <select4-5.2c>
-        1, "Error at ORDER BY in place = 1: term does not match any column in the result set"
+       =  1, "Syntax error: error at ORDER BY in place 1: term does not = match any column in the result set"
         -- = </select4-5.2c>
     })
 
@@ -463,7 +463,7 @@ = test:do_catchsql_test(
         ORDER BY = "xyzzy";
     ]], {
         -- = <select4-5.2d>
-        1, "Error at ORDER BY in place = 1: term does not match any column in the result set"
+       =  1, "Syntax error: error at ORDER BY in place 1: term does not = match any column in the result set"
         -- = </select4-5.2d>
     })
 
@@ -515,7 +515,7 @@ = test:do_catchsql_test(
         ORDER BY = 2;
  =    ]], {
         -- = <select4-5.2h>
-        1, "Error at ORDER BY in place = 1: term out of range - should be between 1 and 1"
+       =  1, "Syntax error: error at ORDER BY in place 1: term out of range = - should be between 1 and 1"
         -- = </select4-5.2h>
     })
 
@@ -567,7 +567,7 @@ = test:do_catchsql_test(
         ORDER BY = log;
  =    ]], {
         -- = <select4-5.3>
-        1, "SELECTs to the left and = right of UNION ALL do not have the same number of result = columns"
+ =        1, "Syntax error: SELECTs to the left and = right of UNION ALL do not have the same number of result = columns"
         -- = </select4-5.3>
     })
 
@@ -577,7 +577,7 @@ = test:do_catchsql_test(
         SELECT 1 UNION SELECT 2, 3 = UNION SELECT 4, 5 ORDER BY 1;
     ]], {
        =  -- <select4-5.3-3807-1>
-        1, "SELECTs to = the left and right of UNION do not have the same number of result = columns"
+ =        1, "Syntax error: SELECTs to the left and = right of UNION do not have the same number of result = columns"
         -- = </select4-5.3-3807-1>
     })
 
@@ -1075,7 +1075,7 @@ = test:do_catchsql_test(
         SELECT x FROM = t2
  =    ]], {
         -- = <select4-11.1>
-        1, "SELECTs to the left and = right of UNION do not have the same number of result = columns"
+ =        1, "Syntax error: SELECTs to the left and = right of UNION do not have the same number of result = columns"
         -- = </select4-11.1>
     })
 
@@ -1087,7 +1087,7 @@ = test:do_catchsql_test(
         SELECT = x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x FROM = t2
  =    ]], {
         -- = <select4-11.2>
-        1, "SELECTs to the left and = right of UNION do not have the same number of result = columns"
+ =        1, "Syntax error: SELECTs to the left and = right of UNION do not have the same number of result = columns"
         -- = </select4-11.2>
     })
 
@@ -1099,7 +1099,7 @@ = test:do_catchsql_test(
         SELECT x FROM = t2
  =    ]], {
         -- = <select4-11.3>
-        1, "SELECTs to the left and = right of UNION ALL do not have the same number of result = columns"
+ =        1, "Syntax error: SELECTs to the left and = right of UNION ALL do not have the same number of result = columns"
         -- = </select4-11.3>
     })
 
@@ -1111,7 +1111,7 @@ = test:do_catchsql_test(
         SELECT = x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x FROM = t2
  =    ]], {
         -- = <select4-11.4>
-        1, "SELECTs to the left and = right of UNION ALL do not have the same number of result = columns"
+ =        1, "Syntax error: SELECTs to the left and = right of UNION ALL do not have the same number of result = columns"
         -- = </select4-11.4>
     })
 
@@ -1123,7 +1123,7 @@ = test:do_catchsql_test(
         SELECT x FROM = t2
  =    ]], {
         -- = <select4-11.5>
-        1, "SELECTs to the left and = right of EXCEPT do not have the same number of result = columns"
+ =        1, "Syntax error: SELECTs to the left and = right of EXCEPT do not have the same number of result = columns"
         -- = </select4-11.5>
     })
 
@@ -1135,7 +1135,7 @@ = test:do_catchsql_test(
         SELECT = x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x FROM = t2
  =    ]], {
         -- = <select4-11.6>
-        1, "SELECTs to the left and = right of EXCEPT do not have the same number of result = columns"
+ =        1, "Syntax error: SELECTs to the left and = right of EXCEPT do not have the same number of result = columns"
         -- = </select4-11.6>
     })
 
@@ -1147,7 +1147,7 @@ = test:do_catchsql_test(
         SELECT x FROM = t2
  =    ]], {
         -- = <select4-11.7>
-        1, "SELECTs to the left and = right of INTERSECT do not have the same number of result = columns"
+ =        1, "Syntax error: SELECTs to the left and = right of INTERSECT do not have the same number of result = columns"
         -- = </select4-11.7>
     })
 
@@ -1159,7 +1159,7 @@ = test:do_catchsql_test(
         SELECT = x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x FROM = t2
  =    ]], {
         -- = <select4-11.8>
-        1, "SELECTs to the left and = right of INTERSECT do not have the same number of result = columns"
+ =        1, "Syntax error: SELECTs to the left and = right of INTERSECT do not have the same number of result = columns"
         -- = </select4-11.8>
     })
 
@@ -1177,7 +1177,7 @@ = test:do_catchsql_test(
         SELECT = x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x FROM = t2
  =    ]], {
         -- = <select4-11.11>
-        1, "SELECTs to the left and = right of INTERSECT do not have the same number of result = columns"
+ =        1, "Syntax error: SELECTs to the left and = right of INTERSECT do not have the same number of result = columns"
         -- = </select4-11.11>
     })
 
@@ -1195,7 +1195,7 @@ = test:do_catchsql_test(
         SELECT x FROM = t2
  =    ]], {
         -- = <select4-11.12>
-        1, "SELECTs to the left and = right of EXCEPT do not have the same number of result = columns"
+ =        1, "Syntax error: SELECTs to the left and = right of EXCEPT do not have the same number of result = columns"
         -- = </select4-11.12>
     })
 
@@ -1213,7 +1213,7 @@ = test:do_catchsql_test(
         SELECT x FROM = t2
  =    ]], {
         -- = <select4-11.13>
-        1, "SELECTs to the left and = right of UNION ALL do not have the same number of result = columns"
+ =        1, "Syntax error: SELECTs to the left and = right of UNION ALL do not have the same number of result = columns"
         -- = </select4-11.13>
     })
 
@@ -1231,7 +1231,7 @@ = test:do_catchsql_test(
         SELECT x FROM = t2
  =    ]], {
         -- = <select4-11.14>
-        1, "SELECTs to the left and = right of UNION do not have the same number of result = columns"
+ =        1, "Syntax error: SELECTs to the left and = right of UNION do not have the same number of result = columns"
         -- = </select4-11.14>
     })
 
@@ -1249,7 +1249,7 @@ = test:do_catchsql_test(
         SELECT x FROM = t2
  =    ]], {
         -- = <select4-11.15>
-        1, "SELECTs to the left and = right of UNION do not have the same number of result = columns"
+ =        1, "Syntax error: SELECTs to the left and = right of UNION do not have the same number of result = columns"
         -- = </select4-11.15>
     })
 
@@ -1259,7 +1259,7 @@ = test:do_catchsql_test(
         INSERT INTO t2(rowid) = VALUES(2) UNION SELECT 3,4 UNION SELECT 5,6 ORDER BY 1;
     ]], = {
  =        -- <select4-11.16>
-       =  1, "SELECTs to the left and right of UNION do not have the same = number of result columns"
+        1, "Syntax error: SELECTs to = the left and right of UNION do not have the same number of result = columns"
         -- = </select4-11.16>
     })
 
@@ -1268,7 +1268,7 @@ = test:do_catchsql_test(
 --   catchsql {
 --     SELECT 1 UNION SELECT = 2,3 UNION SELECT 4,5 ORDER BY 1;
 --   } db2
--- } {1 {SELECTs to the left = and right of UNION do not have the same number of result = columns}}
+-- = } {1 {Syntax error: SELECTs to the left and right of UNION do not have = the same number of result columns}}
 
 
 -- ifcapable compound
diff --git = a/test/sql-tap/select6.test.lua = b/test/sql-tap/select6.test.lua
index c9960dc29..9871509c3 = 100755
--- = a/test/sql-tap/select6.test.lua
+++ = b/test/sql-tap/select6.test.lua
@@ -905,7 +905,7 @@ = test:do_execsql_test(
         CREATE TABLE k(o  INT = primary key);
     ]])
 
-err =3D { 1, "SELECTs to the left and right = of UNION ALL do not have the same number of result columns" = }
+err =3D { = 1, "Syntax error: SELECTs to the left and right of UNION ALL do not have = the same number of result columns" }
 test:do_execsql_test(
    =  10.2,
     [[
diff --git a/test/sql-tap/select7.test.lua = b/test/sql-tap/select7.test.lua
index fec5d7a41..66ffca055 = 100755
--- = a/test/sql-tap/select7.test.lua
+++ = b/test/sql-tap/select7.test.lua
@@ -278,7 +278,7 @@ = test:do_catchsql_test(
         ) WHERE = y=3D1
  =    ]], {
         -- = <8.1>
- =        1, "SELECTs to the left and right of UNION do = not have the same number of result columns"
+       =  1, "Syntax error: SELECTs to the left and right of UNION do not = have the same number of result columns"
         -- = </8.1>
     })
 
@@ -289,7 +289,7 @@ = test:do_catchsql_test(
         EXPLAIN QUERY PLAN SELECT * = FROM v0 WHERE x=3D'0' OR y;
     ]], {
        =  -- <8.2>
-        1, "SELECTs to the left and = right of UNION do not have the same number of result = columns"
+ =        1, "Syntax error: SELECTs to the left and = right of UNION do not have the same number of result = columns"
         -- = </8.2>
     })
 
diff --git a/test/sql-tap/selectE.test.lua = b/test/sql-tap/selectE.test.lua
index 32c3d6a06..0ab48acf7 = 100755
--- = a/test/sql-tap/selectE.test.lua
+++ = b/test/sql-tap/selectE.test.lua
@@ -141,7 +141,7 @@ = test:do_catchsql_test(
         SELECT 1 EXCEPT SELECT 2 = ORDER BY 1 COLLATE "unicode_ci" EXCEPT SELECT 3;
     ]], = {
  =        -- <selectE-3.1>
-       =  1, "ORDER BY clause should come after EXCEPT not = before"
+ =        1, "Syntax error: ORDER BY clause should come = after EXCEPT not before"
         -- = </selectE-3.1>
     })
 
diff --git a/test/sql-tap/sql-errors.test.lua = b/test/sql-tap/sql-errors.test.lua
index b16337682..4aceaa54e = 100755
--- = a/test/sql-tap/sql-errors.test.lua
+++ = b/test/sql-tap/sql-errors.test.lua
@@ -17,7 +17,7 @@ = test:do_catchsql_test(
 = ANALYZE v0;
  ]], {
  = -- <sql-errors-1.1>
- 1,"Syntax error near = 'ANALYZE'"
+ = 1,"Syntax error on line 1 at column 3 near = 'ANALYZE'"
 = -- </sql-errors-1.1>
  = })
 
@@ -422,7 +422,7 @@ test:do_catchsql_test(
  = CREATE TRIGGER r0 AFTER INSERT ON t0 FOR EACH ROW BEGIN INSERT = INTO t0.i VALUES (2); END;
  ]], {
  = -- <sql-errors-1.37>
- 1,"qualified table names = are not allowed on INSERT, UPDATE, and DELETE statements within = triggers"
+ = 1,"Syntax error on line 1 at column 76: qualified table names are = not allowed on INSERT, UPDATE, and DELETE statements within = triggers"
 = -- </sql-errors-1.37>
  = })
 
@@ -432,7 +432,7 @@ test:do_catchsql_test(
  = UPDATE t0 SET (i, a) =3D (100,1,1);
  ]], = {
  = -- <sql-errors-1.38>
- 1,"2 columns assigned 3 = values"
+ = 1,"Syntax error: 2 columns assigned 3 values"
  = -- </sql-errors-1.38>
  })
 
@@ -442,7 +442,7 @@ = test:do_catchsql_test(
 = SELECT * FROM t0();
  ]], = {
  = -- <sql-errors-1.39>
- 1,"'T0' is not a = function"
+ = 1,"Syntax error: 'T0' is not a function"
  = -- </sql-errors-1.39>
  })
 
@@ -452,7 +452,7 @@ = test:do_catchsql_test(
 = SELECT $0;
  ]], {
  = -- <sql-errors-1.40>
- 1,"Index of binding slots = must start from 1"
+ = 1,"Syntax error: index of binding slots must start from = 1"
  = -- </sql-errors-1.40>
  })
 
@@ -472,7 +472,7 @@ = test:do_catchsql_test(
 = SELECT (1, 2);
  ]], {
  = -- <sql-errors-1.42>
- 1,"row value = misused"
+ = 1,"Syntax error: row value misused"
  = -- </sql-errors-1.42>
  })
 
@@ -482,7 +482,7 @@ = test:do_catchsql_test(
 = SELECT (i,a) AS m FROM t0 WHERE m < = 1;
  ]], = {
  = -- <sql-errors-1.43>
- 1,"row value = misused"
+ = 1,"Syntax error: row value misused"
  = -- </sql-errors-1.43>
  })
 
@@ -522,7 +522,7 @@ = test:do_catchsql_test(
 = DROP TABLE IF EXISTS END;
  ]], = {
  = -- <sql-errors-1.47>
- 1, "Keyword 'END' is = reserved. Please use double quotes if 'END' is an = identifier."
+ = 1, "Syntax error on line 1 at column 27: keyword 'END' is = reserved. Please use double quotes if 'END' is an = identifier."
 = -- </sql-errors-1.47>
  = })
 
diff --git a/test/sql-tap/start-transaction.test.lua = b/test/sql-tap/start-transaction.test.lua
index c5703d438..b2cd9a1b9 = 100755
--- = a/test/sql-tap/start-transaction.test.lua
+++ = b/test/sql-tap/start-transaction.test.lua
@@ -21,7 +21,7 @@ = test:do_catchsql_test(
 = COMMIT;
  ]], {
  = -- <start-transaction-1.0>
- 1, "Syntax error near = 'BEGIN'"
+ = 1, "Syntax error on line 2 at column 3 near = 'BEGIN'"
 = -- <start-transaction-1.0>
  = })
 
@@ -46,7 +46,7 @@ test:do_catchsql_test(
  = COMMIT;
 = ]], {
 = -- <start-transaction-1.1>
- 1, "Syntax error near = 'BEGIN'"
+ = 1, "Syntax error on line 2 at column 3 near = 'BEGIN'"
 = -- <start-transaction-1.1>
  = })
 
@@ -94,7 +94,7 @@ test:do_catchsql_test(
  = COMMIT TRANSACTION;
  ]], {
  = -- <start-transaction-1.6>
- 1, "Keyword 'TRANSACTION' = is reserved. Please use double quotes if 'TRANSACTION' is an = identifier."
+ = 1, "Syntax error on line 2 at column 10: keyword 'TRANSACTION' is = reserved. Please use double quotes if 'TRANSACTION' is an = identifier."
 = -- <start-transaction-1.6>
  = })
 
@@ -119,7 +119,7 @@ test:do_catchsql_test(
  = END;
 = ]], {
 = -- <start-transaction-1.8>
- 1, "Keyword 'END' is = reserved. Please use double quotes if 'END' is an = identifier."
+ = 1, "Syntax error on line 2 at column 3: keyword 'END' is = reserved. Please use double quotes if 'END' is an = identifier."
 = -- <start-transaction-1.8>
  = })
 
@@ -144,7 +144,7 @@ test:do_catchsql_test(
  = END TRANSACTION;
 = ]], {
 = -- = <start-transaction-1.10>
- 1, "Keyword 'END' is = reserved. Please use double quotes if 'END' is an = identifier."
+ = 1, "Syntax error on line 2 at column 3: keyword 'END' is = reserved. Please use double quotes if 'END' is an = identifier."
 = -- = <start-transaction-1.10>
  })
 
@@ -193,7 +193,7 @@ = test:do_catchsql_test(
 = COMMIT;
  ]], {
  = -- <start-transaction-1.14>
- 1, "Keyword 'TRANSACTION' = is reserved. Please use double quotes if 'TRANSACTION' is an = identifier."
+ = 1, "Syntax error on line 2 at column 13: keyword 'TRANSACTION' is = reserved. Please use double quotes if 'TRANSACTION' is an = identifier."
 = -- = <start-transaction-1.14>
  })
 
@@ -246,7 +246,7 @@ = test:do_catchsql_test(
 = COMMIT;
  ]], {
  = -- <start-transaction-1.18>
- 1, "Keyword 'TRANSACTION' = is reserved. Please use double quotes if 'TRANSACTION' is an = identifier."
+ = 1, "Syntax error on line 2 at column 13: keyword 'TRANSACTION' is = reserved. Please use double quotes if 'TRANSACTION' is an = identifier."
 = -- = <start-transaction-1.18>
  })
 
diff --git = a/test/sql-tap/subquery.test.lua = b/test/sql-tap/subquery.test.lua
index 6bedf5879..dd90a9f73 = 100755
--- = a/test/sql-tap/subquery.test.lua
+++ = b/test/sql-tap/subquery.test.lua
@@ -614,7 +614,7 @@ = test:do_catchsql_test(
         SELECT max((SELECT count(x) = FROM t35b)) FROM t35a;
     ]], {
         -- = <subquery-3.5.4>
-        1, "misuse of aggregate: = COUNT()"
+ =        1, "Syntax error: misuse of aggregate: = COUNT()"
         -- = </subquery-3.5.4>
     })
 
@@ -624,7 +624,7 @@ = test:do_catchsql_test(
         SELECT max((SELECT count(x) = FROM t35b)) FROM t35a;
     ]], {
         -- = <subquery-3.5.5>
-        1, "misuse of aggregate: = COUNT()"
+ =        1, "Syntax error: misuse of aggregate: = COUNT()"
         -- = </subquery-3.5.5>
     })
 
@@ -634,7 +634,7 @@ = test:do_catchsql_test(
         SELECT max((SELECT a FROM = (SELECT count(x) AS a FROM t35b))) FROM t35a;
     ]], = {
  =        -- <subquery-3.5.6>
-       =  1, "misuse of aggregate: COUNT()"
+        1, "Syntax error: = misuse of aggregate: COUNT()"
         -- = </subquery-3.5.6>
     })
 
@@ -951,7 +951,7 @@ = test:do_catchsql_test(
 =       SELECT * FROM = table1);
 = ]], {
 = -- <subquery-9.1>
- 1, 'ORDER BY clause = should come after UNION ALL not before'
+ 1, 'Syntax error: ORDER = BY clause should come after UNION ALL not before'
  = -- <subquery-9.1>
  })
 
@@ -975,7 +975,7 @@ = test:do_catchsql_test(
 =       SELECT * FROM = table1);
 = ]], {
              -- = <subquery-9.3>
-             1, 'ORDER BY = clause should come after UNION ALL not before'
+         =     1, 'Syntax error: ORDER BY clause should come after UNION = ALL not before'
              -- = <subquery-9.3>
 = })
 
diff --git a/test/sql-tap/table.test.lua = b/test/sql-tap/table.test.lua
index e17b4a2c1..4616a82a6 = 100755
--- = a/test/sql-tap/table.test.lua
+++ = b/test/sql-tap/table.test.lua
@@ -620,7 +620,7 @@ = test:do_catchsql_test(
 = CREATE TEMP TABLE t1(a INTEGER PRIMARY KEY, b = VARCHAR(10));
 = ]], {
 = -- <temp>
- 1, "Syntax error near = 'TEMP'"
+ 1, = "Syntax error on line 1 at column 10 near 'TEMP'"
  -- = <temp>
 = })
 
@@ -630,7 +630,7 @@ test:do_catchsql_test(
  = CREATE TEMPORARY TABLE t1(a INTEGER PRIMARY KEY, b = VARCHAR(10));
 = ]], {
 = -- <temporary>
- 1, "Syntax error near = 'TEMPORARY'"
+ = 1, "Syntax error on line 1 at column 10 near = 'TEMPORARY'"
 = -- <temporary>
  })
 
@@ -1257,7 +1257,7 @@ = test:do_catchsql_test(
         );
     ]], = {
  =        -- <table-22.1>
-       =  1,"Keyword 'CONSTRAINT' is reserved. Please use double quotes if = 'CONSTRAINT' is an identifier."
+        1,"Syntax error = on line 3 at column 28: keyword 'CONSTRAINT' is reserved. Please use = double quotes if 'CONSTRAINT' is an identifier."
        =  -- </table-22.1>
     })
 
@@ -1322,7 +1322,7 @@ = test:do_catchsql_test(
         );
     ]], = {
  =        -- <table-22.6>
-       =  1,"Keyword 'CONSTRAINT' is reserved. Please use double quotes if = 'CONSTRAINT' is an identifier."
+        1,"Syntax error = on line 3 at column 37: keyword 'CONSTRAINT' is reserved. Please use = double quotes if 'CONSTRAINT' is an identifier."
        =  -- </table-22.6>
     })
 
@@ -1336,7 +1336,7 @@ = test:do_catchsql_test(
         );
     ]], = {
  =        -- <table-22.7>
-       =  1,"Keyword 'CONSTRAINT' is reserved. Please use double quotes if = 'CONSTRAINT' is an identifier."
+        1,"Syntax error = on line 3 at column 37: keyword 'CONSTRAINT' is reserved. Please use = double quotes if 'CONSTRAINT' is an identifier."
        =  -- </table-22.7>
     })
 
diff --git = a/test/sql-tap/tkt1514.test.lua = b/test/sql-tap/tkt1514.test.lua
index 685c916a8..95f1d2dec = 100755
--- = a/test/sql-tap/tkt1514.test.lua
+++ = b/test/sql-tap/tkt1514.test.lua
@@ -27,7 +27,7 @@ = test:do_catchsql_test(
         SELECT a FROM t1 WHERE = max(b)<10 GROUP BY a;
     ]], {
         -- = <tkt1514-1.1>
-        1, "misuse of aggregate: = MAX()"
+ =        1, "Syntax error: misuse of aggregate: = MAX()"
  =        -- </tkt1514-1.1>
    =  })
 
diff --git a/test/sql-tap/tkt2822.test.lua = b/test/sql-tap/tkt2822.test.lua
index 86674aeac..800dee74b = 100755
--- = a/test/sql-tap/tkt2822.test.lua
+++ = b/test/sql-tap/tkt2822.test.lua
@@ -200,7 +200,7 @@ = test:do_catchsql_test(
         SELECT a, b, c FROM t1 = UNION ALL SELECT a, b, c FROM t2 ORDER BY x
     ]], = {
  =        -- <tkt2822-4.1>
-       =  1, "Error at ORDER BY in place 1: term does not match any column = in the result set"
+        1, "Syntax error: error at ORDER = BY in place 1: term does not match any column in the result = set"
  =        -- </tkt2822-4.1>
    =  })
 
@@ -298,7 +298,7 @@ test:do_test(
        =  ]]
     end, {
         -- = <tkt2822-7.1>
-        1, "Error at ORDER BY in place = 1: term out of range - should be between 1 and 25"
+       =  1, "Syntax error: error at ORDER BY in place 1: term out of range = - should be between 1 and 25"
         -- = </tkt2822-7.1>
     })
 
@@ -308,7 +308,7 @@ = test:do_catchsql_test(
         SELECT * FROM t7 ORDER BY = 1, 0;
  =    ]], {
         -- = <tkt2822-7.2.1>
-        1, "Error at ORDER BY in place = 2: term out of range - should be between 1 and 25"
+       =  1, "Syntax error: error at ORDER BY in place 2: term out of range = - should be between 1 and 25"
         -- = </tkt2822-7.2.1>
     })
 
@@ -318,7 +318,7 @@ = test:do_catchsql_test(
         SELECT * FROM t7 ORDER BY = 1, 26;
  =    ]], {
         -- = <tkt2822-7.2.2>
-        1, "Error at ORDER BY in place = 2: term out of range - should be between 1 and 25"
+       =  1, "Syntax error: error at ORDER BY in place 2: term out of range = - should be between 1 and 25"
         -- = </tkt2822-7.2.2>
     })
 
@@ -328,7 +328,7 @@ = test:do_catchsql_test(
         SELECT * FROM t7 ORDER BY = 1, 65536;
     ]], {
         -- = <tkt2822-7.2.3>
-        1, "Error at ORDER BY in place = 2: term out of range - should be between 1 and 25"
+       =  1, "Syntax error: error at ORDER BY in place 2: term out of range = - should be between 1 and 25"
         -- = </tkt2822-7.2.3>
     })
 
@@ -338,7 +338,7 @@ = test:do_catchsql_test(
         SELECT * FROM t7 ORDER BY = 1, 2, 0;
     ]], {
         -- = <tkt2822-7.3>
-        1, "Error at ORDER BY in place = 3: term out of range - should be between 1 and 25"
+       =  1, "Syntax error: error at ORDER BY in place 3: term out of range = - should be between 1 and 25"
         -- = </tkt2822-7.3>
     })
 
@@ -348,7 +348,7 @@ = test:do_catchsql_test(
         SELECT * FROM t7 ORDER BY = 1, 2, 3, 0;
     ]], {
         -- = <tkt2822-7.4>
-        1, "Error at ORDER BY in place = 4: term out of range - should be between 1 and 25"
+       =  1, "Syntax error: error at ORDER BY in place 4: term out of range = - should be between 1 and 25"
         -- = </tkt2822-7.4>
     })
 
@@ -358,7 +358,7 @@ = test:do_catchsql_test(
         SELECT * FROM t7 ORDER BY = 1, 2, 3, 4, 5, 6, 7, 8, 0;
     ]], {
        =  -- <tkt2822-7.9>
-        1, "Error at = ORDER BY in place 9: term out of range - should be between 1 and = 25"
+   =      1, "Syntax error: error at ORDER BY in place 9: term = out of range - should be between 1 and 25"
        =  -- </tkt2822-7.9>
     })
 
@@ -368,7 +368,7 @@ = test:do_catchsql_test(
         SELECT * FROM t7 ORDER BY = 1, 2, 3, 4, 5, 6, 7, 8, 9, 0;
     ]], {
        =  -- <tkt2822-7.10>
-        1, "Error at = ORDER BY in place 10: term out of range - should be between 1 and = 25"
+   =      1, "Syntax error: error at ORDER BY in place 10: = term out of range - should be between 1 and 25"
        =  -- </tkt2822-7.10>
     })
 
@@ -378,7 +378,7 @@ = test:do_catchsql_test(
         SELECT * FROM t7 ORDER BY = 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0;
     ]], {
        =  -- <tkt2822-7.11>
-        1, "Error at = ORDER BY in place 11: term out of range - should be between 1 and = 25"
+   =      1, "Syntax error: error at ORDER BY in place 11: = term out of range - should be between 1 and 25"
        =  -- </tkt2822-7.11>
     })
 
@@ -388,7 +388,7 @@ = test:do_catchsql_test(
         SELECT * FROM t7 ORDER BY = 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 0;
     ]], {
        =  -- <tkt2822-7.12>
-        1, "Error at = ORDER BY in place 12: term out of range - should be between 1 and = 25"
+   =      1, "Syntax error: error at ORDER BY in place 12: = term out of range - should be between 1 and 25"
        =  -- </tkt2822-7.12>
     })
 
@@ -398,7 +398,7 @@ = test:do_catchsql_test(
         SELECT * FROM t7 ORDER BY = 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 13, 0;
     ]], = {
  =        -- <tkt2822-7.13>
-       =  1, "Error at ORDER BY in place 13: term out of range - should be = between 1 and 25"
+        1, "Syntax error: error at ORDER = BY in place 13: term out of range - should be between 1 and = 25"
  =        -- </tkt2822-7.13>
    =  })
 
@@ -409,7 +409,7 @@ test:do_catchsql_test(
        =                     =       11,12,13,14,15,16,17,18,19, 0
     ]], = {
  =        -- <tkt2822-7.20>
-       =  1, "Error at ORDER BY in place 20: term out of range - should be = between 1 and 25"
+        1, "Syntax error: error at ORDER = BY in place 20: term out of range - should be between 1 and = 25"
  =        -- </tkt2822-7.20>
    =  })
 
@@ -420,7 +420,7 @@ test:do_catchsql_test(
        =                     =       11,12,13,14,15,16,17,18,19, 20, 0
     ]], = {
  =        -- <tkt2822-7.21>
-       =  1, "Error at ORDER BY in place 21: term out of range - should be = between 1 and 25"
+        1, "Syntax error: error at ORDER = BY in place 21: term out of range - should be between 1 and = 25"
  =        -- </tkt2822-7.21>
    =  })
 
@@ -431,7 +431,7 @@ test:do_catchsql_test(
        =                     =       11,12,13,14,15,16,17,18,19, 20, 21, = 0
  =    ]], {
         -- = <tkt2822-7.22>
-        1, "Error at ORDER BY in place = 22: term out of range - should be between 1 and 25"
+       =  1, "Syntax error: error at ORDER BY in place 22: term out of range = - should be between 1 and 25"
         -- = </tkt2822-7.22>
     })
 
diff --git a/test/sql-tap/tkt3508.test.lua = b/test/sql-tap/tkt3508.test.lua
index 643cf6f54..520a13057 = 100755
--- = a/test/sql-tap/tkt3508.test.lua
+++ = b/test/sql-tap/tkt3508.test.lua
@@ -39,7 +39,7 @@ = test:do_catchsql_test(
           from = modificationsTmp where c > 1 group by = SUBSTRATE_HPRD_ID;
     ]], {
         -- = <tkt3508-1.1>
-        1, "misuse of aggregate: = COUNT()"
+ =        1, "Syntax error: misuse of aggregate: = COUNT()"
         -- = </tkt3508-1.1>
     })
 
diff --git a/test/sql-tap/tokenize.test.lua = b/test/sql-tap/tokenize.test.lua
index b1a097e23..eb11eb8a4 = 100755
--- = a/test/sql-tap/tokenize.test.lua
+++ = b/test/sql-tap/tokenize.test.lua
@@ -1,6 +1,6 @@
 #!/usr/bin/env = tarantool
 test =3D require("sqltester")
-test:plan(14)
+test:plan(16)
 
 --!./tcltestrunner.lua
 -- 2008 July 7
@@ -26,7 +26,7 @@ = test:do_catchsql_test(
         SELECT = 1.0e+
  =    ]], {
         -- = <tokenize-1.1>
-        1, [[Syntax error: unrecognized = token: '1.0e']]
+        1, [[Syntax error on line 1 at = column 16 unrecognized token: '1.0e']]
         -- = </tokenize-1.1>
     })
 
@@ -36,7 +36,7 @@ = test:do_catchsql_test(
         SELECT = 1.0E+
  =    ]], {
         -- = <tokenize-1.2>
-        1, [[Syntax error: unrecognized = token: '1.0E']]
+        1, [[Syntax error on line 1 at = column 16 unrecognized token: '1.0E']]
         -- = </tokenize-1.2>
     })
 
@@ -46,7 +46,7 @@ = test:do_catchsql_test(
         SELECT = 1.0e-
  =    ]], {
         -- = <tokenize-1.3>
-        1, [[Syntax error: unrecognized = token: '1.0e']]
+        1, [[Syntax error on line 1 at = column 16 unrecognized token: '1.0e']]
         -- = </tokenize-1.3>
     })
 
@@ -56,7 +56,7 @@ = test:do_catchsql_test(
         SELECT = 1.0E-
  =    ]], {
         -- = <tokenize-1.4>
-        1, [[Syntax error: unrecognized = token: '1.0E']]
+        1, [[Syntax error on line 1 at = column 16 unrecognized token: '1.0E']]
         -- = </tokenize-1.4>
     })
 
@@ -66,7 +66,7 @@ = test:do_catchsql_test(
         SELECT = 1.0e+/
  =    ]], {
         -- = <tokenize-1.5>
-        1, [[Syntax error: unrecognized = token: '1.0e']]
+        1, [[Syntax error on line 1 at = column 16 unrecognized token: '1.0e']]
         -- = </tokenize-1.5>
     })
 
@@ -76,7 +76,7 @@ = test:do_catchsql_test(
         SELECT = 1.0E+:
  =    ]], {
         -- = <tokenize-1.6>
-        1, [[Syntax error: unrecognized = token: '1.0E']]
+        1, [[Syntax error on line 1 at = column 16 unrecognized token: '1.0E']]
         -- = </tokenize-1.6>
     })
 
@@ -86,7 +86,7 @@ = test:do_catchsql_test(
         SELECT = 1.0e-:
  =    ]], {
         -- = <tokenize-1.7>
-        1, [[Syntax error: unrecognized = token: '1.0e']]
+        1, [[Syntax error on line 1 at = column 16 unrecognized token: '1.0e']]
         -- = </tokenize-1.7>
     })
 
@@ -96,7 +96,7 @@ = test:do_catchsql_test(
         SELECT = 1.0E-/
  =    ]], {
         -- = <tokenize-1.8>
-        1, [[Syntax error: unrecognized = token: '1.0E']]
+        1, [[Syntax error on line 1 at = column 16 unrecognized token: '1.0E']]
         -- = </tokenize-1.8>
     })
 
@@ -106,7 +106,7 @@ = test:do_catchsql_test(
         SELECT = 1.0F+5
  =    ]], {
         -- = <tokenize-1.9>
-        1, [[Syntax error: unrecognized = token: '1.0F']]
+        1, [[Syntax error on line 1 at = column 16 unrecognized token: '1.0F']]
         -- = </tokenize-1.9>
     })
 
@@ -116,7 +116,7 @@ = test:do_catchsql_test(
         SELECT = 1.0d-10
 =    ]], {
         -- = <tokenize-1.10>
-        1, [[Syntax error: unrecognized = token: '1.0d']]
+        1, [[Syntax error on line 1 at = column 16 unrecognized token: '1.0d']]
         -- = </tokenize-1.10>
     })
 
@@ -126,7 +126,7 @@ = test:do_catchsql_test(
         SELECT = 1.0e,5
  =    ]], {
         -- = <tokenize-1.11>
-        1, [[Syntax error: unrecognized = token: '1.0e']]
+        1, [[Syntax error on line 1 at = column 16 unrecognized token: '1.0e']]
         -- = </tokenize-1.11>
     })
 
@@ -136,7 +136,7 @@ = test:do_catchsql_test(
         SELECT = 1.0E.10
 =    ]], {
         -- = <tokenize-1.12>
-        1, [[Syntax error: unrecognized = token: '1.0E']]
+        1, [[Syntax error on line 1 at = column 16 unrecognized token: '1.0E']]
         -- = </tokenize-1.12>
     })
 
@@ -145,7 +145,7 @@ = test:do_catchsql_test(
     [[
         SELECT 1, 2 = /*]], {
 =        -- <tokenize-2.1>
-       =  1, [[Syntax error near '*']]
+        1, [[Syntax error = on line 1 at column 22 near '*']]
         -- = </tokenize-2.1>
     })
 
@@ -159,6 +159,29 @@ = test:do_catchsql_test(
         -- = </tokenize-2.2>
     })
 
+--
+--gh-2611 Check the correct parsing of = single-line comments.
+--
+test:do_execsql_test(
+   =  "tokenize-3.1",
+    [[
+        SELECT 1 + -- 1 + = 1.
+   =      1
+    ]], {
+        -- = <tokenize-2.2>
+        2
+       =  -- </tokenize-2.2>
+    })
 
+test:do_catchsql_test(
+   =  "tokenize-3.2",
+    [[
+        SELECT 1 + -- = Syntax error.
+        *
+    ]], = {
+   =      -- <tokenize-2.2>
+       =  1,"Syntax error on line 2 at column 9 near '*'"
+       =  -- </tokenize-2.2>
+    })
 
 test:finish_test()
diff --git a/test/sql-tap/trigger1.test.lua = b/test/sql-tap/trigger1.test.lua
index bc02d6236..73e6bd5a0 = 100755
--- = a/test/sql-tap/trigger1.test.lua
+++ = b/test/sql-tap/trigger1.test.lua
@@ -74,7 +74,7 @@ = test:do_catchsql_test(
         END;
     ]], = {
  =        -- <trigger1-1.1.3>
-       =  1, [[Syntax error near 'STATEMENT']]
+       =  1, [[Syntax error on line 1 at column 51 near = 'STATEMENT']]
         -- = </trigger1-1.1.3>
     })
 
@@ -307,7 +307,7 @@ = test:do_catchsql_test(
         END;
     ]], = {
  =        -- <trigger1-2.1>
-       =  1, [[Syntax error near ';']]
+        1, [[Syntax error = on line 3 at column 24 near ';']]
         -- = </trigger1-2.1>
     })
 
@@ -321,7 +321,7 @@ = test:do_catchsql_test(
         END;
     ]], = {
  =        -- <trigger1-2.2>
-       =  1, [[Syntax error near ';']]
+        1, [[Syntax error = on line 4 at column 24 near ';']]
         -- = </trigger1-2.2>
     })
 
@@ -744,7 +744,7 @@ = test:do_catchsql_test(
         SELECT = raise(abort,'message');
     ]], {
         -- = <trigger1-11.1>
-        1, "RAISE() may only be used = within a trigger-program"
+        1, "Syntax error: RAISE() may = only be used within a trigger-program"
         -- = </trigger1-11.1>
     })
 
@@ -823,7 +823,7 @@ = test:do_catchsql_test(
         END;
     ]], = {
  =        -- <trigger1-16.4>
-       =  1, "Syntax error in trigger body: the NOT INDEXED clause is not = allowed on UPDATE or DELETE statements within triggers"
+       =  1, "Syntax error on line 2 at column 34 in trigger body: the NOT = INDEXED clause is not allowed on UPDATE or DELETE statements within = triggers"
         -- = </trigger1-16.4>
     })
 
@@ -835,7 +835,7 @@ = test:do_catchsql_test(
         END;
     ]], = {
  =        -- <trigger1-16.5>
-       =  1, "Syntax error in trigger body: the INDEXED BY clause is not = allowed on UPDATE or DELETE statements within triggers"
+       =  1, "Syntax error on line 2 at column 38 in trigger body: the = INDEXED BY clause is not allowed on UPDATE or DELETE statements within = triggers"
         -- = </trigger1-16.5>
     })
 
@@ -847,7 +847,7 @@ = test:do_catchsql_test(
         END;
     ]], = {
  =        -- <trigger1-16.6>
-       =  1, "Syntax error in trigger body: the NOT INDEXED clause is not = allowed on UPDATE or DELETE statements within triggers"
+       =  1, "Syntax error on line 2 at column 39 in trigger body: the NOT = INDEXED clause is not allowed on UPDATE or DELETE statements within = triggers"
         -- = </trigger1-16.6>
     })
 
@@ -859,7 +859,7 @@ = test:do_catchsql_test(
         END;
     ]], = {
  =        -- <trigger1-16.7>
-       =  1, "Syntax error in trigger body: the INDEXED BY clause is not = allowed on UPDATE or DELETE statements within triggers"
+       =  1, "Syntax error on line 2 at column 43 in trigger body: the = INDEXED BY clause is not allowed on UPDATE or DELETE statements within = triggers"
         -- = </trigger1-16.7>
     })
 
diff --git a/test/sql-tap/update.test.lua = b/test/sql-tap/update.test.lua
index 07e4e43d9..152dee9bb = 100755
--- = a/test/sql-tap/update.test.lua
+++ = b/test/sql-tap/update.test.lua
@@ -1123,7 +1123,7 @@ = test:do_catchsql_test(
     [[
         update test = set a =3D 2, a =3D 3;
     ]],
-    {1, "set id list: duplicate = column name A"})
+    {1, "Syntax error: set id list: duplicate = column name A"})
 
 test:do_execsql_test(
   "insert-15.2",
diff --git = a/test/sql-tap/view.test.lua = b/test/sql-tap/view.test.lua
index 6234f863e..d094eec0a = 100755
--- = a/test/sql-tap/view.test.lua
+++ = b/test/sql-tap/view.test.lua
@@ -293,7 +293,7 @@ = test:do_catchsql_test(
         CREATE VIEW v1err(x,y = DESC,z) AS SELECT a, b+c, c-b FROM t1;
     ]], {
        =  -- <view-3.3.4>
-        1, [[Keyword = 'DESC' is reserved. Please use double quotes if 'DESC' is an = identifier.]]
+        1, [[Syntax error on line 1 at = column 31: keyword 'DESC' is reserved. Please use double quotes if = 'DESC' is an identifier.]]
         -- = </view-3.3.4>
     })
 
diff --git a/test/sql-tap/with1.test.lua = b/test/sql-tap/with1.test.lua
index f82b73e63..f0d3c31a1 = 100755
--- = a/test/sql-tap/with1.test.lua
+++ = b/test/sql-tap/with1.test.lua
@@ -123,7 +123,7 @@ test:do_catchsql_test(3.1, = [[
  =  SELECT * FROM tmp1;
 ]], {
   -- <3.1>
-  1, "circular reference: = TMP1"
+ =  1, "Syntax error: circular reference: TMP1"
   -- = </3.1>
 })
 
@@ -134,7 +134,7 @@ test:do_catchsql_test(3.2, = [[
  =  SELECT * FROM tmp;
 ]], {
   -- <3.2>
-  1, "Ambiguous table name in WITH = query: TMP"
+ =  1, "Syntax error: ambiguous table name in WITH query: = TMP"
  =  -- </3.2>
 })
 
@@ -178,7 +178,7 @@ test:do_catchsql_test(3.6, = [[
  =  SELECT * FROM tmp;
 ]], {
   -- <3.6>
-  1, [[Keyword 'SELECT' is reserved. = Please use double quotes if 'SELECT' is an = identifier.]]
+  1, [[Syntax error on line 2 at column 3: keyword = 'SELECT' is reserved. Please use double quotes if 'SELECT' is an = identifier.]]
   -- </3.6>
 })
 
@@ -334,7 +334,7 @@ = test:do_catchsql_test("5.6.1", [[
   SELECT * FROM i;
 ]], {
   -- = <5.6.1>
-  1, "table I has 1 values for 2 = columns"
+ =  1, "Syntax error: table I has 1 values for 2 = columns"
   -- </5.6.1>
 })
 
@@ -343,7 +343,7 @@ = test:do_catchsql_test("5.6.2", [[
   SELECT * FROM i;
 ]], {
   -- = <5.6.2>
-  1, "table I has 2 values for 1 = columns"
+ =  1, "Syntax error: table I has 2 values for 1 = columns"
   -- </5.6.2>
 })
 
@@ -353,7 +353,7 @@ = test:do_catchsql_test("5.6.3", [[
   SELECT * FROM i;
 ]], {
   -- = <5.6.3>
-  1, "table I has 2 values for 1 = columns"
+ =  1, "Syntax error: table I has 2 values for 1 = columns"
   -- </5.6.3>
 })
 
@@ -362,7 +362,7 @@ = test:do_catchsql_test("5.6.4", [[
   SELECT * FROM i;
 ]], {
   -- = <5.6.4>
-  1, "table I has 2 values for 1 = columns"
+ =  1, "Syntax error: table I has 2 values for 1 = columns"
   -- </5.6.4>
 })
 
@@ -371,7 +371,7 @@ = test:do_catchsql_test("5.6.5", [[
   SELECT * FROM i;
 ]], {
   -- = <5.6.5>
-  1, "SELECTs to the left and right of UNION ALL do not = have the same number of result columns"
+  1, "Syntax error: SELECTs to the left = and right of UNION ALL do not have the same number of result = columns"
   -- </5.6.5>
 })
 
@@ -380,7 +380,7 @@ = test:do_catchsql_test("5.6.6", [[
   SELECT * FROM i;
 ]], {
   -- = <5.6.6>
-  1, "SELECTs to the left and right of UNION ALL do not = have the same number of result columns"
+  1, "Syntax error: SELECTs to the left = and right of UNION ALL do not have the same number of result = columns"
   -- </5.6.6>
 })
 
@@ -389,7 +389,7 @@ = test:do_catchsql_test("5.6.7", [[
   SELECT * FROM i;
 ]], {
   -- = <5.6.7>
-  1, "table I has 2 values for 1 = columns"
+ =  1, "Syntax error: table I has 2 values for 1 = columns"
   -- </5.6.7>
 })
 
@@ -501,7 +501,7 @@ = test:do_catchsql_test(7.4, [[
   SELECT id FROM = t;
 ]], = {
  =  -- <7.4>
-  1, "recursive reference in a subquery: = T"
+ =  1, "Syntax error: recursive reference in a subquery: = T"
  =  -- </7.4>
 })
 
@@ -514,7 +514,7 @@ test:do_catchsql_test(7.5, = [[
  =  SELECT id FROM t;
 ]], {
   -- <7.5>
-  1, "multiple recursive references: = T"
+ =  1, "Syntax error: multiple recursive references: = T"
  =  -- </7.5>
 })
 
@@ -527,7 +527,7 @@ test:do_catchsql_test(7.6, = [[
  =  SELECT id FROM t;
 ]], {
   -- <7.6>
-  1, "circular reference: = T"
+ =  1, "Syntax error: circular reference: T"
   -- = </7.6>
 })
 
@@ -782,7 +782,7 @@ test:do_catchsql_test("10.7.1", = [[
  =  SELECT * FROM t
 ]], {
   -- <10.7.1>
-  1, "Error at ORDER BY = in place 1: term does not match any column in the result = set"
+ =  1, "Syntax error: error at ORDER BY in place 1: term does not = match any column in the result set"
   -- = </10.7.1>
 })
 
@@ -1036,7 +1036,7 @@ test:do_catchsql_test(13.3, = [[
  =  SELECT i FROM c;
 ]], {
   -- <13.3>
-  1, "table C has 1 values for 2 = columns"
+ =  1, "Syntax error: table C has 1 values for 2 = columns"
   -- </13.3>
 })
 
diff --git a/test/sql-tap/with2.test.lua = b/test/sql-tap/with2.test.lua
index 8c7f9f2d9..2b6edf72c = 100755
--- = a/test/sql-tap/with2.test.lua
+++ = b/test/sql-tap/with2.test.lua
@@ -215,7 +215,7 @@ = test:do_catchsql_test(1.16, [[
     SELECT * FROM = t4;
 ]], = {
  =    -- <1.16>
-    1, "multiple references to = recursive table: T4"
+    1, "Syntax error: multiple references to = recursive table: T4"
     -- </1.16>
 })
 
@@ -258,7 +258,7 @@ = test:do_catchsql_test(3.1, [[
     SELECT * FROM = i;
 ]], = {
  =    -- <3.1>
-    1, "circular reference: = I"
+   =  1, "Syntax error: circular reference: I"
     -- = </3.1>
 })
 
@@ -270,7 +270,7 @@ test:do_catchsql_test(3.2, = [[
  =    SELECT * FROM i;
 ]], {
     -- = <3.2>
- =    1, "circular reference: I"
+    1, "Syntax error: circular = reference: I"
     -- </3.2>
 })
 
@@ -281,7 +281,7 @@ = test:do_catchsql_test(3.3, [[
     SELECT * FROM = i;
 ]], = {
  =    -- <3.3>
-    1, "circular reference: = I"
+   =  1, "Syntax error: circular reference: I"
     -- = </3.3>
 })
 
@@ -292,7 +292,7 @@ test:do_catchsql_test(3.4, = [[
  =    SELECT * FROM j;
 ]], {
     -- = <3.4>
- =    1, "circular reference: J"
+    1, "Syntax error: circular = reference: J"
     -- </3.4>
 })
 
@@ -305,7 +305,7 @@ = test:do_catchsql_test(3.5, [[
     SELECT * FROM = i;
 ]], = {
  =    -- <3.5>
-    1, "circular reference: = I"
+   =  1, "Syntax error: circular reference: I"
     -- = </3.5>
 })
 
@@ -317,7 +317,7 @@ test:do_catchsql_test(4.1, = [[
  =    SELECT * FROM x;
 ]], {
     -- = <4.1>
- =    1, [[Syntax error near ')']]
+    1, [[Syntax = error on line 1 at column 12 near ')']]
     -- = </4.1>
 })
 
@@ -519,7 +519,7 @@ test:do_catchsql_test(6.2, = [[
  =    INSERT INTO t2 VALUES(1, 2,);
 ]], {
     -- = <6.2>
- =    1, [[Syntax error near ')']]
+    1, [[Syntax = error on line 2 at column 32 near ')']]
     -- = </6.2>
 })
 
@@ -528,7 +528,7 @@ test:do_catchsql_test("6.3.1", = [[
  =    INSERT INTO t2 SELECT a, b, FROM t1;
 ]], {
     -- = <6.3>
- =    1, [[Keyword 'FROM' is reserved. Please use double quotes = if 'FROM' is an identifier.]]
+    1, [[Syntax error on line 2 at = column 33: keyword 'FROM' is reserved. Please use double quotes if = 'FROM' is an identifier.]]
     -- = </6.3>
 })
 
@@ -546,7 +546,7 @@ test:do_catchsql_test(6.4, = [[
  =    INSERT INTO t2 SELECT a, b, FROM t1 a a a;
 ]], {
     -- = <6.4>
- =    1, [[Keyword 'FROM' is reserved. Please use double quotes = if 'FROM' is an identifier.]]
+    1, [[Syntax error on line 2 at = column 33: keyword 'FROM' is reserved. Please use double quotes if = 'FROM' is an identifier.]]
     -- = </6.4>
 })
 
@@ -555,7 +555,7 @@ test:do_catchsql_test(6.5, = [[
  =    DELETE FROM t2 WHERE;
 ]], {
     -- = <6.5>
- =    1, [[Syntax error near ';']]
+    1, [[Syntax = error on line 2 at column 25 near ';']]
     -- = </6.5>
 })
 
@@ -563,7 +563,7 @@ test:do_catchsql_test(6.6, = [[
  =    WITH x AS (SELECT * FROM t1) DELETE FROM t2 = WHERE
 ]], {
     -- <6.6>
-    1, "Syntax = error near '\n'"
+    1, "Syntax error on line 2 at column 1 near = '\n'"
  =    -- </6.6>
 })
 
@@ -571,7 +571,7 @@ test:do_catchsql_test(6.7, = [[
  =    WITH x AS (SELECT * FROM t1) DELETE FROM t2 WHRE = 1;
 ]], = {
  =    -- <6.7>
-    1, "Syntax error near = 'WHRE'"
+ =    1, "Syntax error on line 1 at column 49 near = 'WHRE'"
 =    -- </6.7>
 })
 
@@ -579,7 +579,7 @@ test:do_catchsql_test(6.8, = [[
  =    WITH x AS (SELECT * FROM t1) UPDATE t2 SET a =3D 10, b =3D = ;
 ]], = {
  =    -- <6.8>
-    1, "Syntax error near = ';'"
+ =    1, "Syntax error on line 1 at column 60 near = ';'"
  =    -- </6.8>
 })
 
@@ -587,7 +587,7 @@ test:do_catchsql_test(6.9, = [[
  =    WITH x AS (SELECT * FROM t1) UPDATE t2 SET a =3D 10, b =3D = 1 WHERE a=3D=3D=3Db;
 ]], {
     -- <6.9>
-    1, "Syntax = error near '=3D'"
+    1, "Syntax error on line 1 at column 71 near = '=3D'"
  =    -- </6.9>
 })
 
diff --git a/test/sql/checks.result = b/test/sql/checks.result
index a952b2b70..7ad06a14d 100644
--- = a/test/sql/checks.result
+++ b/test/sql/checks.result
@@ -160,7 +160,7 @@ box.execute("DROP TABLE = t1")
 box.execute("CREATE TABLE first (id NUMBER PRIMARY KEY = CHECK(id < 5), a INT CONSTRAINT ONE CHECK(a >< = 5));")
 ---
 - null
-- Syntax error near '<'
+- Syntax error on line 1 at column 88 near = '<'
 ...
 box.space.FIRST =3D=3D nil
 ---
@@ -290,8 +290,8 @@ = box.execute("DROP TABLE w2;")
 box.execute("CREATE TABLE t5(x INT = PRIMARY KEY, y INT, CHECK( x*y < ? ));")
 ---
 - null
-- 'Failed to create check = constraint ''ck_unnamed_T5_1'': bindings are not = allowed
- =  in DDL'
+- 'Failed to create check constraint ''ck_unnamed_T5_1'': = Syntax error: bindings are
+  not allowed in DDL'
 ...
 -- Test trim CK = constraint code correctness.
 box.execute("CREATE TABLE t1(x TEXT = PRIMARY KEY CHECK(x    LIKE     '1 =  a'))")
diff --git a/test/sql/engine.result = b/test/sql/engine.result
index 3ee93ad19..58b9dacb1 100644
--- = a/test/sql/engine.result
+++ b/test/sql/engine.result
@@ -104,12 +104,12 @@ = box.space.T2_MEMTX:drop()
 box.execute("CREATE TABLE t1_vinyl (id INT PRIMARY = KEY) WITH ENGINE =3D VINYL")
 ---
 - null
-- Syntax error near 'VINYL'
+- Syntax error on line 1 at = column 58 near 'VINYL'
 ...
 box.execute("CREATE TABLE t1_vinyl (id INT PRIMARY KEY) = WITH ENGINE =3D vinyl")
 ---
 - null
-- Syntax error near 'vinyl'
+- Syntax error on line 1 at column 58 near = 'vinyl'
 ...
 box.execute("CREATE TABLE t1_vinyl (id INT PRIMARY KEY) = WITH ENGINE =3D 'VINYL'")
 ---
@@ -119,7 +119,7 @@ box.execute("CREATE TABLE t1_vinyl (id = INT PRIMARY KEY) WITH ENGINE =3D 'VINYL'")
 box.execute("CREATE = TABLE t1_vinyl (id INT PRIMARY KEY) WITH ENGINE =3D = \"vinyl\"")
 ---
 - null
-- Syntax error near '"vinyl"'
+- Syntax error on line 1 at = column 58 near '"vinyl"'
 ...
 -- Make sure that wrong engine name is handled = properly.
 --
diff --git a/test/sql/foreign-keys.result = b/test/sql/foreign-keys.result
index 29538e816..f17234904 = 100644
--- = a/test/sql/foreign-keys.result
+++ = b/test/sql/foreign-keys.result
@@ -396,22 +396,26 @@ box.execute('CREATE = TABLE t1 (id INT PRIMARY KEY);')
 box.execute('CREATE TABLE t2 (id INT = PRIMARY KEY REFERENCES t2 ON DELETE CASCADE ON DELETE = RESTRICT);')
 ---
 - null
-- Keyword 'DELETE' is reserved. Please use double quotes if = 'DELETE' is an identifier.
+- 'Syntax error on line 1 at column 72: = keyword ''DELETE'' is reserved. Please use
+  double quotes if = ''DELETE'' is an identifier.'
 ...
 box.execute('CREATE TABLE t2 (id INT = PRIMARY KEY REFERENCES t2 ON DELETE CASCADE ON DELETE = CASCADE);')
 ---
 - null
-- Keyword 'DELETE' is reserved. Please use double quotes if = 'DELETE' is an identifier.
+- 'Syntax error on line 1 at column 72: = keyword ''DELETE'' is reserved. Please use
+  double quotes if = ''DELETE'' is an identifier.'
 ...
 box.execute('CREATE TABLE t2 (id INT = PRIMARY KEY REFERENCES t2 ON DELETE CASCADE ON UPDATE RESTRICT ON DELETE = RESTRICT);')
 ---
 - null
-- Keyword 'ON' is reserved. Please use double quotes if 'ON' = is an identifier.
+- 'Syntax error on line 1 at column 88: keyword ''ON'' is = reserved. Please use double
+  quotes if ''ON'' is an = identifier.'
 ...
 box.execute('CREATE TABLE t2 (id INT PRIMARY KEY = REFERENCES t2 ON DELETE CASCADE MATCH FULL);')
 ---
 - null
-- Keyword 'MATCH' is = reserved. Please use double quotes if 'MATCH' is an = identifier.
+-= 'Syntax error on line 1 at column 69: keyword ''MATCH'' is reserved. = Please use
+ =  double quotes if ''MATCH'' is an identifier.'
 ...
 box.space.T1:drop()
 ---
diff --git = a/test/sql/gh-3888-values-blob-assert.result = b/test/sql/gh-3888-values-blob-assert.result
index 4b8e7ede6..f20598e4a = 100644
--- = a/test/sql/gh-3888-values-blob-assert.result
+++ = b/test/sql/gh-3888-values-blob-assert.result
@@ -18,23 +18,23 @@ = box.execute('pragma = sql_default_engine=3D\''..engine..'\'')
 box.execute('VALUES(scalar)')
 ---
 - null
-- Syntax error near = 'scalar'
+- = Syntax error on line 1 at column 8 near 'scalar'
 ...
 box.execute('VALUES(float)')
 ---
 - null
-- Syntax error near = 'float'
+- = Syntax error on line 1 at column 8 near 'float'
 ...
 -- check 'SELECT' = against typedef keywords (should fail)
 box.execute('SELECT = scalar')
 ---
 - null
-- Syntax error near 'scalar'
+- Syntax error on line 1 at column 8 near = 'scalar'
 ...
 box.execute('SELECT float')
 ---
 - null
-- Syntax error near = 'float'
+- = Syntax error on line 1 at column 8 near 'float'
 ...
 -- check 'VALUES' = against ID (should fail)
 box.execute('VALUES(TheColumnName)')
diff --git = a/test/sql/iproto.result b/test/sql/iproto.result
index 67acd0ac1..fb2772605 = 100644
--- = a/test/sql/iproto.result
+++ b/test/sql/iproto.result
@@ -106,7 +106,7 @@ cn:execute('insert into = not_existing_table values ("kek")')
 ...
 cn:execute('insert qwerty gjsdjq  q =  qwd qmq;; q;qwd;')
 ---
-- error: Syntax error near 'qwerty'
+- error: Syntax error on = line 1 at column 8 near 'qwerty'
 ...
 -- Empty result.
 cn:execute('select id = as identifier from test where a =3D 5;')
@@ -119,7 +119,7 @@ cn:execute('select id as = identifier from test where a =3D 5;')
 -- netbox API errors.
 cn:execute(100)
 ---
-- error: Syntax error near = '100'
+- = error: Syntax error on line 1 at column 1 near '100'
 ...
 cn:execute('select 1', = nil, {dry_run =3D true})
 ---
@@ -352,11 +352,11 @@ cn:execute('drop table if exists = test3')
 --
 cn:execute('select ?1, ?2, ?3', {1, 2, = 3})
 ---
-- error: Syntax error near '?1'
+- error: Syntax error on = line 1 at column 10 near '?1'
 ...
 cn:execute('select $name, $name2', {1, = 2})
 ---
-- error: Index of binding slots must start from = 1
+- error: = 'Syntax error: index of binding slots must start from = 1'
 ...
 parameters =3D {}
 ---
diff --git a/test/sql/misc.result = b/test/sql/misc.result
index a157ddbc1..82b86f574 100644
--- = a/test/sql/misc.result
+++ b/test/sql/misc.result
@@ -20,12 +20,14 @@ box.execute('select = 1;')
 box.execute('select 1; select 2;')
 ---
 - null
-- Keyword 'select' is = reserved. Please use double quotes if 'select' is an = identifier.
+-= 'Syntax error on line 1 at column 11: keyword ''select'' is reserved. = Please use
+ =  double quotes if ''select'' is an identifier.'
 ...
 box.execute('create = table t1 (id INT primary key); select 100;')
 ---
 - null
-- Keyword 'select' is = reserved. Please use double quotes if 'select' is an = identifier.
+-= 'Syntax error on line 1 at column 39: keyword ''select'' is reserved. = Please use
+ =  double quotes if ''select'' is an identifier.'
 ...
 box.space.t1 =3D=3D = nil
 ---
@@ -56,17 +58,20 @@ box.execute('\n\n\n\t\t\t   = ')
 box.execute('CREATE TABLE test (id INTEGER PRIMARY KEY, = b INTEGER CONSTRAINT c1 NULL)')
 ---
 - null
-- Keyword 'NULL' is reserved. Please use = double quotes if 'NULL' is an identifier.
+- 'Syntax error on line 1 at = column 68: keyword ''NULL'' is reserved. Please use = double
+ =  quotes if ''NULL'' is an identifier.'
 ...
 box.execute('CREATE = TABLE test (id INTEGER PRIMARY KEY, b INTEGER CONSTRAINT c1 DEFAULT = 300)')
 ---
 - null
-- Keyword 'DEFAULT' is reserved. Please use double quotes if = 'DEFAULT' is an identifier.
+- 'Syntax error on line 1 at column 68: = keyword ''DEFAULT'' is reserved. Please use
+  double quotes if = ''DEFAULT'' is an identifier.'
 ...
 box.execute('CREATE TABLE test (id = INTEGER PRIMARY KEY, b TEXT CONSTRAINT c1 COLLATE = "binary")')
 ---
 - null
-- Keyword 'COLLATE' is reserved. Please use double quotes if = 'COLLATE' is an identifier.
+- 'Syntax error on line 1 at column 65: = keyword ''COLLATE'' is reserved. Please use
+  double quotes if = ''COLLATE'' is an identifier.'
 ...
 -- Make sure that type of literals in = meta complies with its real
 -- type. For instance, typeof(0.5) is = number, not integer.
diff --git a/test/sql/on-conflict.result = b/test/sql/on-conflict.result
index 6851e217e..328656ea1 = 100644
--- = a/test/sql/on-conflict.result
+++ = b/test/sql/on-conflict.result
@@ -15,44 +15,52 @@ box.execute('pragma = sql_default_engine=3D\''..engine..'\'')
 box.execute("CREATE TABLE t (id INTEGER = PRIMARY KEY, v INTEGER UNIQUE ON CONFLICT ABORT)")
 ---
 - null
-- Keyword 'ON' is reserved. = Please use double quotes if 'ON' is an identifier.
+- 'Syntax error on line 1 at = column 58: keyword ''ON'' is reserved. Please use = double
+ =  quotes if ''ON'' is an identifier.'
 ...
 box.execute("CREATE = TABLE q (id INTEGER PRIMARY KEY, v INTEGER UNIQUE ON CONFLICT = FAIL)")
 ---
 - null
-- Keyword 'ON' is reserved. Please use double quotes if 'ON' = is an identifier.
+- 'Syntax error on line 1 at column 58: keyword ''ON'' is = reserved. Please use double
+  quotes if ''ON'' is an = identifier.'
 ...
 box.execute("CREATE TABLE p (id INTEGER PRIMARY KEY, v = INTEGER UNIQUE ON CONFLICT IGNORE)")
 ---
 - null
-- Keyword 'ON' is reserved. Please use double = quotes if 'ON' is an identifier.
+- 'Syntax error on line 1 at column 58: = keyword ''ON'' is reserved. Please use double
+  quotes if ''ON'' is = an identifier.'
 ...
 box.execute("CREATE TABLE g (id INTEGER PRIMARY KEY, v = INTEGER UNIQUE ON CONFLICT REPLACE)")
 ---
 - null
-- Keyword 'ON' is reserved. Please use double = quotes if 'ON' is an identifier.
+- 'Syntax error on line 1 at column 58: = keyword ''ON'' is reserved. Please use double
+  quotes if ''ON'' is = an identifier.'
 ...
 box.execute("CREATE TABLE e (id INTEGER PRIMARY KEY ON = CONFLICT REPLACE, v INTEGER)")
 ---
 - null
-- Keyword 'ON' is reserved. Please use double = quotes if 'ON' is an identifier.
+- 'Syntax error on line 1 at column 40: = keyword ''ON'' is reserved. Please use double
+  quotes if ''ON'' is = an identifier.'
 ...
 box.execute("CREATE TABLE t1(a INT PRIMARY KEY ON = CONFLICT REPLACE)")
 ---
 - null
-- Keyword 'ON' is reserved. Please use double quotes if 'ON' = is an identifier.
+- 'Syntax error on line 1 at column 35: keyword ''ON'' is = reserved. Please use double
+  quotes if ''ON'' is an = identifier.'
 ...
 box.execute("CREATE TABLE t2(a INT PRIMARY KEY ON = CONFLICT IGNORE)")
 ---
 - null
-- Keyword 'ON' is reserved. Please use double quotes if 'ON' = is an identifier.
+- 'Syntax error on line 1 at column 35: keyword ''ON'' is = reserved. Please use double
+  quotes if ''ON'' is an = identifier.'
 ...
 -- CHECK constraint is illegal with REPLACE = option.
 --
 box.execute("CREATE TABLE t (id INTEGER PRIMARY KEY, a = INTEGER CHECK (a > 5) ON CONFLICT REPLACE);")
 ---
 - null
-- Keyword 'ON' is reserved. = Please use double quotes if 'ON' is an identifier.
+- 'Syntax error on line 1 at = column 65: keyword ''ON'' is reserved. Please use = double
+ =  quotes if ''ON'' is an identifier.'
 ...
 --
 -- gh-3473: Primary key = can't be declared with NULL.
diff --git a/test/sql/triggers.result = b/test/sql/triggers.result
index 9dfe981a0..f11f7617f = 100644
--- = a/test/sql/triggers.result
+++ = b/test/sql/triggers.result
@@ -487,14 +487,14 @@ space_id =3D box.space.T1.id
 box.execute("CREATE TRIGGER tr1 AFTER = INSERT ON t1 FOR EACH ROW WHEN new.a =3D ? BEGIN SELECT 1; = END;")
 ---
 - null
-- bindings are not allowed in DDL
+- 'Syntax error: bindings = are not allowed in DDL'
 ...
 tuple =3D {"TR1", space_id, {sql =3D [[CREATE TRIGGER = tr1 AFTER INSERT ON t1 FOR EACH ROW WHEN new.a =3D ? BEGIN SELECT 1; = END;]]}}
 ---
 ...
 box.space._trigger:insert(tuple)
 ---
-- error: bindings are not = allowed in DDL
+- error: 'Syntax error: bindings are not allowed in = DDL'
 ...
 box.execute("DROP TABLE t1;")
 ---
@@ -513,7 +513,8 @@ space_id = =3D box.space.T1.id
 box.execute("CREATE TRIGGER tr1 AFTER = INSERT ON t1 BEGIN ; END;")
 ---
 - null
-- FOR EACH STATEMENT triggers are not = implemented, please supply FOR EACH ROW clause
+- 'Syntax error on line 1 at = column 39: FOR EACH STATEMENT triggers are not = implemented,
+=  please supply FOR EACH ROW clause'
 ...
 box.execute("DROP TABLE = t1;")
 ---
diff --git a/test/sql/types.result = b/test/sql/types.result
index 1ad52e8c7..d824d22f7 100644
--- = a/test/sql/types.result
+++ b/test/sql/types.result
@@ -9,27 +9,30 @@ test_run =3D = env.new()
 box.execute("CREATE TABLE t1 (id PRIMARY = KEY);")
 ---
 - null
-- Keyword 'PRIMARY' is reserved. Please use double quotes if = 'PRIMARY' is an identifier.
+- 'Syntax error on line 1 at column 21: = keyword ''PRIMARY'' is reserved. Please use
+  double quotes if = ''PRIMARY'' is an identifier.'
 ...
 box.execute("CREATE TABLE t1 (a, id INT = PRIMARY KEY);")
 ---
 - null
-- Syntax error near ','
+- Syntax error on line 1 at column 19 near = ','
 ...
 box.execute("CREATE TABLE t1 (id PRIMARY KEY, a = INT);")
 ---
 - null
-- Keyword 'PRIMARY' is reserved. Please use double quotes if = 'PRIMARY' is an identifier.
+- 'Syntax error on line 1 at column 21: = keyword ''PRIMARY'' is reserved. Please use
+  double quotes if = ''PRIMARY'' is an identifier.'
 ...
 box.execute("CREATE TABLE t1 (id INT = PRIMARY KEY, a);")
 ---
 - null
-- Syntax error near ')'
+- Syntax error on line 1 at column 39 near = ')'
 ...
 box.execute("CREATE TABLE t1 (id INT PRIMARY KEY, a = INT, b UNIQUE);")
 ---
 - null
-- Keyword 'UNIQUE' is reserved. Please use double quotes if = 'UNIQUE' is an identifier.
+- 'Syntax error on line 1 at column 47: = keyword ''UNIQUE'' is reserved. Please use
+  double quotes if = ''UNIQUE'' is an identifier.'
 ...
 -- gh-3104: real type is stored in space = format.
 --


= --Apple-Mail=_17CB3347-326E-4006-91FC-8A9F0EC2B57C--