[Tarantool-patches] [PATCH] sql: display line and position in syntax errors

Nikita Pettik korablev at tarantool.org
Wed Dec 11 17:36:16 MSK 2019


When it comes for huge queries, it may turn out to be useful to see
exact position of occurred error. Hence, let's now display line and
position within line near which syntax error takes place. Note that it
can be done only during parsing process (since AST can be analysed only
after its construction is completed), so most of semantic errors still
don't contain position. A few errors have been reworked to match new
formatting patterns.

First iteration of this patch is implemented by @romanhabibov

Closes #2611
---
Branch: https://github.com/tarantool/tarantool/tree/np/gh-2611-line-pos-syntax-error
Issue: https://github.com/tarantool/tarantool/issues/2611
v1: https://lists.tarantool.org/pipermail/tarantool-patches/2019-October/011841.html

 extra/addopcodes.sh                        |  1 +
 src/box/errcode.h                          |  9 +++---
 src/box/sql/build.c                        | 10 +++---
 src/box/sql/parse.y                        | 39 +++++++++++++----------
 src/box/sql/prepare.c                      |  2 ++
 src/box/sql/select.c                       |  5 +--
 src/box/sql/sqlInt.h                       |  7 ++++
 src/box/sql/tokenize.c                     | 33 ++++++++++++++++---
 test/box/misc.result                       |  5 +--
 test/sql-tap/alter2.test.lua               |  4 +--
 test/sql-tap/autoinc.test.lua              |  4 +--
 test/sql-tap/blob.test.lua                 | 20 ++++++------
 test/sql-tap/check.test.lua                | 14 ++++----
 test/sql-tap/count.test.lua                |  2 +-
 test/sql-tap/default.test.lua              |  4 +--
 test/sql-tap/e_select1.test.lua            |  8 ++---
 test/sql-tap/func.test.lua                 |  4 +--
 test/sql-tap/gh2168-temp-tables.test.lua   | 23 ++++++++++----
 test/sql-tap/identifier_case.test.lua      |  2 +-
 test/sql-tap/index-info.test.lua           |  2 +-
 test/sql-tap/index1.test.lua               |  2 +-
 test/sql-tap/index7.test.lua               | 11 +++++--
 test/sql-tap/join.test.lua                 |  2 +-
 test/sql-tap/keyword1.test.lua             | 18 +++++++++--
 test/sql-tap/misc1.test.lua                | 25 ++++++++++-----
 test/sql-tap/misc5.test.lua                |  4 +--
 test/sql-tap/null.test.lua                 |  8 ++---
 test/sql-tap/pragma.test.lua               |  4 +--
 test/sql-tap/select1.test.lua              | 20 ++++++------
 test/sql-tap/select3.test.lua              |  4 +--
 test/sql-tap/sql-errors.test.lua           |  8 ++---
 test/sql-tap/start-transaction.test.lua    | 14 ++++----
 test/sql-tap/table.test.lua                | 10 +++---
 test/sql-tap/tkt3935.test.lua              | 14 ++++----
 test/sql-tap/tokenize.test.lua             | 51 ++++++++++++++++++++++--------
 test/sql-tap/trigger1.test.lua             | 14 ++++----
 test/sql-tap/view.test.lua                 |  2 +-
 test/sql-tap/with1.test.lua                |  2 +-
 test/sql-tap/with2.test.lua                | 18 +++++------
 test/sql/checks.result                     | 10 +++---
 test/sql/collation.result                  | 12 +++----
 test/sql/engine.result                     |  6 ++--
 test/sql/foreign-keys.result               | 12 ++++---
 test/sql/gh-3888-values-blob-assert.result |  8 ++---
 test/sql/iproto.result                     |  6 ++--
 test/sql/misc.result                       | 15 ++++++---
 test/sql/on-conflict.result                | 24 +++++++++-----
 test/sql/triggers.result                   |  7 ++--
 test/sql/types.result                      | 13 +++++---
 49 files changed, 334 insertions(+), 208 deletions(-)

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="            \
     ASTERISK        \
     SPAN            \
     ANALYZE         \
+    LINEFEED        \
     SPACE           \
     ILLEGAL         \
 "
diff --git a/src/box/errcode.h b/src/box/errcode.h
index c660b1c70..0eddc0b8a 100644
--- a/src/box/errcode.h
+++ b/src/box/errcode.h
@@ -231,13 +231,13 @@ struct errcode_record {
 	/*176 */_(ER_SQL_CANT_RESOLVE_FIELD,	"Can’t 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_WITH_POS,	"Syntax error at line %d at or near position %d: %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'") \
+	/*183 */_(ER_SQL_KEYWORD_IS_RESERVED,	"At line %d at or near position %d: keyword '%.*s' is reserved. Please use double quotes if '%.*s' is an identifier.") \
+	/*184 */_(ER_SQL_SYNTAX_NEAR_TOKEN,	"Syntax error at line %d near '%.*s'") \
+	/*185 */_(ER_SQL_UNKNOWN_TOKEN,		"At line %d at or near position %d: unrecognized token '%.*s'") \
 	/*186 */_(ER_SQL_PARSER_GENERIC,	"%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)") \
@@ -258,6 +258,7 @@ struct errcode_record {
 	/*203 */_(ER_BOOTSTRAP_READONLY,	"Trying to bootstrap a local read-only instance as master") \
 	/*204 */_(ER_SQL_FUNC_WRONG_RET_COUNT,	"SQL expects exactly one argument returned from %s, got %d")\
 	/*205 */_(ER_FUNC_INVALID_RETURN_TYPE,	"Function '%s' returned value of invalid type: expected %s got %s") \
+	/*186 */_(ER_SQL_PARSER_GENERIC_WITH_POS,"At line %d at or near position %d: %s") \
 
 /*
  * !IMPORTANT! Please follow instructions at start of the file
diff --git a/src/box/sql/build.c b/src/box/sql/build.c
index 51cd7ce63..24e66c047 100644
--- a/src/box/sql/build.c
+++ b/src/box/sql/build.c
@@ -2920,8 +2920,9 @@ sqlSrcListAppendFromTerm(Parse * pParse,	/* Parsing context */
 	struct SrcList_item *pItem;
 	sql *db = pParse->db;
 	if (!p && (pOn || pUsing)) {
-		diag_set(ClientError, ER_SQL_SYNTAX, "FROM clause",
-			 "a JOIN clause is required before ON and USING");
+		diag_set(ClientError, ER_SQL_SYNTAX_WITH_POS,
+			 pParse->line_count, pParse->line_pos, "a JOIN clause "\
+			 "is required before ON and USING");
 		pParse->is_aborted = true;
 		goto append_from_error;
 	}
@@ -3208,8 +3209,9 @@ 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_WITH_POS,
+			 parse_context->line_count, parse_context->line_pos,
+			 "table must feature at most one AUTOINCREMENT field");
 		parse_context->is_aborted = true;
 		return -1;
 	}
diff --git a/src/box/sql/parse.y b/src/box/sql/parse.y
index 1d0c95fac..93bba72f1 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);
+    diag_set(ClientError, ER_SQL_KEYWORD_IS_RESERVED, pParse->line_count,
+             pParse->line_pos, TOKEN.n, TOKEN.z, TOKEN.n, TOKEN.z);
   } else {
-    diag_set(ClientError, ER_SQL_UNRECOGNIZED_SYNTAX, TOKEN.n, TOKEN.z);
+    diag_set(ClientError, ER_SQL_SYNTAX_NEAR_TOKEN, pParse->line_count, TOKEN.n,
+             TOKEN.z);
   }
   pParse->is_aborted = true;
 }
@@ -274,7 +275,8 @@ columnname(A) ::= nm(A) typedef(Y). {sqlAddColumn(pParse,&A,&Y);}
 %type nm {Token}
 nm(A) ::= id(A). {
   if(A.isReserved) {
-    diag_set(ClientError, ER_SQL_KEYWORD_IS_RESERVED, A.n, A.z, A.n, A.z);
+    diag_set(ClientError, ER_SQL_KEYWORD_IS_RESERVED, pParse->line_count,
+             pParse->line_pos, A.n, A.z, A.n, A.z);
     pParse->is_aborted = true;
   }
 }
@@ -1076,15 +1078,15 @@ expr(A) ::= VARIABLE(X).     {
   Token t = X;
   if (pParse->parse_only) {
     spanSet(&A, &t, &t);
-    diag_set(ClientError, ER_SQL_PARSER_GENERIC,
-             "bindings are not allowed in DDL");
+    diag_set(ClientError, ER_SQL_PARSER_GENERIC_WITH_POS, pParse->line_count,
+             pParse->line_pos, "bindings are not allowed in DDL");
     pParse->is_aborted = true;
     A.pExpr = NULL;
   } else if (!(X.z[0]=='#' && sqlIsdigit(X.z[1]))) {
     u32 n = X.n;
     spanExpr(&A, pParse, TK_VARIABLE, X);
     if (A.pExpr->u.zToken[0] == '?' && n > 1) {
-      diag_set(ClientError, ER_SQL_UNRECOGNIZED_SYNTAX, t.n, t.z);
+      diag_set(ClientError, ER_SQL_SYNTAX_NEAR_TOKEN, pParse->line_count, t.n, t.z);
       pParse->is_aborted = true;
     } else {
       sqlExprAssignVarNumber(pParse, A.pExpr, n);
@@ -1092,7 +1094,7 @@ expr(A) ::= VARIABLE(X).     {
   }else{
     assert( t.n>=2 );
     spanSet(&A, &t, &t);
-    diag_set(ClientError, ER_SQL_UNRECOGNIZED_SYNTAX, t.n, t.z);
+    diag_set(ClientError, ER_SQL_SYNTAX_NEAR_TOKEN, pParse->line_count, t.n, t.z);
     pParse->is_aborted = true;
     A.pExpr = NULL;
   }
@@ -1608,8 +1610,9 @@ trigger_event(A) ::= UPDATE(X).          {A.a = @X; /*A-overwrites-X*/ A.b = 0;}
 trigger_event(A) ::= UPDATE OF idlist(X).{A.a = TK_UPDATE; A.b = X;}
 
 foreach_clause ::= . {
-  diag_set(ClientError, ER_SQL_PARSER_GENERIC, "FOR EACH STATEMENT "
-	       "triggers are not implemented, please supply FOR EACH ROW clause");
+  diag_set(ClientError, ER_SQL_PARSER_GENERIC_WITH_POS, pParse->line_count,
+           pParse->line_pos, "FOR EACH STATEMENT triggers are not implemented, "
+           "please supply FOR EACH ROW clause");
   pParse->is_aborted = true;
 }
 foreach_clause ::= FOR EACH ROW.
@@ -1639,8 +1642,9 @@ trigger_cmd_list(A) ::= trigger_cmd(A) SEMI. {
 trnm(A) ::= nm(A).
 trnm(A) ::= nm DOT nm(X). {
   A = X;
-  diag_set(ClientError, ER_SQL_PARSER_GENERIC, "qualified table names are not "\
-           "allowed on INSERT, UPDATE, and DELETE statements within triggers");
+  diag_set(ClientError, ER_SQL_PARSER_GENERIC_WITH_POS, pParse->line_count,
+           pParse->line_pos, "qualified table names are not allowed on INSERT, "
+           "UPDATE, and DELETE statements within triggers");
   pParse->is_aborted = true;
 }
 
@@ -1650,14 +1654,15 @@ trnm(A) ::= nm DOT nm(X). {
 //
 tridxby ::= .
 tridxby ::= 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");
+  diag_set(ClientError, ER_SQL_SYNTAX_WITH_POS, pParse->line_count,
+           pParse->line_pos, "the INDEXED BY clause is not allowed on UPDATE "\
+           "or DELETE statements within triggers");
   pParse->is_aborted = true;
 }
 tridxby ::= NOT INDEXED. {
-  diag_set(ClientError, ER_SQL_SYNTAX, "trigger body", "the NOT INDEXED "\
-           "clause is not allowed on UPDATE or DELETE statements within "\
-           "triggers");
+  diag_set(ClientError, ER_SQL_SYNTAX_WITH_POS, pParse->line_count,
+           pParse->line_pos, "the NOT INDEXED BY clause is not allowed on "\
+           "UPDATE or DELETE statements within triggers");
   pParse->is_aborted = 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 = db;
 	parser->sql_flags = sql_flags;
+	parser->line_count = 1;
+	parser->line_pos = 1;
 	region_create(&parser->region, &cord()->slabc);
 }
 
diff --git a/src/box/sql/select.c b/src/box/sql/select.c
index 8f93edd16..c6441a4b3 100644
--- a/src/box/sql/select.c
+++ b/src/box/sql/select.c
@@ -2115,8 +2115,9 @@ computeLimitRegisters(Parse * pParse, Select * p, int iBreak)
 		if((p->pLimit->flags & EP_Collate) != 0 ||
 		   (p->pOffset != NULL &&
 		   (p->pOffset->flags & EP_Collate) != 0)) {
-			diag_set(ClientError, ER_SQL_UNRECOGNIZED_SYNTAX,
-				 sizeof("COLLATE"), "COLLATE");
+			diag_set(ClientError, ER_SQL_SYNTAX_NEAR_TOKEN,
+				 pParse->line_count, sizeof("COLLATE"),
+				 "COLLATE");
 			pParse->is_aborted = true;
 			return;
 		}
diff --git a/src/box/sql/sqlInt.h b/src/box/sql/sqlInt.h
index 2594b73e0..6f9a3d23e 100644
--- a/src/box/sql/sqlInt.h
+++ b/src/box/sql/sqlInt.h
@@ -2181,6 +2181,13 @@ struct Parse {
   ***********************************************************************/
 
 	Token sLastToken;	/* The last token parsed */
+	/** The line counter. */
+	uint32_t line_count;
+	/**
+	 * The position in a line. Line and position are used
+	 * for detailed error diagnostics.
+	 */
+	int 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 */
diff --git a/src/box/sql/tokenize.c b/src/box/sql/tokenize.c
index 9fa069d09..f2541d926 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[] = {
 /*       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 = 1 + sql_skip_spaces(z+1);
 		*type = TK_SPACE;
 		return i;
+	case CC_LINEFEED:
+		*type = 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] == '-') {
-			for (i = 2; (c = z[i]) != 0 && c != '\n'; i++) {
+			for (i = 2; true; i++) {
+				if (z[i] == '\0') {
+					*type = TK_SPACE;
+					return i;
+				} else if (z[i] == '\n') {
+					*type = TK_LINEFEED;
+					return ++i;
+				}
 			}
-			*type = TK_SPACE;
-			return i;
 		}
 		*type = TK_MINUS;
 		return 1;
@@ -500,11 +513,16 @@ sqlRunParser(Parse * pParse, const char *zSql)
 			       || tokenType == TK_ILLEGAL);
 			if (tokenType == TK_ILLEGAL) {
 				diag_set(ClientError, ER_SQL_UNKNOWN_TOKEN,
+					 pParse->line_count, pParse->line_pos,
 					 pParse->sLastToken.n,
 					 pParse->sLastToken.z);
 				pParse->is_aborted = true;
 				break;
 			}
+		} else if (tokenType == TK_LINEFEED) {
+			pParse->line_count++;
+			pParse->line_pos = 1;
+			continue;
 		} else {
 			sqlParser(pEngine, tokenType, pParse->sLastToken,
 				      pParse);
@@ -512,6 +530,7 @@ sqlRunParser(Parse * pParse, const char *zSql)
 			if (pParse->is_aborted || db->mallocFailed)
 				break;
 		}
+		pParse->line_pos += pParse->sLastToken.n;
 	}
 	pParse->zTail = &zSql[i];
 	sqlParserFree(pEngine, sql_free);
@@ -537,6 +556,12 @@ sql_expr_compile(sql *db, const char *expr, int expr_len)
 
 	struct Parse parser;
 	sql_parser_create(&parser, db, default_flags);
+	/*
+	 * Since SELECT token is added to the original expression,
+	 * to make error message display correct position we should
+	 * account its length.
+	 */
+	parser.line_pos -= strlen(outer);
 	parser.parse_only = true;
 
 	struct Expr *expression = NULL;
diff --git a/test/box/misc.result b/test/box/misc.result
index d2a20307a..6a8b69790 100644
--- a/test/box/misc.result
+++ b/test/box/misc.result
@@ -528,11 +528,11 @@ t;
   176: box.error.SQL_CANT_RESOLVE_FIELD
   177: box.error.INDEX_EXISTS_IN_SPACE
   178: box.error.INCONSISTENT_TYPES
-  179: box.error.SQL_SYNTAX
+  179: box.error.SQL_SYNTAX_WITH_POS
   180: box.error.SQL_STACK_OVERFLOW
   181: box.error.SQL_SELECT_WILDCARD
   182: box.error.SQL_STATEMENT_EMPTY
-  184: box.error.SQL_UNRECOGNIZED_SYNTAX
+  184: box.error.SQL_SYNTAX_NEAR_TOKEN
   185: box.error.SQL_UNKNOWN_TOKEN
   186: box.error.SQL_PARSER_GENERIC
   187: box.error.SQL_ANALYZE_ARGUMENT
@@ -554,6 +554,7 @@ t;
   203: box.error.BOOTSTRAP_READONLY
   204: box.error.SQL_FUNC_WRONG_RET_COUNT
   205: box.error.FUNC_INVALID_RETURN_TYPE
+  206: box.error.SQL_PARSER_GENERIC_WITH_POS
 ...
 test_run:cmd("setopt delimiter ''");
 ---
diff --git a/test/sql-tap/alter2.test.lua b/test/sql-tap/alter2.test.lua
index e0bd60727..dd94d09d4 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, "At line 1 at or near position 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 at line 1 near '('"
         -- </alter2-4.2>
     })
 
diff --git a/test/sql-tap/autoinc.test.lua b/test/sql-tap/autoinc.test.lua
index 39e47966b..6105db3c7 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 at line 1 at or near position 69: 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 at line 1 at or near position 87: 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..d4845bbd4 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, [[At line 1 at or near position 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, [[At line 1 at or near position 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, [[At line 1 at or near position 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, [[At line 1 at or near position 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, [[At line 1 at or near position 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, [[At line 1 at or near position 16: unrecognized token 'x'012:45'']]
         -- </blob-1.9>
     })
 
@@ -131,7 +131,7 @@ test:do_catchsql_test(
         SELECT x'012 at 45'
     ]], {
         -- <blob-1.10>
-        1, [[Syntax error: unrecognized token: 'x'012 at 45'']]
+        1, [[At line 1 at or near position 16: unrecognized token 'x'012 at 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, [[At line 1 at or near position 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, [[At line 1 at or near position 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, [[At line 1 at or near position 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..21ededaba 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 at line 2 near ','"
         -- </check-2.10>
     })
 
@@ -296,7 +296,7 @@ test:do_catchsql_test(
         );
     ]], {
         -- <check-2.10>
-        1,"Syntax error near ','"
+        1,"Syntax error at line 3 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': At line 1 at or near position 9: 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': At line 1 at or near position 6: 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, "At line 2 at or near position 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, "At line 2 at or near position 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, "At line 2 at or near position 9: keyword 'ON' is reserved. Please use double quotes if 'ON' is an identifier."
         -- </9.3>
     })
 
diff --git a/test/sql-tap/count.test.lua b/test/sql-tap/count.test.lua
index cf5bfccdd..08c225bc5 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 at line 1 near '*']]
         -- </count-2.2>
     })
 
diff --git a/test/sql-tap/default.test.lua b/test/sql-tap/default.test.lua
index f2a5db071..d3e35c71c 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 at line 1 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 at line 1 near '\"id\"'"
     -- </default-5.3>
 })
 
diff --git a/test/sql-tap/e_select1.test.lua b/test/sql-tap/e_select1.test.lua
index a0a671644..48d8c226e 100755
--- a/test/sql-tap/e_select1.test.lua
+++ b/test/sql-tap/e_select1.test.lua
@@ -105,7 +105,7 @@ test:do_catchsql_test(
         SELECT count(*) FROM t1, t2 USING (a) ON (t1.a=t2.a)
     ]], {
         -- <e_select-0.1.5>
-        1, [[Keyword 'ON' is reserved. Please use double quotes if 'ON' is an identifier.]]
+        1, [[At line 1 at or near position 47: keyword 'ON' is reserved. Please use double quotes if 'ON' is an identifier.]]
         -- </e_select-0.1.5>
     })
 
@@ -805,9 +805,9 @@ test:do_select_tests(
 -- FROM clause.
 --
 data = {
-    {"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 at line 1 near '*'"},
+    {"1.2", "SELECT a, b, c FROM z1 GROUP BY *", "Syntax error at line 1 near '*'"},
+    {"1.3", "SELECT 1 + * FROM z1",  "Syntax error at line 1 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"},
diff --git a/test/sql-tap/func.test.lua b/test/sql-tap/func.test.lua
index 4574ddfeb..8c3abba1c 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 at line 1 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 at line 1 near 'FROM'"
         -- </func-22.38>
     })
 
diff --git a/test/sql-tap/gh2168-temp-tables.test.lua b/test/sql-tap/gh2168-temp-tables.test.lua
index 3b29c9ed2..37db002a4 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 = 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 at line 1 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 at line 1 near 'TEMP'"
+		-- <trigger2-10.3>
 });
 
 
diff --git a/test/sql-tap/identifier_case.test.lua b/test/sql-tap/identifier_case.test.lua
index 65ed9aea1..2a00626fc 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 = {
     { 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 at line 1 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/index-info.test.lua b/test/sql-tap/index-info.test.lua
index a5ed9a98e..a1402eeee 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 = t1.a;",
     {
-        1, "Syntax error near '.'",
+        1, "Syntax error at line 1 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..e173e685c 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 at line 1 near '.'"
         -- </index-21.1>
     })
 
diff --git a/test/sql-tap/index7.test.lua b/test/sql-tap/index7.test.lua
index ca5cb1910..c98f17218 100755
--- a/test/sql-tap/index7.test.lua
+++ b/test/sql-tap/index7.test.lua
@@ -1,6 +1,6 @@
 #!/usr/bin/env tarantool
 test = 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 = 3;
     ]], {
-        1, "Keyword 'WHERE' is reserved. Please use double quotes if 'WHERE' is an identifier."
+        1, "At line 1 at or near position 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/join.test.lua b/test/sql-tap/join.test.lua
index ac7d32b84..4f014e086 100755
--- a/test/sql-tap/join.test.lua
+++ b/test/sql-tap/join.test.lua
@@ -570,7 +570,7 @@ test:do_catchsql_test(
         SELECT * FROM t1 USING(a) 
     ]], {
         -- <join-3.5>
-        1, "Syntax error in FROM clause: a JOIN clause is required before ON and USING"
+        1, "Syntax error at line 1 at or near position 40: a JOIN clause is required before ON and USING"
         -- </join-3.5>
     })
 
diff --git a/test/sql-tap/keyword1.test.lua b/test/sql-tap/keyword1.test.lua
index 571e1dcbe..e39b22087 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 = 'CREATE TABLE '..kw..'(a INT PRIMARY KEY);'
-    test:do_catchsql_test(
+    if kw == 'end' or kw == 'match' or kw == 'release' or kw == 'rename' or
+       kw == 'replace' or kw == 'binary' or kw == 'character' or
+       kw == '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, "At line 1 at or near position "..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, "At line 1 at or near position 14: keyword '"..kw..
+            "' is reserved. Please use double quotes if '"..kw..
+            "' is an identifier."
+        })
+    end
 end
 
 
diff --git a/test/sql-tap/misc1.test.lua b/test/sql-tap/misc1.test.lua
index b84093e3c..b47dbf018 100755
--- a/test/sql-tap/misc1.test.lua
+++ b/test/sql-tap/misc1.test.lua
@@ -1,6 +1,6 @@
 #!/usr/bin/env tarantool
 test = 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=0 WHEREwww b=2;
     ]], {
-        -- <misc1-5.1>
-        1, [[Syntax error near 'WHEREwww']]
-        -- </misc1-5.1>
+        -- <misc1-5.1.2>
+        1, [[Syntax error at line 1 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 at line 1 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 at line 1 near '#0']]
         -- </misc1-21.2>
     })
 
diff --git a/test/sql-tap/misc5.test.lua b/test/sql-tap/misc5.test.lua
index 5f98f21f6..2725e6782 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, [[At line 1 at or near position 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, [[At line 1 at or near position 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..93589754c 100755
--- a/test/sql-tap/null.test.lua
+++ b/test/sql-tap/null.test.lua
@@ -517,7 +517,7 @@ test:do_catchsql_test(
     ]],
     {
     -- <index-1.3>
-    1, "Syntax error near '1'"
+    1, "Syntax error at line 1 near '1'"
     -- <index-1.3>
     })
 
@@ -528,7 +528,7 @@ test:do_catchsql_test(
     ]],
     {
     -- <index-1.3>
-    1, "Syntax error near '1'"
+    1, "Syntax error at line 1 near '1'"
     -- <index-1.3>
     })
 
@@ -539,7 +539,7 @@ test:do_catchsql_test(
     ]],
     {
     -- <index-1.3>
-    1, "Syntax error near '1'"
+    1, "Syntax error at line 1 near '1'"
     -- <index-1.3>
     })
 
@@ -550,7 +550,7 @@ test:do_catchsql_test(
     ]],
     {
     -- <index-1.3>
-    1, "Syntax error near '1'"
+    1, "Syntax error at line 1 near '1'"
     -- <index-1.3>
     })
 
diff --git a/test/sql-tap/pragma.test.lua b/test/sql-tap/pragma.test.lua
index b3821dcf7..c36f9b939 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 at line 1 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 at line 1 near '1'"
 })
 
 --
diff --git a/test/sql-tap/select1.test.lua b/test/sql-tap/select1.test.lua
index 4bbfbd67b..13b5390cb 100755
--- a/test/sql-tap/select1.test.lua
+++ b/test/sql-tap/select1.test.lua
@@ -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(
@@ -1406,7 +1406,7 @@ test:do_catchsql_test(
         SELECT f1 FROM test1 WHERE f2=;
     ]], {
         -- <select1-7.1>
-        1, [[Syntax error near ';']]
+        1, [[Syntax error at line 1 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, [[At line 1 at or near position 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, [[At line 1 at or near position 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 at line 1 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, [[At line 1 at or near position 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, [[At line 1 at or near position 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 at line 1 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 at line 1 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, [[At line 1 at or near position 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..92e7f8ee2 100755
--- a/test/sql-tap/select3.test.lua
+++ b/test/sql-tap/select3.test.lua
@@ -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, [[At line 1 at or near position 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 at line 1 near ';']]
   -- </select3-2.14>
 })
 
diff --git a/test/sql-tap/sql-errors.test.lua b/test/sql-tap/sql-errors.test.lua
index b16337682..5ec94bfe3 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 at line 1 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,"At line 1 at or near position 76: qualified table names are not allowed on INSERT, UPDATE, and DELETE statements within triggers"
 		-- </sql-errors-1.37>
 	})
 
@@ -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, "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, "At line 1 at or near position 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..6d6b00b26 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 at line 2 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 at line 2 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, "At line 2 at or near position 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, "At line 2 at or near position 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, "At line 2 at or near position 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, "At line 2 at or near position 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, "At line 2 at or near position 13: keyword 'TRANSACTION' is reserved. Please use double quotes if 'TRANSACTION' is an identifier."
 		-- <start-transaction-1.18>
 	})
 
diff --git a/test/sql-tap/table.test.lua b/test/sql-tap/table.test.lua
index e17b4a2c1..1b4ec1173 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 at line 1 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 at line 1 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,"At line 3 at or near position 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,"At line 3 at or near position 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,"At line 3 at or near position 37: keyword 'CONSTRAINT' is reserved. Please use double quotes if 'CONSTRAINT' is an identifier."
         -- </table-22.7>
     })
 
diff --git a/test/sql-tap/tkt3935.test.lua b/test/sql-tap/tkt3935.test.lua
index cc8fea7ab..5b458983a 100755
--- a/test/sql-tap/tkt3935.test.lua
+++ b/test/sql-tap/tkt3935.test.lua
@@ -57,7 +57,7 @@ test:do_catchsql_test(
         SELECT a FROM (t1) AS t ON b USING(a) 
     ]], {
         -- <tkt3935.4>
-        1, "Syntax error in FROM clause: a JOIN clause is required before ON and USING"
+        1, "Syntax error at line 1 at or near position 52: a JOIN clause is required before ON and USING"
         -- </tkt3935.4>
     })
 
@@ -67,7 +67,7 @@ test:do_catchsql_test(
         SELECT a FROM (t1) AS t ON b 
     ]], {
         -- <tkt3935.5>
-        1, "Syntax error in FROM clause: a JOIN clause is required before ON and USING"
+        1, "Syntax error at line 1 at or near position 43: a JOIN clause is required before ON and USING"
         -- </tkt3935.5>
     })
 
@@ -77,7 +77,7 @@ test:do_catchsql_test(
         SELECT a FROM (SELECT * FROM t1) AS t ON b USING(a) 
     ]], {
         -- <tkt3935.6>
-        1, "Syntax error in FROM clause: a JOIN clause is required before ON and USING"
+        1, "Syntax error at line 1 at or near position 66: a JOIN clause is required before ON and USING"
         -- </tkt3935.6>
     })
 
@@ -87,7 +87,7 @@ test:do_catchsql_test(
         SELECT a FROM (SELECT * FROM t1) AS t ON b 
     ]], {
         -- <tkt3935.7>
-        1, "Syntax error in FROM clause: a JOIN clause is required before ON and USING"
+        1, "Syntax error at line 1 at or near position 57: a JOIN clause is required before ON and USING"
         -- </tkt3935.7>
     })
 
@@ -97,7 +97,7 @@ test:do_catchsql_test(
         SELECT a FROM t1 AS t ON b 
     ]], {
         -- <tkt3935.8>
-        1, "Syntax error in FROM clause: a JOIN clause is required before ON and USING"
+        1, "Syntax error at line 1 at or near position 41: a JOIN clause is required before ON and USING"
         -- </tkt3935.8>
     })
 
@@ -107,7 +107,7 @@ test:do_catchsql_test(
         SELECT a FROM t1 AS t ON b USING(a) 
     ]], {
         -- <tkt3935.9>
-        1, "Syntax error in FROM clause: a JOIN clause is required before ON and USING"
+        1, "Syntax error at line 1 at or near position 50: a JOIN clause is required before ON and USING"
         -- </tkt3935.9>
     })
 
@@ -117,7 +117,7 @@ test:do_catchsql_test(
         SELECT a FROM t1 AS t USING(a) 
     ]], {
         -- <tkt3935.10>
-        1, "Syntax error in FROM clause: a JOIN clause is required before ON and USING"
+        1, "Syntax error at line 1 at or near position 45: a JOIN clause is required before ON and USING"
         -- </tkt3935.10>
     })
 
diff --git a/test/sql-tap/tokenize.test.lua b/test/sql-tap/tokenize.test.lua
index b1a097e23..2c0f7e368 100755
--- a/test/sql-tap/tokenize.test.lua
+++ b/test/sql-tap/tokenize.test.lua
@@ -1,6 +1,6 @@
 #!/usr/bin/env tarantool
 test = 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, [[At line 1 at or near position 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, [[At line 1 at or near position 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, [[At line 1 at or near position 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, [[At line 1 at or near position 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, [[At line 1 at or near position 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, [[At line 1 at or near position 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, [[At line 1 at or near position 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, [[At line 1 at or near position 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, [[At line 1 at or near position 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, [[At line 1 at or near position 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, [[At line 1 at or near position 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, [[At line 1 at or near position 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 at line 1 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 at line 2 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..6fd5294b1 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 at line 1 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 at line 3 near ';']]
         -- </trigger1-2.1>
     })
 
@@ -321,7 +321,7 @@ test:do_catchsql_test(
         END;
     ]], {
         -- <trigger1-2.2>
-        1, [[Syntax error near ';']]
+        1, [[Syntax error at line 4 near ';']]
         -- </trigger1-2.2>
     })
 
@@ -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 at line 2 at or near position 34: the NOT INDEXED BY 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 at line 2 at or near position 38: 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 at line 2 at or near position 39: the NOT INDEXED BY 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 at line 2 at or near position 43: the INDEXED BY clause is not allowed on UPDATE or DELETE statements within triggers"
         -- </trigger1-16.7>
     })
 
diff --git a/test/sql-tap/view.test.lua b/test/sql-tap/view.test.lua
index 6234f863e..e553b91c7 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, [[At line 1 at or near position 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..75935108c 100755
--- a/test/sql-tap/with1.test.lua
+++ b/test/sql-tap/with1.test.lua
@@ -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, [[At line 2 at or near position 3: keyword 'SELECT' is reserved. Please use double quotes if 'SELECT' is an identifier.]]
   -- </3.6>
 })
 
diff --git a/test/sql-tap/with2.test.lua b/test/sql-tap/with2.test.lua
index 8c7f9f2d9..1aa39b32e 100755
--- a/test/sql-tap/with2.test.lua
+++ b/test/sql-tap/with2.test.lua
@@ -317,7 +317,7 @@ test:do_catchsql_test(4.1, [[
     SELECT * FROM x;
 ]], {
     -- <4.1>
-    1, [[Syntax error near ')']]
+    1, [[Syntax error at line 1 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 at line 2 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, [[At line 2 at or near position 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, [[At line 2 at or near position 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 at line 2 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 at line 2 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 at line 1 near 'WHRE'"
     -- </6.7>
 })
 
@@ -579,7 +579,7 @@ test:do_catchsql_test(6.8, [[
     WITH x AS (SELECT * FROM t1) UPDATE t2 SET a = 10, b = ;
 ]], {
     -- <6.8>
-    1, "Syntax error near ';'"
+    1, "Syntax error at line 1 near ';'"
     -- </6.8>
 })
 
@@ -587,7 +587,7 @@ test:do_catchsql_test(6.9, [[
     WITH x AS (SELECT * FROM t1) UPDATE t2 SET a = 10, b = 1 WHERE a===b;
 ]], {
     -- <6.9>
-    1, "Syntax error near '='"
+    1, "Syntax error at line 1 near '='"
     -- </6.9>
 })
 
diff --git a/test/sql/checks.result b/test/sql/checks.result
index a952b2b70..dfea8480a 100644
--- a/test/sql/checks.result
+++ b/test/sql/checks.result
@@ -39,8 +39,8 @@ _ = box.space.test:create_index('pk')
 -- Invalid expression test.
 box.space._ck_constraint:insert({513, 'CK_CONSTRAINT_01', false, 'SQL', 'X><5', true})
 ---
-- error: 'Failed to create check constraint ''CK_CONSTRAINT_01'': Syntax error near
-    ''<'''
+- error: 'Failed to create check constraint ''CK_CONSTRAINT_01'': Syntax error at
+    line 1 near ''<'''
 ...
 -- Non-existent space test.
 box.space._ck_constraint:insert({550, 'CK_CONSTRAINT_01', false, 'SQL', 'X<5', true})
@@ -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 at line 1 near '<'
 ...
 box.space.FIRST == 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'': At line 1 at or near position
+  8: 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/collation.result b/test/sql/collation.result
index 11962ef47..cf8ba7657 100644
--- a/test/sql/collation.result
+++ b/test/sql/collation.result
@@ -16,27 +16,27 @@ box.execute('pragma sql_default_engine=\''..engine..'\'')
 box.execute("SELECT 1 LIMIT 1 COLLATE BINARY;")
 ---
 - null
-- Syntax error near 'COLLATE'
+- Syntax error at line 1 near 'COLLATE'
 ...
 box.execute("SELECT 1 LIMIT 1 COLLATE BINARY OFFSET 1;")
 ---
 - null
-- Syntax error near 'COLLATE'
+- Syntax error at line 1 near 'COLLATE'
 ...
 box.execute("SELECT 1 LIMIT 1 OFFSET 1 COLLATE BINARY;")
 ---
 - null
-- Syntax error near 'COLLATE'
+- Syntax error at line 1 near 'COLLATE'
 ...
 box.execute("SELECT 1 LIMIT 1, 1 COLLATE BINARY;")
 ---
 - null
-- Syntax error near 'COLLATE'
+- Syntax error at line 1 near 'COLLATE'
 ...
 box.execute("SELECT 1 LIMIT 1 COLLATE BINARY, 1;")
 ---
 - null
-- Syntax error near 'COLLATE'
+- Syntax error at line 1 near 'COLLATE'
 ...
 -- gh-3052: upper/lower support only default locale
 -- For tr-TR result depends on collation
@@ -147,7 +147,7 @@ cn = remote.connect(box.cfg.listen)
 ...
 cn:execute('select 1 limit ? collate not_exist', {1})
 ---
-- error: Syntax error near 'COLLATE'
+- error: Syntax error at line 1 near 'COLLATE'
 ...
 cn:close()
 ---
diff --git a/test/sql/engine.result b/test/sql/engine.result
index 3ee93ad19..ff8712966 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 = VINYL")
 ---
 - null
-- Syntax error near 'VINYL'
+- Syntax error at line 1 near 'VINYL'
 ...
 box.execute("CREATE TABLE t1_vinyl (id INT PRIMARY KEY) WITH ENGINE = vinyl")
 ---
 - null
-- Syntax error near 'vinyl'
+- Syntax error at line 1 near 'vinyl'
 ...
 box.execute("CREATE TABLE t1_vinyl (id INT PRIMARY KEY) WITH ENGINE = 'VINYL'")
 ---
@@ -119,7 +119,7 @@ box.execute("CREATE TABLE t1_vinyl (id INT PRIMARY KEY) WITH ENGINE = 'VINYL'")
 box.execute("CREATE TABLE t1_vinyl (id INT PRIMARY KEY) WITH ENGINE = \"vinyl\"")
 ---
 - null
-- Syntax error near '"vinyl"'
+- Syntax error at line 1 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..f1d973443 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.
+- 'At line 1 at or near position 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.
+- 'At line 1 at or near position 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.
+- 'At line 1 at or near position 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.
+- 'At line 1 at or near position 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..7f9a0bfab 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=\''..engine..'\'')
 box.execute('VALUES(scalar)')
 ---
 - null
-- Syntax error near 'scalar'
+- Syntax error at line 1 near 'scalar'
 ...
 box.execute('VALUES(float)')
 ---
 - null
-- Syntax error near 'float'
+- Syntax error at line 1 near 'float'
 ...
 -- check 'SELECT' against typedef keywords (should fail)
 box.execute('SELECT scalar')
 ---
 - null
-- Syntax error near 'scalar'
+- Syntax error at line 1 near 'scalar'
 ...
 box.execute('SELECT float')
 ---
 - null
-- Syntax error near 'float'
+- Syntax error at line 1 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..99dc58baf 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 at line 1 near 'qwerty'
 ...
 -- Empty result.
 cn:execute('select id as identifier from test where a = 5;')
@@ -119,7 +119,7 @@ cn:execute('select id as identifier from test where a = 5;')
 -- netbox API errors.
 cn:execute(100)
 ---
-- error: Syntax error near '100'
+- error: Syntax error at line 1 near '100'
 ...
 cn:execute('select 1', nil, {dry_run = true})
 ---
@@ -352,7 +352,7 @@ cn:execute('drop table if exists test3')
 --
 cn:execute('select ?1, ?2, ?3', {1, 2, 3})
 ---
-- error: Syntax error near '?1'
+- error: Syntax error at line 1 near '?1'
 ...
 cn:execute('select $name, $name2', {1, 2})
 ---
diff --git a/test/sql/misc.result b/test/sql/misc.result
index a157ddbc1..1e8d2e20d 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.
+- 'At line 1 at or near position 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.
+- 'At line 1 at or near position 39: keyword ''select'' is reserved. Please use double
+  quotes if ''select'' is an identifier.'
 ...
 box.space.t1 == 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.
+- 'At line 1 at or near position 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.
+- 'At line 1 at or near position 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.
+- 'At line 1 at or near position 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..d5a69388c 100644
--- a/test/sql/on-conflict.result
+++ b/test/sql/on-conflict.result
@@ -15,44 +15,52 @@ box.execute('pragma sql_default_engine=\''..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.
+- 'At line 1 at or near position 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.
+- 'At line 1 at or near position 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.
+- 'At line 1 at or near position 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.
+- 'At line 1 at or near position 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.
+- 'At line 1 at or near position 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.
+- 'At line 1 at or near position 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.
+- 'At line 1 at or near position 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.
+- 'At line 1 at or near position 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..7611ea96a 100644
--- a/test/sql/triggers.result
+++ b/test/sql/triggers.result
@@ -487,14 +487,14 @@ space_id = box.space.T1.id
 box.execute("CREATE TRIGGER tr1 AFTER INSERT ON t1 FOR EACH ROW WHEN new.a = ? BEGIN SELECT 1; END;")
 ---
 - null
-- bindings are not allowed in DDL
+- 'At line 1 at or near position 67: bindings are not allowed in DDL'
 ...
 tuple = {"TR1", space_id, {sql = [[CREATE TRIGGER tr1 AFTER INSERT ON t1 FOR EACH ROW WHEN new.a = ? BEGIN SELECT 1; END;]]}}
 ---
 ...
 box.space._trigger:insert(tuple)
 ---
-- error: bindings are not allowed in DDL
+- error: 'At line 1 at or near position 67: bindings are not allowed in DDL'
 ...
 box.execute("DROP TABLE t1;")
 ---
@@ -513,7 +513,8 @@ space_id = 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
+- 'At line 1 at or near position 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..bac856f79 100644
--- a/test/sql/types.result
+++ b/test/sql/types.result
@@ -9,27 +9,30 @@ test_run = env.new()
 box.execute("CREATE TABLE t1 (id PRIMARY KEY);")
 ---
 - null
-- Keyword 'PRIMARY' is reserved. Please use double quotes if 'PRIMARY' is an identifier.
+- 'At line 1 at or near position 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 at line 1 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.
+- 'At line 1 at or near position 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 at line 1 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.
+- 'At line 1 at or near position 47: keyword ''UNIQUE'' is reserved. Please use double
+  quotes if ''UNIQUE'' is an identifier.'
 ...
 -- gh-3104: real type is stored in space format.
 --
-- 
2.15.1



More information about the Tarantool-patches mailing list