[tarantool-patches] Re: [PATCH v4 8/8] sql: remove sqlErrorMsg()

Mergen Imeev imeevma at tarantool.org
Tue Mar 26 20:52:20 MSK 2019


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

On Tue, Mar 26, 2019 at 04:34:26PM +0300, n.pettik wrote:
> 
> >> @@ -1039,8 +1036,8 @@ resolveCompoundOrderBy(Parse * pParse,    /* Parsing context.  Leave error messages
> >>                        const char *err = "Error at ORDER BY in place %d: "\
> >>                                          "term does not match any column in "\
> >>                                          "the result set";
> >> -                       err = tt_sprintf(err, i + 1);
> >> -                       diag_set(ClientError, ER_SQL_PARSER_GENERIC, err);
> >> +                       diag_set(ClientError, ER_SQL_PARSER_GENERIC,
> >> +                                tt_sprintf(err, i + 1));
> >> 
> >>> @@ -1444,10 +1469,37 @@ resolveSelectStep(Walker * pWalker, Select * p)
> >>>    * number of expressions in the select list.
> >>>    */
> >>>   if (p->pNext && p->pEList->nExpr != p->pNext->pEList->nExpr) {
> >>> -     sqlSelectWrongNumTermsError(pParse, p->pNext);
> >>> +     if (p->pNext->selFlags & SF_Values) {
> >>> +       diag_set(ClientError, ER_SQL_PARSER_GENERIC,
> >>> +          "all VALUES must have the same "\
> >>> +          "number of terms");
> >>> +     } else {
> >>> +       const char *err_msg =
> >>> +         "SELECTs to the left and right of %s "\
> >>> +         "do not have the same number of "\
> >>> +         "result columns";
> >>> +       switch (p->pNext->op) {
> >>> +       case TK_ALL:
> >>> +         err_msg = tt_sprintf(err_msg,
> >>> +                  "UNION ALL");
> >>> +         break;
> >> 
> >> Why don’t use selectOpName?
> >> Like it was in  sqlSelectWrongNumTermsError().
> >> 
> > Function selectOpName defined in different file and is static.
> > I think it isn't worth to share it for one error.
> 
> I believe it is worth doing. For instance, you can return
> sqlSelectWrongNumTermsError() which was placed in select.c
> and called that static func.
> 
Fixed.

> > Diff between versions:
> > 
> > diff --git a/src/box/sql/expr.c b/src/box/sql/expr.c
> > index e26596a..1077285 100644
> > --- a/src/box/sql/expr.c
> > +++ b/src/box/sql/expr.c
> > @@ -666,13 +666,7 @@ codeVectorCompare(Parse * pParse,	/* Code generator context */
> > 	int regRight = 0;
> > 	u8 op = pExpr->op;
> > 	int addrDone = sqlVdbeMakeLabel(v);
> > -
> > -	if (nLeft != sqlExprVectorSize(pRight)) {
> > -		diag_set(ClientError, ER_SQL_PARSER_GENERIC,
> > -			 "row value misused");
> > -		pParse->is_aborted = true;
> > -		return;
> > -	}
> 
> Here the problem is that function is never called in our test suite:
> I placed assert(0); and no one test failed. Please, add at least
> simple tests like SELECT (1, 2) == (1, 2) to make sure that
> codeVectorCompare() can be processed. Tests which you’ve added
> fails before this func is called.
> 
> Added comment:
> 
> diff --git a/src/box/sql/expr.c b/src/box/sql/expr.c
> index 107728590..397f8209c 100644
> --- a/src/box/sql/expr.c
> +++ b/src/box/sql/expr.c
> @@ -666,6 +666,11 @@ codeVectorCompare(Parse * pParse,  /* Code generator context */
>         int regRight = 0;
>         u8 op = pExpr->op;
>         int addrDone = sqlVdbeMakeLabel(v);
> +       /*
> +        * Situation when vectors have different dimensions is
> +        * filtred way before - during expr resolution:
> +        * see resolveExprStep().
> +        */
> 
Added.

> > +	assert(nLeft == sqlExprVectorSize(pRight));
> > 	assert(pExpr->op == TK_EQ || pExpr->op == TK_NE
> > 	       || pExpr->op == TK_LT || pExpr->op == TK_GT
> > 	       || pExpr->op == TK_LE || pExpr->op == TK_GE);
> > 
> > 
> > @@ -4384,10 +4378,8 @@ sqlWhereBegin(Parse * pParse,	/* The parser context */
> > 	 * equal to pTabList->nSrc but might be shortened to 1 if the
> > 	 * WHERE_OR_SUBCLAUSE flag is set.
> > 	 */
> > -	for (ii = 0; ii < pTabList->nSrc; ii++) {
> > +	for (ii = 0; ii < pTabList->nSrc; ii++)
> > 		createMask(pMaskSet, pTabList->a[ii].iCursor);
> > -		sqlWhereTabFuncArgs(pParse, &pTabList->a[ii], &pWInfo->sWC);
> 
> Move removal of this func to a separate patch pls alongside with mentions of
> table-valued funcs. It is not related to errors.
> 
> 
Returned this function, replaced error in it by assert.


Diff:

diff --git a/src/box/sql/expr.c b/src/box/sql/expr.c
index 1077285..80d17d1 100644
--- a/src/box/sql/expr.c
+++ b/src/box/sql/expr.c
@@ -666,6 +666,12 @@ codeVectorCompare(Parse * pParse,	/* Code generator context */
 	int regRight = 0;
 	u8 op = pExpr->op;
 	int addrDone = sqlVdbeMakeLabel(v);
+
+	/*
+	 * Situation when vectors have different dimensions is
+	 * filtred way before - during expr resolution:
+	 * see resolveExprStep().
+	 */
 	assert(nLeft == sqlExprVectorSize(pRight));
 	assert(pExpr->op == TK_EQ || pExpr->op == TK_NE
 	       || pExpr->op == TK_LT || pExpr->op == TK_GT
diff --git a/src/box/sql/resolve.c b/src/box/sql/resolve.c
index c08d934..e4e3697 100644
--- a/src/box/sql/resolve.c
+++ b/src/box/sql/resolve.c
@@ -1459,28 +1459,13 @@ resolveSelectStep(Walker * pWalker, Select * p)
 					 "all VALUES must have the same "\
 					 "number of terms");
 			} else {
-				const char *err_msg =
+				const char *err =
 					"SELECTs to the left and right of %s "\
 					"do not have the same number of "\
 					"result columns";
-				switch (p->pNext->op) {
-				case TK_ALL:
-					err_msg = tt_sprintf(err_msg,
-							     "UNION ALL");
-					break;
-				case TK_INTERSECT:
-					err_msg = tt_sprintf(err_msg,
-							     "INTERSECT");
-					break;
-				case TK_EXCEPT:
-					err_msg = tt_sprintf(err_msg, "EXCEPT");
-					break;
-				default:
-					err_msg = tt_sprintf(err_msg, "UNION");
-					break;
-				}
+				const char *op = select_op_name(p->pNext->op);
 				diag_set(ClientError, ER_SQL_PARSER_GENERIC,
-					 err_msg);
+					 tt_sprintf(err, op));
 			}
 			pParse->is_aborted = true;
 			return WRC_Abort;
diff --git a/src/box/sql/select.c b/src/box/sql/select.c
index e217c19..778de2c 100644
--- a/src/box/sql/select.c
+++ b/src/box/sql/select.c
@@ -1466,25 +1466,25 @@ sql_expr_list_to_key_info(struct Parse *parse, struct ExprList *list, int start)
 /*
  * Name of the connection operator, used for error messages.
  */
-static const char *
-selectOpName(int id)
+const char *
+select_op_name(int op_id)
 {
-	char *z;
-	switch (id) {
+	const char *op_name;
+	switch (op_id) {
 	case TK_ALL:
-		z = "UNION ALL";
+		op_name = "UNION ALL";
 		break;
 	case TK_INTERSECT:
-		z = "INTERSECT";
+		op_name = "INTERSECT";
 		break;
 	case TK_EXCEPT:
-		z = "EXCEPT";
+		op_name = "EXCEPT";
 		break;
 	default:
-		z = "UNION";
+		op_name = "UNION";
 		break;
 	}
-	return z;
+	return op_name;
 }
 
 /*
@@ -1542,7 +1542,7 @@ explainComposite(Parse * pParse,	/* Parse context */
 				   "COMPOUND SUBQUERIES %d AND %d %s(%s)",
 				   iSub1, iSub2,
 				   bUseTmp ? "USING TEMP B-TREE " : "",
-				   selectOpName(op)
+				   select_op_name(op)
 		    );
 		sqlVdbeAddOp4(v, OP_Explain, pParse->iSelectId, 0, 0, zMsg,
 				  P4_DYNAMIC);
@@ -2614,7 +2614,7 @@ multiSelect(Parse * pParse,	/* Parsing context */
 	if (pPrior->pOrderBy) {
 		const char *err_msg =
 			tt_sprintf("ORDER BY clause should come after %s not "\
-				   "before", selectOpName(p->op));
+				   "before", select_op_name(p->op));
 		diag_set(ClientError, ER_SQL_PARSER_GENERIC, err_msg);
 		pParse->is_aborted = true;
 		rc = 1;
@@ -2623,7 +2623,7 @@ multiSelect(Parse * pParse,	/* Parsing context */
 	if (pPrior->pLimit) {
 		const char *err_msg =
 			tt_sprintf("LIMIT clause should come after %s not "\
-				   "before", selectOpName(p->op));
+				   "before", select_op_name(p->op));
 		diag_set(ClientError, ER_SQL_PARSER_GENERIC, err_msg);
 		pParse->is_aborted = true;
 		rc = 1;
diff --git a/src/box/sql/sqlInt.h b/src/box/sql/sqlInt.h
index 15e6f22..50fc812 100644
--- a/src/box/sql/sqlInt.h
+++ b/src/box/sql/sqlInt.h
@@ -4426,6 +4426,15 @@ void sqlExpirePreparedStatements(sql *);
 int sqlCodeSubselect(Parse *, Expr *, int);
 void sqlSelectPrep(Parse *, Select *, NameContext *);
 
+/**
+ * Returns name of the connection operator.
+ *
+ * @param op_id ID of the connection operator.
+ * @retval Name of the connection operator.
+ */
+const char *
+select_op_name(int op_id);
+
 int sqlMatchSpanName(const char *, const char *, const char *);
 int sqlResolveExprNames(NameContext *, Expr *);
 int sqlResolveExprListNames(NameContext *, ExprList *);
diff --git a/src/box/sql/where.c b/src/box/sql/where.c
index c71a170..19ee2d0 100644
--- a/src/box/sql/where.c
+++ b/src/box/sql/where.c
@@ -4378,8 +4378,10 @@ sqlWhereBegin(Parse * pParse,	/* The parser context */
 	 * equal to pTabList->nSrc but might be shortened to 1 if the
 	 * WHERE_OR_SUBCLAUSE flag is set.
 	 */
-	for (ii = 0; ii < pTabList->nSrc; ii++)
+	for (ii = 0; ii < pTabList->nSrc; ii++) {
 		createMask(pMaskSet, pTabList->a[ii].iCursor);
+		sqlWhereTabFuncArgs(pParse, &pTabList->a[ii], &pWInfo->sWC);
+	}
 #ifdef SQL_DEBUG
 	for (ii = 0; ii < pTabList->nSrc; ii++) {
 		Bitmask m =
diff --git a/src/box/sql/whereInt.h b/src/box/sql/whereInt.h
index 9cf1eb8..47430ae 100644
--- a/src/box/sql/whereInt.h
+++ b/src/box/sql/whereInt.h
@@ -479,6 +479,7 @@ void sqlWhereSplit(WhereClause *, Expr *, u8);
 Bitmask sqlWhereExprUsage(WhereMaskSet *, Expr *);
 Bitmask sqlWhereExprListUsage(WhereMaskSet *, ExprList *);
 void sqlWhereExprAnalyze(SrcList *, WhereClause *);
+void sqlWhereTabFuncArgs(Parse *, struct SrcList_item *, WhereClause *);
 
 /*
  * Bitmasks for the operators on WhereTerm objects.  These are all
diff --git a/src/box/sql/whereexpr.c b/src/box/sql/whereexpr.c
index 9d01a7e..ec08889 100644
--- a/src/box/sql/whereexpr.c
+++ b/src/box/sql/whereexpr.c
@@ -1472,3 +1472,45 @@ sqlWhereExprAnalyze(SrcList * pTabList,	/* the FROM clause */
 		exprAnalyze(pTabList, pWC, i);
 	}
 }
+
+/*
+ * For table-valued-functions, transform the function arguments into
+ * new WHERE clause terms.
+ */
+void
+sqlWhereTabFuncArgs(Parse * pParse,	/* Parsing context */
+			struct SrcList_item *pItem,	/* The FROM clause term to process */
+			WhereClause * pWC	/* Xfer function arguments to here */
+    )
+{
+	int j, k;
+	ExprList *pArgs;
+	Expr *pColRef;
+	Expr *pTerm;
+	if (pItem->fg.isTabFunc == 0)
+		return;
+	struct space_def *space_def = pItem->space->def;
+	pArgs = pItem->u1.pFuncArg;
+	if (pArgs == 0)
+		return;
+	for (j = k = 0; j < pArgs->nExpr; j++) {
+		while (k < (int)space_def->field_count)
+			k++;
+		/*
+		 * This assert replaces error. At the moment, this
+		 * error cannot appear due to this function being
+		 * unused.
+		 */
+		assert(k < (int)space_def->field_count);
+		pColRef = sqlExprAlloc(pParse->db, TK_COLUMN, 0, 0);
+		if (pColRef == 0)
+			return;
+		pColRef->iTable = pItem->iCursor;
+		pColRef->iColumn = k++;
+		pColRef->space_def = space_def;
+		pTerm = sqlPExpr(pParse, TK_EQ, pColRef,
+				     sqlExprDup(pParse->db,
+						    pArgs->a[j].pExpr, 0));
+		whereClauseInsert(pWC, pTerm, TERM_DYNAMIC);
+	}
+}
diff --git a/test/sql-tap/sql-errors.test.lua b/test/sql-tap/sql-errors.test.lua
index a132139..5585dbb 100755
--- a/test/sql-tap/sql-errors.test.lua
+++ b/test/sql-tap/sql-errors.test.lua
@@ -1,6 +1,6 @@
 #!/usr/bin/env tarantool
 test = require("sqltester")
-test:plan(43)
+test:plan(45)
 
 test:execsql([[
 	CREATE TABLE t0 (i INT PRIMARY KEY, a INT);
@@ -486,4 +486,24 @@ test:do_catchsql_test(
 		-- </sql-errors-1.43>
 	})
 
+test:do_execsql_test(
+	"sql-errors-1.44",
+	[[
+		SELECT (1, 2, 3) < (1, 2, 4);
+	]], {
+		-- <sql-errors-1.44>
+		1
+		-- </sql-errors-1.44>
+	})
+
+test:do_execsql_test(
+	"sql-errors-1.45",
+	[[
+		SELECT (1, 2, 3) < (1, 2, 2);
+	]], {
+		-- <sql-errors-1.45>
+		0
+		-- </sql-errors-1.45>
+	})
+
 test:finish_test()


New patch:

commit 43d2787aeec1eb133e0261308d4b6242fe220833
Author: Mergen Imeev <imeevma at gmail.com>
Date:   Sat Mar 9 18:54:19 2019 +0300

    sql: remove sqlErrorMsg()
    
    This patch completely replaces sqlErrorMsg() with diag_set() and
    removes sqlErrorMsg().
    
    Closes #3965
    Closes #3036

diff --git a/src/box/sql/build.c b/src/box/sql/build.c
index fe53262..39c86bc 100644
--- a/src/box/sql/build.c
+++ b/src/box/sql/build.c
@@ -499,13 +499,12 @@ sql_column_add_nullable_action(struct Parse *parser,
 	if (field->nullable_action != ON_CONFLICT_ACTION_DEFAULT &&
 	    nullable_action != field->nullable_action) {
 		/* Prevent defining nullable_action many times. */
-		const char *err_msg =
-			tt_sprintf("NULL declaration for column '%s' of table "
-				   "'%s' has been already set to '%s'",
-				   field->name, def->name,
-				   on_conflict_action_strs[field->
-							   nullable_action]);
-		diag_set(ClientError, ER_SQL, err_msg);
+		const char *err = "NULL declaration for column '%s' of table "
+				  "'%s' has been already set to '%s'";
+		const char *action =
+			on_conflict_action_strs[field->nullable_action];
+		err = tt_sprintf(err, field->name, def->name, action);
+		diag_set(ClientError, ER_SQL, err);
 		parser->is_aborted = true;
 		return;
 	}
@@ -3057,11 +3056,12 @@ sqlWithAdd(Parse * pParse,	/* Parsing context */
 	zName = sqlNameFromToken(pParse->db, pName);
 	if (zName && pWith) {
 		int i;
+		const char *err = "Ambiguous table name in WITH query: %s";
 		for (i = 0; i < pWith->nCte; i++) {
 			if (strcmp(zName, pWith->a[i].zName) == 0) {
-				sqlErrorMsg(pParse,
-						"duplicate WITH table name: %s",
-						zName);
+				diag_set(ClientError, ER_SQL_PARSER_GENERIC,
+					 tt_sprintf(err, zName));
+				pParse->is_aborted = true;
 			}
 		}
 	}
diff --git a/src/box/sql/delete.c b/src/box/sql/delete.c
index 0eb28d7..f536bb8 100644
--- a/src/box/sql/delete.c
+++ b/src/box/sql/delete.c
@@ -102,10 +102,10 @@ sql_table_truncate(struct Parse *parse, struct SrcList *tab_list)
 		goto tarantool_error;
 	}
 	if (! rlist_empty(&space->parent_fk_constraint)) {
-		const char *err_msg =
-			tt_sprintf("can not truncate space '%s' because other "
-				   "objects depend on it", space->def->name);
-		diag_set(ClientError, ER_SQL, err_msg);
+		const char *err = "can not truncate space '%s' because other "
+				  "objects depend on it";
+		diag_set(ClientError, ER_SQL,
+			 tt_sprintf(err, space->def->name));
 		goto tarantool_error;
 	}
 	if (space->def->opts.is_view) {
diff --git a/src/box/sql/expr.c b/src/box/sql/expr.c
index de993c1..80d17d1 100644
--- a/src/box/sql/expr.c
+++ b/src/box/sql/expr.c
@@ -667,10 +667,12 @@ codeVectorCompare(Parse * pParse,	/* Code generator context */
 	u8 op = pExpr->op;
 	int addrDone = sqlVdbeMakeLabel(v);
 
-	if (nLeft != sqlExprVectorSize(pRight)) {
-		sqlErrorMsg(pParse, "row value misused");
-		return;
-	}
+	/*
+	 * Situation when vectors have different dimensions is
+	 * filtred way before - during expr resolution:
+	 * see resolveExprStep().
+	 */
+	assert(nLeft == sqlExprVectorSize(pRight));
 	assert(pExpr->op == TK_EQ || pExpr->op == TK_NE
 	       || pExpr->op == TK_LT || pExpr->op == TK_GT
 	       || pExpr->op == TK_LE || pExpr->op == TK_GE);
@@ -1201,7 +1203,14 @@ sqlExprAssignVarNumber(Parse * pParse, Expr * pExpr, u32 n)
 			testcase(i == 1);
 			testcase(i == SQL_BIND_PARAMETER_MAX - 1);
 			testcase(i == SQL_BIND_PARAMETER_MAX);
-			if (!is_ok || i < 1 || i > SQL_BIND_PARAMETER_MAX) {
+			if (i < 1) {
+				diag_set(ClientError, ER_SQL_PARSER_GENERIC,
+					 "Index of binding slots must start "\
+					 "from 1");
+				pParse->is_aborted = true;
+				return;
+			}
+			if (!is_ok || i > SQL_BIND_PARAMETER_MAX) {
 				diag_set(ClientError, ER_SQL_BIND_PARAMETER_MAX,
 					 SQL_BIND_PARAMETER_MAX);
 				pParse->is_aborted = true;
@@ -1785,8 +1794,10 @@ sqlExprListAppendVector(Parse * pParse,	/* Parsing context */
 	 */
 	if (pExpr->op != TK_SELECT
 	    && pColumns->nId != (n = sqlExprVectorSize(pExpr))) {
-		sqlErrorMsg(pParse, "%d columns assigned %d values",
-				pColumns->nId, n);
+		const char *err = tt_sprintf("%d columns assigned %d values",
+					     pColumns->nId, n);
+		diag_set(ClientError, ER_SQL_PARSER_GENERIC, err);
+		pParse->is_aborted = true;
 		goto vector_append_error;
 	}
 
@@ -2669,41 +2680,6 @@ expr_in_type(Parse *pParse, Expr *pExpr)
 }
 
 /*
- * Load the Parse object passed as the first argument with an error
- * message of the form:
- *
- *   "sub-select returns N columns - expected M"
- */
-void
-sqlSubselectError(Parse * pParse, int nActual, int nExpect)
-{
-	const char *zFmt = "sub-select returns %d columns - expected %d";
-	sqlErrorMsg(pParse, zFmt, nActual, nExpect);
-}
-
-/*
- * Expression pExpr is a vector that has been used in a context where
- * it is not permitted. If pExpr is a sub-select vector, this routine
- * loads the Parse object with a message of the form:
- *
- *   "sub-select returns N columns - expected 1"
- *
- * Or, if it is a regular scalar vector:
- *
- *   "row value misused"
- */
-void
-sqlVectorErrorMsg(Parse * pParse, Expr * pExpr)
-{
-	if (pExpr->flags & EP_xIsSelect) {
-		sqlSubselectError(pParse, pExpr->x.pSelect->pEList->nExpr,
-				      1);
-	} else {
-		sqlErrorMsg(pParse, "row value misused");
-	}
-}
-
-/*
  * Generate code for scalar subqueries used as a subquery expression, EXISTS,
  * or IN operators.  Examples:
  *
@@ -2984,15 +2960,23 @@ int
 sqlExprCheckIN(Parse * pParse, Expr * pIn)
 {
 	int nVector = sqlExprVectorSize(pIn->pLeft);
+	const char *err;
 	if ((pIn->flags & EP_xIsSelect)) {
 		if (nVector != pIn->x.pSelect->pEList->nExpr) {
-			sqlSubselectError(pParse,
-					      pIn->x.pSelect->pEList->nExpr,
-					      nVector);
+			err = "sub-select returns %d columns - expected %d";
+			int expr_count = pIn->x.pSelect->pEList->nExpr;
+			diag_set(ClientError, ER_SQL_PARSER_GENERIC,
+				 tt_sprintf(err, expr_count, nVector));
+			pParse->is_aborted = true;
 			return 1;
 		}
 	} else if (nVector != 1) {
-		sqlVectorErrorMsg(pParse, pIn->pLeft);
+		assert((pIn->pLeft->flags & EP_xIsSelect) != 0);
+		int expr_count = pIn->pLeft->x.pSelect->pEList->nExpr;
+		err = tt_sprintf("sub-select returns %d columns - expected 1",
+				 expr_count);
+		diag_set(ClientError, ER_SQL_PARSER_GENERIC, err);
+		pParse->is_aborted = true;
 		return 1;
 	}
 	return 0;
@@ -3990,9 +3974,10 @@ sqlExprCodeTarget(Parse * pParse, Expr * pExpr, int target)
 			AggInfo *pInfo = pExpr->pAggInfo;
 			if (pInfo == 0) {
 				assert(!ExprHasProperty(pExpr, EP_IntValue));
-				sqlErrorMsg(pParse,
-						"misuse of aggregate: %s()",
-						pExpr->u.zToken);
+				const char *err = "misuse of aggregate: %s()";
+				diag_set(ClientError, ER_SQL_PARSER_GENERIC,
+					 tt_sprintf(err, pExpr->u.zToken));
+				pParse->is_aborted = true;
 			} else {
 				pExpr->type = pInfo->aFunc->pFunc->ret_type;
 				return pInfo->aFunc[pExpr->iAgg].iMem;
@@ -4159,7 +4144,11 @@ sqlExprCodeTarget(Parse * pParse, Expr * pExpr, int target)
 			testcase(op == TK_SELECT);
 			if (op == TK_SELECT
 			    && (nCol = pExpr->x.pSelect->pEList->nExpr) != 1) {
-				sqlSubselectError(pParse, nCol, 1);
+				const char *err = "sub-select returns %d "\
+						  "columns - expected 1";
+				diag_set(ClientError, ER_SQL_PARSER_GENERIC,
+					 tt_sprintf(err, nCol));
+				pParse->is_aborted = true;
 			} else {
 				return sqlCodeSubselect(pParse, pExpr, 0);
 			}
@@ -4178,9 +4167,11 @@ sqlExprCodeTarget(Parse * pParse, Expr * pExpr, int target)
 						 sqlExprVectorSize(pExpr->
 								       pLeft))
 			    ) {
-				sqlErrorMsg(pParse,
-						"%d columns assigned %d values",
-						pExpr->iTable, n);
+				const char *err =
+					"%d columns assigned %d values";
+				diag_set(ClientError, ER_SQL_PARSER_GENERIC,
+					 tt_sprintf(err, pExpr->iTable, n));
+				pParse->is_aborted = true;
 			}
 			return pExpr->pLeft->iTable + pExpr->iColumn;
 		}
@@ -4279,7 +4270,9 @@ sqlExprCodeTarget(Parse * pParse, Expr * pExpr, int target)
 		}
 
 	case TK_VECTOR:{
-			sqlErrorMsg(pParse, "row value misused");
+			diag_set(ClientError, ER_SQL_PARSER_GENERIC,
+				 "row value misused");
+			pParse->is_aborted = true;
 			break;
 		}
 
@@ -4379,8 +4372,9 @@ sqlExprCodeTarget(Parse * pParse, Expr * pExpr, int target)
 		}
 	case TK_RAISE:
 		if (pParse->triggered_space == NULL) {
-			sqlErrorMsg(pParse, "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 = true;
 			return 0;
 		}
 		if (pExpr->on_conflict_action == ON_CONFLICT_ACTION_ABORT)
diff --git a/src/box/sql/insert.c b/src/box/sql/insert.c
index 0ca38ae..7e98f42 100644
--- a/src/box/sql/insert.c
+++ b/src/box/sql/insert.c
@@ -396,10 +396,11 @@ sqlInsert(Parse * pParse,	/* Parser context */
 				goto insert_cleanup;
 			}
 			if (bit_test(used_columns, j)) {
-				const char *err;
-				err = "table id list: duplicate column name %s";
-				sqlErrorMsg(pParse,
-						err, pColumn->a[i].zName);
+				const char *err = "table id list: duplicate "\
+						  "column name %s";
+				diag_set(ClientError, ER_SQL_PARSER_GENERIC,
+					 tt_sprintf(err, pColumn->a[i].zName));
+				pParse->is_aborted = true;
 				goto insert_cleanup;
 			}
 			bit_set(used_columns, j);
@@ -510,14 +511,19 @@ sqlInsert(Parse * pParse,	/* Parser context */
 
 	if (pColumn == NULL && nColumn != 0 &&
 	    nColumn != (int)space_def->field_count) {
-		sqlErrorMsg(pParse,
-				"table %S has %d columns but %d values were supplied",
-				pTabList, 0, space_def->field_count, nColumn);
+		const char *err =
+			"table %s has %d columns but %d values were supplied";
+		err = tt_sprintf(err, pTabList->a[0].zName,
+				 space_def->field_count, nColumn);
+		diag_set(ClientError, ER_SQL_PARSER_GENERIC, err);
+		pParse->is_aborted = true;
 		goto insert_cleanup;
 	}
 	if (pColumn != 0 && nColumn != pColumn->nId) {
-		sqlErrorMsg(pParse, "%d values for %d columns", nColumn,
-				pColumn->nId);
+		const char *err = "%d values for %d columns";
+		diag_set(ClientError, ER_SQL_PARSER_GENERIC,
+			 tt_sprintf(err, nColumn, pColumn->nId));
+		pParse->is_aborted = true;
 		goto insert_cleanup;
 	}
 
diff --git a/src/box/sql/parse.y b/src/box/sql/parse.y
index a141065..d2614d9 100644
--- a/src/box/sql/parse.y
+++ b/src/box/sql/parse.y
@@ -904,7 +904,9 @@ expr(A) ::= VARIABLE(X).     {
   Token t = X;
   if (pParse->parse_only) {
     spanSet(&A, &t, &t);
-    sqlErrorMsg(pParse, "bindings are not allowed in DDL");
+    diag_set(ClientError, ER_SQL_PARSER_GENERIC,
+             "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;
@@ -1390,9 +1392,9 @@ trigger_cmd_list(A) ::= trigger_cmd(A) SEMI. {
 trnm(A) ::= nm(A).
 trnm(A) ::= nm DOT nm(X). {
   A = X;
-  sqlErrorMsg(pParse,
-        "qualified table names are not allowed on INSERT, UPDATE, and DELETE "
-        "statements within triggers");
+  diag_set(ClientError, ER_SQL_PARSER_GENERIC, "qualified table names are not "\
+           "allowed on INSERT, UPDATE, and DELETE statements within triggers");
+  pParse->is_aborted = true;
 }
 
 // Disallow the INDEX BY and NOT INDEXED clauses on UPDATE and DELETE
diff --git a/src/box/sql/resolve.c b/src/box/sql/resolve.c
index 30a6b5f..e4e3697 100644
--- a/src/box/sql/resolve.c
+++ b/src/box/sql/resolve.c
@@ -390,16 +390,21 @@ lookupName(Parse * pParse,	/* The parsing context */
 					assert(pExpr->x.pList == 0);
 					assert(pExpr->x.pSelect == 0);
 					pOrig = pEList->a[j].pExpr;
+					const char *err = "misuse of aliased "\
+							  "aggregate %s";
 					if ((pNC->ncFlags & NC_AllowAgg) == 0
 					    && ExprHasProperty(pOrig, EP_Agg)) {
-						sqlErrorMsg(pParse,
-								"misuse of aliased aggregate %s",
-								zAs);
+						diag_set(ClientError,
+							 ER_SQL_PARSER_GENERIC,
+							 tt_sprintf(err, zAs));
+						pParse->is_aborted = true;
 						return WRC_Abort;
 					}
 					if (sqlExprVectorSize(pOrig) != 1) {
-						sqlErrorMsg(pParse,
-								"row value misused");
+						diag_set(ClientError,
+							 ER_SQL_PARSER_GENERIC,
+							 "row value misused");
+						pParse->is_aborted = true;
 						return WRC_Abort;
 					}
 					resolveAlias(pParse, pEList, j, pExpr,
@@ -426,12 +431,15 @@ lookupName(Parse * pParse,	/* The parsing context */
 	 * more matches.  Either way, we have an error.
 	 */
 	if (cnt > 1) {
+		const char *err;
 		if (zTab) {
-			sqlErrorMsg(pParse, "ambiguous column name: %s.%s",
-				    zTab, zCol);
+			err = tt_sprintf("ambiguous column name: %s.%s", zTab,
+					 zCol);
 		} else {
-			sqlErrorMsg(pParse, "ambiguous column name: %s", zCol);
+			err = tt_sprintf("ambiguous column name: %s", zCol);
 		}
+		diag_set(ClientError, ER_SQL_PARSER_GENERIC, err);
+		pParse->is_aborted = true;
 		pTopNC->nErr++;
 	}
 	if (cnt == 0) {
@@ -626,7 +634,7 @@ resolveExprStep(Walker * pWalker, Expr * pExpr)
 			} else {
 				is_agg = pDef->xFinalize != 0;
 				pExpr->type = pDef->ret_type;
-				const char *err_msg =
+				const char *err =
 					"second argument to likelihood() must "\
 					"be a constant between 0.0 and 1.0";
 				if (pDef->funcFlags & SQL_FUNC_UNLIKELY) {
@@ -639,7 +647,7 @@ resolveExprStep(Walker * pWalker, Expr * pExpr)
 						if (pExpr->iTable < 0) {
 							diag_set(ClientError,
 								 ER_ILLEGAL_PARAMS,
-								 err_msg);
+								 err);
 							pParse->is_aborted =
 								true;
 							pNC->nErr++;
@@ -679,9 +687,11 @@ resolveExprStep(Walker * pWalker, Expr * pExpr)
 				}
 			}
 			if (is_agg && (pNC->ncFlags & NC_AllowAgg) == 0) {
-				sqlErrorMsg(pParse,
-						"misuse of aggregate function %.*s()",
-						nId, zId);
+				const char *err =
+					tt_sprintf("misuse of aggregate "\
+						   "function %.*s()", nId, zId);
+				diag_set(ClientError, ER_SQL_PARSER_GENERIC, err);
+				pParse->is_aborted = true;
 				pNC->nErr++;
 				is_agg = 0;
 			} else if (no_such_func && pParse->db->init.busy == 0
@@ -693,9 +703,11 @@ resolveExprStep(Walker * pWalker, Expr * pExpr)
 				pParse->is_aborted = true;
 				pNC->nErr++;
 			} else if (wrong_num_args) {
-				sqlErrorMsg(pParse,
-						"wrong number of arguments to function %.*s()",
-						nId, zId);
+				const char *err = "wrong number of arguments "\
+						  "to function %.*s()";
+				diag_set(ClientError, ER_SQL_PARSER_GENERIC,
+					 tt_sprintf(err, nId, zId));
+				pParse->is_aborted = true;
 				pNC->nErr++;
 			}
 			if (is_agg)
@@ -796,7 +808,9 @@ resolveExprStep(Walker * pWalker, Expr * pExpr)
 				testcase(pExpr->op == TK_GT);
 				testcase(pExpr->op == TK_GE);
 				testcase(pExpr->op == TK_BETWEEN);
-				sqlErrorMsg(pParse, "row value misused");
+				diag_set(ClientError, ER_SQL_PARSER_GENERIC,
+					 "row value misused");
+				pParse->is_aborted = true;
 			}
 			break;
 		}
@@ -898,21 +912,6 @@ resolveOrderByTermToExprList(Parse * pParse,	/* Parsing context for error messag
 }
 
 /*
- * Generate an ORDER BY or GROUP BY term out-of-range error.
- */
-static void
-resolveOutOfRangeError(Parse * pParse,	/* The error context into which to write the error */
-		       const char *zType,	/* "ORDER" or "GROUP" */
-		       int i,	/* The index (1-based) of the term out of range */
-		       int mx	/* Largest permissible value of i */
-    )
-{
-	sqlErrorMsg(pParse,
-			"%r %s BY term out of range - should be "
-			"between 1 and %d", i, zType, mx);
-}
-
-/*
  * Analyze the ORDER BY clause in a compound SELECT statement.   Modify
  * each term of the ORDER BY clause is a constant integer between 1
  * and N where N is the number of columns in the compound SELECT.
@@ -973,9 +972,15 @@ resolveCompoundOrderBy(Parse * pParse,	/* Parsing context.  Leave error messages
 			pE = sqlExprSkipCollate(pItem->pExpr);
 			if (sqlExprIsInteger(pE, &iCol)) {
 				if (iCol <= 0 || iCol > pEList->nExpr) {
-					resolveOutOfRangeError(pParse, "ORDER",
-							       i + 1,
-							       pEList->nExpr);
+					const char *err =
+						"Error at ORDER BY in place "\
+						"%d: term out of range - "\
+						"should be between 1 and %d";
+					err = tt_sprintf(err, i + 1,
+							 pEList->nExpr);
+					diag_set(ClientError,
+						 ER_SQL_PARSER_GENERIC, err);
+					pParse->is_aborted = true;
 					return 1;
 				}
 			} else {
@@ -1021,9 +1026,12 @@ resolveCompoundOrderBy(Parse * pParse,	/* Parsing context.  Leave error messages
 	}
 	for (i = 0; i < pOrderBy->nExpr; i++) {
 		if (pOrderBy->a[i].done == 0) {
-			sqlErrorMsg(pParse,
-					"%r ORDER BY term does not match any "
-					"column in the result set", i + 1);
+			const char *err = "Error at ORDER BY in place %d: "\
+					  "term does not match any column in "\
+					  "the result set";
+			diag_set(ClientError, ER_SQL_PARSER_GENERIC,
+				 tt_sprintf(err, i + 1));
+			pParse->is_aborted = true;
 			return 1;
 		}
 	}
@@ -1071,8 +1079,14 @@ sqlResolveOrderGroupBy(Parse * pParse,	/* Parsing context.  Leave error messages
 	for (i = 0, pItem = pOrderBy->a; i < pOrderBy->nExpr; i++, pItem++) {
 		if (pItem->u.x.iOrderByCol) {
 			if (pItem->u.x.iOrderByCol > pEList->nExpr) {
-				resolveOutOfRangeError(pParse, zType, i + 1,
-						       pEList->nExpr);
+				const char *err = "Error at %s BY in place "\
+						  "%d: term out of range - "\
+						  "should be between 1 and %d";
+				err = tt_sprintf(err, zType, i + 1,
+						 pEList->nExpr);
+				diag_set(ClientError, ER_SQL_PARSER_GENERIC,
+					 err);
+				pParse->is_aborted = true;
 				return 1;
 			}
 			resolveAlias(pParse, pEList, pItem->u.x.iOrderByCol - 1,
@@ -1136,8 +1150,13 @@ 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) {
-				resolveOutOfRangeError(pParse, zType, i + 1,
-						       nResult);
+				const char *err = "Error at %s BY in place "\
+						  "%d: term out of range - "\
+						  "should be between 1 and %d";
+				err = tt_sprintf(err, zType, i + 1, nResult);
+				diag_set(ClientError, ER_SQL_PARSER_GENERIC,
+					 err);
+				pParse->is_aborted = true;
 				return 1;
 			}
 			pItem->u.x.iOrderByCol = (u16) iCol;
@@ -1417,12 +1436,15 @@ resolveSelectStep(Walker * pWalker, Select * p)
 			    || db->mallocFailed) {
 				return WRC_Abort;
 			}
+			const char *err_msg = "aggregate functions are not "\
+					      "allowed in the GROUP BY clause";
 			for (i = 0, pItem = pGroupBy->a; i < pGroupBy->nExpr;
 			     i++, pItem++) {
 				if (ExprHasProperty(pItem->pExpr, EP_Agg)) {
-					sqlErrorMsg(pParse,
-							"aggregate functions are not allowed in "
-							"the GROUP BY clause");
+					diag_set(ClientError,
+						 ER_SQL_PARSER_GENERIC,
+						 err_msg);
+					pParse->is_aborted = true;
 					return WRC_Abort;
 				}
 			}
@@ -1432,10 +1454,22 @@ resolveSelectStep(Walker * pWalker, Select * p)
 		 * number of expressions in the select list.
 		 */
 		if (p->pNext && p->pEList->nExpr != p->pNext->pEList->nExpr) {
-			sqlSelectWrongNumTermsError(pParse, p->pNext);
+			if (p->pNext->selFlags & SF_Values) {
+				diag_set(ClientError, ER_SQL_PARSER_GENERIC,
+					 "all VALUES must have the same "\
+					 "number of terms");
+			} else {
+				const char *err =
+					"SELECTs to the left and right of %s "\
+					"do not have the same number of "\
+					"result columns";
+				const char *op = select_op_name(p->pNext->op);
+				diag_set(ClientError, ER_SQL_PARSER_GENERIC,
+					 tt_sprintf(err, op));
+			}
+			pParse->is_aborted = true;
 			return WRC_Abort;
 		}
-
 		/* Advance to the next term of the compound
 		 */
 		p = p->pPrior;
diff --git a/src/box/sql/select.c b/src/box/sql/select.c
index 23c9499..778de2c 100644
--- a/src/box/sql/select.c
+++ b/src/box/sql/select.c
@@ -397,13 +397,19 @@ sqlJoinType(Parse * pParse, Token * pA, Token * pB, Token * pC)
 	}
 	if ((jointype & (JT_INNER | JT_OUTER)) == (JT_INNER | JT_OUTER) ||
 	    (jointype & JT_ERROR) != 0) {
-		const char *zSp = " ";
 		assert(pB != 0);
-		if (pC == 0) {
-			zSp++;
+		const char *err;
+		if (pC == NULL) {
+			err = tt_sprintf("unknown or unsupported join type: "\
+					 "%.*s %.*s", pA->n, pA->z, pB->n,
+					 pB->z);
+		} else {
+			err = tt_sprintf("unknown or unsupported join type: "\
+					 "%.*s %.*s %.*s", pA->n, pA->z, pB->n,
+					 pB->z, pC->n, pC->z);
 		}
-		sqlErrorMsg(pParse, "unknown or unsupported join type: "
-				"%T %T%s%T", pA, pB, zSp, pC);
+		diag_set(ClientError, ER_SQL_PARSER_GENERIC, err);
+		pParse->is_aborted = true;
 		jointype = JT_INNER;
 	} else if ((jointype & JT_OUTER) != 0
 		   && (jointype & (JT_LEFT | JT_RIGHT)) != JT_LEFT) {
@@ -590,9 +596,10 @@ sqlProcessJoin(Parse * pParse, Select * p)
 		 */
 		if (pRight->fg.jointype & JT_NATURAL) {
 			if (pRight->pOn || pRight->pUsing) {
-				sqlErrorMsg(pParse,
-						"a NATURAL join may not have "
-						"an ON or USING clause", 0);
+				diag_set(ClientError, ER_SQL_PARSER_GENERIC,
+					 "a NATURAL join may not have "
+					 "an ON or USING clause");
+				pParse->is_aborted = true;
 				return 1;
 			}
 			for (j = 0; j < (int)right_space->def->field_count; j++) {
@@ -613,8 +620,10 @@ sqlProcessJoin(Parse * pParse, Select * p)
 		/* Disallow both ON and USING clauses in the same join
 		 */
 		if (pRight->pOn && pRight->pUsing) {
-			sqlErrorMsg(pParse, "cannot have both ON and USING "
-					"clauses in the same join");
+			diag_set(ClientError, ER_SQL_PARSER_GENERIC,
+				 "cannot have both ON and USING clauses in "\
+				 "the same join");
+			pParse->is_aborted = true;
 			return 1;
 		}
 
@@ -637,6 +646,8 @@ sqlProcessJoin(Parse * pParse, Select * p)
 		 * not contained in both tables to be joined.
 		 */
 		if (pRight->pUsing) {
+			const char *err = "cannot join using column %s - "\
+					  "column not present in both tables";
 			IdList *pList = pRight->pUsing;
 			for (j = 0; j < pList->nId; j++) {
 				char *zName;	/* Name of the term in the USING clause */
@@ -650,10 +661,10 @@ sqlProcessJoin(Parse * pParse, Select * p)
 				    || !tableAndColumnIndex(pSrc, i + 1, zName,
 							    &iLeft, &iLeftCol)
 				    ) {
-					sqlErrorMsg(pParse,
-							"cannot join using column %s - column "
-							"not present in both tables",
-							zName);
+					err = tt_sprintf(err, zName);
+					diag_set(ClientError,
+						 ER_SQL_PARSER_GENERIC, err);
+					pParse->is_aborted = true;
 					return 1;
 				}
 				addWhereTerm(pParse, pSrc, iLeft, iLeftCol,
@@ -1455,25 +1466,25 @@ sql_expr_list_to_key_info(struct Parse *parse, struct ExprList *list, int start)
 /*
  * Name of the connection operator, used for error messages.
  */
-static const char *
-selectOpName(int id)
+const char *
+select_op_name(int op_id)
 {
-	char *z;
-	switch (id) {
+	const char *op_name;
+	switch (op_id) {
 	case TK_ALL:
-		z = "UNION ALL";
+		op_name = "UNION ALL";
 		break;
 	case TK_INTERSECT:
-		z = "INTERSECT";
+		op_name = "INTERSECT";
 		break;
 	case TK_EXCEPT:
-		z = "EXCEPT";
+		op_name = "EXCEPT";
 		break;
 	default:
-		z = "UNION";
+		op_name = "UNION";
 		break;
 	}
-	return z;
+	return op_name;
 }
 
 /*
@@ -1531,7 +1542,7 @@ explainComposite(Parse * pParse,	/* Parse context */
 				   "COMPOUND SUBQUERIES %d AND %d %s(%s)",
 				   iSub1, iSub2,
 				   bUseTmp ? "USING TEMP B-TREE " : "",
-				   selectOpName(op)
+				   select_op_name(op)
 		    );
 		sqlVdbeAddOp4(v, OP_Explain, pParse->iSelectId, 0, 0, zMsg,
 				  P4_DYNAMIC);
@@ -2601,16 +2612,20 @@ multiSelect(Parse * pParse,	/* Parsing context */
 	pPrior = p->pPrior;
 	dest = *pDest;
 	if (pPrior->pOrderBy) {
-		sqlErrorMsg(pParse,
-				"ORDER BY clause should come after %s not before",
-				selectOpName(p->op));
+		const char *err_msg =
+			tt_sprintf("ORDER BY clause should come after %s not "\
+				   "before", select_op_name(p->op));
+		diag_set(ClientError, ER_SQL_PARSER_GENERIC, err_msg);
+		pParse->is_aborted = true;
 		rc = 1;
 		goto multi_select_end;
 	}
 	if (pPrior->pLimit) {
-		sqlErrorMsg(pParse,
-				"LIMIT clause should come after %s not before",
-				selectOpName(p->op));
+		const char *err_msg =
+			tt_sprintf("LIMIT clause should come after %s not "\
+				   "before", select_op_name(p->op));
+		diag_set(ClientError, ER_SQL_PARSER_GENERIC, err_msg);
+		pParse->is_aborted = true;
 		rc = 1;
 		goto multi_select_end;
 	}
@@ -2988,19 +3003,6 @@ multiSelect(Parse * pParse,	/* Parsing context */
 }
 #endif				/* SQL_OMIT_COMPOUND_SELECT */
 
-void
-sqlSelectWrongNumTermsError(struct Parse *parse, struct Select * p)
-{
-	if (p->selFlags & SF_Values) {
-		sqlErrorMsg(parse, "all VALUES must have the same number "\
-				"of terms");
-	} else {
-		sqlErrorMsg(parse, "SELECTs to the left and right of %s "
-				"do not have the same number of result columns",
-				selectOpName(p->op));
-	}
-}
-
 /**
  * Code an output subroutine for a coroutine implementation of a
  * SELECT statment.
@@ -3624,7 +3626,14 @@ substExpr(Parse * pParse,	/* Report errors here */
 			assert(pEList != 0 && pExpr->iColumn < pEList->nExpr);
 			assert(pExpr->pLeft == 0 && pExpr->pRight == 0);
 			if (sqlExprIsVector(pCopy)) {
-				sqlVectorErrorMsg(pParse, pCopy);
+				assert((pCopy->flags & EP_xIsSelect) != 0);
+				const char *err = "sub-select returns %d "\
+						  "columns - expected 1";
+				int expr_count =
+					pCopy->x.pSelect->pEList->nExpr;
+				diag_set(ClientError, ER_SQL_PARSER_GENERIC,
+					 tt_sprintf(err, expr_count));
+				pParse->is_aborted = true;
 			} else {
 				pNew = sqlExprDup(db, pCopy, 0);
 				if (pNew && (pExpr->flags & EP_FromJoin)) {
@@ -4520,21 +4529,6 @@ convertCompoundSelectToSubquery(Walker * pWalker, Select * p)
 	return WRC_Continue;
 }
 
-/*
- * Check to see if the FROM clause term pFrom has table-valued function
- * arguments.  If it does, leave an error message in pParse and return
- * non-zero, since pFrom is not allowed to be a table-valued function.
- */
-static int
-cannotBeFunction(Parse * pParse, struct SrcList_item *pFrom)
-{
-	if (pFrom->fg.isTabFunc) {
-		sqlErrorMsg(pParse, "'%s' is not a function", pFrom->zName);
-		return 1;
-	}
-	return 0;
-}
-
 #ifndef SQL_OMIT_CTE
 /*
  * Argument pWith (which may be NULL) points to a linked list of nested
@@ -4629,11 +4623,18 @@ withExpand(Walker * pWalker, struct SrcList_item *pFrom)
 		 * In this case, proceed.
 		 */
 		if (pCte->zCteErr) {
-			sqlErrorMsg(pParse, pCte->zCteErr, pCte->zName);
+			diag_set(ClientError, ER_SQL_PARSER_GENERIC,
+				 tt_sprintf(pCte->zCteErr, pCte->zName));
+			pParse->is_aborted = true;
 			return SQL_ERROR;
 		}
-		if (cannotBeFunction(pParse, pFrom))
+		if (pFrom->fg.isTabFunc) {
+			const char *err = "'%s' is not a function";
+			diag_set(ClientError, ER_SQL_PARSER_GENERIC,
+				 tt_sprintf(err, pFrom->zName));
+			pParse->is_aborted = true;
 			return SQL_ERROR;
+		}
 
 		assert(pFrom->space == NULL);
 		pFrom->space = sql_ephemeral_space_new(pParse, pCte->zName);
@@ -4665,9 +4666,11 @@ withExpand(Walker * pWalker, struct SrcList_item *pFrom)
 			}
 		}
 		if (ref_counter > 1) {
-			sqlErrorMsg(pParse,
-					"multiple references to recursive table: %s",
-					pCte->zName);
+			const char *err_msg =
+				tt_sprintf("multiple references to recursive "\
+					   "table: %s", pCte->zName);
+			diag_set(ClientError, ER_SQL_PARSER_GENERIC, err_msg);
+			pParse->is_aborted = true;
 			return SQL_ERROR;
 		}
 		assert(ref_counter == 0 ||
@@ -4683,10 +4686,13 @@ withExpand(Walker * pWalker, struct SrcList_item *pFrom)
 		pEList = pLeft->pEList;
 		if (pCte->pCols) {
 			if (pEList && pEList->nExpr != pCte->pCols->nExpr) {
-				sqlErrorMsg(pParse,
-						"table %s has %d values for %d columns",
-						pCte->zName, pEList->nExpr,
-						pCte->pCols->nExpr);
+				const char *err_msg =
+					tt_sprintf("table %s has %d values "\
+						   "for %d columns",
+						   pCte->zName, pEList->nExpr,
+						   pCte->pCols->nExpr);
+				diag_set(ClientError, ER_SQL_PARSER_GENERIC, err_msg);
+				pParse->is_aborted = true;
 				pParse->pWith = pSavedWith;
 				return SQL_ERROR;
 			}
@@ -4842,8 +4848,15 @@ selectExpander(Walker * pWalker, Select * p)
 			struct space *space = sql_lookup_space(pParse, pFrom);
 			if (space == NULL)
 				return WRC_Abort;
-			if (cannotBeFunction(pParse, pFrom))
+			if (pFrom->fg.isTabFunc) {
+				const char *err =
+					tt_sprintf("'%s' is not a function",
+						   pFrom->zName);
+				diag_set(ClientError, ER_SQL_PARSER_GENERIC,
+					 err);
+				pParse->is_aborted = true;
 				return WRC_Abort;
+			}
 			if (space->def->opts.is_view) {
 				struct Select *select =
 					sql_view_compile(db, space->def->opts.sql);
@@ -5254,9 +5267,10 @@ resetAccumulator(Parse * pParse, AggInfo * pAggInfo)
 			Expr *pE = pFunc->pExpr;
 			assert(!ExprHasProperty(pE, EP_xIsSelect));
 			if (pE->x.pList == 0 || pE->x.pList->nExpr != 1) {
-				sqlErrorMsg(pParse,
-						"DISTINCT aggregates must have exactly one "
-						"argument");
+				diag_set(ClientError, ER_SQL_PARSER_GENERIC,
+					 "DISTINCT aggregates must have "\
+					 "exactly one argument");
+				pParse->is_aborted = true;
 				pFunc->iDistinct = -1;
 			} else {
 				struct sql_key_info *key_info =
diff --git a/src/box/sql/sqlInt.h b/src/box/sql/sqlInt.h
index 8fb2b18..50fc812 100644
--- a/src/box/sql/sqlInt.h
+++ b/src/box/sql/sqlInt.h
@@ -3193,7 +3193,6 @@ void sqlTreeViewWith(TreeView *, const With *);
 #endif
 
 void sqlSetString(char **, sql *, const char *);
-void sqlErrorMsg(Parse *, const char *, ...);
 void sqlDequote(char *);
 void sqlNormalizeName(char *z);
 void sqlTokenInit(Token *, char *);
@@ -4428,14 +4427,13 @@ int sqlCodeSubselect(Parse *, Expr *, int);
 void sqlSelectPrep(Parse *, Select *, NameContext *);
 
 /**
- * Error message for when two or more terms of a compound select
- * have different size result sets.
+ * Returns name of the connection operator.
  *
- * @param parse Parsing context.
- * @param p Select struct to analyze.
+ * @param op_id ID of the connection operator.
+ * @retval Name of the connection operator.
  */
-void
-sqlSelectWrongNumTermsError(struct Parse *parse, struct Select *p);
+const char *
+select_op_name(int op_id);
 
 int sqlMatchSpanName(const char *, const char *, const char *);
 int sqlResolveExprNames(NameContext *, Expr *);
@@ -4884,7 +4882,6 @@ int sqlExprVectorSize(Expr * pExpr);
 int sqlExprIsVector(Expr * pExpr);
 Expr *sqlVectorFieldSubexpr(Expr *, int);
 Expr *sqlExprForVectorField(Parse *, Expr *, int);
-void sqlVectorErrorMsg(Parse *, Expr *);
 
 /* Tarantool: right now query compilation is invoked on top of
  * fiber's stack. Need to limit number of nested programs under
diff --git a/src/box/sql/trigger.c b/src/box/sql/trigger.c
index b23d60a..c984950 100644
--- a/src/box/sql/trigger.c
+++ b/src/box/sql/trigger.c
@@ -621,8 +621,9 @@ codeTriggerProgram(Parse * pParse,	/* The parser context */
 	sqlSubProgramsRemaining--;
 
 	if (sqlSubProgramsRemaining == 0) {
-		sqlErrorMsg(pParse,
-				"Maximum number of chained trigger activations exceeded.");
+		diag_set(ClientError, ER_SQL_PARSER_GENERIC, "Maximum number "\
+			 "of chained trigger activations exceeded.");
+		pParse->is_aborted = true;
 	}
 
 	for (pStep = pStepList; pStep; pStep = pStep->pNext) {
diff --git a/src/box/sql/update.c b/src/box/sql/update.c
index 71a1e00..0b645eb 100644
--- a/src/box/sql/update.c
+++ b/src/box/sql/update.c
@@ -179,10 +179,15 @@ sqlUpdate(Parse * pParse,		/* The parser context */
 				    sql_space_column_is_in_pk(space, j))
 					is_pk_modified = true;
 				if (aXRef[j] != -1) {
-					sqlErrorMsg(pParse,
-							"set id list: duplicate"
-							" column name %s",
-							pChanges->a[i].zName);
+					const char *err =
+						"set id list: duplicate "\
+						"column name %s";
+					err = tt_sprintf(err,
+							 pChanges->a[i].zName);
+					diag_set(ClientError,
+						 ER_SQL_PARSER_GENERIC,
+						 err);
+					pParse->is_aborted = true;
 					goto update_cleanup;
 				}
 				aXRef[j] = i;
diff --git a/src/box/sql/util.c b/src/box/sql/util.c
index d9bb2af..cac404f 100644
--- a/src/box/sql/util.c
+++ b/src/box/sql/util.c
@@ -211,38 +211,6 @@ sqlErrorWithMsg(sql * db, int err_code, const char *zFormat, ...)
 }
 
 /*
- * Add an error to the diagnostics area and set
- * pParse->is_aborted.
- * The following formatting characters are allowed:
- *
- *      %s      Insert a string
- *      %z      A string that should be freed after use
- *      %d      Insert an integer
- *      %T      Insert a token
- *      %S      Insert the first element of a SrcList
- *
- * This function should be used to report any error that occurs while
- * compiling an SQL statement (i.e. within sql_prepare()). The
- * last thing the sql_prepare() function does is copy the error
- * stored by this function into the database handle using sqlError().
- * Functions sqlError() or sqlErrorWithMsg() should be used
- * during statement execution (sql_step() etc.).
- */
-void
-sqlErrorMsg(Parse * pParse, const char *zFormat, ...)
-{
-	char *zMsg;
-	va_list ap;
-	sql *db = pParse->db;
-	va_start(ap, zFormat);
-	zMsg = sqlVMPrintf(db, zFormat, ap);
-	va_end(ap);
-	diag_set(ClientError, ER_SQL_PARSER_GENERIC, zMsg);
-	sqlDbFree(db, zMsg);
-	pParse->is_aborted = true;
-}
-
-/*
  * Convert an SQL-style quoted string into a normal string by removing
  * the quote characters.  The conversion is done in-place.  If the
  * input does not begin with a quote character, then this routine
diff --git a/src/box/sql/vdbemem.c b/src/box/sql/vdbemem.c
index f417c49..15a2f55 100644
--- a/src/box/sql/vdbemem.c
+++ b/src/box/sql/vdbemem.c
@@ -1208,15 +1208,9 @@ valueFromFunction(sql * db,	/* The database connection */
 	ctx.pOut = pVal;
 	ctx.pFunc = pFunc;
 	pFunc->xSFunc(&ctx, nVal, apVal);
-	if (ctx.isError) {
-		rc = ctx.isError;
-		sqlErrorMsg(pCtx->pParse, "%s", sql_value_text(pVal));
-	} else {
-		sql_value_apply_type(pVal, type);
-		assert(rc == SQL_OK);
-	}
-	if (rc != SQL_OK)
-		pCtx->pParse->is_aborted = true;
+	assert(!ctx.isError);
+	sql_value_apply_type(pVal, type);
+	assert(rc == SQL_OK);
 
  value_from_function_out:
 	if (rc != SQL_OK) {
diff --git a/src/box/sql/where.c b/src/box/sql/where.c
index 2f83e81..19ee2d0 100644
--- a/src/box/sql/where.c
+++ b/src/box/sql/where.c
@@ -3913,11 +3913,7 @@ wherePathSolver(WhereInfo * pWInfo, LogEst nRowEst)
 		nFrom = nTo;
 	}
 
-	if (nFrom == 0) {
-		sqlErrorMsg(pParse, "no query solution");
-		sqlDbFree(db, pSpace);
-		return SQL_ERROR;
-	}
+	assert(nFrom != 0);
 
 	/* Find the lowest cost path.  pFrom will be left pointing to that path */
 	pFrom = aFrom;
diff --git a/src/box/sql/whereexpr.c b/src/box/sql/whereexpr.c
index 6df28ad..ec08889 100644
--- a/src/box/sql/whereexpr.c
+++ b/src/box/sql/whereexpr.c
@@ -1496,12 +1496,12 @@ sqlWhereTabFuncArgs(Parse * pParse,	/* Parsing context */
 	for (j = k = 0; j < pArgs->nExpr; j++) {
 		while (k < (int)space_def->field_count)
 			k++;
-		if (k >= (int)space_def->field_count) {
-			sqlErrorMsg(pParse,
-					"too many arguments on %s() - max %d",
-					space_def->name, j);
-			return;
-		}
+		/*
+		 * This assert replaces error. At the moment, this
+		 * error cannot appear due to this function being
+		 * unused.
+		 */
+		assert(k < (int)space_def->field_count);
 		pColRef = sqlExprAlloc(pParse->db, TK_COLUMN, 0, 0);
 		if (pColRef == 0)
 			return;
diff --git a/test/sql-tap/e_select1.test.lua b/test/sql-tap/e_select1.test.lua
index e190ad7..8e9a2bb 100755
--- a/test/sql-tap/e_select1.test.lua
+++ b/test/sql-tap/e_select1.test.lua
@@ -1855,13 +1855,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, "1st ORDER BY term does not match any column in the result set"})
+        1, "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, "2nd ORDER BY term does not match any column in the result set"})
+        1, "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",
@@ -2077,12 +2077,12 @@ test:do_select_tests(
 -- EVIDENCE-OF: R-39265-04070 If no matching expression can be found in
 -- the result columns of any constituent SELECT, it is an error.
 --
-for _, val in ipairs({{1, "SELECT a FROM d5 UNION SELECT c FROM d6 ORDER BY a+1", "1st"},
-    {2, "SELECT a FROM d5 UNION SELECT c FROM d6 ORDER BY a, a+1", "2nd"},
-    {3, "SELECT * FROM d5 INTERSECT SELECT * FROM d6 ORDER BY \"hello\"", "1st"},
-    {4, "SELECT * FROM d5 INTERSECT SELECT * FROM d6 ORDER BY blah", "1st"},
-    {5, "SELECT * FROM d5 INTERSECT SELECT * FROM d6 ORDER BY c,d,c+d", "3rd"},
-    {6, "SELECT * FROM d5 EXCEPT SELECT * FROM d7 ORDER BY 1,2,b,a/b", "4th"}}) do
+for _, val in ipairs({{1, "SELECT a FROM d5 UNION SELECT c FROM d6 ORDER BY a+1", "1"},
+    {2, "SELECT a FROM d5 UNION SELECT c FROM d6 ORDER BY a, a+1", "2"},
+    {3, "SELECT * FROM d5 INTERSECT SELECT * FROM d6 ORDER BY \"hello\"", "1"},
+    {4, "SELECT * FROM d5 INTERSECT SELECT * FROM d6 ORDER BY blah", "1"},
+    {5, "SELECT * FROM d5 INTERSECT SELECT * FROM d6 ORDER BY c,d,c+d", "3"},
+    {6, "SELECT * FROM d5 EXCEPT SELECT * FROM d7 ORDER BY 1,2,b,a/b", "4"}}) do
     local tn = val[1]
     local select = val[2]
     local err_param = val[3]
@@ -2090,7 +2090,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("%s ORDER BY term does not match any column in the result set", err_param)})
+            1, string.format("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/null.test.lua b/test/sql-tap/null.test.lua
index 50a2cfb..de4d503 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, "1st ORDER BY term does not match any column in the result set"
+        1, "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, "1st ORDER BY term does not match any column in the result set"
+        1, "Error at ORDER BY in place 1: term does not match any column in the result set"
         -- </null-6.6>
     })
 
diff --git a/test/sql-tap/select1.test.lua b/test/sql-tap/select1.test.lua
index d73429a..545ae9d 100755
--- a/test/sql-tap/select1.test.lua
+++ b/test/sql-tap/select1.test.lua
@@ -840,7 +840,7 @@ test:do_catchsql_test(
         SELECT * FROM t5 ORDER BY 3;
     ]], {
         -- <select1-4.10.1>
-        1, "1st ORDER BY term out of range - should be between 1 and 2"
+        1, "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, "1st ORDER BY term out of range - should be between 1 and 2"
+        1, "Error at ORDER BY in place 1: term out of range - should be between 1 and 2"
         -- </select1-4.10.2>
     })
 
@@ -1334,7 +1334,7 @@ test:do_catchsql2_test(
             ORDER BY f2+101;
         ]], {
             -- <select1-6.11>
-            1, "1st ORDER BY term does not match any column in the result set"
+            1, "Error at ORDER BY in place 1: term does not match any column in the result set"
             -- </select1-6.11>
         })
 
diff --git a/test/sql-tap/select3.test.lua b/test/sql-tap/select3.test.lua
index 9fb825f..3c88f77 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, "1st GROUP BY term out of range - should be between 1 and 2"
+  1, "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, "1st GROUP BY term out of range - should be between 1 and 2"
+  1, "Error at GROUP BY in place 1: term out of range - should be between 1 and 2"
   -- </select3-2.11>
 })
 
diff --git a/test/sql-tap/select4.test.lua b/test/sql-tap/select4.test.lua
index bd2ada9..3aafedb 100755
--- a/test/sql-tap/select4.test.lua
+++ b/test/sql-tap/select4.test.lua
@@ -450,7 +450,7 @@ test:do_catchsql_test(
         ORDER BY "xyzzy";
     ]], {
         -- <select4-5.2c>
-        1, "1st ORDER BY term does not match any column in the result set"
+        1, "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, "1st ORDER BY term does not match any column in the result set"
+        1, "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, "1st ORDER BY term out of range - should be between 1 and 1"
+        1, "Error at ORDER BY in place 1: term out of range - should be between 1 and 1"
         -- </select4-5.2h>
     })
 
diff --git a/test/sql-tap/sql-errors.test.lua b/test/sql-tap/sql-errors.test.lua
index 635df6a..5585dbb 100755
--- a/test/sql-tap/sql-errors.test.lua
+++ b/test/sql-tap/sql-errors.test.lua
@@ -1,9 +1,9 @@
 #!/usr/bin/env tarantool
 test = require("sqltester")
-test:plan(36)
+test:plan(45)
 
 test:execsql([[
-	CREATE TABLE t0 (i INT PRIMARY KEY);
+	CREATE TABLE t0 (i INT PRIMARY KEY, a INT);
 	CREATE VIEW v0 AS SELECT * FROM t0;
 ]])
 format = {}
@@ -79,7 +79,7 @@ test:do_catchsql_test(
 test:do_catchsql_test(
 	"sql-errors-1.7",
 	[[
-		CREATE VIEW v7(a,b) AS SELECT * FROM t0;
+		CREATE VIEW v7(a,b,c) AS SELECT * FROM t0;
 	]], {
 		-- <sql-errors-1.7>
 		1,"Failed to create space 'V7': number of aliases doesn't match provided columns"
@@ -416,4 +416,94 @@ test:do_catchsql_test(
 		-- </sql-errors-1.36>
 	})
 
+test:do_catchsql_test(
+	"sql-errors-1.37",
+	[[
+		CREATE TRIGGER r0 AFTER INSERT ON t0 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"
+		-- </sql-errors-1.37>
+	})
+
+test:do_catchsql_test(
+	"sql-errors-1.38",
+	[[
+		UPDATE t0 SET (i, a) = (100,1,1);
+	]], {
+		-- <sql-errors-1.38>
+		1,"2 columns assigned 3 values"
+		-- </sql-errors-1.38>
+	})
+
+test:do_catchsql_test(
+	"sql-errors-1.39",
+	[[
+		SELECT * FROM t0();
+	]], {
+		-- <sql-errors-1.39>
+		1,"'T0' is not a function"
+		-- </sql-errors-1.39>
+	})
+
+test:do_catchsql_test(
+	"sql-errors-1.40",
+	[[
+		SELECT $0;
+	]], {
+		-- <sql-errors-1.40>
+		1,"Index of binding slots must start from 1"
+		-- </sql-errors-1.40>
+	})
+
+test:do_catchsql_test(
+	"sql-errors-1.41",
+	[[
+		SELECT (1,2,3) == (1,2,3,4);
+	]], {
+		-- <sql-errors-1.41>
+		1,"row value misused"
+		-- </sql-errors-1.41>
+	})
+
+test:do_catchsql_test(
+	"sql-errors-1.42",
+	[[
+		SELECT (1, 2);
+	]], {
+		-- <sql-errors-1.42>
+		1,"row value misused"
+		-- </sql-errors-1.42>
+	})
+
+test:do_catchsql_test(
+	"sql-errors-1.43",
+	[[
+		SELECT (i,a) AS m FROM t0 WHERE m < 1;
+	]], {
+		-- <sql-errors-1.43>
+		1,"row value misused"
+		-- </sql-errors-1.43>
+	})
+
+test:do_execsql_test(
+	"sql-errors-1.44",
+	[[
+		SELECT (1, 2, 3) < (1, 2, 4);
+	]], {
+		-- <sql-errors-1.44>
+		1
+		-- </sql-errors-1.44>
+	})
+
+test:do_execsql_test(
+	"sql-errors-1.45",
+	[[
+		SELECT (1, 2, 3) < (1, 2, 2);
+	]], {
+		-- <sql-errors-1.45>
+		0
+		-- </sql-errors-1.45>
+	})
+
 test:finish_test()
diff --git a/test/sql-tap/tkt2822.test.lua b/test/sql-tap/tkt2822.test.lua
index 4212cbd..86674ae 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, "1st ORDER BY term does not match any column in the result set"
+        1, "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, "1st ORDER BY term out of range - should be between 1 and 25"
+        1, "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, "2nd ORDER BY term out of range - should be between 1 and 25"
+        1, "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, "2nd ORDER BY term out of range - should be between 1 and 25"
+        1, "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, "2nd ORDER BY term out of range - should be between 1 and 25"
+        1, "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, "3rd ORDER BY term out of range - should be between 1 and 25"
+        1, "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, "4th ORDER BY term out of range - should be between 1 and 25"
+        1, "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, "9th ORDER BY term out of range - should be between 1 and 25"
+        1, "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, "10th ORDER BY term out of range - should be between 1 and 25"
+        1, "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, "11th ORDER BY term out of range - should be between 1 and 25"
+        1, "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, "12th ORDER BY term out of range - should be between 1 and 25"
+        1, "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, "13th ORDER BY term out of range - should be between 1 and 25"
+        1, "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, "20th ORDER BY term out of range - should be between 1 and 25"
+        1, "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, "21st ORDER BY term out of range - should be between 1 and 25"
+        1, "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, "22nd ORDER BY term out of range - should be between 1 and 25"
+        1, "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/with1.test.lua b/test/sql-tap/with1.test.lua
index 16c9b12..f1a1699 100755
--- a/test/sql-tap/with1.test.lua
+++ b/test/sql-tap/with1.test.lua
@@ -134,7 +134,7 @@ test:do_catchsql_test(3.2, [[
   SELECT * FROM tmp;
 ]], {
   -- <3.2>
-  1, "duplicate WITH table name: TMP"
+  1, "Ambiguous table name in WITH query: TMP"
   -- </3.2>
 })
 
@@ -782,7 +782,7 @@ test:do_catchsql_test("10.7.1", [[
   SELECT * FROM t
 ]], {
   -- <10.7.1>
-  1, "1st ORDER BY term does not match any column in the result set"
+  1, "Error at ORDER BY in place 1: term does not match any column in the result set"
   -- </10.7.1>
 })
 
diff --git a/test/sql/iproto.result b/test/sql/iproto.result
index 56099fa..48376c8 100644
--- a/test/sql/iproto.result
+++ b/test/sql/iproto.result
@@ -571,7 +571,8 @@ cn:execute('select ?1, ?2, ?3', {1, 2, 3})
 ...
 cn:execute('select $name, $name2', {1, 2})
 ---
-- error: 'Failed to execute SQL statement: SQL bind parameter limit reached: 65000'
+- error: 'Failed to execute SQL statement: Index of binding slots must start from
+    1'
 ...
 parameters = {}
 ---





More information about the Tarantool-patches mailing list