Tarantool development patches archive
 help / color / mirror / Atom feed
* [tarantool-patches] [PATCH v1 0/9] sql: set errors in VDBE using diag_set()
@ 2019-05-28 11:39 imeevma
  2019-05-28 11:39 ` [tarantool-patches] [PATCH v1 1/9] sql: remove mayAbort field from struct Parse imeevma
                   ` (10 more replies)
  0 siblings, 11 replies; 25+ messages in thread
From: imeevma @ 2019-05-28 11:39 UTC (permalink / raw)
  To: v.shpilevoy; +Cc: tarantool-patches

The main purpose of this patch-set is to replace the SQL error
system with the Tarantool error system.

https://github.com/tarantool/tarantool/issues/4074
https://github.com/tarantool/tarantool/tree/imeevma/gh-4074-diag_set-in-vdbe

Mergen Imeev (9):
  sql: remove mayAbort field from struct Parse
  sql: remove error codes SQL_TARANTOOL_*_FAIL
  sql: remove error ER_SQL
  sql: rework diag_set() in OP_Halt
  sql: make SQL_TARANTOOL_ERROR the only errcode of OP_Halt
  sql: remove error SQL_INTERRUPT
  sql: remove error SQL_MISMATCH
  sql: use diag_set() to set an error in SQL functions
  sql: set errors in VDBE using diag_set()

 src/box/alter.cc                                   |   4 +-
 src/box/errcode.h                                  |   2 +-
 src/box/execute.c                                  |  23 +-
 src/box/lua/lua_sql.c                              |  13 +-
 src/box/sql.c                                      |  37 +-
 src/box/sql/analyze.c                              |   6 +-
 src/box/sql/build.c                                |  59 +--
 src/box/sql/date.c                                 |   8 +-
 src/box/sql/delete.c                               |   4 +-
 src/box/sql/expr.c                                 |   9 +-
 src/box/sql/fk_constraint.c                        |  42 +-
 src/box/sql/func.c                                 | 102 +++--
 src/box/sql/insert.c                               |  31 +-
 src/box/sql/main.c                                 |   5 -
 src/box/sql/malloc.c                               |   4 -
 src/box/sql/resolve.c                              |   2 +-
 src/box/sql/select.c                               |  13 +-
 src/box/sql/sqlInt.h                               |  32 --
 src/box/sql/tarantoolInt.h                         |   5 +-
 src/box/sql/tokenize.c                             |   3 -
 src/box/sql/trigger.c                              |  18 +-
 src/box/sql/vdbe.c                                 | 431 ++++++---------------
 src/box/sql/vdbe.h                                 |   3 -
 src/box/sql/vdbeInt.h                              |  38 +-
 src/box/sql/vdbeapi.c                              | 170 +-------
 src/box/sql/vdbeaux.c                              | 234 +----------
 src/box/sql/vdbemem.c                              |  15 +-
 test/box/misc.result                               |   1 -
 test/sql-tap/autoinc.test.lua                      |   4 +-
 test/sql-tap/e_select1.test.lua                    |   4 +-
 test/sql-tap/func.test.lua                         |   2 +-
 test/sql-tap/gh-2931-savepoints.test.lua           |   6 +-
 .../gh-3307-xfer-optimization-issue.test.lua       |  10 +-
 test/sql-tap/gh2259-in-stmt-trans.test.lua         |   8 +-
 test/sql-tap/gh2964-abort.test.lua                 |   2 +-
 test/sql-tap/intpkey.test.lua                      |   2 +-
 test/sql-tap/limit.test.lua                        |  26 +-
 test/sql-tap/misc1.test.lua                        |   2 +-
 test/sql-tap/select3.test.lua                      |   2 +-
 test/sql-tap/select4.test.lua                      |   8 +-
 test/sql-tap/select5.test.lua                      |  10 +-
 test/sql-tap/subselect.test.lua                    |   6 +-
 test/sql-tap/table.test.lua                        |   8 +-
 test/sql-tap/tkt-4a03edc4c8.test.lua               |   2 +-
 test/sql-tap/tkt1473.test.lua                      |  36 +-
 test/sql-tap/trigger1.test.lua                     |   6 +-
 test/sql-tap/unique.test.lua                       |  10 +-
 test/sql/collation.result                          |  18 +-
 test/sql/delete.result                             |   7 +-
 test/sql/errinj.result                             |   6 +-
 test/sql/foreign-keys.result                       |   3 +-
 test/sql/insert-unique.result                      |   6 +-
 test/sql/iproto.result                             |  21 +-
 test/sql/on-conflict.result                        |   4 +-
 test/sql/persistency.result                        |   6 +-
 test/sql/savepoints.result                         |   2 +-
 test/sql/transition.result                         |   6 +-
 test/sql/triggers.result                           |  21 +-
 test/sql/types.result                              |   9 +-
 59 files changed, 420 insertions(+), 1157 deletions(-)

-- 
2.7.4

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [tarantool-patches] [PATCH v1 1/9] sql: remove mayAbort field from struct Parse
  2019-05-28 11:39 [tarantool-patches] [PATCH v1 0/9] sql: set errors in VDBE using diag_set() imeevma
@ 2019-05-28 11:39 ` imeevma
  2019-05-28 11:39 ` [tarantool-patches] [PATCH v1 2/9] sql: remove error codes SQL_TARANTOOL_*_FAIL imeevma
                   ` (9 subsequent siblings)
  10 siblings, 0 replies; 25+ messages in thread
From: imeevma @ 2019-05-28 11:39 UTC (permalink / raw)
  To: v.shpilevoy; +Cc: tarantool-patches

Currently, the mayAbort field is working with SQL error
SQL_CONSTRAINT. Since we want to replace SQL_CONSTRAINT with a
Tarantool error, we need to change the way the mayAbort field
works or delete it. Since this field is used only for make an
assertion in debug mode, it is better to simply remove it.
---
 src/box/sql/build.c         |  28 ----------
 src/box/sql/expr.c          |   2 -
 src/box/sql/fk_constraint.c |  35 ------------
 src/box/sql/insert.c        |   2 -
 src/box/sql/sqlInt.h        |   2 -
 src/box/sql/vdbe.h          |   3 --
 src/box/sql/vdbeaux.c       | 127 --------------------------------------------
 7 files changed, 199 deletions(-)

diff --git a/src/box/sql/build.c b/src/box/sql/build.c
index 91b977d..23b562e 100644
--- a/src/box/sql/build.c
+++ b/src/box/sql/build.c
@@ -152,8 +152,6 @@ sql_finish_coding(struct Parse *parse_context)
 	 * Begin by generating some termination code at the end
 	 * of the vdbe program
 	 */
-	assert(!parse_context->isMultiWrite ||
-	       sqlVdbeAssertMayAbort(v, parse_context->mayAbort));
 	int last_instruction = v->nOp;
 	if (parse_context->initiateTTrans)
 		sqlVdbeAddOp0(v, OP_TTransaction);
@@ -2985,29 +2983,6 @@ sql_set_multi_write(struct Parse *parse_context, bool is_set)
 }
 
 /*
- * The code generator calls this routine if is discovers that it is
- * possible to abort a statement prior to completion.  In order to
- * perform this abort without corrupting the database, we need to make
- * sure that the statement is protected by a statement transaction.
- *
- * Technically, we only need to set the mayAbort flag if the
- * isMultiWrite flag was previously set.  There is a time dependency
- * such that the abort must occur after the multiwrite.  This makes
- * some statements involving the REPLACE conflict resolution algorithm
- * go a little faster.  But taking advantage of this time dependency
- * makes it more difficult to prove that the code is correct (in
- * particular, it prevents us from writing an effective
- * implementation of sqlAssertMayAbort()) and so we have chosen
- * to take the safe route and skip the optimization.
- */
-void
-sqlMayAbort(Parse * pParse)
-{
-	Parse *pToplevel = sqlParseToplevel(pParse);
-	pToplevel->mayAbort = 1;
-}
-
-/*
  * Code an OP_Halt that causes the vdbe to return an SQL_CONSTRAINT
  * error. The onError parameter determines which (if any) of the statement
  * and/or current transaction is rolled back.
@@ -3023,9 +2998,6 @@ sqlHaltConstraint(Parse * pParse,	/* Parsing context */
 {
 	Vdbe *v = sqlGetVdbe(pParse);
 	assert((errCode & 0xff) == SQL_CONSTRAINT);
-	if (onError == ON_CONFLICT_ACTION_ABORT) {
-		sqlMayAbort(pParse);
-	}
 	sqlVdbeAddOp4(v, OP_Halt, errCode, onError, 0, p4, p4type);
 	sqlVdbeChangeP5(v, p5Errmsg);
 }
diff --git a/src/box/sql/expr.c b/src/box/sql/expr.c
index ba7eea5..6ac42d7 100644
--- a/src/box/sql/expr.c
+++ b/src/box/sql/expr.c
@@ -4380,8 +4380,6 @@ sqlExprCodeTarget(Parse * pParse, Expr * pExpr, int target)
 			pParse->is_aborted = true;
 			return 0;
 		}
-		if (pExpr->on_conflict_action == ON_CONFLICT_ACTION_ABORT)
-			sqlMayAbort(pParse);
 		assert(!ExprHasProperty(pExpr, EP_IntValue));
 		if (pExpr->on_conflict_action == ON_CONFLICT_ACTION_IGNORE) {
 			sqlVdbeAddOp4(v, OP_Halt, SQL_OK,
diff --git a/src/box/sql/fk_constraint.c b/src/box/sql/fk_constraint.c
index 8151c66..7d36edc 100644
--- a/src/box/sql/fk_constraint.c
+++ b/src/box/sql/fk_constraint.c
@@ -292,8 +292,6 @@ fk_constraint_lookup_parent(struct Parse *parse_context, struct space *parent,
 				      ON_CONFLICT_ACTION_ABORT, 0, P4_STATIC,
 				      P5_ConstraintFK);
 	} else {
-		if (incr_count > 0 && !fk_def->is_deferred)
-			sqlMayAbort(parse_context);
 		sqlVdbeAddOp2(v, OP_FkCounter, fk_def->is_deferred,
 				  incr_count);
 	}
@@ -634,41 +632,8 @@ fk_constraint_emit_check(struct Parse *parser, struct space *space, int reg_old,
 						    fk->def, reg_new, -1);
 		}
 		if (reg_old != 0) {
-			enum fk_constraint_action action = fk_def->on_update;
 			fk_constraint_scan_children(parser, src, space->def,
 						    fk->def, reg_old, 1);
-			/*
-			 * If this is a deferred FK constraint, or
-			 * a CASCADE or SET NULL action applies,
-			 * then any foreign key violations caused
-			 * by removing the parent key will be
-			 * rectified by the action trigger. So do
-			 * not set the "may-abort" flag in this
-			 * case.
-			 *
-			 * Note 1: If the FK is declared "ON
-			 * UPDATE CASCADE", then the may-abort
-			 * flag will eventually be set on this
-			 * statement anyway (when this function is
-			 * called as part of processing the UPDATE
-			 * within the action trigger).
-			 *
-			 * Note 2: At first glance it may seem
-			 * like sql could simply omit all
-			 * OP_FkCounter related scans when either
-			 * CASCADE or SET NULL applies. The
-			 * trouble starts if the CASCADE or SET
-			 * NULL action trigger causes other
-			 * triggers or action rules attached to
-			 * the child table to fire. In these cases
-			 * the fk constraint counters might be set
-			 * incorrectly if any OP_FkCounter related
-			 * scans are omitted.
-			 */
-			if (!fk_def->is_deferred &&
-			    action != FKEY_ACTION_CASCADE &&
-			    action != FKEY_ACTION_SET_NULL)
-				sqlMayAbort(parser);
 		}
 		sqlSrcListDelete(db, src);
 	}
diff --git a/src/box/sql/insert.c b/src/box/sql/insert.c
index 2813415..6f50726 100644
--- a/src/box/sql/insert.c
+++ b/src/box/sql/insert.c
@@ -887,8 +887,6 @@ vdbe_emit_constraint_checks(struct Parse *parse_context, struct space *space,
 		int addr;
 		switch (on_conflict_nullable) {
 		case ON_CONFLICT_ACTION_ABORT:
-			sqlMayAbort(parse_context);
-			FALLTHROUGH;
 		case ON_CONFLICT_ACTION_ROLLBACK:
 		case ON_CONFLICT_ACTION_FAIL:
 			err_msg = sqlMPrintf(db, "%s.%s", def->name,
diff --git a/src/box/sql/sqlInt.h b/src/box/sql/sqlInt.h
index 997a465..e59b57f 100644
--- a/src/box/sql/sqlInt.h
+++ b/src/box/sql/sqlInt.h
@@ -2589,7 +2589,6 @@ struct Parse {
 	u8 colNamesSet;		/* TRUE after OP_ColumnName has been issued to pVdbe */
 	u8 nTempReg;		/* Number of temporary registers in aTempReg[] */
 	u8 isMultiWrite;	/* True if statement may modify/insert multiple rows */
-	u8 mayAbort;		/* True if statement may throw an ABORT exception */
 	u8 hasCompound;		/* Need to invoke convertCompoundSelectToSubquery() */
 	u8 okConstFactor;	/* OK to factor out constants */
 	u8 disableLookaside;	/* Number of times lookaside has been disabled */
@@ -3916,7 +3915,6 @@ vdbe_emit_insertion_completion(struct Vdbe *v, struct space *space,
 
 void
 sql_set_multi_write(Parse *, bool);
-void sqlMayAbort(Parse *);
 void sqlHaltConstraint(Parse *, int, int, char *, i8, u8);
 
 Expr *sqlExprDup(sql *, Expr *, int);
diff --git a/src/box/sql/vdbe.h b/src/box/sql/vdbe.h
index f9bb96f..6234dff 100644
--- a/src/box/sql/vdbe.h
+++ b/src/box/sql/vdbe.h
@@ -253,9 +253,6 @@ void sqlVdbeMakeReady(Vdbe *, Parse *);
 int sqlVdbeFinalize(Vdbe *);
 void sqlVdbeResolveLabel(Vdbe *, int);
 int sqlVdbeCurrentAddr(Vdbe *);
-#ifdef SQL_DEBUG
-int sqlVdbeAssertMayAbort(Vdbe *, int);
-#endif
 void sqlVdbeResetStepResult(Vdbe *);
 void sqlVdbeRewind(Vdbe *);
 int sqlVdbeReset(Vdbe *);
diff --git a/src/box/sql/vdbeaux.c b/src/box/sql/vdbeaux.c
index 25d4cd7..140bb97 100644
--- a/src/box/sql/vdbeaux.c
+++ b/src/box/sql/vdbeaux.c
@@ -500,133 +500,6 @@ sqlVdbeRunOnlyOnce(Vdbe * p)
 	p->runOnlyOnce = 1;
 }
 
-#ifdef SQL_DEBUG		/* sqlAssertMayAbort() logic */
-
-/*
- * The following type and function are used to iterate through all opcodes
- * in a Vdbe main program and each of the sub-programs (triggers) it may
- * invoke directly or indirectly. It should be used as follows:
- *
- *   Op *pOp;
- *   VdbeOpIter sIter;
- *
- *   memset(&sIter, 0, sizeof(sIter));
- *   sIter.v = v;                            // v is of type Vdbe*
- *   while( (pOp = opIterNext(&sIter)) ){
- *     // Do something with pOp
- *   }
- *   sqlDbFree(v->db, sIter.apSub);
- *
- */
-typedef struct VdbeOpIter VdbeOpIter;
-struct VdbeOpIter {
-	Vdbe *v;		/* Vdbe to iterate through the opcodes of */
-	SubProgram **apSub;	/* Array of subprograms */
-	int nSub;		/* Number of entries in apSub */
-	int iAddr;		/* Address of next instruction to return */
-	int iSub;		/* 0 = main program, 1 = first sub-program etc. */
-};
-
-static Op *
-opIterNext(VdbeOpIter * p)
-{
-	Vdbe *v = p->v;
-	Op *pRet = 0;
-	Op *aOp;
-	int nOp;
-
-	if (p->iSub <= p->nSub) {
-
-		if (p->iSub == 0) {
-			aOp = v->aOp;
-			nOp = v->nOp;
-		} else {
-			aOp = p->apSub[p->iSub - 1]->aOp;
-			nOp = p->apSub[p->iSub - 1]->nOp;
-		}
-		assert(p->iAddr < nOp);
-
-		pRet = &aOp[p->iAddr];
-		p->iAddr++;
-		if (p->iAddr == nOp) {
-			p->iSub++;
-			p->iAddr = 0;
-		}
-
-		if (pRet->p4type == P4_SUBPROGRAM) {
-			int nByte = (p->nSub + 1) * sizeof(SubProgram *);
-			int j;
-			for (j = 0; j < p->nSub; j++) {
-				if (p->apSub[j] == pRet->p4.pProgram)
-					break;
-			}
-			if (j == p->nSub) {
-				p->apSub =
-				    sqlDbReallocOrFree(v->db, p->apSub,
-							   nByte);
-				if (!p->apSub) {
-					pRet = 0;
-				} else {
-					p->apSub[p->nSub++] = pRet->p4.pProgram;
-				}
-			}
-		}
-	}
-
-	return pRet;
-}
-
-/*
- * Check if the program stored in the VM associated with pParse may
- * throw an ABORT exception (causing the statement, but not entire transaction
- * to be rolled back). This condition is true if the main program or any
- * sub-programs contains any of the following:
- *
- *   *  OP_Halt with P1=SQL_CONSTRAINT and P2=ON_CONFLICT_ACTION_ABORT.
- *   *  OP_HaltIfNull with P1=SQL_CONSTRAINT and P2=ON_CONFLICT_ACTION_ABORT.
- *   *  OP_FkCounter with P2==0 (immediate foreign key constraint)
- *
- * Then check that the value of Parse.mayAbort is true if an
- * ABORT may be thrown, or false otherwise. Return true if it does
- * match, or false otherwise. This function is intended to be used as
- * part of an assert statement in the compiler. Similar to:
- *
- *   assert( sqlVdbeAssertMayAbort(pParse->pVdbe, pParse->mayAbort) );
- */
-int
-sqlVdbeAssertMayAbort(Vdbe * v, int mayAbort)
-{
-	int hasAbort = 0;
-	int hasFkCounter = 0;
-	Op *pOp;
-	VdbeOpIter sIter;
-	memset(&sIter, 0, sizeof(sIter));
-	sIter.v = v;
-
-	while ((pOp = opIterNext(&sIter)) != 0) {
-		int opcode = pOp->opcode;
-		if ((opcode == OP_Halt || opcode == OP_HaltIfNull) &&
-		    (pOp->p1 & 0xff) == SQL_CONSTRAINT &&
-	            pOp->p2 == ON_CONFLICT_ACTION_ABORT){
-			hasAbort = 1;
-			break;
-		}
-		if (opcode == OP_FkCounter && pOp->p1 == 0 && pOp->p2 == 1) {
-			hasFkCounter = 1;
-		}
-	}
-	sqlDbFree(v->db, sIter.apSub);
-
-	/* Return true if hasAbort==mayAbort. Or if a malloc failure occurred.
-	 * If malloc failed, then the while() loop above may not have iterated
-	 * through all opcodes and hasAbort may be set incorrectly. Return
-	 * true for this case to prevent the assert() in the callers frame
-	 * from failing.
-	 */
-	return (v->db->mallocFailed || hasAbort == mayAbort || hasFkCounter);
-}
-#endif				/* SQL_DEBUG - the sqlAssertMayAbort() function */
-
 /*
  * This routine is called after all opcodes have been inserted.  It loops
  * through all the opcodes and fixes up some details.
-- 
2.7.4

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [tarantool-patches] [PATCH v1 2/9] sql: remove error codes SQL_TARANTOOL_*_FAIL
  2019-05-28 11:39 [tarantool-patches] [PATCH v1 0/9] sql: set errors in VDBE using diag_set() imeevma
  2019-05-28 11:39 ` [tarantool-patches] [PATCH v1 1/9] sql: remove mayAbort field from struct Parse imeevma
@ 2019-05-28 11:39 ` imeevma
  2019-05-28 11:39 ` [tarantool-patches] [PATCH v1 3/9] sql: remove error ER_SQL imeevma
                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 25+ messages in thread
From: imeevma @ 2019-05-28 11:39 UTC (permalink / raw)
  To: v.shpilevoy; +Cc: tarantool-patches

The error codes SQL_TARANTOOL_DELETE_FAIL,
SQL_TARANTOOL_ITERATOR_FAIL and SQL_TARANTOOL_INSERT_FAIL have
practically no functions, but their use can lead to incorrect
behavior. This patch replaces them with SQL_TARANTOOL_ERROR. This
will simplify the work with errors.
---
 src/box/sql.c                                      | 37 ++++++++--------------
 src/box/sql/main.c                                 |  3 --
 src/box/sql/sqlInt.h                               |  3 --
 src/box/sql/tarantoolInt.h                         |  5 +--
 src/box/sql/vdbe.c                                 |  2 +-
 test/sql-tap/autoinc.test.lua                      |  2 +-
 test/sql-tap/gh-2931-savepoints.test.lua           |  4 +--
 .../gh-3307-xfer-optimization-issue.test.lua       | 10 +++---
 test/sql-tap/gh2259-in-stmt-trans.test.lua         |  8 ++---
 test/sql-tap/gh2964-abort.test.lua                 |  2 +-
 test/sql-tap/intpkey.test.lua                      |  2 +-
 test/sql-tap/misc1.test.lua                        |  2 +-
 test/sql-tap/table.test.lua                        |  8 ++---
 test/sql-tap/tkt-4a03edc4c8.test.lua               |  2 +-
 test/sql-tap/trigger1.test.lua                     |  6 ++--
 test/sql-tap/unique.test.lua                       | 10 +++---
 test/sql/collation.result                          | 18 ++++-------
 test/sql/errinj.result                             |  6 ++--
 test/sql/foreign-keys.result                       |  3 +-
 test/sql/insert-unique.result                      |  6 ++--
 test/sql/iproto.result                             |  3 +-
 test/sql/persistency.result                        |  6 ++--
 test/sql/transition.result                         |  6 ++--
 test/sql/triggers.result                           |  2 +-
 24 files changed, 62 insertions(+), 94 deletions(-)

diff --git a/src/box/sql.c b/src/box/sql.c
index fbfa599..59a8bfb 100644
--- a/src/box/sql.c
+++ b/src/box/sql.c
@@ -162,15 +162,6 @@ const char *tarantoolErrorMessage()
 	return box_error_message(box_error_last());
 }
 
-int
-is_tarantool_error(int rc)
-{
-	return (rc == SQL_TARANTOOL_ERROR ||
-		rc == SQL_TARANTOOL_ITERATOR_FAIL ||
-		rc == SQL_TARANTOOL_DELETE_FAIL ||
-		rc == SQL_TARANTOOL_INSERT_FAIL);
-}
-
 const void *tarantoolsqlPayloadFetch(BtCursor *pCur, u32 *pAmt)
 {
 	assert(pCur->curFlags & BTCF_TaCursor ||
@@ -421,7 +412,7 @@ int tarantoolsqlEphemeralInsert(struct space *space, const char *tuple,
 	assert(space != NULL);
 	mp_tuple_assert(tuple, tuple_end);
 	if (space_ephemeral_replace(space, tuple, tuple_end) != 0)
-		return SQL_TARANTOOL_INSERT_FAIL;
+		return SQL_TARANTOOL_ERROR;
 	return SQL_OK;
 }
 
@@ -448,7 +439,7 @@ insertOrReplace(struct space *space, const char *tuple, const char *tuple_end,
 	request.type = type;
 	mp_tuple_assert(request.tuple, request.tuple_end);
 	int rc = box_process_rw(&request, space, NULL);
-	return rc == 0 ? SQL_OK : SQL_TARANTOOL_INSERT_FAIL;
+	return rc == 0 ? SQL_OK : SQL_TARANTOOL_ERROR;
 }
 
 int tarantoolsqlInsert(struct space *space, const char *tuple,
@@ -483,12 +474,12 @@ int tarantoolsqlEphemeralDelete(BtCursor *pCur)
 				pCur->iter->index->def->key_def,
 				MULTIKEY_NONE, &key_size);
 	if (key == NULL)
-		return SQL_TARANTOOL_DELETE_FAIL;
+		return SQL_TARANTOOL_ERROR;
 
 	int rc = space_ephemeral_delete(pCur->space, key);
 	if (rc != 0) {
 		diag_log();
-		return SQL_TARANTOOL_DELETE_FAIL;
+		return SQL_TARANTOOL_ERROR;
 	}
 	return SQL_OK;
 }
@@ -509,11 +500,11 @@ int tarantoolsqlDelete(BtCursor *pCur, u8 flags)
 				pCur->iter->index->def->key_def,
 				MULTIKEY_NONE, &key_size);
 	if (key == NULL)
-		return SQL_TARANTOOL_DELETE_FAIL;
+		return SQL_TARANTOOL_ERROR;
 	rc = sql_delete_by_key(pCur->space, pCur->index->def->iid, key,
 			       key_size);
 
-	return rc == 0 ? SQL_OK : SQL_TARANTOOL_DELETE_FAIL;
+	return rc == 0 ? SQL_OK : SQL_TARANTOOL_ERROR;
 }
 
 int
@@ -531,7 +522,7 @@ sql_delete_by_key(struct space *space, uint32_t iid, char *key,
 	assert(space_index(space, iid)->def->opts.is_unique);
 	int rc = box_process_rw(&request, space, &unused);
 
-	return rc == 0 ? SQL_OK : SQL_TARANTOOL_DELETE_FAIL;
+	return rc == 0 ? SQL_OK : SQL_TARANTOOL_ERROR;
 }
 
 /*
@@ -553,7 +544,7 @@ int tarantoolsqlEphemeralClearTable(BtCursor *pCur)
 						    0 /* part_count */);
 	if (it == NULL) {
 		pCur->eState = CURSOR_INVALID;
-		return SQL_TARANTOOL_ITERATOR_FAIL;
+		return SQL_TARANTOOL_ERROR;
 	}
 
 	struct tuple *tuple;
@@ -565,7 +556,7 @@ int tarantoolsqlEphemeralClearTable(BtCursor *pCur)
 					MULTIKEY_NONE, &key_size);
 		if (space_ephemeral_delete(pCur->space, key) != 0) {
 			iterator_delete(it);
-			return SQL_TARANTOOL_DELETE_FAIL;
+			return SQL_TARANTOOL_ERROR;
 		}
 	}
 	iterator_delete(it);
@@ -592,7 +583,7 @@ int tarantoolsqlClearTable(struct space *space, uint32_t *tuple_count)
 	struct index *pk = space_index(space, 0 /* PK */);
 	struct iterator *iter = index_create_iterator(pk, ITER_ALL, nil_key, 0);
 	if (iter == NULL)
-		return SQL_TARANTOOL_ITERATOR_FAIL;
+		return SQL_TARANTOOL_ERROR;
 	while (iterator_next(iter, &tuple) == 0 && tuple != NULL) {
 		request.key = tuple_extract_key(tuple, pk->def->key_def,
 						MULTIKEY_NONE, &key_size);
@@ -600,7 +591,7 @@ int tarantoolsqlClearTable(struct space *space, uint32_t *tuple_count)
 		rc = box_process_rw(&request, space, &unused);
 		if (rc != 0) {
 			iterator_delete(iter);
-			return SQL_TARANTOOL_DELETE_FAIL;
+			return SQL_TARANTOOL_ERROR;
 		}
 		(*tuple_count)++;
 	}
@@ -903,7 +894,7 @@ cursor_seek(BtCursor *pCur, int *pRes)
 	uint32_t part_count = mp_decode_array(&key);
 	if (key_validate(pCur->index->def, pCur->iter_type, key, part_count)) {
 		diag_log();
-		return SQL_TARANTOOL_ITERATOR_FAIL;
+		return SQL_TARANTOOL_ERROR;
 	}
 
 	struct space *space = pCur->space;
@@ -917,7 +908,7 @@ cursor_seek(BtCursor *pCur, int *pRes)
 		if (txn != NULL)
 			txn_rollback_stmt();
 		pCur->eState = CURSOR_INVALID;
-		return SQL_TARANTOOL_ITERATOR_FAIL;
+		return SQL_TARANTOOL_ERROR;
 	}
 	if (txn != NULL)
 		txn_commit_ro_stmt(txn);
@@ -944,7 +935,7 @@ cursor_advance(BtCursor *pCur, int *pRes)
 
 	struct tuple *tuple;
 	if (iterator_next(pCur->iter, &tuple) != 0)
-		return SQL_TARANTOOL_ITERATOR_FAIL;
+		return SQL_TARANTOOL_ERROR;
 	if (pCur->last_tuple)
 		box_tuple_unref(pCur->last_tuple);
 	if (tuple) {
diff --git a/src/box/sql/main.c b/src/box/sql/main.c
index fe1135a..ed07553 100644
--- a/src/box/sql/main.c
+++ b/src/box/sql/main.c
@@ -383,9 +383,6 @@ sqlErrStr(int rc)
 		/* SQL_MISUSE      */
 		    "library routine called out of sequence",
 		/* SQL_RANGE       */ "bind or column index out of range",
-		/* SQL_TARANTOOL_ITERATOR_FAIL */ "Tarantool's iterator failed",
-		/* SQL_TARANTOOL_INSERT_FAIL */ "Tarantool's insert failed",
-		/* SQL_TARANTOOL_DELETE_FAIL */ "Tarantool's delete failed",
 		/* SQL_TARANTOOL_ERROR */ "SQL-/Tarantool error",
 	};
 	const char *zErr = "unknown error";
diff --git a/src/box/sql/sqlInt.h b/src/box/sql/sqlInt.h
index e59b57f..05a4042 100644
--- a/src/box/sql/sqlInt.h
+++ b/src/box/sql/sqlInt.h
@@ -392,9 +392,6 @@ enum sql_ret_code {
 	SQL_MISUSE,
 	/** 2nd parameter to sql_bind out of range. */
 	SQL_RANGE,
-	SQL_TARANTOOL_ITERATOR_FAIL,
-	SQL_TARANTOOL_INSERT_FAIL,
-	SQL_TARANTOOL_DELETE_FAIL,
 	SQL_TARANTOOL_ERROR,
 	/** Warnings from sql_log(). */
 	SQL_WARNING,
diff --git a/src/box/sql/tarantoolInt.h b/src/box/sql/tarantoolInt.h
index 2b04d96..f15e147 100644
--- a/src/box/sql/tarantoolInt.h
+++ b/src/box/sql/tarantoolInt.h
@@ -13,8 +13,6 @@ struct fk_constraint_def;
 /* Misc */
 const char *tarantoolErrorMessage();
 
-int is_tarantool_error(int rc);
-
 /* Storage interface. */
 const void *tarantoolsqlPayloadFetch(BtCursor * pCur, u32 * pAmt);
 
@@ -51,8 +49,7 @@ int tarantoolsqlDelete(BtCursor * pCur, u8 flags);
  * @param key Key of record to be deleted.
  * @param key_size Size of key.
  *
- * @retval SQL_OK on success, SQL_TARANTOOL_DELETE_FAIL
- *         otherwise.
+ * @retval SQL_OK on success, SQL_TARANTOOL_ERROR otherwise.
  */
 int
 sql_delete_by_key(struct space *space, uint32_t iid, char *key,
diff --git a/src/box/sql/vdbe.c b/src/box/sql/vdbe.c
index d083d37..a64c846 100644
--- a/src/box/sql/vdbe.c
+++ b/src/box/sql/vdbe.c
@@ -5469,7 +5469,7 @@ abort_due_to_error:
 		/* Avoiding situation when Tarantool error is set,
 		 * but error message isn't.
 		 */
-		if (is_tarantool_error(rc) && tarantoolErrorMessage()) {
+		if (rc == SQL_TARANTOOL_ERROR && tarantoolErrorMessage()) {
 			msg = tarantoolErrorMessage();
 		} else {
 			msg = sqlErrStr(rc);
diff --git a/test/sql-tap/autoinc.test.lua b/test/sql-tap/autoinc.test.lua
index 4db2783..257621b 100755
--- a/test/sql-tap/autoinc.test.lua
+++ b/test/sql-tap/autoinc.test.lua
@@ -531,7 +531,7 @@ test:do_catchsql_test(
         INSERT INTO t6 VALUES(NULL,1);
     ]], {
         -- <autoinc-6.2>
-        1, "Failed to execute SQL statement: Sequence 'T6' has overflowed"
+        1, "Sequence 'T6' has overflowed"
         -- </autoinc-6.2>
     })
 
diff --git a/test/sql-tap/gh-2931-savepoints.test.lua b/test/sql-tap/gh-2931-savepoints.test.lua
index 5c0daef..6123fc4 100755
--- a/test/sql-tap/gh-2931-savepoints.test.lua
+++ b/test/sql-tap/gh-2931-savepoints.test.lua
@@ -81,13 +81,13 @@ local testcases = {
 		{0,{1,2,10,11,1,2,4,10,11}}},
 	{"14",
 		[[insert into t1 values(4);]],
-		{1,"Failed to execute SQL statement: Duplicate key exists in unique index 'pk_unnamed_T2_1' in space 'T2'"}},
+		{1,"Duplicate key exists in unique index 'pk_unnamed_T2_1' in space 'T2'"}},
 	{"15",
 		[[select * from t1 union all select * from t2;]],
 		{0,{1,2,10,11,1,2,4,10,11}}},
 	{"16",
 		[[insert or rollback into t1 values(4);]],
-		{1,"Failed to execute SQL statement: Duplicate key exists in unique index 'pk_unnamed_T2_1' in space 'T2'"}},
+		{1,"Duplicate key exists in unique index 'pk_unnamed_T2_1' in space 'T2'"}},
 	{"17",  -- should work as transaction is rolled back
 		[[insert or rollback into t1 values(4);
 		select * from t1 union all select * from t2;]],
diff --git a/test/sql-tap/gh-3307-xfer-optimization-issue.test.lua b/test/sql-tap/gh-3307-xfer-optimization-issue.test.lua
index 859a6ff..bb8a498 100755
--- a/test/sql-tap/gh-3307-xfer-optimization-issue.test.lua
+++ b/test/sql-tap/gh-3307-xfer-optimization-issue.test.lua
@@ -139,7 +139,7 @@ test:do_catchsql_xfer_test(
         INSERT INTO t2 SELECT * FROM t1;
     ]], {
         -- <xfer-optimization-1.9>
-        1, "Failed to execute SQL statement: Duplicate key exists in unique index 'pk_unnamed_T2_1' in space 'T2'"
+        1, "Duplicate key exists in unique index 'pk_unnamed_T2_1' in space 'T2'"
         -- <xfer-optimization-1.9>
     }, {
         exp_xfer_count = 0
@@ -210,7 +210,7 @@ test:do_catchsql_xfer_test(
             INSERT INTO t2 SELECT * FROM t1;
     ]], {
         -- <xfer-optimization-1.13>
-        1, "Failed to execute SQL statement: Duplicate key exists in unique index 'pk_unnamed_T2_1' in space 'T2'"
+        1, "Duplicate key exists in unique index 'pk_unnamed_T2_1' in space 'T2'"
         -- <xfer-optimization-1.13>
     }, {
         exp_xfer_count = 0
@@ -245,7 +245,7 @@ test:do_catchsql_xfer_test(
             INSERT OR ABORT INTO t2 SELECT * FROM t1;
     ]], {
         -- <xfer-optimization-1.20>
-        1, "Failed to execute SQL statement: Duplicate key exists in unique index 'pk_unnamed_T2_1' in space 'T2'"
+        1, "Duplicate key exists in unique index 'pk_unnamed_T2_1' in space 'T2'"
         -- <xfer-optimization-1.20>
     }, {
         exp_xfer_count = 1
@@ -313,7 +313,7 @@ test:do_catchsql_xfer_test(
             INSERT OR ROLLBACK INTO t2 SELECT * FROM t1;
     ]], {
         -- <xfer-optimization-1.24>
-        1, "Failed to execute SQL statement: Duplicate key exists in unique index 'pk_unnamed_T2_1' in space 'T2'"
+        1, "Duplicate key exists in unique index 'pk_unnamed_T2_1' in space 'T2'"
         -- <xfer-optimization-1.24>
     }, {
         exp_xfer_count = 0
@@ -381,7 +381,7 @@ test:do_catchsql_xfer_test(
             INSERT OR FAIL INTO t2 SELECT * FROM t1;
     ]], {
         -- <xfer-optimization-1.28>
-        1, "Failed to execute SQL statement: Duplicate key exists in unique index 'pk_unnamed_T2_1' in space 'T2'"
+        1, "Duplicate key exists in unique index 'pk_unnamed_T2_1' in space 'T2'"
         -- <xfer-optimization-1.28>
     }, {
         exp_xfer_count = 1
diff --git a/test/sql-tap/gh2259-in-stmt-trans.test.lua b/test/sql-tap/gh2259-in-stmt-trans.test.lua
index 36f5e90..6bd0550 100755
--- a/test/sql-tap/gh2259-in-stmt-trans.test.lua
+++ b/test/sql-tap/gh2259-in-stmt-trans.test.lua
@@ -18,7 +18,7 @@ for _, prefix in pairs({"BEFORE", "AFTER"}) do
 
     test:do_catchsql_test(prefix..'_insert1',
                           'INSERT INTO t1 VALUES(1, 2)',
-                          {1,"Failed to execute SQL statement: Duplicate key exists in unique index 'pk_unnamed_T2_2' in space 'T2'"})
+                          {1,"Duplicate key exists in unique index 'pk_unnamed_T2_2' in space 'T2'"})
 
     test:do_execsql_test(prefix..'_insert1_check1',
                          'SELECT *  FROM t1',
@@ -34,7 +34,7 @@ for _, prefix in pairs({"BEFORE", "AFTER"}) do
 
     test:do_catchsql_test(prefix..'_update1',
                           'UPDATE t1 SET s1=1',
-                          {1,"Failed to execute SQL statement: Duplicate key exists in unique index 'pk_unnamed_T2_2' in space 'T2'"})
+                          {1,"Duplicate key exists in unique index 'pk_unnamed_T2_2' in space 'T2'"})
 
     test:do_execsql_test(prefix..'_update1_check1',
                          'SELECT *  FROM t1',
@@ -52,7 +52,7 @@ for _, prefix in pairs({"BEFORE", "AFTER"}) do
 
     test:do_catchsql_test(prefix..'delete1',
                           'DELETE FROM t1;',
-                          {1, "Failed to execute SQL statement: Duplicate key exists in unique index 'pk_unnamed_T2_2' in space 'T2'"})
+                          {1, "Duplicate key exists in unique index 'pk_unnamed_T2_2' in space 'T2'"})
 
     -- Nothing should be inserted due to abort
     test:do_execsql_test('delete1_check1',
@@ -69,7 +69,7 @@ end
 -- Check multi-insert
 test:do_catchsql_test('insert2',
                       'INSERT INTO t1 VALUES (5, 6), (6, 7)',
-                      {1, "Failed to execute SQL statement: Duplicate key exists in unique index 'pk_unnamed_T2_2' in space 'T2'"})
+                      {1, "Duplicate key exists in unique index 'pk_unnamed_T2_2' in space 'T2'"})
 test:do_execsql_test('insert2_check',
                      'SELECT * FROM t1;',
                      {3, 3})
diff --git a/test/sql-tap/gh2964-abort.test.lua b/test/sql-tap/gh2964-abort.test.lua
index db9a111..3bce569 100755
--- a/test/sql-tap/gh2964-abort.test.lua
+++ b/test/sql-tap/gh2964-abort.test.lua
@@ -12,7 +12,7 @@ test:do_catchsql_test(
     test_prefix.."1.0.2",
     "CREATE TABLE t2 (a int primary key);")
 
-local insert_err = {1, "Failed to execute SQL statement: Duplicate key exists in unique index 'pk_unnamed_T2_1' in space 'T2'"}
+local insert_err = {1, "Duplicate key exists in unique index 'pk_unnamed_T2_1' in space 'T2'"}
 local data = {
 --id|TRIG TYPE|INSERT TYPE|insert error|commit error| result
  {1, "AFTER", "or abort",   insert_err, {0},          {1,1,2}},
diff --git a/test/sql-tap/intpkey.test.lua b/test/sql-tap/intpkey.test.lua
index b2e8084..bec2670 100755
--- a/test/sql-tap/intpkey.test.lua
+++ b/test/sql-tap/intpkey.test.lua
@@ -96,7 +96,7 @@ test:do_catchsql_test(
         INSERT INTO t1 VALUES(5,'second','entry');
     ]], {
         -- <intpkey-1.6>
-        1, "Failed to execute SQL statement: Duplicate key exists in unique index 'pk_unnamed_T1_1' in space 'T1'"
+        1, "Duplicate key exists in unique index 'pk_unnamed_T1_1' in space 'T1'"
         -- </intpkey-1.6>
     })
 
diff --git a/test/sql-tap/misc1.test.lua b/test/sql-tap/misc1.test.lua
index 914f920..f332fb7 100755
--- a/test/sql-tap/misc1.test.lua
+++ b/test/sql-tap/misc1.test.lua
@@ -383,7 +383,7 @@ test:do_catchsql_test(
         INSERT INTO t5 VALUES(1,2,4);
     ]], {
         -- <misc1-7.4>
-        1, "Failed to execute SQL statement: Duplicate key exists in unique index 'pk_unnamed_T5_1' in space 'T5'"
+        1, "Duplicate key exists in unique index 'pk_unnamed_T5_1' in space 'T5'"
         -- </misc1-7.4>
     })
 
diff --git a/test/sql-tap/table.test.lua b/test/sql-tap/table.test.lua
index 5b793c0..04fd175 100755
--- a/test/sql-tap/table.test.lua
+++ b/test/sql-tap/table.test.lua
@@ -1211,7 +1211,7 @@ test:do_catchsql_test(
         INSERT INTO T21 VALUES(1, 2, 2);
     ]], {
         -- <table-21.2>
-        1, "Failed to execute SQL statement: Duplicate key exists in unique index 'pk_unnamed_T21_1' in space 'T21'"
+        1, "Duplicate key exists in unique index 'pk_unnamed_T21_1' in space 'T21'"
         -- </table-21.2>
     })
 
@@ -1283,7 +1283,7 @@ test:do_catchsql_test(
         INSERT INTO T22 VALUES(2, 1, 1);
     ]], {
         -- <table-22.3>
-        1,"Failed to execute SQL statement: Duplicate key exists in unique index 'unique_ONE_2' in space 'T22'"
+        1,"Duplicate key exists in unique index 'unique_ONE_2' in space 'T22'"
         -- </table-22.3>
     })
 
@@ -1308,7 +1308,7 @@ test:do_catchsql_test(
         INSERT INTO T24 VALUES(2, 1, 1);
     ]], {
         -- <table-22.5>
-        1, "Failed to execute SQL statement: Duplicate key exists in unique index 'unique_TWO_2' in space 'T24'"
+        1, "Duplicate key exists in unique index 'unique_TWO_2' in space 'T24'"
         -- </table-22.5>
     })
 
@@ -1362,7 +1362,7 @@ test:do_catchsql_test(
         INSERT INTO T28 VALUES(11);
     ]], {
         -- <table-22.9>
-        1,"Failed to execute SQL statement: Duplicate key exists in unique index 'pk_unnamed_T28_1' in space 'T28'"
+        1,"Duplicate key exists in unique index 'pk_unnamed_T28_1' in space 'T28'"
         -- </table-22.9>
     })
 
diff --git a/test/sql-tap/tkt-4a03edc4c8.test.lua b/test/sql-tap/tkt-4a03edc4c8.test.lua
index 0f44d4f..cb7a982 100755
--- a/test/sql-tap/tkt-4a03edc4c8.test.lua
+++ b/test/sql-tap/tkt-4a03edc4c8.test.lua
@@ -38,7 +38,7 @@ test:do_test(
         ]]
     end, {
         -- <tkt-4a03ed-1.1>
-        1, "Failed to execute SQL statement: Duplicate key exists in unique index 'pk_unnamed_T1_1' in space 'T1'"
+        1, "Duplicate key exists in unique index 'pk_unnamed_T1_1' in space 'T1'"
         -- </tkt-4a03ed-1.1>
     })
 
diff --git a/test/sql-tap/trigger1.test.lua b/test/sql-tap/trigger1.test.lua
index dfc2822..64763fa 100755
--- a/test/sql-tap/trigger1.test.lua
+++ b/test/sql-tap/trigger1.test.lua
@@ -260,7 +260,7 @@ test:do_catchsql_test(
         end;
     ]], {
         -- <trigger1-1.12>
-        1, "Failed to execute SQL statement: SQL error: cannot create INSTEAD OF trigger on space: T1"
+        1, "SQL error: cannot create INSTEAD OF trigger on space: T1"
         -- </trigger1-1.12>
     })
 
@@ -274,7 +274,7 @@ test:do_catchsql_test(
         end;
     ]], {
         -- <trigger1-1.13>
-        1, "Failed to execute SQL statement: SQL error: cannot create BEFORE trigger on view: V1"
+        1, "SQL error: cannot create BEFORE trigger on view: V1"
         -- </trigger1-1.13>
     })
 
@@ -289,7 +289,7 @@ test:do_catchsql_test(
         end;
     ]], {
         -- <trigger1-1.14>
-        1, "Failed to execute SQL statement: SQL error: cannot create AFTER trigger on view: V1"
+        1, "SQL error: cannot create AFTER trigger on view: V1"
         -- </trigger1-1.14>
     })
 
diff --git a/test/sql-tap/unique.test.lua b/test/sql-tap/unique.test.lua
index a9add83..fbd73a6 100755
--- a/test/sql-tap/unique.test.lua
+++ b/test/sql-tap/unique.test.lua
@@ -70,7 +70,7 @@ test:do_catchsql_test(
         INSERT INTO t1(a,b,c) VALUES(1,3,4)
     ]], {
         -- <unique-1.3>
-        1, "Failed to execute SQL statement: Duplicate key exists in unique index 'pk_unnamed_T1_1' in space 'T1'"
+        1, "Duplicate key exists in unique index 'pk_unnamed_T1_1' in space 'T1'"
         -- </unique-1.3>
     })
 
@@ -91,7 +91,7 @@ test:do_catchsql_test(
         INSERT INTO t1(a,b,c) VALUES(3,2,4)
     ]], {
         -- <unique-1.5>
-        1, "Failed to execute SQL statement: Duplicate key exists in unique index 'unique_unnamed_T1_2' in space 'T1'"
+        1, "Duplicate key exists in unique index 'unique_unnamed_T1_2' in space 'T1'"
         -- </unique-1.5>
     })
 
@@ -167,7 +167,7 @@ test:do_catchsql_test(
         INSERT INTO t2 VALUES(3, 1,5);
     ]], {
         -- <unique-2.3>
-        1, "Failed to execute SQL statement: Duplicate key exists in unique index 'I2' in space 'T2'"
+        1, "Duplicate key exists in unique index 'I2' in space 'T2'"
         -- </unique-2.3>
     })
 
@@ -287,7 +287,7 @@ test:do_catchsql_test(
         SELECT a,b,c,d FROM t3 ORDER BY a,b,c,d;
     ]], {
         -- <unique-3.4>
-        1, "Failed to execute SQL statement: Duplicate key exists in unique index 'unique_unnamed_T3_2' in space 'T3'"
+        1, "Duplicate key exists in unique index 'unique_unnamed_T3_2' in space 'T3'"
         -- </unique-3.4>
     })
 
@@ -444,7 +444,7 @@ test:do_catchsql_test(
         INSERT INTO t5 VALUES(2, 1,2,3,4,5,6);
     ]], {
         -- <unique-5.2>
-        1, "Failed to execute SQL statement: Duplicate key exists in unique index 'unique_unnamed_T5_2' in space 'T5'"
+        1, "Duplicate key exists in unique index 'unique_unnamed_T5_2' in space 'T5'"
         -- </unique-5.2>
     })
 
diff --git a/test/sql/collation.result b/test/sql/collation.result
index 0988965..436ce32 100644
--- a/test/sql/collation.result
+++ b/test/sql/collation.result
@@ -676,8 +676,7 @@ box.execute("INSERT INTO t3b VALUES ('A');")
 ...
 box.execute("INSERT INTO t3b VALUES ('a');")
 ---
-- error: 'Failed to execute SQL statement: Duplicate key exists in unique index ''pk_unnamed_T3B_1''
-    in space ''T3B'''
+- error: Duplicate key exists in unique index 'pk_unnamed_T3B_1' in space 'T3B'
 ...
 box.execute("SELECT * FROM t3b;")
 ---
@@ -741,8 +740,7 @@ box.execute("INSERT INTO t3c VALUES ('A');")
 ...
 box.execute("INSERT INTO t3c VALUES ('a');")
 ---
-- error: 'Failed to execute SQL statement: Duplicate key exists in unique index ''pk_unnamed_T3C_1''
-    in space ''T3C'''
+- error: Duplicate key exists in unique index 'pk_unnamed_T3C_1' in space 'T3C'
 ...
 box.execute("SELECT * FROM t3c;")
 ---
@@ -806,8 +804,7 @@ box.execute("INSERT INTO t3d VALUES ('A');")
 ...
 box.execute("INSERT INTO t3d VALUES ('a');")
 ---
-- error: 'Failed to execute SQL statement: Duplicate key exists in unique index ''pk_unnamed_T3D_1''
-    in space ''T3D'''
+- error: Duplicate key exists in unique index 'pk_unnamed_T3D_1' in space 'T3D'
 ...
 box.execute("SELECT * FROM t3d;")
 ---
@@ -837,8 +834,7 @@ box.execute("INSERT INTO t3e VALUES ('a');")
 ...
 box.execute("INSERT INTO t3e VALUES ('A');")
 ---
-- error: 'Failed to execute SQL statement: Duplicate key exists in unique index ''pk_unnamed_T3E_1''
-    in space ''T3E'''
+- error: Duplicate key exists in unique index 'pk_unnamed_T3E_1' in space 'T3E'
 ...
 box.execute("SELECT * FROM t3e;")
 ---
@@ -901,8 +897,7 @@ box.execute("INSERT INTO t3f VALUES ('A');")
 ...
 box.execute("INSERT INTO t3f VALUES ('a');")
 ---
-- error: 'Failed to execute SQL statement: Duplicate key exists in unique index ''pk_unnamed_T3F_1''
-    in space ''T3F'''
+- error: Duplicate key exists in unique index 'pk_unnamed_T3F_1' in space 'T3F'
 ...
 box.execute("SELECT * FROM t3f;")
 ---
@@ -932,8 +927,7 @@ box.execute("INSERT INTO t3g VALUES ('a');")
 ...
 box.execute("INSERT INTO t3g VALUES ('A');")
 ---
-- error: 'Failed to execute SQL statement: Duplicate key exists in unique index ''pk_unnamed_T3G_1''
-    in space ''T3G'''
+- error: Duplicate key exists in unique index 'pk_unnamed_T3G_1' in space 'T3G'
 ...
 box.execute("SELECT * FROM t3g;")
 ---
diff --git a/test/sql/errinj.result b/test/sql/errinj.result
index ee36a38..75faad1 100644
--- a/test/sql/errinj.result
+++ b/test/sql/errinj.result
@@ -189,7 +189,7 @@ box.error.injection.set("ERRINJ_WAL_IO", true)
 ...
 box.execute("CREATE TRIGGER t1t INSERT ON t1 FOR EACH ROW BEGIN INSERT INTO t2 VALUES (1, 1); END;")
 ---
-- error: 'Failed to execute SQL statement: Failed to write to disk'
+- error: Failed to write to disk
 ...
 box.execute("CREATE INDEX t1a ON t1(a);")
 ---
@@ -257,7 +257,7 @@ box.error.injection.set("ERRINJ_WAL_IO", true)
 ...
 box.execute("DROP TRIGGER t1t;")
 ---
-- error: 'Failed to execute SQL statement: Failed to write to disk'
+- error: Failed to write to disk
 ...
 box.error.injection.set("ERRINJ_WAL_IO", false)
 ---
@@ -374,7 +374,7 @@ errinj.set("ERRINJ_WAL_IO", true)
 ...
 box.execute("ALTER TABLE t3 DROP CONSTRAINT fk1;")
 ---
-- error: 'Failed to execute SQL statement: Failed to write to disk'
+- error: Failed to write to disk
 ...
 box.execute("INSERT INTO t3 VALUES(1, 1, 3);")
 ---
diff --git a/test/sql/foreign-keys.result b/test/sql/foreign-keys.result
index 66eb94b..f3cca5c 100644
--- a/test/sql/foreign-keys.result
+++ b/test/sql/foreign-keys.result
@@ -181,8 +181,7 @@ t = box.space._fk_constraint:insert(t)
 --
 box.execute("DROP INDEX i1 on t1;")
 ---
-- error: 'Failed to execute SQL statement: Can''t modify space ''T1'': can not drop
-    a referenced index'
+- error: 'Can''t modify space ''T1'': can not drop a referenced index'
 ...
 -- Referenced index can't be altered as well, if alter leads to
 -- rebuild of index (e.g. index still can be renamed).
diff --git a/test/sql/insert-unique.result b/test/sql/insert-unique.result
index 61b35a3..236046f 100644
--- a/test/sql/insert-unique.result
+++ b/test/sql/insert-unique.result
@@ -28,14 +28,12 @@ box.execute("INSERT INTO zoobar VALUES (111, 222, 'c3', 444)")
 -- PK must be unique
 box.execute("INSERT INTO zoobar VALUES (112, 222, 'c3', 444)")
 ---
-- error: 'Failed to execute SQL statement: Duplicate key exists in unique index ''pk_unnamed_ZOOBAR_1''
-    in space ''ZOOBAR'''
+- error: Duplicate key exists in unique index 'pk_unnamed_ZOOBAR_1' in space 'ZOOBAR'
 ...
 -- Unique index must be respected
 box.execute("INSERT INTO zoobar VALUES (111, 223, 'c3', 444)")
 ---
-- error: 'Failed to execute SQL statement: Duplicate key exists in unique index ''ZOOBAR2''
-    in space ''ZOOBAR'''
+- error: Duplicate key exists in unique index 'ZOOBAR2' in space 'ZOOBAR'
 ...
 -- Cleanup
 box.execute("DROP INDEX zoobar2 ON zoobar")
diff --git a/test/sql/iproto.result b/test/sql/iproto.result
index e734872..73497b4 100644
--- a/test/sql/iproto.result
+++ b/test/sql/iproto.result
@@ -437,8 +437,7 @@ future1:wait_result()
 future2:wait_result()
 ---
 - null
-- 'Failed to execute SQL statement: Duplicate key exists in unique index ''pk_unnamed_TEST_1''
-  in space ''TEST'''
+- Duplicate key exists in unique index 'pk_unnamed_TEST_1' in space 'TEST'
 ...
 future3:wait_result()
 ---
diff --git a/test/sql/persistency.result b/test/sql/persistency.result
index 3f85725..3508a22 100644
--- a/test/sql/persistency.result
+++ b/test/sql/persistency.result
@@ -31,8 +31,7 @@ box.execute("INSERT INTO foobar VALUES (1000, 'foobar')")
 ...
 box.execute("INSERT INTO foobar VALUES (1, 'duplicate')")
 ---
-- error: 'Failed to execute SQL statement: Duplicate key exists in unique index ''pk_unnamed_FOOBAR_1''
-    in space ''FOOBAR'''
+- error: Duplicate key exists in unique index 'pk_unnamed_FOOBAR_1' in space 'FOOBAR'
 ...
 -- simple select
 box.execute("SELECT bar, foo, 42, 'awesome' FROM foobar")
@@ -416,8 +415,7 @@ box.execute("SELECT \"name\", \"opts\" FROM \"_trigger\"")
 -- prove barfoo2 still exists
 box.execute("INSERT INTO barfoo VALUES ('xfoo', 1)")
 ---
-- error: 'Failed to execute SQL statement: Duplicate key exists in unique index ''pk_unnamed_BARFOO_1''
-    in space ''BARFOO'''
+- error: Duplicate key exists in unique index 'pk_unnamed_BARFOO_1' in space 'BARFOO'
 ...
 box.execute("SELECT * FROM barfoo")
 ---
diff --git a/test/sql/transition.result b/test/sql/transition.result
index dec5474..6f5e763 100644
--- a/test/sql/transition.result
+++ b/test/sql/transition.result
@@ -28,8 +28,7 @@ box.execute("INSERT INTO foobar VALUES (1000, 'foobar')")
 ...
 box.execute("INSERT INTO foobar VALUES (1, 'duplicate')")
 ---
-- error: 'Failed to execute SQL statement: Duplicate key exists in unique index ''pk_unnamed_FOOBAR_1''
-    in space ''FOOBAR'''
+- error: Duplicate key exists in unique index 'pk_unnamed_FOOBAR_1' in space 'FOOBAR'
 ...
 -- simple select
 box.execute("SELECT bar, foo, 42, 'awesome' FROM foobar")
@@ -312,8 +311,7 @@ box.execute("INSERT INTO barfoo VALUES ('foobar', 1000)")
 -- prove barfoo2 was created
 box.execute("INSERT INTO barfoo VALUES ('xfoo', 1)")
 ---
-- error: 'Failed to execute SQL statement: Duplicate key exists in unique index ''pk_unnamed_BARFOO_1''
-    in space ''BARFOO'''
+- error: Duplicate key exists in unique index 'pk_unnamed_BARFOO_1' in space 'BARFOO'
 ...
 box.execute("SELECT foo, bar FROM barfoo")
 ---
diff --git a/test/sql/triggers.result b/test/sql/triggers.result
index af9085d..38fe32c 100644
--- a/test/sql/triggers.result
+++ b/test/sql/triggers.result
@@ -480,7 +480,7 @@ 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;")
 ---
-- error: 'Failed to execute SQL statement: bindings are not allowed in DDL'
+- error: 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;]]}}
 ---
-- 
2.7.4

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [tarantool-patches] [PATCH v1 3/9] sql: remove error ER_SQL
  2019-05-28 11:39 [tarantool-patches] [PATCH v1 0/9] sql: set errors in VDBE using diag_set() imeevma
  2019-05-28 11:39 ` [tarantool-patches] [PATCH v1 1/9] sql: remove mayAbort field from struct Parse imeevma
  2019-05-28 11:39 ` [tarantool-patches] [PATCH v1 2/9] sql: remove error codes SQL_TARANTOOL_*_FAIL imeevma
@ 2019-05-28 11:39 ` imeevma
  2019-05-28 11:39 ` [tarantool-patches] [PATCH v1 4/9] sql: rework diag_set() in OP_Halt imeevma
                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 25+ messages in thread
From: imeevma @ 2019-05-28 11:39 UTC (permalink / raw)
  To: v.shpilevoy; +Cc: tarantool-patches

The ER_SQL error code is very similar to the ER_SQL_EXECUTE error
code: they have almost identical description and usage. To avoid
misunderstandings, it is better to remove one of them. The ER_SQL
error code has a slightly more vague description, so it was
decided to remove it.
---
 src/box/alter.cc               |  4 ++--
 src/box/errcode.h              |  2 +-
 src/box/sql/build.c            |  2 +-
 src/box/sql/delete.c           |  4 ++--
 src/box/sql/resolve.c          |  2 +-
 src/box/sql/trigger.c          |  6 +++---
 test/box/misc.result           |  1 -
 test/sql-tap/select3.test.lua  |  2 +-
 test/sql-tap/select5.test.lua  | 10 +++++-----
 test/sql-tap/trigger1.test.lua |  6 +++---
 test/sql/delete.result         |  7 ++++---
 test/sql/on-conflict.result    |  4 ++--
 test/sql/triggers.result       | 19 +++++++++++--------
 13 files changed, 36 insertions(+), 33 deletions(-)

diff --git a/src/box/alter.cc b/src/box/alter.cc
index 965945a..92d85b3 100644
--- a/src/box/alter.cc
+++ b/src/box/alter.cc
@@ -3555,7 +3555,7 @@ on_replace_dd_trigger(struct trigger * /* trigger */, void *event)
 		if (strlen(trigger_name) != trigger_name_len ||
 		    memcmp(trigger_name_src, trigger_name,
 			   trigger_name_len) != 0) {
-			tnt_raise(ClientError, ER_SQL,
+			tnt_raise(ClientError, ER_SQL_EXECUTE,
 				  "trigger name does not match extracted "
 				  "from SQL");
 		}
@@ -3563,7 +3563,7 @@ on_replace_dd_trigger(struct trigger * /* trigger */, void *event)
 			tuple_field_u32_xc(new_tuple,
 					   BOX_TRIGGER_FIELD_SPACE_ID);
 		if (space_id != sql_trigger_space_id(new_trigger)) {
-			tnt_raise(ClientError, ER_SQL,
+			tnt_raise(ClientError, ER_SQL_EXECUTE,
 				  "trigger space_id does not match the value "
 				  "resolved on AST building from SQL");
 		}
diff --git a/src/box/errcode.h b/src/box/errcode.h
index 9c15f33..e148654 100644
--- a/src/box/errcode.h
+++ b/src/box/errcode.h
@@ -212,7 +212,7 @@ struct errcode_record {
 	/*157 */_(ER_SQL_BIND_TYPE,             "Bind value type %s for parameter %s is not supported") \
 	/*158 */_(ER_SQL_BIND_PARAMETER_MAX,    "SQL bind parameter limit reached: %d") \
 	/*159 */_(ER_SQL_EXECUTE,               "Failed to execute SQL statement: %s") \
-	/*160 */_(ER_SQL,			"SQL error: %s") \
+	/*160 */_(ER_UNUSED,			"") \
 	/*161 */_(ER_SQL_BIND_NOT_FOUND,	"Parameter %s was not found in the statement") \
 	/*162 */_(ER_ACTION_MISMATCH,		"Field %s contains %s on conflict action, but %s in index parts") \
 	/*163 */_(ER_VIEW_MISSING_SQL,		"Space declared as a view must have SQL statement") \
diff --git a/src/box/sql/build.c b/src/box/sql/build.c
index 23b562e..41813ed 100644
--- a/src/box/sql/build.c
+++ b/src/box/sql/build.c
@@ -467,7 +467,7 @@ sql_column_add_nullable_action(struct Parse *parser,
 		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);
+		diag_set(ClientError, ER_SQL_EXECUTE, err);
 		parser->is_aborted = true;
 		return;
 	}
diff --git a/src/box/sql/delete.c b/src/box/sql/delete.c
index a95b071..ca59abc 100644
--- a/src/box/sql/delete.c
+++ b/src/box/sql/delete.c
@@ -104,7 +104,7 @@ sql_table_truncate(struct Parse *parse, struct SrcList *tab_list)
 	if (! rlist_empty(&space->parent_fk_constraint)) {
 		const char *err = "can not truncate space '%s' because other "
 				  "objects depend on it";
-		diag_set(ClientError, ER_SQL,
+		diag_set(ClientError, ER_SQL_EXECUTE,
 			 tt_sprintf(err, space->def->name));
 		goto tarantool_error;
 	}
@@ -112,7 +112,7 @@ sql_table_truncate(struct Parse *parse, struct SrcList *tab_list)
 		const char *err_msg =
 			tt_sprintf("can not truncate space '%s' because space "\
 				   "is a view", space->def->name);
-		diag_set(ClientError, ER_SQL, err_msg);
+		diag_set(ClientError, ER_SQL_EXECUTE, err_msg);
 		goto tarantool_error;
 	}
 	sqlVdbeAddOp2(v, OP_Clear, space->def->id, true);
diff --git a/src/box/sql/resolve.c b/src/box/sql/resolve.c
index 504096e..e136312 100644
--- a/src/box/sql/resolve.c
+++ b/src/box/sql/resolve.c
@@ -1333,7 +1333,7 @@ resolveSelectStep(Walker * pWalker, Select * p)
 				return WRC_Abort;
 			if ((sNC.ncFlags & NC_HasAgg) == 0 ||
 			    (sNC.ncFlags & NC_HasUnaggregatedId) != 0) {
-				diag_set(ClientError, ER_SQL, "HAVING "
+				diag_set(ClientError, ER_SQL_EXECUTE, "HAVING "
 					 "argument must appear in the GROUP BY "
 					 "clause or be used in an aggregate "
 					 "function");
diff --git a/src/box/sql/trigger.c b/src/box/sql/trigger.c
index fe19244..0a4cd09 100644
--- a/src/box/sql/trigger.c
+++ b/src/box/sql/trigger.c
@@ -444,7 +444,7 @@ sql_trigger_replace(const char *name, uint32_t space_id,
 	if (trigger != NULL) {
 		/* Do not create a trigger on a system space. */
 		if (space_is_system(space)) {
-			diag_set(ClientError, ER_SQL,
+			diag_set(ClientError, ER_SQL_EXECUTE,
 				 "cannot create trigger on system table");
 			return -1;
 		}
@@ -453,7 +453,7 @@ sql_trigger_replace(const char *name, uint32_t space_id,
 		 * views only support INSTEAD of triggers.
 		 */
 		if (space->def->opts.is_view && trigger->tr_tm != TK_INSTEAD) {
-			diag_set(ClientError, ER_SQL,
+			diag_set(ClientError, ER_SQL_EXECUTE,
 				 tt_sprintf("cannot create %s "\
                          "trigger on view: %s", trigger->tr_tm == TK_BEFORE ?
 						"BEFORE" : "AFTER",
@@ -461,7 +461,7 @@ sql_trigger_replace(const char *name, uint32_t space_id,
 			return -1;
 		}
 		if (!space->def->opts.is_view && trigger->tr_tm == TK_INSTEAD) {
-			diag_set(ClientError, ER_SQL,
+			diag_set(ClientError, ER_SQL_EXECUTE,
 				 tt_sprintf("cannot create "\
                          "INSTEAD OF trigger on space: %s", space->def->name));
 			return -1;
diff --git a/test/box/misc.result b/test/box/misc.result
index 4fcd13a..b3b5bbc 100644
--- a/test/box/misc.result
+++ b/test/box/misc.result
@@ -489,7 +489,6 @@ t;
   157: box.error.SQL_BIND_TYPE
   158: box.error.SQL_BIND_PARAMETER_MAX
   159: box.error.SQL_EXECUTE
-  160: box.error.SQL
   161: box.error.SQL_BIND_NOT_FOUND
   162: box.error.ACTION_MISMATCH
   163: box.error.VIEW_MISSING_SQL
diff --git a/test/sql-tap/select3.test.lua b/test/sql-tap/select3.test.lua
index cb97363..2807d42 100755
--- a/test/sql-tap/select3.test.lua
+++ b/test/sql-tap/select3.test.lua
@@ -200,7 +200,7 @@ test:do_catchsql_test("select3-3.1", [[
   SELECT log, count(*) FROM t1 HAVING log>=4
 ]], {
   -- <select3-3.1>
-  1, "SQL error: HAVING argument must appear in the GROUP BY clause or be used in an aggregate function"
+  1, "Failed to execute SQL statement: HAVING argument must appear in the GROUP BY clause or be used in an aggregate function"
   -- </select3-3.1>
 })
 
diff --git a/test/sql-tap/select5.test.lua b/test/sql-tap/select5.test.lua
index 1353b39..d34de31 100755
--- a/test/sql-tap/select5.test.lua
+++ b/test/sql-tap/select5.test.lua
@@ -424,7 +424,7 @@ test:do_catchsql_test(
         SELECT s1 FROM te40 HAVING s1 = 1;
     ]], {
     -- <select5-9.1>
-    1, "SQL error: HAVING argument must appear in the GROUP BY clause or be used in an aggregate function"
+    1, "Failed to execute SQL statement: HAVING argument must appear in the GROUP BY clause or be used in an aggregate function"
     -- </select5-9.1>
 })
 
@@ -434,7 +434,7 @@ test:do_catchsql_test(
         SELECT SUM(s1) FROM te40 HAVING s1 = 2;
     ]], {
     -- <select5-9.2>
-    1, "SQL error: HAVING argument must appear in the GROUP BY clause or be used in an aggregate function"
+    1, "Failed to execute SQL statement: HAVING argument must appear in the GROUP BY clause or be used in an aggregate function"
     -- </select5-9.2>
 })
 
@@ -444,7 +444,7 @@ test:do_catchsql_test(
         SELECT s1 FROM te40 HAVING SUM(s1) = 2;
     ]], {
     -- <select5-9.3>
-    1, "SQL error: HAVING argument must appear in the GROUP BY clause or be used in an aggregate function"
+    1, "Failed to execute SQL statement: HAVING argument must appear in the GROUP BY clause or be used in an aggregate function"
     -- </select5-9.3>
 })
 
@@ -484,7 +484,7 @@ test:do_catchsql_test(
         SELECT SUM(s1),s2 FROM te40 HAVING SUM(s1) > 0;
     ]], {
     -- <select5-9.7>
-    1, "SQL error: HAVING argument must appear in the GROUP BY clause or be used in an aggregate function"
+    1, "Failed to execute SQL statement: HAVING argument must appear in the GROUP BY clause or be used in an aggregate function"
     -- </select5-9.7>
 })
 
@@ -494,7 +494,7 @@ test:do_catchsql_test(
         SELECT SUM(s1) FROM te40 HAVING SUM(s1) > 0 and s2 > 0;
     ]], {
     -- <select5-9.8>
-    1, "SQL error: HAVING argument must appear in the GROUP BY clause or be used in an aggregate function"
+    1, "Failed to execute SQL statement: HAVING argument must appear in the GROUP BY clause or be used in an aggregate function"
     -- </select5-9.8>
 })
 
diff --git a/test/sql-tap/trigger1.test.lua b/test/sql-tap/trigger1.test.lua
index 64763fa..38d7c55 100755
--- a/test/sql-tap/trigger1.test.lua
+++ b/test/sql-tap/trigger1.test.lua
@@ -260,7 +260,7 @@ test:do_catchsql_test(
         end;
     ]], {
         -- <trigger1-1.12>
-        1, "SQL error: cannot create INSTEAD OF trigger on space: T1"
+        1, "Failed to execute SQL statement: cannot create INSTEAD OF trigger on space: T1"
         -- </trigger1-1.12>
     })
 
@@ -274,7 +274,7 @@ test:do_catchsql_test(
         end;
     ]], {
         -- <trigger1-1.13>
-        1, "SQL error: cannot create BEFORE trigger on view: V1"
+        1, "Failed to execute SQL statement: cannot create BEFORE trigger on view: V1"
         -- </trigger1-1.13>
     })
 
@@ -289,7 +289,7 @@ test:do_catchsql_test(
         end;
     ]], {
         -- <trigger1-1.14>
-        1, "SQL error: cannot create AFTER trigger on view: V1"
+        1, "Failed to execute SQL statement: cannot create AFTER trigger on view: V1"
         -- </trigger1-1.14>
     })
 
diff --git a/test/sql/delete.result b/test/sql/delete.result
index 0e442e5..0bc389f 100644
--- a/test/sql/delete.result
+++ b/test/sql/delete.result
@@ -128,7 +128,8 @@ box.execute("CREATE VIEW v1 AS SELECT * FROM t1;")
 ...
 box.execute("TRUNCATE TABLE v1;")
 ---
-- error: 'SQL error: can not truncate space ''V1'' because space is a view'
+- error: 'Failed to execute SQL statement: can not truncate space ''V1'' because space
+    is a view'
 ...
 -- Can't truncate table with FK.
 box.execute("CREATE TABLE t2(x INT PRIMARY KEY REFERENCES t1(id));")
@@ -137,8 +138,8 @@ box.execute("CREATE TABLE t2(x INT PRIMARY KEY REFERENCES t1(id));")
 ...
 box.execute("TRUNCATE TABLE t1;")
 ---
-- error: 'SQL error: can not truncate space ''T1'' because other objects depend on
-    it'
+- error: 'Failed to execute SQL statement: can not truncate space ''T1'' because other
+    objects depend on it'
 ...
 -- Table triggers should be ignored.
 box.execute("DROP TABLE t2;")
diff --git a/test/sql/on-conflict.result b/test/sql/on-conflict.result
index 2f29f5b..be89caf 100644
--- a/test/sql/on-conflict.result
+++ b/test/sql/on-conflict.result
@@ -59,8 +59,8 @@ box.execute("CREATE TABLE te17 (s1 INT NULL PRIMARY KEY);")
 ...
 box.execute("CREATE TABLE test (a int PRIMARY KEY, b int NULL ON CONFLICT IGNORE);")
 ---
-- error: 'SQL error: NULL declaration for column ''B'' of table ''TEST'' has been
-    already set to ''none'''
+- error: 'Failed to execute SQL statement: NULL declaration for column ''B'' of table
+    ''TEST'' has been already set to ''none'''
 ...
 box.execute("CREATE TABLE test (a int, b int NULL, c int, PRIMARY KEY(a, b, c))")
 ---
diff --git a/test/sql/triggers.result b/test/sql/triggers.result
index 38fe32c..307b390 100644
--- a/test/sql/triggers.result
+++ b/test/sql/triggers.result
@@ -45,22 +45,24 @@ tuple = {"T1t", space_id, {sql = "CREATE TRIGGER t1t AFTER INSERT ON t1 FOR EACH
 ...
 box.space._trigger:insert(tuple)
 ---
-- error: 'SQL error: trigger name does not match extracted from SQL'
+- error: 'Failed to execute SQL statement: trigger name does not match extracted from
+    SQL'
 ...
 tuple = {"T1t", space_id, {sql = "CREATE TRIGGER t12t AFTER INSERT ON t1 FOR EACH ROW BEGIN INSERT INTO t2 VALUES(1); END;"}}
 ---
 ...
 box.space._trigger:insert(tuple)
 ---
-- error: 'SQL error: trigger name does not match extracted from SQL'
+- error: 'Failed to execute SQL statement: trigger name does not match extracted from
+    SQL'
 ...
 tuple = {"T2T", box.space.T1.id + 1, {sql = "CREATE TRIGGER t2t AFTER INSERT ON t1 FOR EACH ROW BEGIN INSERT INTO t2 VALUES(1); END;"}}
 ---
 ...
 box.space._trigger:insert(tuple)
 ---
-- error: 'SQL error: trigger space_id does not match the value resolved on AST building
-    from SQL'
+- error: 'Failed to execute SQL statement: trigger space_id does not match the value
+    resolved on AST building from SQL'
 ...
 immutable_part(box.space._trigger:select())
 ---
@@ -244,7 +246,8 @@ tuple = {"T1T", space_id, {sql = [[create trigger t1t instead of update on t1 fo
 ...
 box.space._trigger:insert(tuple)
 ---
-- error: 'SQL error: cannot create INSTEAD OF trigger on space: T1'
+- error: 'Failed to execute SQL statement: cannot create INSTEAD OF trigger on space:
+    T1'
 ...
 box.execute("CREATE VIEW V1 AS SELECT * FROM t1;")
 ---
@@ -258,14 +261,14 @@ tuple = {"V1T", space_id, {sql = [[create trigger v1t before update on v1 for ea
 ...
 box.space._trigger:insert(tuple)
 ---
-- error: 'SQL error: cannot create BEFORE trigger on view: V1'
+- error: 'Failed to execute SQL statement: cannot create BEFORE trigger on view: V1'
 ...
 tuple = {"V1T", space_id, {sql = [[create trigger v1t AFTER update on v1 for each row begin delete from t1 WHERE a=old.a+2; end;]]}}
 ---
 ...
 box.space._trigger:insert(tuple)
 ---
-- error: 'SQL error: cannot create AFTER trigger on view: V1'
+- error: 'Failed to execute SQL statement: cannot create AFTER trigger on view: V1'
 ...
 space_id =  box.space._fk_constraint.id
 ---
@@ -275,7 +278,7 @@ tuple = {"T1T", space_id, {sql = [[create trigger t1t instead of update on "_fk_
 ...
 box.space._trigger:insert(tuple)
 ---
-- error: 'SQL error: cannot create trigger on system table'
+- error: 'Failed to execute SQL statement: cannot create trigger on system table'
 ...
 box.execute("DROP VIEW V1;")
 ---
-- 
2.7.4

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [tarantool-patches] [PATCH v1 4/9] sql: rework diag_set() in OP_Halt
  2019-05-28 11:39 [tarantool-patches] [PATCH v1 0/9] sql: set errors in VDBE using diag_set() imeevma
                   ` (2 preceding siblings ...)
  2019-05-28 11:39 ` [tarantool-patches] [PATCH v1 3/9] sql: remove error ER_SQL imeevma
@ 2019-05-28 11:39 ` imeevma
  2019-06-02 16:35   ` [tarantool-patches] " Vladislav Shpilevoy
  2019-05-28 11:39 ` [tarantool-patches] [PATCH v1 5/9] sql: make SQL_TARANTOOL_ERROR the only errcode of OP_Halt imeevma
                   ` (6 subsequent siblings)
  10 siblings, 1 reply; 25+ messages in thread
From: imeevma @ 2019-05-28 11:39 UTC (permalink / raw)
  To: v.shpilevoy; +Cc: tarantool-patches

Prior to this patch, the way to set Tarantool error in OP_Halt was
too universal. It was possible to set a description of the error
that does not match its errcode. This change will also make it
easier to work with an error in OP_Halt, since you no longer need
to create a complete error message.

Example of wrong error code:
...

tarantool> box.execute('select 1 limit true')
---
- error: Only positive integers are allowed in the LIMIT clause
...

tarantool> box.error.last().code
---
- 0
...
---
 src/box/sql/build.c             |  9 ++-------
 src/box/sql/select.c            | 13 ++++++-------
 src/box/sql/trigger.c           | 12 ++++--------
 src/box/sql/vdbe.c              |  9 +++------
 test/sql-tap/e_select1.test.lua |  4 ++--
 test/sql-tap/limit.test.lua     | 26 +++++++++++++-------------
 test/sql-tap/select4.test.lua   |  8 ++++----
 test/sql-tap/subselect.test.lua |  6 +++---
 test/sql-tap/tkt1473.test.lua   | 36 ++++++++++++++++++------------------
 test/sql/iproto.result          | 18 ++++++++++++------
 test/sql/types.result           |  9 ++++++---
 11 files changed, 73 insertions(+), 77 deletions(-)

diff --git a/src/box/sql/build.c b/src/box/sql/build.c
index 41813ed..327f6a8 100644
--- a/src/box/sql/build.c
+++ b/src/box/sql/build.c
@@ -1009,12 +1009,10 @@ vdbe_emit_fk_constraint_create(struct Parse *parse_context,
 	 * Lets check that constraint with this name hasn't
 	 * been created before.
 	 */
-	const char *error_msg =
-		tt_sprintf(tnt_errcode_desc(ER_CONSTRAINT_EXISTS), name_copy);
 	if (vdbe_emit_halt_with_presence_test(parse_context,
 					      BOX_FK_CONSTRAINT_ID, 0,
 					      constr_tuple_reg, 2,
-					      ER_CONSTRAINT_EXISTS, error_msg,
+					      ER_CONSTRAINT_EXISTS, name_copy,
 					      false, OP_NoConflict) != 0)
 		return;
 	sqlVdbeAddOp2(vdbe, OP_Bool, fk->is_deferred, constr_tuple_reg + 3);
@@ -1397,13 +1395,10 @@ vdbe_emit_fk_constraint_drop(struct Parse *parse_context, char *constraint_name,
 	sqlVdbeAddOp4(vdbe, OP_String8, 0, key_reg, 0, constraint_name,
 			  P4_DYNAMIC);
 	sqlVdbeAddOp2(vdbe, OP_Integer, child_id,  key_reg + 1);
-	const char *error_msg =
-		tt_sprintf(tnt_errcode_desc(ER_NO_SUCH_CONSTRAINT),
-			   constraint_name);
 	if (vdbe_emit_halt_with_presence_test(parse_context,
 					      BOX_FK_CONSTRAINT_ID, 0,
 					      key_reg, 2, ER_NO_SUCH_CONSTRAINT,
-					      error_msg, false,
+					      constraint_name, false,
 					      OP_Found) != 0) {
 		sqlDbFree(parse_context->db, constraint_name);
 		return;
diff --git a/src/box/sql/select.c b/src/box/sql/select.c
index d3472a9..3f0b540 100644
--- a/src/box/sql/select.c
+++ b/src/box/sql/select.c
@@ -2116,6 +2116,7 @@ computeLimitRegisters(Parse * pParse, Select * p, int iBreak)
 				  0, 0,
 				  wrong_limit_error,
 				  P4_STATIC);
+		sqlVdbeChangeP5(v, ER_SQL_EXECUTE);
 
 		sqlVdbeResolveLabel(v, positive_limit_label);
 		VdbeCoverage(v);
@@ -2142,9 +2143,8 @@ computeLimitRegisters(Parse * pParse, Select * p, int iBreak)
 				sqlVdbeAddOp2(v, OP_Integer, 1, r1);
 				int no_err = sqlVdbeMakeLabel(v);
 				sqlVdbeAddOp3(v, OP_Eq, iLimit, no_err, r1);
-				const char *error =
-					"SQL error: Expression subquery could "
-					"be limited only with 1";
+				const char *error = "Expression subquery could "
+						    "be limited only with 1";
 				sqlVdbeAddOp4(v, OP_Halt,
 						  SQL_TARANTOOL_ERROR,
 						  0, 0, error, P4_STATIC);
@@ -2178,6 +2178,7 @@ computeLimitRegisters(Parse * pParse, Select * p, int iBreak)
 					  0, 0,
 					  wrong_offset_error,
 					  P4_STATIC);
+			sqlVdbeChangeP5(v, ER_SQL_EXECUTE);
 
 			sqlVdbeResolveLabel(v, positive_offset_label);
             		sqlReleaseTempReg(pParse, r1);
@@ -5446,10 +5447,8 @@ vdbe_code_raise_on_multiple_rows(struct Parse *parser, int limit_reg, int end_ma
 	int r1 = sqlGetTempReg(parser);
 	sqlVdbeAddOp2(v, OP_Integer, 0, r1);
 	sqlVdbeAddOp3(v, OP_Ne, r1, end_mark, limit_reg);
-	const char *error =
-		"SQL error: Expression subquery returned more than 1 row";
-	sqlVdbeAddOp4(v, OP_Halt, SQL_TARANTOOL_ERROR, 0, 0, error,
-			  P4_STATIC);
+	const char *error = "Expression subquery returned more than 1 row";
+	sqlVdbeAddOp4(v, OP_Halt, SQL_TARANTOOL_ERROR, 0, 0, error, P4_STATIC);
 	sqlVdbeChangeP5(v, ER_SQL_EXECUTE);
 	sqlReleaseTempReg(parser, r1);
 }
diff --git a/src/box/sql/trigger.c b/src/box/sql/trigger.c
index 0a4cd09..cf0abbd 100644
--- a/src/box/sql/trigger.c
+++ b/src/box/sql/trigger.c
@@ -99,9 +99,6 @@ sql_trigger_begin(struct Parse *parse)
 		struct Vdbe *v = sqlGetVdbe(parse);
 		if (v != NULL)
 			sqlVdbeCountChanges(v);
-		const char *error_msg =
-			tt_sprintf(tnt_errcode_desc(ER_TRIGGER_EXISTS),
-				   trigger_name);
 		char *name_copy = sqlDbStrDup(db, trigger_name);
 		if (name_copy == NULL)
 			goto trigger_cleanup;
@@ -112,7 +109,8 @@ sql_trigger_begin(struct Parse *parse)
 		if (vdbe_emit_halt_with_presence_test(parse, BOX_TRIGGER_ID, 0,
 						      name_reg, 1,
 						      ER_TRIGGER_EXISTS,
-						      error_msg, (no_err != 0),
+						      trigger_name,
+						      (no_err != 0),
 						      OP_NoConflict) != 0)
 			goto trigger_cleanup;
 	}
@@ -411,9 +409,6 @@ sql_drop_trigger(struct Parse *parser)
 
 	assert(name->nSrc == 1);
 	const char *trigger_name = name->a[0].zName;
-	const char *error_msg =
-		tt_sprintf(tnt_errcode_desc(ER_NO_SUCH_TRIGGER),
-			   trigger_name);
 	char *name_copy = sqlDbStrDup(db, trigger_name);
 	if (name_copy == NULL)
 		goto drop_trigger_cleanup;
@@ -421,7 +416,8 @@ sql_drop_trigger(struct Parse *parser)
 	sqlVdbeAddOp4(v, OP_String8, 0, name_reg, 0, name_copy, P4_DYNAMIC);
 	if (vdbe_emit_halt_with_presence_test(parser, BOX_TRIGGER_ID, 0,
 					      name_reg, 1, ER_NO_SUCH_TRIGGER,
-					      error_msg, no_err, OP_Found) != 0)
+					      trigger_name,
+					      no_err, OP_Found) != 0)
 		goto drop_trigger_cleanup;
 
 	vdbe_code_drop_trigger(parser, trigger_name, true);
diff --git a/src/box/sql/vdbe.c b/src/box/sql/vdbe.c
index a64c846..3c2cd2b 100644
--- a/src/box/sql/vdbe.c
+++ b/src/box/sql/vdbe.c
@@ -1032,12 +1032,9 @@ case OP_Halt: {
 	p->pc = pcx;
 	if (p->rc) {
 		if (p->rc == SQL_TARANTOOL_ERROR) {
-			if (pOp->p4.z == NULL) {
-				assert(! diag_is_empty(diag_get()));
-			} else {
-				box_error_set(__FILE__, __LINE__, pOp->p5,
-					      pOp->p4.z);
-			}
+			if (pOp->p4.z != NULL)
+				diag_set(ClientError, pOp->p5, pOp->p4.z);
+			assert(! diag_is_empty(diag_get()));
 		} else if (pOp->p5 != 0) {
 			static const char * const azType[] = { "NOT NULL", "UNIQUE", "CHECK",
 							       "FOREIGN KEY" };
diff --git a/test/sql-tap/e_select1.test.lua b/test/sql-tap/e_select1.test.lua
index 6f17471..9968038 100755
--- a/test/sql-tap/e_select1.test.lua
+++ b/test/sql-tap/e_select1.test.lua
@@ -2170,7 +2170,7 @@ for _, val in ipairs({
         "e_select-9.2."..tn,
         select,
         {
-            1, "Only positive integers are allowed in the LIMIT clause"})
+            1, "Failed to execute SQL statement: Only positive integers are allowed in the LIMIT clause"})
 end
 
 -- EVIDENCE-OF: R-03014-26414 If the LIMIT expression evaluates to a
@@ -2224,7 +2224,7 @@ for _, val in ipairs({
     test:do_catchsql_test(
         "e_select-9.7."..tn,
         select, {
-            1, "Only positive integers are allowed in the OFFSET clause"
+            1, "Failed to execute SQL statement: Only positive integers are allowed in the OFFSET clause"
         })
 
 end
diff --git a/test/sql-tap/limit.test.lua b/test/sql-tap/limit.test.lua
index 9b728d8..40b787b 100755
--- a/test/sql-tap/limit.test.lua
+++ b/test/sql-tap/limit.test.lua
@@ -84,7 +84,7 @@ test:do_catchsql_test(
         SELECT x FROM t1 ORDER BY x+1 LIMIT 5 OFFSET -2
     ]], {
         -- <limit-1.2.13>
-        1 ,"Only positive integers are allowed in the OFFSET clause"
+        1 ,"Failed to execute SQL statement: Only positive integers are allowed in the OFFSET clause"
         -- </limit-1.2.13>
     })
 
@@ -94,7 +94,7 @@ test:do_catchsql_test(
         SELECT x FROM t1 ORDER BY x+1 LIMIT 2, -5
     ]], {
         -- <limit-1.2.4>
-        1, "Only positive integers are allowed in the LIMIT clause"
+        1, "Failed to execute SQL statement: Only positive integers are allowed in the LIMIT clause"
         -- </limit-1.2.4>
     })
 
@@ -115,7 +115,7 @@ test:do_catchsql_test(
         SELECT x FROM t1 ORDER BY x+1 LIMIT -2, 5
     ]], {
         -- <limit-1.2.6>
-        1, "Only positive integers are allowed in the OFFSET clause"
+        1, "Failed to execute SQL statement: Only positive integers are allowed in the OFFSET clause"
         -- </limit-1.2.6>
     })
 
@@ -135,7 +135,7 @@ test:do_catchsql_test(
         SELECT x FROM t1 ORDER BY x+1 LIMIT -2, -5
     ]], {
         -- <limit-1.2.8>
-        1, "Only positive integers are allowed in the LIMIT clause"
+        1, "Failed to execute SQL statement: Only positive integers are allowed in the LIMIT clause"
         -- </limit-1.2.8>
     })
 
@@ -384,7 +384,7 @@ test:do_catchsql_test(
         SELECT * FROM t6 LIMIT -1 OFFSET -1;
     ]], {
         -- <limit-6.2>
-        1, "Only positive integers are allowed in the LIMIT clause"
+        1, "Failed to execute SQL statement: Only positive integers are allowed in the LIMIT clause"
         -- </limit-6.2>
     })
 
@@ -394,7 +394,7 @@ test:do_catchsql_test(
         SELECT * FROM t6 LIMIT 2 OFFSET -123;
     ]], {
         -- <limit-6.3>
-        1, "Only positive integers are allowed in the OFFSET clause"
+        1, "Failed to execute SQL statement: Only positive integers are allowed in the OFFSET clause"
         -- </limit-6.3>
     })
 
@@ -414,7 +414,7 @@ test:do_catchsql_test(
         SELECT * FROM t6 LIMIT -432 OFFSET 2;
     ]], {
         -- <limit-6.4>
-        1, "Only positive integers are allowed in the LIMIT clause"
+        1, "Failed to execute SQL statement: Only positive integers are allowed in the LIMIT clause"
         -- </limit-6.4>
     })
 
@@ -434,7 +434,7 @@ test:do_catchsql_test(
         SELECT * FROM t6 LIMIT -1
     ]], {
         -- <limit-6.5>
-        1, "Only positive integers are allowed in the LIMIT clause"
+        1, "Failed to execute SQL statement: Only positive integers are allowed in the LIMIT clause"
         -- </limit-6.5>
     })
 
@@ -454,7 +454,7 @@ test:do_catchsql_test(
         SELECT * FROM t6 LIMIT -1 OFFSET 1
     ]], {
         -- <limit-6.6>
-        1, "Only positive integers are allowed in the LIMIT clause"
+        1, "Failed to execute SQL statement: Only positive integers are allowed in the LIMIT clause"
         -- </limit-6.6>
     })
 
@@ -734,7 +734,7 @@ test:do_test(
         return test:catchsql("SELECT x FROM t1 WHERE x<10 LIMIT "..limit)
     end, {
         -- <limit-10.4>
-        1, "Only positive integers are allowed in the LIMIT clause"
+        1, "Failed to execute SQL statement: Only positive integers are allowed in the LIMIT clause"
         -- </limit-10.4>
     })
 
@@ -745,7 +745,7 @@ test:do_test(
         return test:catchsql("SELECT x FROM t1 WHERE x<10 LIMIT "..limit)
     end, {
         -- <limit-10.5>
-        1, "Only positive integers are allowed in the LIMIT clause"
+        1, "Failed to execute SQL statement: Only positive integers are allowed in the LIMIT clause"
         -- </limit-10.5>
     })
 
@@ -1320,7 +1320,7 @@ test:do_catchsql_test(
         SELECT 123 LIMIT -1 OFFSET 0
     ]], {
         -- <limit-14.6.1>
-        1, "Only positive integers are allowed in the LIMIT clause"
+        1, "Failed to execute SQL statement: Only positive integers are allowed in the LIMIT clause"
         -- </limit-14.6.1>
     })
 
@@ -1340,7 +1340,7 @@ test:do_catchsql_test(
         SELECT 123 LIMIT -1 OFFSET 1
     ]], {
         -- <limit-14.7.1>
-        1, "Only positive integers are allowed in the LIMIT clause"
+        1, "Failed to execute SQL statement: Only positive integers are allowed in the LIMIT clause"
         -- </limit-14.7.1>
     })
 
diff --git a/test/sql-tap/select4.test.lua b/test/sql-tap/select4.test.lua
index b78091b..1c0804b 100755
--- a/test/sql-tap/select4.test.lua
+++ b/test/sql-tap/select4.test.lua
@@ -990,7 +990,7 @@ test:do_catchsql_test(
         SELECT DISTINCT log FROM t1 ORDER BY log LIMIT -1
     ]], {
         -- <select4-10.4.1>
-    1,"Only positive integers are allowed in the LIMIT clause"
+    1,"Failed to execute SQL statement: Only positive integers are allowed in the LIMIT clause"
         -- </select4-10.4.1>
     })
 test:do_execsql_test(
@@ -1009,7 +1009,7 @@ test:do_catchsql_test(
         SELECT DISTINCT log FROM t1 ORDER BY log LIMIT -1 OFFSET 2
     ]], {
         -- <select4-10.5.1>
-        1,"Only positive integers are allowed in the LIMIT clause"
+        1,"Failed to execute SQL statement: Only positive integers are allowed in the LIMIT clause"
         -- </select4-10.5.1>
     })
 test:do_execsql_test(
@@ -1402,7 +1402,7 @@ test:do_catchsql_test(
         SELECT (VALUES(1),(2),(3),(4))
     ]], {
         -- <select4-14.10>
-        1, "SQL error: Expression subquery returned more than 1 row"
+        1, "Failed to execute SQL statement: Expression subquery returned more than 1 row"
         -- </select4-14.10>
     })
 
@@ -1412,7 +1412,7 @@ test:do_catchsql_test(
         SELECT (SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4)
     ]], {
         -- <select4-14.11>
-        1, "SQL error: Expression subquery returned more than 1 row"
+        1, "Failed to execute SQL statement: Expression subquery returned more than 1 row"
         -- </select4-14.11>
     })
 
diff --git a/test/sql-tap/subselect.test.lua b/test/sql-tap/subselect.test.lua
index 5b71390..ebfdf43 100755
--- a/test/sql-tap/subselect.test.lua
+++ b/test/sql-tap/subselect.test.lua
@@ -350,7 +350,7 @@ test:do_catchsql_test(
         SELECT (SELECT a FROM t5);
     ]], {
     -- <subselect-5.1>
-    1, "SQL error: Expression subquery returned more than 1 row"
+    1, "Failed to execute SQL statement: Expression subquery returned more than 1 row"
     -- </subselect-5.1>
 })
 
@@ -360,7 +360,7 @@ test:do_catchsql_test(
         SELECT b FROM t5 WHERE a = (SELECT a FROM t5 WHERE b=6);
     ]], {
     -- <subselect-5.2>
-    1, "SQL error: Expression subquery returned more than 1 row"
+    1, "Failed to execute SQL statement: Expression subquery returned more than 1 row"
     -- </subselect-5.2>
 })
 
@@ -380,7 +380,7 @@ test:do_catchsql_test(
         SELECT b FROM t1 WHERE a = (SELECT a FROM t1 WHERE b=6 LIMIT (SELECT b FROM t1 WHERE a =1));
     ]], {
     -- <subselect-5.2>
-    1, "SQL error: Expression subquery could be limited only with 1"
+    1, "Failed to execute SQL statement: Expression subquery could be limited only with 1"
     -- </subselect-5.2>
 })
 
diff --git a/test/sql-tap/tkt1473.test.lua b/test/sql-tap/tkt1473.test.lua
index 3e93203..ada18d0 100755
--- a/test/sql-tap/tkt1473.test.lua
+++ b/test/sql-tap/tkt1473.test.lua
@@ -125,7 +125,7 @@ test:do_catchsql_test(
         SELECT (SELECT 1 FROM t1 WHERE a=1 UNION ALL SELECT 2 FROM t1 WHERE b=0)
     ]], {
         -- <tkt1473-2.2>
-        1, "SQL error: Expression subquery returned more than 1 row"
+        1, "Failed to execute SQL statement: Expression subquery returned more than 1 row"
         -- </tkt1473-2.2>
     })
 
@@ -145,7 +145,7 @@ test:do_catchsql_test(
         SELECT (SELECT 1 FROM t1 WHERE a=1 UNION ALL SELECT 2 FROM t1 WHERE b=4)
     ]], {
         -- <tkt1473-2.4>
-        1, "SQL error: Expression subquery returned more than 1 row"
+        1, "Failed to execute SQL statement: Expression subquery returned more than 1 row"
         -- </tkt1473-2.4>
     })
 
@@ -155,7 +155,7 @@ test:do_catchsql_test(
         SELECT (SELECT 1 FROM t1 WHERE a=1 UNION SELECT 2 FROM t1 WHERE b=4)
     ]], {
         -- <tkt1473-2.5>
-        1, "SQL error: Expression subquery returned more than 1 row"
+        1, "Failed to execute SQL statement: Expression subquery returned more than 1 row"
         -- </tkt1473-2.5>
     })
 
@@ -165,7 +165,7 @@ test:do_catchsql_test(
         SELECT (SELECT 1 FROM t1 WHERE a=0 UNION ALL SELECT 2 FROM t1 WHERE b=4)
     ]], {
         -- <tkt1473-2.6>
-        1, "SQL error: Expression subquery returned more than 1 row"
+        1, "Failed to execute SQL statement: Expression subquery returned more than 1 row"
         -- </tkt1473-2.6>
     })
 
@@ -206,7 +206,7 @@ test:do_catchsql_test(
           (SELECT 1 FROM t1 WHERE a=1 UNION ALL SELECT 2 FROM t1 WHERE b=0)
     ]], {
         -- <tkt1473-3.2>
-        1, "SQL error: Expression subquery returned more than 1 row"
+        1, "Failed to execute SQL statement: Expression subquery returned more than 1 row"
         -- </tkt1473-3.2>
     })
 
@@ -228,7 +228,7 @@ test:do_catchsql_test(
           (SELECT 1 FROM t1 WHERE a=1 UNION ALL SELECT 2 FROM t1 WHERE b=4)
     ]], {
         -- <tkt1473-3.4>
-        1, "SQL error: Expression subquery returned more than 1 row"
+        1, "Failed to execute SQL statement: Expression subquery returned more than 1 row"
         -- </tkt1473-3.4>
     })
 
@@ -239,7 +239,7 @@ test:do_catchsql_test(
           (SELECT 1 FROM t1 WHERE a=1 UNION SELECT 2 FROM t1 WHERE b=4)
     ]], {
         -- <tkt1473-3.5>
-        1, "SQL error: Expression subquery returned more than 1 row"
+        1, "Failed to execute SQL statement: Expression subquery returned more than 1 row"
         -- </tkt1473-3.5>
     })
 
@@ -250,7 +250,7 @@ test:do_catchsql_test(
           (SELECT 1 FROM t1 WHERE a=0 UNION ALL SELECT 2 FROM t1 WHERE b=4)
     ]], {
         -- <tkt1473-3.6>
-        1, "SQL error: Expression subquery returned more than 1 row"
+        1, "Failed to execute SQL statement: Expression subquery returned more than 1 row"
         -- </tkt1473-3.6>
     })
 
@@ -359,7 +359,7 @@ test:do_catchsql_test(
         )
     ]], {
         -- <tkt1473-4.3>
-        1, "SQL error: Expression subquery returned more than 1 row"
+        1, "Failed to execute SQL statement: Expression subquery returned more than 1 row"
         -- </tkt1473-4.3>
     })
 
@@ -389,7 +389,7 @@ test:do_catchsql_test(
         )
     ]], {
         -- <tkt1473-4.4>
-        1, "SQL error: Expression subquery returned more than 1 row"
+        1, "Failed to execute SQL statement: Expression subquery returned more than 1 row"
         -- </tkt1473-4.4>
     })
 
@@ -419,7 +419,7 @@ test:do_catchsql_test(
         )
     ]], {
         -- <tkt1473-4.5>
-        1, "SQL error: Expression subquery returned more than 1 row"
+        1, "Failed to execute SQL statement: Expression subquery returned more than 1 row"
         -- </tkt1473-4.5>
     })
 
@@ -449,7 +449,7 @@ test:do_catchsql_test(
         )
     ]], {
         -- <tkt1473-4.6>
-        1, "SQL error: Expression subquery returned more than 1 row"
+        1, "Failed to execute SQL statement: Expression subquery returned more than 1 row"
         -- </tkt1473-4.6>
     })
 
@@ -509,7 +509,7 @@ test:do_catchsql_test(
         )
     ]], {
         -- <tkt1473-5.3>
-        1, "SQL error: Expression subquery returned more than 1 row"
+        1, "Failed to execute SQL statement: Expression subquery returned more than 1 row"
         -- </tkt1473-5.3>
     })
 
@@ -539,7 +539,7 @@ test:do_catchsql_test(
         )
     ]], {
         -- <tkt1473-5.4>
-        1, "SQL error: Expression subquery returned more than 1 row"
+        1, "Failed to execute SQL statement: Expression subquery returned more than 1 row"
         -- </tkt1473-5.4>
     })
 
@@ -569,7 +569,7 @@ test:do_catchsql_test(
         )
     ]], {
         -- <tkt1473-5.5>
-        1, "SQL error: Expression subquery returned more than 1 row"
+        1, "Failed to execute SQL statement: Expression subquery returned more than 1 row"
         -- </tkt1473-5.5>
     })
 
@@ -599,7 +599,7 @@ test:do_catchsql_test(
         )
     ]], {
         -- <tkt1473-5.6>
-        1, "SQL error: Expression subquery returned more than 1 row"
+        1, "Failed to execute SQL statement: Expression subquery returned more than 1 row"
         -- </tkt1473-5.6>
     })
 
@@ -659,7 +659,7 @@ test:do_catchsql_test(
         )
     ]], {
         -- <tkt1473-6.3>
-        1, "SQL error: Expression subquery returned more than 1 row"
+        1, "Failed to execute SQL statement: Expression subquery returned more than 1 row"
         -- </tkt1473-6.3>
     })
 
@@ -689,7 +689,7 @@ test:do_catchsql_test(
         )
     ]], {
         -- <tkt1473-6.4>
-        1, "SQL error: Expression subquery returned more than 1 row"
+        1, "Failed to execute SQL statement: Expression subquery returned more than 1 row"
         -- </tkt1473-6.4>
     })
 
diff --git a/test/sql/iproto.result b/test/sql/iproto.result
index 73497b4..9639ba7 100644
--- a/test/sql/iproto.result
+++ b/test/sql/iproto.result
@@ -164,15 +164,18 @@ cn:execute('select * from test limit ?', {2})
 ...
 cn:execute('select * from test limit ?', {-2})
 ---
-- error: Only positive integers are allowed in the LIMIT clause
+- error: 'Failed to execute SQL statement: Only positive integers are allowed in the
+    LIMIT clause'
 ...
 cn:execute('select * from test limit ?', {2.7})
 ---
-- error: Only positive integers are allowed in the LIMIT clause
+- error: 'Failed to execute SQL statement: Only positive integers are allowed in the
+    LIMIT clause'
 ...
 cn:execute('select * from test limit ?', {'Hello'})
 ---
-- error: Only positive integers are allowed in the LIMIT clause
+- error: 'Failed to execute SQL statement: Only positive integers are allowed in the
+    LIMIT clause'
 ...
 cn:execute('select * from test limit 1 offset ?', {2})
 ---
@@ -188,15 +191,18 @@ cn:execute('select * from test limit 1 offset ?', {2})
 ...
 cn:execute('select * from test limit 1 offset ?', {-2})
 ---
-- error: Only positive integers are allowed in the OFFSET clause
+- error: 'Failed to execute SQL statement: Only positive integers are allowed in the
+    OFFSET clause'
 ...
 cn:execute('select * from test limit 1 offset ?', {2.7})
 ---
-- error: Only positive integers are allowed in the OFFSET clause
+- error: 'Failed to execute SQL statement: Only positive integers are allowed in the
+    OFFSET clause'
 ...
 cn:execute('select * from test limit 1 offset ?', {'Hello'})
 ---
-- error: Only positive integers are allowed in the OFFSET clause
+- error: 'Failed to execute SQL statement: Only positive integers are allowed in the
+    OFFSET clause'
 ...
 -- gh-2608 SQL iproto DDL
 cn:execute('create table test2(id int primary key, a int, b int, c int)')
diff --git a/test/sql/types.result b/test/sql/types.result
index a53d6f7..572a83c 100644
--- a/test/sql/types.result
+++ b/test/sql/types.result
@@ -383,11 +383,13 @@ box.execute("SELECT true IN (1, 'abc', false)")
 ...
 box.execute("SELECT 1 LIMIT true;")
 ---
-- error: Only positive integers are allowed in the LIMIT clause
+- error: 'Failed to execute SQL statement: Only positive integers are allowed in the
+    LIMIT clause'
 ...
 box.execute("SELECT 1 LIMIT 1 OFFSET true;")
 ---
-- error: Only positive integers are allowed in the OFFSET clause
+- error: 'Failed to execute SQL statement: Only positive integers are allowed in the
+    OFFSET clause'
 ...
 box.execute("SELECT 'abc' || true;")
 ---
@@ -551,7 +553,8 @@ box.execute("SELECT b FROM t GROUP BY b LIMIT 1;")
 ...
 box.execute("SELECT b FROM t LIMIT true;")
 ---
-- error: Only positive integers are allowed in the LIMIT clause
+- error: 'Failed to execute SQL statement: Only positive integers are allowed in the
+    LIMIT clause'
 ...
 -- Most of aggregates don't accept boolean arguments.
 --
-- 
2.7.4

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [tarantool-patches] [PATCH v1 5/9] sql: make SQL_TARANTOOL_ERROR the only errcode of OP_Halt
  2019-05-28 11:39 [tarantool-patches] [PATCH v1 0/9] sql: set errors in VDBE using diag_set() imeevma
                   ` (3 preceding siblings ...)
  2019-05-28 11:39 ` [tarantool-patches] [PATCH v1 4/9] sql: rework diag_set() in OP_Halt imeevma
@ 2019-05-28 11:39 ` imeevma
  2019-06-02 16:35   ` [tarantool-patches] " Vladislav Shpilevoy
  2019-05-28 11:39 ` [tarantool-patches] [PATCH v1 6/9] sql: remove error SQL_INTERRUPT imeevma
                   ` (5 subsequent siblings)
  10 siblings, 1 reply; 25+ messages in thread
From: imeevma @ 2019-05-28 11:39 UTC (permalink / raw)
  To: v.shpilevoy; +Cc: tarantool-patches

Currently, in OP_Halt, you can get a SQL error other than
SQL_TARANTOOL_ERROR, for example, the SQL_CONSTRAINT error. After
this patch, all errors going through OP_Halt will have SQL error
code SQL_TARANTOOL_ERROR and have diag set.

Part of #4074
---
 src/box/sql/build.c         | 20 --------------------
 src/box/sql/expr.c          |  7 ++++---
 src/box/sql/fk_constraint.c |  7 +++----
 src/box/sql/insert.c        | 29 ++++++++++++++---------------
 src/box/sql/sqlInt.h        |  1 -
 src/box/sql/vdbe.c          | 23 ++++-------------------
 6 files changed, 25 insertions(+), 62 deletions(-)

diff --git a/src/box/sql/build.c b/src/box/sql/build.c
index 327f6a8..a0d0088 100644
--- a/src/box/sql/build.c
+++ b/src/box/sql/build.c
@@ -2977,26 +2977,6 @@ sql_set_multi_write(struct Parse *parse_context, bool is_set)
 	pToplevel->isMultiWrite |= is_set;
 }
 
-/*
- * Code an OP_Halt that causes the vdbe to return an SQL_CONSTRAINT
- * error. The onError parameter determines which (if any) of the statement
- * and/or current transaction is rolled back.
- */
-void
-sqlHaltConstraint(Parse * pParse,	/* Parsing context */
-		      int errCode,	/* extended error code */
-		      int onError,	/* Constraint type */
-		      char *p4,	/* Error message */
-		      i8 p4type,	/* P4_STATIC or P4_TRANSIENT */
-		      u8 p5Errmsg	/* P5_ErrMsg type */
-    )
-{
-	Vdbe *v = sqlGetVdbe(pParse);
-	assert((errCode & 0xff) == SQL_CONSTRAINT);
-	sqlVdbeAddOp4(v, OP_Halt, errCode, onError, 0, p4, p4type);
-	sqlVdbeChangeP5(v, p5Errmsg);
-}
-
 #ifndef SQL_OMIT_CTE
 /*
  * This routine is invoked once per CTE by the parser while parsing a
diff --git a/src/box/sql/expr.c b/src/box/sql/expr.c
index 6ac42d7..a4a2d71 100644
--- a/src/box/sql/expr.c
+++ b/src/box/sql/expr.c
@@ -4386,9 +4386,10 @@ sqlExprCodeTarget(Parse * pParse, Expr * pExpr, int target)
 					  ON_CONFLICT_ACTION_IGNORE, 0,
 					  pExpr->u.zToken, 0);
 		} else {
-			sqlHaltConstraint(pParse, SQL_CONSTRAINT_TRIGGER,
-					      pExpr->on_conflict_action,
-					      pExpr->u.zToken, 0, 0);
+			sqlVdbeAddOp4(v, OP_Halt, SQL_TARANTOOL_ERROR,
+				      pExpr->on_conflict_action, 0,
+				      pExpr->u.zToken, 0);
+			sqlVdbeChangeP5(v, ER_SQL_EXECUTE);
 		}
 		break;
 	}
diff --git a/src/box/sql/fk_constraint.c b/src/box/sql/fk_constraint.c
index 7d36edc..602f439 100644
--- a/src/box/sql/fk_constraint.c
+++ b/src/box/sql/fk_constraint.c
@@ -287,10 +287,9 @@ fk_constraint_lookup_parent(struct Parse *parse_context, struct space *parent,
 		 * transaction.
 		 */
 		assert(incr_count == 1);
-		sqlHaltConstraint(parse_context,
-				      SQL_CONSTRAINT_FOREIGNKEY,
-				      ON_CONFLICT_ACTION_ABORT, 0, P4_STATIC,
-				      P5_ConstraintFK);
+		sqlVdbeAddOp4(v, OP_Halt, SQL_TARANTOOL_ERROR, 0, 0, "FOREIGN "\
+			      "KEY constraint failed", P4_STATIC);
+		sqlVdbeChangeP5(v, ER_SQL_EXECUTE);
 	} else {
 		sqlVdbeAddOp2(v, OP_FkCounter, fk_def->is_deferred,
 				  incr_count);
diff --git a/src/box/sql/insert.c b/src/box/sql/insert.c
index 6f50726..a28fcde 100644
--- a/src/box/sql/insert.c
+++ b/src/box/sql/insert.c
@@ -853,7 +853,6 @@ vdbe_emit_constraint_checks(struct Parse *parse_context, struct space *space,
 			    enum on_conflict_action on_conflict,
 			    int ignore_label, int *upd_cols)
 {
-	struct sql *db = parse_context->db;
 	struct Vdbe *v = sqlGetVdbe(parse_context);
 	assert(v != NULL);
 	bool is_update = upd_cols != NULL;
@@ -883,20 +882,18 @@ vdbe_emit_constraint_checks(struct Parse *parse_context, struct space *space,
 		if (on_conflict_nullable == ON_CONFLICT_ACTION_REPLACE &&
 		    dflt == NULL)
 			on_conflict_nullable = ON_CONFLICT_ACTION_ABORT;
-		char *err_msg;
+		const char *err;
 		int addr;
 		switch (on_conflict_nullable) {
 		case ON_CONFLICT_ACTION_ABORT:
 		case ON_CONFLICT_ACTION_ROLLBACK:
 		case ON_CONFLICT_ACTION_FAIL:
-			err_msg = sqlMPrintf(db, "%s.%s", def->name,
-						 def->fields[i].name);
-			sqlVdbeAddOp3(v, OP_HaltIfNull,
-					  SQL_CONSTRAINT_NOTNULL,
-					  on_conflict_nullable,
-					  new_tuple_reg + i);
-			sqlVdbeAppendP4(v, err_msg, P4_DYNAMIC);
-			sqlVdbeChangeP5(v, P5_ConstraintNotNull);
+			err = tt_sprintf("NOT NULL constraint failed: %s.%s",
+					 def->name, def->fields[i].name);
+			sqlVdbeAddOp4(v, OP_HaltIfNull, SQL_TARANTOOL_ERROR,
+				      on_conflict_nullable, new_tuple_reg + i,
+				      err, P4_STATIC);
+			sqlVdbeChangeP5(v, ER_SQL_EXECUTE);
 			break;
 		case ON_CONFLICT_ACTION_IGNORE:
 			sqlVdbeAddOp2(v, OP_IsNull, new_tuple_reg + i,
@@ -939,11 +936,13 @@ vdbe_emit_constraint_checks(struct Parse *parse_context, struct space *space,
 				char *name = checks->a[i].zName;
 				if (name == NULL)
 					name = def->name;
-				sqlHaltConstraint(parse_context,
-						      SQL_CONSTRAINT_CHECK,
-						      on_conflict_check, name,
-						      P4_TRANSIENT,
-						      P5_ConstraintCheck);
+				const char *err =
+					tt_sprintf("CHECK constraint failed: "\
+						   "%s", name);
+				sqlVdbeAddOp4(v, OP_Halt, SQL_TARANTOOL_ERROR,
+					      on_conflict_check, 0, err,
+					      P4_STATIC);
+				sqlVdbeChangeP5(v, ER_SQL_EXECUTE);
 			}
 			sqlVdbeResolveLabel(v, all_ok);
 		}
diff --git a/src/box/sql/sqlInt.h b/src/box/sql/sqlInt.h
index 05a4042..5c71c51 100644
--- a/src/box/sql/sqlInt.h
+++ b/src/box/sql/sqlInt.h
@@ -3912,7 +3912,6 @@ vdbe_emit_insertion_completion(struct Vdbe *v, struct space *space,
 
 void
 sql_set_multi_write(Parse *, bool);
-void sqlHaltConstraint(Parse *, int, int, char *, i8, u8);
 
 Expr *sqlExprDup(sql *, Expr *, int);
 SrcList *sqlSrcListDup(sql *, SrcList *, int);
diff --git a/src/box/sql/vdbe.c b/src/box/sql/vdbe.c
index 3c2cd2b..30ea549 100644
--- a/src/box/sql/vdbe.c
+++ b/src/box/sql/vdbe.c
@@ -1031,25 +1031,10 @@ case OP_Halt: {
 	p->errorAction = (u8)pOp->p2;
 	p->pc = pcx;
 	if (p->rc) {
-		if (p->rc == SQL_TARANTOOL_ERROR) {
-			if (pOp->p4.z != NULL)
-				diag_set(ClientError, pOp->p5, pOp->p4.z);
-			assert(! diag_is_empty(diag_get()));
-		} else if (pOp->p5 != 0) {
-			static const char * const azType[] = { "NOT NULL", "UNIQUE", "CHECK",
-							       "FOREIGN KEY" };
-			testcase( pOp->p5==1);
-			testcase( pOp->p5==2);
-			testcase( pOp->p5==3);
-			testcase( pOp->p5==4);
-			sqlVdbeError(p, "%s constraint failed", azType[pOp->p5-1]);
-			if (pOp->p4.z) {
-				p->zErrMsg = sqlMPrintf(db, "%z: %s", p->zErrMsg, pOp->p4.z);
-			}
-		} else {
-			sqlVdbeError(p, "%s", pOp->p4.z);
-		}
-		sql_log(pOp->p1, "abort at %d in [%s]: %s", pcx, p->zSql, p->zErrMsg);
+		assert(p->rc == SQL_TARANTOOL_ERROR);
+		if (pOp->p4.z != NULL)
+			diag_set(ClientError, pOp->p5, pOp->p4.z);
+		assert(! diag_is_empty(diag_get()));
 	}
 	rc = sqlVdbeHalt(p);
 	assert(rc==SQL_BUSY || rc==SQL_OK || rc==SQL_ERROR);
-- 
2.7.4

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [tarantool-patches] [PATCH v1 6/9] sql: remove error SQL_INTERRUPT
  2019-05-28 11:39 [tarantool-patches] [PATCH v1 0/9] sql: set errors in VDBE using diag_set() imeevma
                   ` (4 preceding siblings ...)
  2019-05-28 11:39 ` [tarantool-patches] [PATCH v1 5/9] sql: make SQL_TARANTOOL_ERROR the only errcode of OP_Halt imeevma
@ 2019-05-28 11:39 ` imeevma
  2019-05-28 11:39 ` [tarantool-patches] [PATCH v1 7/9] sql: remove error SQL_MISMATCH imeevma
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 25+ messages in thread
From: imeevma @ 2019-05-28 11:39 UTC (permalink / raw)
  To: v.shpilevoy; +Cc: tarantool-patches

Since the interrupt system is no longer used in SQL, the
SQL_INTERRUPT error is out of date and should be removed. Also
this patch removes currently unused progress callback system.
---
 src/box/sql/main.c     |  1 -
 src/box/sql/malloc.c   |  4 ---
 src/box/sql/sqlInt.h   | 11 -------
 src/box/sql/tokenize.c |  3 --
 src/box/sql/vdbe.c     | 84 ++------------------------------------------------
 src/box/sql/vdbeapi.c  |  7 -----
 src/box/sql/vdbeaux.c  | 41 ++++++++++--------------
 7 files changed, 19 insertions(+), 132 deletions(-)

diff --git a/src/box/sql/main.c b/src/box/sql/main.c
index ed07553..0c6ad47 100644
--- a/src/box/sql/main.c
+++ b/src/box/sql/main.c
@@ -371,7 +371,6 @@ sqlErrStr(int rc)
 		/* SQL_BUSY        */ "database is locked",
 		/* SQL_LOCKED      */ "database table is locked",
 		/* SQL_NOMEM       */ "out of memory",
-		/* SQL_INTERRUPT   */ "interrupted",
 		/* SQL_IOERR       */ "disk I/O error",
 		/* SQL_NOTFOUND    */ "unknown operation",
 		/* SQL_FULL        */ "database or disk is full",
diff --git a/src/box/sql/malloc.c b/src/box/sql/malloc.c
index d6f99b4..dbc6846 100644
--- a/src/box/sql/malloc.c
+++ b/src/box/sql/malloc.c
@@ -898,9 +898,6 @@ sqlOomFault(sql * db)
 {
 	if (db->mallocFailed == 0 && db->bBenignMalloc == 0) {
 		db->mallocFailed = 1;
-		if (db->nVdbeExec > 0) {
-			db->u1.isInterrupted = 1;
-		}
 		db->lookaside.bDisable++;
 	}
 }
@@ -917,7 +914,6 @@ sqlOomClear(sql * db)
 {
 	if (db->mallocFailed && db->nVdbeExec == 0) {
 		db->mallocFailed = 0;
-		db->u1.isInterrupted = 0;
 		assert(db->lookaside.bDisable > 0);
 		db->lookaside.bDisable--;
 	}
diff --git a/src/box/sql/sqlInt.h b/src/box/sql/sqlInt.h
index 5c71c51..7f47da6 100644
--- a/src/box/sql/sqlInt.h
+++ b/src/box/sql/sqlInt.h
@@ -370,8 +370,6 @@ enum sql_ret_code {
 	SQL_LOCKED,
 	/** A malloc() failed. */
 	SQL_NOMEM,
-	/** Operation terminated by sql_interrupt(). */
-	SQL_INTERRUPT,
 	/** Some kind of disk I/O error occurred. */
 	SQL_IOERR,
 	/** Unknown opcode in sql_file_control(). */
@@ -1468,16 +1466,7 @@ struct sql {
 	void (*xUpdateCallback) (void *, int, const char *, const char *,
 				 sql_int64);
 	sql_value *pErr;	/* Most recent error message */
-	union {
-		volatile int isInterrupted;	/* True if sql_interrupt has been called */
-		double notUsed1;	/* Spacer */
-	} u1;
 	Lookaside lookaside;	/* Lookaside malloc configuration */
-#ifndef SQL_OMIT_PROGRESS_CALLBACK
-	int (*xProgress) (void *);	/* The progress callback */
-	void *pProgressArg;	/* Argument to the progress callback */
-	unsigned nProgressOps;	/* Number of opcodes for progress callback */
-#endif
 	Hash aFunc;		/* Hash table of connection functions */
 	int *pnBytesFreed;	/* If not NULL, increment this in DbFree() */
 };
diff --git a/src/box/sql/tokenize.c b/src/box/sql/tokenize.c
index 8cc3532..5cb4b7a 100644
--- a/src/box/sql/tokenize.c
+++ b/src/box/sql/tokenize.c
@@ -457,9 +457,6 @@ sqlRunParser(Parse * pParse, const char *zSql)
 
 	assert(zSql != 0);
 	mxSqlLen = db->aLimit[SQL_LIMIT_SQL_LENGTH];
-	if (db->nVdbeActive == 0) {
-		db->u1.isInterrupted = 0;
-	}
 	pParse->zTail = zSql;
 	i = 0;
 	/* sqlParserTrace(stdout, "parser: "); */
diff --git a/src/box/sql/vdbe.c b/src/box/sql/vdbe.c
index 30ea549..169ac45 100644
--- a/src/box/sql/vdbe.c
+++ b/src/box/sql/vdbe.c
@@ -92,18 +92,6 @@ int sql_xfer_count = 0;
 #endif
 
 /*
- * When this global variable is positive, it gets decremented once before
- * each instruction in the VDBE.  When it reaches zero, the u1.isInterrupted
- * field of the sql structure is set in order to simulate an interrupt.
- *
- * This facility is used for testing purposes only.  It does not function
- * in an ordinary build.
- */
-#ifdef SQL_TEST
-int sql_interrupt_count = 0;
-#endif
-
-/*
  * The next global variable is incremented each type the OP_Sort opcode
  * is executed.  The test procedures use this information to make sure that
  * sorting is occurring or not occurring at appropriate times.   This variable
@@ -631,9 +619,6 @@ int sqlVdbeExec(Vdbe *p)
 	sql *db = p->db;       /* The database */
 	int iCompare = 0;          /* Result of last comparison */
 	unsigned nVmStep = 0;      /* Number of virtual machine steps */
-#ifndef SQL_OMIT_PROGRESS_CALLBACK
-	unsigned nProgressLimit = 0;/* Invoke xProgress() when nVmStep reaches this */
-#endif
 	Mem *aMem = p->aMem;       /* Copy of p->aMem */
 	Mem *pIn1 = 0;             /* 1st input operand */
 	Mem *pIn2 = 0;             /* 2nd input operand */
@@ -658,15 +643,7 @@ int sqlVdbeExec(Vdbe *p)
 	p->iCurrentTime = 0;
 	assert(p->explain==0);
 	p->pResultSet = 0;
-	if (db->u1.isInterrupted) goto abort_due_to_interrupt;
 	sqlVdbeIOTraceSql(p);
-#ifndef SQL_OMIT_PROGRESS_CALLBACK
-	if (db->xProgress) {
-		u32 iPrior = p->aCounter[SQL_STMTSTATUS_VM_STEP];
-		assert(0 < db->nProgressOps);
-		nProgressLimit = db->nProgressOps - (iPrior % db->nProgressOps);
-	}
-#endif
 #ifdef SQL_DEBUG
 	sqlBeginBenignMalloc();
 	if (p->pc==0
@@ -810,40 +787,7 @@ int sqlVdbeExec(Vdbe *p)
  * to the current line should be indented for EXPLAIN output.
  */
 case OP_Goto: {             /* jump */
-			jump_to_p2_and_check_for_interrupt:
-	pOp = &aOp[pOp->p2 - 1];
-
-	/* Opcodes that are used as the bottom of a loop (OP_Next, OP_Prev,
-	 * OP_RowSetNext, or OP_SorterNext) all jump here upon
-	 * completion.  Check to see if sql_interrupt() has been called
-	 * or if the progress callback needs to be invoked.
-	 *
-	 * This code uses unstructured "goto" statements and does not look clean.
-	 * But that is not due to sloppy coding habits. The code is written this
-	 * way for performance, to avoid having to run the interrupt and progress
-	 * checks on every opcode.  This helps sql_step() to run about 1.5%
-	 * faster according to "valgrind --tool=cachegrind"
-	 */
-			check_for_interrupt:
-	if (db->u1.isInterrupted) goto abort_due_to_interrupt;
-#ifndef SQL_OMIT_PROGRESS_CALLBACK
-	/* Call the progress callback if it is configured and the required number
-	 * of VDBE ops have been executed (either since this invocation of
-	 * sqlVdbeExec() or since last time the progress callback was called).
-	 * If the progress callback returns non-zero, exit the virtual machine with
-	 * a return code SQL_ABORT.
-	 */
-	if (db->xProgress!=0 && nVmStep>=nProgressLimit) {
-		assert(db->nProgressOps!=0);
-		nProgressLimit = nVmStep + db->nProgressOps - (nVmStep%db->nProgressOps);
-		if (db->xProgress(db->pProgressArg)) {
-			rc = SQL_INTERRUPT;
-			goto abort_due_to_error;
-		}
-	}
-#endif
-
-	break;
+	goto jump_to_p2;
 }
 
 /* Opcode:  Gosub P1 P2 * * *
@@ -1387,18 +1331,6 @@ case OP_ResultRow: {
 	assert(pOp->p1>0);
 	assert(pOp->p1+pOp->p2<=(p->nMem+1 - p->nCursor)+1);
 
-#ifndef SQL_OMIT_PROGRESS_CALLBACK
-	/* Run the progress counter just before returning.
-	 */
-	if (db->xProgress!=0
-	    && nVmStep>=nProgressLimit
-	    && db->xProgress(db->pProgressArg)!=0
-		) {
-		rc = SQL_INTERRUPT;
-		goto abort_due_to_error;
-	}
-#endif
-
 	/* If this statement has violated immediate foreign key constraints, do
 	 * not return the number of rows modified. And do not RELEASE the statement
 	 * transaction. It needs to be rolled back.
@@ -4340,11 +4272,11 @@ case OP_Next:          /* jump */
 #ifdef SQL_TEST
 		sql_search_count++;
 #endif
-		goto jump_to_p2_and_check_for_interrupt;
+		goto jump_to_p2;
 	} else {
 		pC->nullRow = 1;
 	}
-	goto check_for_interrupt;
+	break;
 }
 
 /* Opcode: SorterInsert P1 P2 * * *
@@ -5491,14 +5423,4 @@ no_mem:
 	sqlVdbeError(p, "out of memory");
 	rc = SQL_NOMEM;
 	goto abort_due_to_error;
-
-	/* Jump to here if the sql_interrupt() API sets the interrupt
-	 * flag.
-	 */
-abort_due_to_interrupt:
-	assert(db->u1.isInterrupted);
-	rc = db->mallocFailed ? SQL_NOMEM : SQL_INTERRUPT;
-	p->rc = rc;
-	sqlVdbeError(p, "%s", sqlErrStr(rc));
-	goto abort_due_to_error;
 }
diff --git a/src/box/sql/vdbeapi.c b/src/box/sql/vdbeapi.c
index e480ae7..597d37e 100644
--- a/src/box/sql/vdbeapi.c
+++ b/src/box/sql/vdbeapi.c
@@ -539,13 +539,6 @@ sqlStep(Vdbe * p)
 		goto end_of_step;
 	}
 	if (p->pc < 0) {
-		/* If there are no other statements currently running, then
-		 * reset the interrupt flag.  This prevents a call to sql_interrupt
-		 * from interrupting a statement that has not yet started.
-		 */
-		if (db->nVdbeActive == 0) {
-			db->u1.isInterrupted = 0;
-		}
 
 #ifndef SQL_OMIT_TRACE
 		if ((db->xProfile || (db->mTrace & SQL_TRACE_PROFILE) != 0)
diff --git a/src/box/sql/vdbeaux.c b/src/box/sql/vdbeaux.c
index 140bb97..27fa5b2 100644
--- a/src/box/sql/vdbeaux.c
+++ b/src/box/sql/vdbeaux.c
@@ -1486,10 +1486,6 @@ sqlVdbeList(Vdbe * p)
 	if (i >= nRow) {
 		p->rc = SQL_OK;
 		rc = SQL_DONE;
-	} else if (db->u1.isInterrupted) {
-		p->rc = SQL_INTERRUPT;
-		rc = SQL_ERROR;
-		sqlVdbeError(p, sqlErrStr(p->rc));
 	} else {
 		char *zP4;
 		Op *pOp;
@@ -2208,7 +2204,6 @@ sqlVdbeHalt(Vdbe * p)
 	 *     SQL_NOMEM
 	 *     SQL_IOERR
 	 *     SQL_FULL
-	 *     SQL_INTERRUPT
 	 *
 	 * Then the internal cache might have been left in an inconsistent
 	 * state.  We need to rollback the statement transaction, if there is
@@ -2234,13 +2229,11 @@ sqlVdbeHalt(Vdbe * p)
 
 		/* Check for one of the special errors */
 		mrc = p->rc & 0xff;
-		isSpecialError = mrc == SQL_NOMEM || mrc == SQL_IOERR
-		    || mrc == SQL_INTERRUPT || mrc == SQL_FULL;
+		isSpecialError = mrc == SQL_NOMEM || mrc == SQL_IOERR ||
+				 mrc == SQL_FULL;
 		if (isSpecialError) {
-			/* If the query was read-only and the error code is SQL_INTERRUPT,
-			 * no rollback is necessary. Otherwise, at least a savepoint
-			 * transaction must be rolled back to restore the database to a
-			 * consistent state.
+			/* At least a savepoint transaction must be rolled back
+			 * to restore the database to a consistent state.
 			 *
 			 * Even if the statement is read-only, it is important to perform
 			 * a statement or transaction rollback operation. If the error
@@ -2249,20 +2242,18 @@ sqlVdbeHalt(Vdbe * p)
 			 * pagerStress() in pager.c), the rollback is required to restore
 			 * the pager to a consistent state.
 			 */
-			if (mrc != SQL_INTERRUPT) {
-				if ((mrc == SQL_NOMEM || mrc == SQL_FULL)
-				    && box_txn()) {
-					eStatementOp = SAVEPOINT_ROLLBACK;
-				} else {
-					/* We are forced to roll back the active transaction. Before doing
-					 * so, abort any other statements this handle currently has active.
-					 */
-					box_txn_rollback();
-					closeCursorsAndFree(p);
-					sqlRollbackAll(p);
-					sqlCloseSavepoints(p);
-					p->nChange = 0;
-				}
+			if ((mrc == SQL_NOMEM || mrc == SQL_FULL)
+			    && box_txn()) {
+				eStatementOp = SAVEPOINT_ROLLBACK;
+			} else {
+				/* We are forced to roll back the active transaction. Before doing
+				 * so, abort any other statements this handle currently has active.
+				 */
+				box_txn_rollback();
+				closeCursorsAndFree(p);
+				sqlRollbackAll(p);
+				sqlCloseSavepoints(p);
+				p->nChange = 0;
 			}
 		}
 
-- 
2.7.4

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [tarantool-patches] [PATCH v1 7/9] sql: remove error SQL_MISMATCH
  2019-05-28 11:39 [tarantool-patches] [PATCH v1 0/9] sql: set errors in VDBE using diag_set() imeevma
                   ` (5 preceding siblings ...)
  2019-05-28 11:39 ` [tarantool-patches] [PATCH v1 6/9] sql: remove error SQL_INTERRUPT imeevma
@ 2019-05-28 11:39 ` imeevma
  2019-05-28 11:39 ` [tarantool-patches] [PATCH v1 8/9] sql: use diag_set() to set an error in SQL functions imeevma
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 25+ messages in thread
From: imeevma @ 2019-05-28 11:39 UTC (permalink / raw)
  To: v.shpilevoy; +Cc: tarantool-patches

This patch replaces SQL error SQL_MISMATCH by Tarantool error
ER_SQL_TYPE_MISMATCH.
---
 src/box/sql/main.c            | 1 -
 src/box/sql/sqlInt.h          | 2 --
 src/box/sql/vdbe.c            | 6 ++++--
 test/sql-tap/autoinc.test.lua | 2 +-
 4 files changed, 5 insertions(+), 6 deletions(-)

diff --git a/src/box/sql/main.c b/src/box/sql/main.c
index 0c6ad47..a3c6aa1 100644
--- a/src/box/sql/main.c
+++ b/src/box/sql/main.c
@@ -378,7 +378,6 @@ sqlErrStr(int rc)
 		/* SQL_SCHEMA      */ "database schema has changed",
 		/* SQL_TOOBIG      */ "string or blob too big",
 		/* SQL_CONSTRAINT  */ "constraint failed",
-		/* SQL_MISMATCH    */ "datatype mismatch",
 		/* SQL_MISUSE      */
 		    "library routine called out of sequence",
 		/* SQL_RANGE       */ "bind or column index out of range",
diff --git a/src/box/sql/sqlInt.h b/src/box/sql/sqlInt.h
index 7f47da6..3981fbf 100644
--- a/src/box/sql/sqlInt.h
+++ b/src/box/sql/sqlInt.h
@@ -384,8 +384,6 @@ enum sql_ret_code {
 	SQL_TOOBIG,
 	/** Abort due to constraint violation. */
 	SQL_CONSTRAINT,
-	/** Data type mismatch. */
-	SQL_MISMATCH,
 	/** Library used incorrectly. */
 	SQL_MISUSE,
 	/** 2nd parameter to sql_bind out of range. */
diff --git a/src/box/sql/vdbe.c b/src/box/sql/vdbe.c
index 169ac45..d48b5b8 100644
--- a/src/box/sql/vdbe.c
+++ b/src/box/sql/vdbe.c
@@ -1853,7 +1853,7 @@ case OP_AddImm: {            /* in1 */
  * Force the value in register P1 to be an integer.  If the value
  * in P1 is not an integer and cannot be converted into an integer
  * without data loss, then jump immediately to P2, or if P2==0
- * raise an SQL_MISMATCH exception.
+ * raise an ER_SQL_TYPE_MISMATCH error.
  */
 case OP_MustBeInt: {            /* jump, in1 */
 	pIn1 = &aMem[pOp->p1];
@@ -1862,7 +1862,9 @@ case OP_MustBeInt: {            /* jump, in1 */
 		VdbeBranchTaken((pIn1->flags&MEM_Int)==0, 2);
 		if ((pIn1->flags & MEM_Int)==0) {
 			if (pOp->p2==0) {
-				rc = SQL_MISMATCH;
+				diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
+					 sql_value_text(pIn1), "integer");
+				rc = SQL_TARANTOOL_ERROR;
 				goto abort_due_to_error;
 			} else {
 				goto jump_to_p2;
diff --git a/test/sql-tap/autoinc.test.lua b/test/sql-tap/autoinc.test.lua
index 257621b..3e3eaad 100755
--- a/test/sql-tap/autoinc.test.lua
+++ b/test/sql-tap/autoinc.test.lua
@@ -810,7 +810,7 @@ test:do_catchsql_test(
         INSERT INTO t1 SELECT s2, s2 FROM t1;
     ]], {
         -- <autoinc-gh-3670>
-        1, "Failed to execute SQL statement: datatype mismatch"
+        1, "Type mismatch: can not convert a to integer"
         -- </autoinc-gh-3670>
     })
 
-- 
2.7.4

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [tarantool-patches] [PATCH v1 8/9] sql: use diag_set() to set an error in SQL functions
  2019-05-28 11:39 [tarantool-patches] [PATCH v1 0/9] sql: set errors in VDBE using diag_set() imeevma
                   ` (6 preceding siblings ...)
  2019-05-28 11:39 ` [tarantool-patches] [PATCH v1 7/9] sql: remove error SQL_MISMATCH imeevma
@ 2019-05-28 11:39 ` imeevma
  2019-06-02 16:35   ` [tarantool-patches] " Vladislav Shpilevoy
  2019-05-28 11:39 ` [tarantool-patches] [PATCH v1 9/9] sql: set errors in VDBE using diag_set() imeevma
                   ` (2 subsequent siblings)
  10 siblings, 1 reply; 25+ messages in thread
From: imeevma @ 2019-05-28 11:39 UTC (permalink / raw)
  To: v.shpilevoy; +Cc: tarantool-patches

After this patch, all errors in the SQL functions will be set
using diag_set().

Part of #4074
---
 src/box/lua/lua_sql.c      |  13 +++--
 src/box/sql/analyze.c      |   6 +--
 src/box/sql/date.c         |   8 +--
 src/box/sql/func.c         | 102 ++++++++++++++++-------------------
 src/box/sql/sqlInt.h       |  13 -----
 src/box/sql/vdbe.c         |  26 +++------
 src/box/sql/vdbeInt.h      |  28 ++--------
 src/box/sql/vdbeapi.c      | 129 ++++-----------------------------------------
 src/box/sql/vdbeaux.c      |  46 ----------------
 src/box/sql/vdbemem.c      |   9 ++--
 test/sql-tap/func.test.lua |   2 +-
 11 files changed, 91 insertions(+), 291 deletions(-)

diff --git a/src/box/lua/lua_sql.c b/src/box/lua/lua_sql.c
index 36b75ff..529ee59 100644
--- a/src/box/lua/lua_sql.c
+++ b/src/box/lua/lua_sql.c
@@ -77,13 +77,15 @@ lua_sql_call(sql_context *pCtx, int nVal, sql_value **apVal) {
 			lua_pushboolean(L, sql_value_boolean(param));
 			break;
 		default:
-			sql_result_error(pCtx, "Unsupported type passed "
-					     "to Lua", -1);
+			diag_set(ClientError, ER_SQL_EXECUTE, "Unsupported "\
+				 "type passed to Lua");
+			pCtx->is_aborted = true;
 			goto error;
 		}
 	}
 	if (lua_pcall(L, lua_gettop(L) - 1, 1, 0) != 0){
-		sql_result_error(pCtx, lua_tostring(L, -1), -1);
+		diag_set(ClientError, ER_SQL_EXECUTE, lua_tostring(L, -1));
+		pCtx->is_aborted = true;
 		goto error;
 	}
 	switch(lua_type(L, -1)) {
@@ -101,8 +103,9 @@ lua_sql_call(sql_context *pCtx, int nVal, sql_value **apVal) {
 		sql_result_null(pCtx);
 		break;
 	default:
-		sql_result_error(pCtx, "Unsupported type returned from Lua",
-				     -1);
+		diag_set(ClientError, ER_SQL_EXECUTE, "Unsupported type "\
+			 "passed from Lua");
+		pCtx->is_aborted = true;
 		goto error;
 	}
 error:
diff --git a/src/box/sql/analyze.c b/src/box/sql/analyze.c
index d2d29c5..9795429 100644
--- a/src/box/sql/analyze.c
+++ b/src/box/sql/analyze.c
@@ -298,7 +298,7 @@ statInit(sql_context * context, int argc, sql_value ** argv)
 	db = sql_context_db_handle(context);
 	p = sqlDbMallocZero(db, n);
 	if (p == 0) {
-		sql_result_error_nomem(context);
+		context->is_aborted = true;
 		return;
 	}
 
@@ -669,7 +669,7 @@ statGet(sql_context * context, int argc, sql_value ** argv)
 
 		char *zRet = sqlMallocZero((p->nKeyCol + 1) * 25);
 		if (zRet == 0) {
-			sql_result_error_nomem(context);
+			context->is_aborted = true;
 			return;
 		}
 
@@ -715,7 +715,7 @@ statGet(sql_context * context, int argc, sql_value ** argv)
 
 	char *zRet = sqlMallocZero(p->nCol * 25);
 	if (zRet == 0) {
-		sql_result_error_nomem(context);
+		context->is_aborted = true;
 	} else {
 		int i;
 		char *z = zRet;
diff --git a/src/box/sql/date.c b/src/box/sql/date.c
index 07a57ab..6d3a2b0 100644
--- a/src/box/sql/date.c
+++ b/src/box/sql/date.c
@@ -617,7 +617,8 @@ localtimeOffset(DateTime * p,	/* Date at which to calculate offset */
 	computeJD(&x);
 	t = (time_t) (x.iJD / 1000 - 21086676 * (i64) 10000);
 	if (osLocaltime(&t, &sLocal)) {
-		sql_result_error(pCtx, "local time unavailable", -1);
+		diag_set(ClientError, ER_SQL_EXECUTE, "local time unavailable");
+		pCtx->is_aborted = true;
 		*pRc = SQL_ERROR;
 		return 0;
 	}
@@ -1108,12 +1109,13 @@ strftimeFunc(sql_context * context, int argc, sql_value ** argv)
 	if (n < sizeof(zBuf)) {
 		z = zBuf;
 	} else if (n > (u64) db->aLimit[SQL_LIMIT_LENGTH]) {
-		sql_result_error_toobig(context);
+		diag_set(ClientError, ER_SQL_EXECUTE, "string or blob too big");
+		context->is_aborted = true;
 		return;
 	} else {
 		z = sqlDbMallocRawNN(db, (int)n);
 		if (z == 0) {
-			sql_result_error_nomem(context);
+			context->is_aborted = true;
 			return;
 		}
 	}
diff --git a/src/box/sql/func.c b/src/box/sql/func.c
index bb7405e..593aa94 100644
--- a/src/box/sql/func.c
+++ b/src/box/sql/func.c
@@ -181,13 +181,9 @@ absFunc(sql_context * context, int argc, sql_value ** argv)
 			i64 iVal = sql_value_int64(argv[0]);
 			if (iVal < 0) {
 				if (iVal == SMALLEST_INT64) {
-					/* IMP: R-31676-45509 If X is the integer -9223372036854775808
-					 * then abs(X) throws an integer overflow error since there is no
-					 * equivalent positive 64-bit two complement value.
-					 */
-					sql_result_error(context,
-							     "integer overflow",
-							     -1);
+					diag_set(ClientError, ER_SQL_EXECUTE,
+						 "integer is overflowed");
+					context->is_aborted = true;
 					return;
 				}
 				iVal = -iVal;
@@ -203,8 +199,7 @@ absFunc(sql_context * context, int argc, sql_value ** argv)
 	case MP_BOOL: {
 		diag_set(ClientError, ER_INCONSISTENT_TYPES, "number",
 			 "boolean");
-		context->isError = SQL_TARANTOOL_ERROR;
-		context->fErrorOrAux = 1;
+		context->is_aborted = true;
 		return;
 	}
 	default:{
@@ -256,8 +251,7 @@ position_func(struct sql_context *context, int argc, struct Mem **argv)
 	if (inconsistent_type_arg != NULL) {
 		diag_set(ClientError, ER_INCONSISTENT_TYPES, "TEXT or BLOB",
 			 mem_type_to_str(inconsistent_type_arg));
-		context->isError = SQL_TARANTOOL_ERROR;
-		context->fErrorOrAux = 1;
+		context->is_aborted = true;
 		return;
 	}
 	/*
@@ -267,8 +261,7 @@ position_func(struct sql_context *context, int argc, struct Mem **argv)
 	if (haystack_type != needle_type) {
 		diag_set(ClientError, ER_INCONSISTENT_TYPES,
 			 mem_type_to_str(needle), mem_type_to_str(haystack));
-		context->isError = SQL_TARANTOOL_ERROR;
-		context->fErrorOrAux = 1;
+		context->is_aborted = true;
 		return;
 	}
 
@@ -513,7 +506,6 @@ roundFunc(sql_context * context, int argc, sql_value ** argv)
 {
 	int n = 0;
 	double r;
-	char *zBuf;
 	assert(argc == 1 || argc == 2);
 	if (argc == 2) {
 		if (sql_value_is_null(argv[1]))
@@ -534,23 +526,17 @@ roundFunc(sql_context * context, int argc, sql_value ** argv)
 	} else if (n == 0 && r < 0 && (-r) < LARGEST_INT64 - 1) {
 		r = -(double)((sql_int64) ((-r) + 0.5));
 	} else {
-		zBuf = sql_mprintf("%.*f", n, r);
-		if (zBuf == 0) {
-			sql_result_error_nomem(context);
-			return;
-		}
-		sqlAtoF(zBuf, &r, sqlStrlen30(zBuf));
-		sql_free(zBuf);
+		const char *rounded_value = tt_sprintf("%.*f", n, r);
+		sqlAtoF(rounded_value, &r, sqlStrlen30(rounded_value));
 	}
 	sql_result_double(context, r);
 }
 
 /*
  * Allocate nByte bytes of space using sqlMalloc(). If the
- * allocation fails, call sql_result_error_nomem() to notify
- * the database handle that malloc() has failed and return NULL.
- * If nByte is larger than the maximum string or blob length, then
- * raise an SQL_TOOBIG exception and return NULL.
+ * allocation fails, return NULL. If nByte is larger than the
+ * maximum string or blob length, then raise an error and return
+ * NULL.
  */
 static void *
 contextMalloc(sql_context * context, i64 nByte)
@@ -561,13 +547,13 @@ contextMalloc(sql_context * context, i64 nByte)
 	testcase(nByte == db->aLimit[SQL_LIMIT_LENGTH]);
 	testcase(nByte == db->aLimit[SQL_LIMIT_LENGTH] + 1);
 	if (nByte > db->aLimit[SQL_LIMIT_LENGTH]) {
-		sql_result_error_toobig(context);
+		diag_set(ClientError, ER_SQL_EXECUTE, "string or blob too big");
+		context->is_aborted = true;
 		z = 0;
 	} else {
 		z = sqlMalloc(nByte);
-		if (!z) {
-			sql_result_error_nomem(context);
-		}
+		if (z == NULL)
+			context->is_aborted = true;
 	}
 	return z;
 }
@@ -594,8 +580,8 @@ case_type##ICUFunc(sql_context *context, int argc, sql_value **argv)   \
 	if (!z2)                                                               \
 		return;                                                        \
 	z1 = contextMalloc(context, ((i64) n) + 1);                            \
-	if (!z1) {                                                             \
-		sql_result_error_nomem(context);                           \
+	if (z1 == NULL) {                                                      \
+		context->is_aborted = true;                                    \
 		return;                                                        \
 	}                                                                      \
 	UErrorCode status = U_ZERO_ERROR;                                      \
@@ -612,8 +598,8 @@ case_type##ICUFunc(sql_context *context, int argc, sql_value **argv)   \
 		status = U_ZERO_ERROR;                                         \
 		sql_free(z1);                                              \
 		z1 = contextMalloc(context, ((i64) len) + 1);                  \
-		if (!z1) {                                                     \
-			sql_result_error_nomem(context);                   \
+		if (z1 == NULL) {                                              \
+			context->is_aborted = true;                            \
 			return;                                                \
 		}                                                              \
 		ucasemap_utf8To##case_type(case_map, z1, len, z2, n, &status); \
@@ -919,8 +905,7 @@ likeFunc(sql_context *context, int argc, sql_value **argv)
 					  mem_type_to_str(argv[1]);
 		diag_set(ClientError, ER_INCONSISTENT_TYPES, "TEXT",
 			 inconsistent_type);
-		context->fErrorOrAux = 1;
-		context->isError = SQL_TARANTOOL_ERROR;
+		context->is_aborted = true;
 		return;
 	}
 	const char *zB = (const char *) sql_value_text(argv[0]);
@@ -937,8 +922,9 @@ likeFunc(sql_context *context, int argc, sql_value **argv)
 	testcase(nPat == db->aLimit[SQL_LIMIT_LIKE_PATTERN_LENGTH]);
 	testcase(nPat == db->aLimit[SQL_LIMIT_LIKE_PATTERN_LENGTH] + 1);
 	if (nPat > db->aLimit[SQL_LIMIT_LIKE_PATTERN_LENGTH]) {
-		sql_result_error(context,
-				     "LIKE pattern is too complex", -1);
+		diag_set(ClientError, ER_SQL_EXECUTE, "LIKE pattern is too "\
+			 "complex");
+		context->is_aborted = true;
 		return;
 	}
 	/* Encoding did not change */
@@ -953,10 +939,10 @@ likeFunc(sql_context *context, int argc, sql_value **argv)
 		const unsigned char *zEsc = sql_value_text(argv[2]);
 		if (zEsc == 0)
 			return;
-		const char *const err_msg =
-			"ESCAPE expression must be a single character";
 		if (sql_utf8_char_count(zEsc, sql_value_bytes(argv[2])) != 1) {
-			sql_result_error(context, err_msg, -1);
+			diag_set(ClientError, ER_SQL_EXECUTE, "ESCAPE "\
+				 "expression must be a single character");
+			context->is_aborted = true;
 			return;
 		}
 		escape = sqlUtf8Read(&zEsc);
@@ -967,9 +953,9 @@ likeFunc(sql_context *context, int argc, sql_value **argv)
 	res = sql_utf8_pattern_compare(zB, zA, zB_end, zA_end,
 				       is_like_ci, escape);
 	if (res == INVALID_PATTERN) {
-		const char *const err_msg =
-			"LIKE pattern can only contain UTF-8 characters";
-		sql_result_error(context, err_msg, -1);
+		diag_set(ClientError, ER_SQL_EXECUTE, "LIKE pattern can only "\
+			 "contain UTF-8 characters");
+		context->is_aborted = true;
 		return;
 	}
 	sql_result_bool(context, res == MATCH);
@@ -1136,8 +1122,8 @@ charFunc(sql_context * context, int argc, sql_value ** argv)
 	unsigned char *z, *zOut;
 	int i;
 	zOut = z = sql_malloc64(argc * 4 + 1);
-	if (z == 0) {
-		sql_result_error_nomem(context);
+	if (z == NULL) {
+		context->is_aborted = true;
 		return;
 	}
 	for (i = 0; i < argc; i++) {
@@ -1200,15 +1186,14 @@ static void
 zeroblobFunc(sql_context * context, int argc, sql_value ** argv)
 {
 	i64 n;
-	int rc;
 	assert(argc == 1);
 	UNUSED_PARAMETER(argc);
 	n = sql_value_int64(argv[0]);
 	if (n < 0)
 		n = 0;
-	rc = sql_result_zeroblob64(context, n);	/* IMP: R-00293-64994 */
-	if (rc) {
-		sql_result_error_code(context, rc);
+	if (sql_result_zeroblob64(context, n) != SQL_OK) {
+		diag_set(ClientError, ER_SQL_EXECUTE, "string or blob too big");
+		context->is_aborted = true;
 	}
 }
 
@@ -1275,14 +1260,16 @@ replaceFunc(sql_context * context, int argc, sql_value ** argv)
 			testcase(nOut - 1 == db->aLimit[SQL_LIMIT_LENGTH]);
 			testcase(nOut - 2 == db->aLimit[SQL_LIMIT_LENGTH]);
 			if (nOut - 1 > db->aLimit[SQL_LIMIT_LENGTH]) {
-				sql_result_error_toobig(context);
+				diag_set(ClientError, ER_SQL_EXECUTE, "string "\
+					 "or blob too big");
+				context->is_aborted = true;
 				sql_free(zOut);
 				return;
 			}
 			zOld = zOut;
 			zOut = sql_realloc64(zOut, (int)nOut);
 			if (zOut == 0) {
-				sql_result_error_nomem(context);
+				context->is_aborted = true;
 				sql_free(zOld);
 				return;
 			}
@@ -1605,8 +1592,7 @@ sum_step(struct sql_context *context, int argc, sql_value **argv)
 		if (mem_apply_numeric_type(argv[0]) != 0) {
 			diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
 				 sql_value_text(argv[0]), "number");
-			context->fErrorOrAux = 1;
-			context->isError = SQL_TARANTOOL_ERROR;
+			context->is_aborted = true;
 			return;
 		}
 		type = sql_value_type(argv[0]);
@@ -1632,7 +1618,9 @@ sumFinalize(sql_context * context)
 	p = sql_aggregate_context(context, 0);
 	if (p && p->cnt > 0) {
 		if (p->overflow) {
-			sql_result_error(context, "integer overflow", -1);
+			diag_set(ClientError, ER_SQL_EXECUTE, "integer "\
+				 "overflow");
+			context->is_aborted = true;
 		} else if (p->approx) {
 			sql_result_double(context, p->rSum);
 		} else {
@@ -1789,9 +1777,11 @@ groupConcatFinalize(sql_context * context)
 	pAccum = sql_aggregate_context(context, 0);
 	if (pAccum) {
 		if (pAccum->accError == STRACCUM_TOOBIG) {
-			sql_result_error_toobig(context);
+			diag_set(ClientError, ER_SQL_EXECUTE, "string or blob "\
+				 "too big");
+			context->is_aborted = true;
 		} else if (pAccum->accError == STRACCUM_NOMEM) {
-			sql_result_error_nomem(context);
+			context->is_aborted = true;
 		} else {
 			sql_result_text(context,
 					    sqlStrAccumFinish(pAccum),
diff --git a/src/box/sql/sqlInt.h b/src/box/sql/sqlInt.h
index 3981fbf..9c0659b 100644
--- a/src/box/sql/sqlInt.h
+++ b/src/box/sql/sqlInt.h
@@ -476,19 +476,6 @@ void
 sql_result_double(sql_context *, double);
 
 void
-sql_result_error(sql_context *, const char *,
-		     int);
-
-void
-sql_result_error_toobig(sql_context *);
-
-void
-sql_result_error_nomem(sql_context *);
-
-void
-sql_result_error_code(sql_context *, int);
-
-void
 sql_result_int(sql_context *, int);
 
 void
diff --git a/src/box/sql/vdbe.c b/src/box/sql/vdbe.c
index d48b5b8..43d7329 100644
--- a/src/box/sql/vdbe.c
+++ b/src/box/sql/vdbe.c
@@ -1717,17 +1717,13 @@ case OP_Function: {
 	}
 #endif
 	MemSetTypeFlag(pCtx->pOut, MEM_Null);
-	pCtx->fErrorOrAux = 0;
+	pCtx->is_aborted = false;
 	(*pCtx->pFunc->xSFunc)(pCtx, pCtx->argc, pCtx->argv);/* IMP: R-24505-23230 */
 
 	/* If the function returned an error, throw an exception */
-	if (pCtx->fErrorOrAux) {
-		if (pCtx->isError) {
-			sqlVdbeError(p, "%s", sql_value_text(pCtx->pOut));
-			rc = pCtx->isError;
-		}
-		sqlVdbeDeleteAuxData(db, &p->pAuxData, pCtx->iOp, pOp->p1);
-		if (rc) goto abort_due_to_error;
+	if (pCtx->is_aborted) {
+		rc = SQL_TARANTOOL_ERROR;
+		goto abort_due_to_error;
 	}
 
 	/* Copy the result of the function into register P3 */
@@ -4894,9 +4890,6 @@ case OP_Program: {        /* jump */
 	pFrame->pParent = p->pFrame;
 	pFrame->nChange = p->nChange;
 	pFrame->nDbChange = p->db->nChange;
-	assert(pFrame->pAuxData==0);
-	pFrame->pAuxData = p->pAuxData;
-	p->pAuxData = 0;
 	p->nChange = 0;
 	p->pFrame = pFrame;
 	p->aMem = aMem = VdbeFrameMem(pFrame);
@@ -5159,16 +5152,13 @@ case OP_AggStep: {
 	pMem->n++;
 	sqlVdbeMemInit(&t, db, MEM_Null);
 	pCtx->pOut = &t;
-	pCtx->fErrorOrAux = 0;
+	pCtx->is_aborted = false;
 	pCtx->skipFlag = 0;
 	(pCtx->pFunc->xSFunc)(pCtx,pCtx->argc,pCtx->argv); /* IMP: R-24505-23230 */
-	if (pCtx->fErrorOrAux) {
-		if (pCtx->isError) {
-			sqlVdbeError(p, "%s", sql_value_text(&t));
-			rc = pCtx->isError;
-		}
+	if (pCtx->is_aborted) {
 		sqlVdbeMemRelease(&t);
-		if (rc) goto abort_due_to_error;
+		rc = SQL_TARANTOOL_ERROR;
+		goto abort_due_to_error;
 	} else {
 		assert(t.flags==MEM_Null);
 	}
diff --git a/src/box/sql/vdbeInt.h b/src/box/sql/vdbeInt.h
index a3100e5..ee14510 100644
--- a/src/box/sql/vdbeInt.h
+++ b/src/box/sql/vdbeInt.h
@@ -62,9 +62,6 @@ typedef unsigned Bool;
 /* Opaque type used by code in vdbesort.c */
 typedef struct VdbeSorter VdbeSorter;
 
-/* Elements of the linked list at Vdbe.pAuxData */
-typedef struct AuxData AuxData;
-
 /* Types of VDBE cursors */
 #define CURTYPE_TARANTOOL   0
 #define CURTYPE_SORTER      1
@@ -161,7 +158,6 @@ struct VdbeFrame {
 	Mem *aMem;		/* Array of memory cells for parent frame */
 	VdbeCursor **apCsr;	/* Array of Vdbe cursors for parent frame */
 	void *token;		/* Copy of SubProgram.token */
-	AuxData *pAuxData;	/* Linked list of auxdata allocations */
 	int nCursor;		/* Number of entries in apCsr */
 	int pc;			/* Program Counter in parent (calling) frame */
 	int nOp;		/* Size of aOp array */
@@ -304,21 +300,6 @@ mem_apply_numeric_type(struct Mem *record);
 #endif
 
 /*
- * Each auxiliary data pointer stored by a user defined function
- * implementation calling sql_set_auxdata() is stored in an instance
- * of this structure. All such structures associated with a single VM
- * are stored in a linked list headed at Vdbe.pAuxData. All are destroyed
- * when the VM is halted (if not before).
- */
-struct AuxData {
-	int iOp;		/* Instruction number of OP_Function opcode */
-	int iArg;		/* Index of function argument. */
-	void *pAux;		/* Aux data pointer */
-	void (*xDelete) (void *);	/* Destructor for the aux data */
-	AuxData *pNext;		/* Next element in list */
-};
-
-/*
  * The "context" argument for an installable function.  A pointer to an
  * instance of this structure is the first argument to the routines used
  * implement the SQL functions.
@@ -337,9 +318,12 @@ struct sql_context {
 	Mem *pMem;		/* Memory cell used to store aggregate context */
 	Vdbe *pVdbe;		/* The VM that owns this context */
 	int iOp;		/* Instruction number of OP_Function */
-	int isError;		/* Error code returned by the function. */
+	/*
+	 * True, if an error occurred during the execution of the
+	 * function.
+	 */
+	bool is_aborted;
 	u8 skipFlag;		/* Skip accumulator loading if true */
-	u8 fErrorOrAux;		/* isError!=0 or pVdbe->pAuxData modified */
 	u8 argc;		/* Number of arguments */
 	sql_value *argv[1];	/* Argument set */
 };
@@ -445,7 +429,6 @@ struct Vdbe {
 	int nFrame;		/* Number of frames in pFrame list */
 	u32 expmask;		/* Binding to these vars invalidates VM */
 	SubProgram *pProgram;	/* Linked list of all sub-programs used by VM */
-	AuxData *pAuxData;	/* Linked list of auxdata allocations */
 	/* Anonymous savepoint for aborts only */
 	Savepoint *anonymous_savepoint;
 #ifdef SQL_ENABLE_STMT_SCANSTATUS
@@ -478,7 +461,6 @@ u32 sqlVdbeSerialTypeLen(u32);
 u32 sqlVdbeSerialType(Mem *, int, u32 *);
 u32 sqlVdbeSerialPut(unsigned char *, Mem *, u32);
 u32 sqlVdbeSerialGet(const unsigned char *, u32, Mem *);
-void sqlVdbeDeleteAuxData(sql *, AuxData **, int, int);
 
 int sqlVdbeExec(Vdbe *);
 int sqlVdbeList(Vdbe *);
diff --git a/src/box/sql/vdbeapi.c b/src/box/sql/vdbeapi.c
index 597d37e..673ccd1 100644
--- a/src/box/sql/vdbeapi.c
+++ b/src/box/sql/vdbeapi.c
@@ -321,7 +321,8 @@ setResultStrOrError(sql_context * pCtx,	/* Function context */
     )
 {
 	if (sqlVdbeMemSetStr(pCtx->pOut, z, n,1, xDel) == SQL_TOOBIG) {
-		sql_result_error_toobig(pCtx);
+		diag_set(ClientError, ER_SQL_EXECUTE, "string or blob too big");
+		pCtx->is_aborted = true;
 	}
 }
 
@@ -339,8 +340,10 @@ invokeValueDestructor(const void *p,	/* Value to destroy */
 	} else {
 		xDel((void *)p);
 	}
-	if (pCtx)
-		sql_result_error_toobig(pCtx);
+	if (pCtx) {
+		diag_set(ClientError, ER_SQL_EXECUTE, "string or blob too big");
+		pCtx->is_aborted = true;
+	}
 	return SQL_TOOBIG;
 }
 
@@ -351,7 +354,8 @@ sql_result_blob(sql_context * pCtx,
 {
 	assert(n >= 0);
 	if (sqlVdbeMemSetStr(pCtx->pOut, z, n,0, xDel) == SQL_TOOBIG) {
-		sql_result_error_toobig(pCtx);
+		diag_set(ClientError, ER_SQL_EXECUTE, "string or blob too big");
+		pCtx->is_aborted = true;
 	}
 }
 
@@ -375,14 +379,6 @@ sql_result_double(sql_context * pCtx, double rVal)
 }
 
 void
-sql_result_error(sql_context * pCtx, const char *z, int n)
-{
-	pCtx->isError = SQL_ERROR;
-	pCtx->fErrorOrAux = 1;
-	sqlVdbeMemSetStr(pCtx->pOut, z, n, 1, SQL_TRANSIENT);
-}
-
-void
 sql_result_int(sql_context * pCtx, int iVal)
 {
 	sqlVdbeMemSetInt64(pCtx->pOut, (i64) iVal);
@@ -451,37 +447,6 @@ sql_result_zeroblob64(sql_context * pCtx, u64 n)
 	return SQL_OK;
 }
 
-void
-sql_result_error_code(sql_context * pCtx, int errCode)
-{
-	pCtx->isError = errCode;
-	pCtx->fErrorOrAux = 1;
-	if (pCtx->pOut->flags & MEM_Null) {
-		sqlVdbeMemSetStr(pCtx->pOut, sqlErrStr(errCode), -1, 1,
-				     SQL_STATIC);
-	}
-}
-
-/* Force an SQL_TOOBIG error. */
-void
-sql_result_error_toobig(sql_context * pCtx)
-{
-	pCtx->isError = SQL_TOOBIG;
-	pCtx->fErrorOrAux = 1;
-	sqlVdbeMemSetStr(pCtx->pOut, "string or blob too big", -1, 1,
-			     SQL_STATIC);
-}
-
-/* An SQL_NOMEM error. */
-void
-sql_result_error_nomem(sql_context * pCtx)
-{
-	sqlVdbeMemSetNull(pCtx->pOut);
-	pCtx->isError = SQL_NOMEM;
-	pCtx->fErrorOrAux = 1;
-	sqlOomFault(pCtx->pOut->db);
-}
-
 /*
  * Execute the statement pStmt, either until a row of data is ready, the
  * statement is completely executed or an error occurs.
@@ -712,13 +677,10 @@ sqlInvalidFunction(sql_context * context,	/* The function calling context */
     )
 {
 	const char *zName = context->pFunc->zName;
-	char *zErr;
 	UNUSED_PARAMETER2(NotUsed, NotUsed2);
-	zErr =
-	    sql_mprintf
-	    ("unable to use function %s in the requested context", zName);
-	sql_result_error(context, zErr, -1);
-	sql_free(zErr);
+	const char *err = "unable to use function %s in the requested context";
+	diag_set(ClientError, ER_SQL_EXECUTE, tt_sprintf(err, zName));
+	context->is_aborted = true;
 }
 
 /*
@@ -762,75 +724,6 @@ sql_aggregate_context(sql_context * p, int nByte)
 }
 
 /*
- * Return the auxiliary data pointer, if any, for the iArg'th argument to
- * the user-function defined by pCtx.
- */
-void *
-sql_get_auxdata(sql_context * pCtx, int iArg)
-{
-	AuxData *pAuxData;
-
-	if (pCtx->pVdbe == 0)
-		return 0;
-
-	for (pAuxData = pCtx->pVdbe->pAuxData; pAuxData;
-	     pAuxData = pAuxData->pNext) {
-		if (pAuxData->iOp == pCtx->iOp && pAuxData->iArg == iArg)
-			break;
-	}
-
-	return (pAuxData ? pAuxData->pAux : 0);
-}
-
-/*
- * Set the auxiliary data pointer and delete function, for the iArg'th
- * argument to the user-function defined by pCtx. Any previous value is
- * deleted by calling the delete function specified when it was set.
- */
-void
-sql_set_auxdata(sql_context * pCtx,
-		    int iArg, void *pAux, void (*xDelete) (void *)
-    )
-{
-	AuxData *pAuxData;
-	Vdbe *pVdbe = pCtx->pVdbe;
-
-	if (iArg < 0)
-		goto failed;
-	if (pVdbe == 0)
-		goto failed;
-
-	for (pAuxData = pVdbe->pAuxData; pAuxData; pAuxData = pAuxData->pNext) {
-		if (pAuxData->iOp == pCtx->iOp && pAuxData->iArg == iArg)
-			break;
-	}
-	if (pAuxData == 0) {
-		pAuxData = sqlDbMallocZero(pVdbe->db, sizeof(AuxData));
-		if (!pAuxData)
-			goto failed;
-		pAuxData->iOp = pCtx->iOp;
-		pAuxData->iArg = iArg;
-		pAuxData->pNext = pVdbe->pAuxData;
-		pVdbe->pAuxData = pAuxData;
-		if (pCtx->fErrorOrAux == 0) {
-			pCtx->isError = 0;
-			pCtx->fErrorOrAux = 1;
-		}
-	} else if (pAuxData->xDelete) {
-		pAuxData->xDelete(pAuxData->pAux);
-	}
-
-	pAuxData->pAux = pAux;
-	pAuxData->xDelete = xDelete;
-	return;
-
- failed:
-	if (xDelete) {
-		xDelete(pAux);
-	}
-}
-
-/*
  * Return the number of columns in the result set for the statement pStmt.
  */
 int
diff --git a/src/box/sql/vdbeaux.c b/src/box/sql/vdbeaux.c
index 27fa5b2..619b211 100644
--- a/src/box/sql/vdbeaux.c
+++ b/src/box/sql/vdbeaux.c
@@ -1401,7 +1401,6 @@ sqlVdbeFrameDelete(VdbeFrame * p)
 		sqlVdbeFreeCursor(p->v, apCsr[i]);
 	}
 	releaseMemArray(aMem, p->nChildMem);
-	sqlVdbeDeleteAuxData(p->v->db, &p->pAuxData, -1, 0);
 	sqlDbFree(p->v->db, p);
 }
 
@@ -1920,9 +1919,6 @@ sqlVdbeFrameRestore(VdbeFrame * pFrame)
 	v->nCursor = pFrame->nCursor;
 	v->nChange = pFrame->nChange;
 	v->db->nChange = pFrame->nDbChange;
-	sqlVdbeDeleteAuxData(v->db, &v->pAuxData, -1, 0);
-	v->pAuxData = pFrame->pAuxData;
-	pFrame->pAuxData = 0;
 	return pFrame->pc;
 }
 
@@ -1966,11 +1962,6 @@ closeCursorsAndFree(Vdbe * p)
 		p->pDelFrame = pDel->pParent;
 		sqlVdbeFrameDelete(pDel);
 	}
-
-	/* Delete any auxdata allocations made by the VM */
-	if (p->pAuxData)
-		sqlVdbeDeleteAuxData(p->db, &p->pAuxData, -1, 0);
-	assert(p->pAuxData == 0);
 }
 
 /*
@@ -2528,43 +2519,6 @@ sqlVdbeFinalize(Vdbe * p)
 }
 
 /*
- * If parameter iOp is less than zero, then invoke the destructor for
- * all auxiliary data pointers currently cached by the VM passed as
- * the first argument.
- *
- * Or, if iOp is greater than or equal to zero, then the destructor is
- * only invoked for those auxiliary data pointers created by the user
- * function invoked by the OP_Function opcode at instruction iOp of
- * VM pVdbe, and only then if:
- *
- *    * the associated function parameter is the 32nd or later (counting
- *      from left to right), or
- *
- *    * the corresponding bit in argument mask is clear (where the first
- *      function parameter corresponds to bit 0 etc.).
- */
-void
-sqlVdbeDeleteAuxData(sql * db, AuxData ** pp, int iOp, int mask)
-{
-	while (*pp) {
-		AuxData *pAux = *pp;
-		if ((iOp < 0)
-		    || (pAux->iOp == iOp
-			&& (pAux->iArg > 31 || !(mask & MASKBIT32(pAux->iArg))))
-		    ) {
-			testcase(pAux->iArg == 31);
-			if (pAux->xDelete) {
-				pAux->xDelete(pAux->pAux);
-			}
-			*pp = pAux->pNext;
-			sqlDbFree(db, pAux);
-		} else {
-			pp = &pAux->pNext;
-		}
-	}
-}
-
-/*
  * Free all memory associated with the Vdbe passed as the second argument,
  * except for object itself, which is preserved.
  *
diff --git a/src/box/sql/vdbemem.c b/src/box/sql/vdbemem.c
index 08b6499..312c661 100644
--- a/src/box/sql/vdbemem.c
+++ b/src/box/sql/vdbemem.c
@@ -321,7 +321,6 @@ sqlVdbeMemStringify(Mem * pMem, u8 bForce)
 int
 sqlVdbeMemFinalize(Mem * pMem, FuncDef * pFunc)
 {
-	int rc = SQL_OK;
 	if (ALWAYS(pFunc && pFunc->xFinalize)) {
 		sql_context ctx;
 		Mem t;
@@ -338,9 +337,9 @@ sqlVdbeMemFinalize(Mem * pMem, FuncDef * pFunc)
 		if (pMem->szMalloc > 0)
 			sqlDbFree(pMem->db, pMem->zMalloc);
 		memcpy(pMem, &t, sizeof(t));
-		rc = ctx.isError;
+		return ctx.is_aborted ? SQL_TARANTOOL_ERROR : SQL_OK;
 	}
-	return rc;
+	return SQL_OK;
 }
 
 /*
@@ -1287,7 +1286,7 @@ valueFromFunction(sql * db,	/* The database connection */
 	ctx.pOut = pVal;
 	ctx.pFunc = pFunc;
 	pFunc->xSFunc(&ctx, nVal, apVal);
-	assert(!ctx.isError);
+	assert(!ctx.is_aborted);
 	sql_value_apply_type(pVal, type);
 	assert(rc == SQL_OK);
 
@@ -1492,7 +1491,7 @@ recordFunc(sql_context * context, int argc, sql_value ** argv)
 	nRet = 1 + nSerial + nVal;
 	aRet = sqlDbMallocRawNN(db, nRet);
 	if (aRet == 0) {
-		sql_result_error_nomem(context);
+		context->is_aborted = true;
 	} else {
 		aRet[0] = nSerial + 1;
 		putVarint32(&aRet[1], iSerial);
diff --git a/test/sql-tap/func.test.lua b/test/sql-tap/func.test.lua
index 09b1cf9..f9044ad 100755
--- a/test/sql-tap/func.test.lua
+++ b/test/sql-tap/func.test.lua
@@ -1730,7 +1730,7 @@ test:do_catchsql_test(
         SELECT abs(-9223372036854775807-1);
     ]], {
         -- <func-18.32>
-        1, "Failed to execute SQL statement: integer overflow"
+        1, "Failed to execute SQL statement: integer is overflowed"
         -- </func-18.32>
     })
 
-- 
2.7.4

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [tarantool-patches] [PATCH v1 9/9] sql: set errors in VDBE using diag_set()
  2019-05-28 11:39 [tarantool-patches] [PATCH v1 0/9] sql: set errors in VDBE using diag_set() imeevma
                   ` (7 preceding siblings ...)
  2019-05-28 11:39 ` [tarantool-patches] [PATCH v1 8/9] sql: use diag_set() to set an error in SQL functions imeevma
@ 2019-05-28 11:39 ` imeevma
  2019-06-02 16:34   ` [tarantool-patches] " Vladislav Shpilevoy
  2019-06-09 17:14 ` [tarantool-patches] Re: [PATCH v1 0/9] " Vladislav Shpilevoy
  2019-06-13  9:44 ` Kirill Yukhin
  10 siblings, 1 reply; 25+ messages in thread
From: imeevma @ 2019-05-28 11:39 UTC (permalink / raw)
  To: v.shpilevoy; +Cc: tarantool-patches

After this patch, all errors in VDBE will be set using diag_set().

Closes #4074
---
 src/box/execute.c                        |  23 +--
 src/box/sql/vdbe.c                       | 297 +++++++++++--------------------
 src/box/sql/vdbeInt.h                    |  10 --
 src/box/sql/vdbeapi.c                    |  34 +---
 src/box/sql/vdbeaux.c                    |  20 +--
 src/box/sql/vdbemem.c                    |  10 +-
 test/sql-tap/gh-2931-savepoints.test.lua |   2 +-
 test/sql/savepoints.result               |   2 +-
 8 files changed, 122 insertions(+), 276 deletions(-)

diff --git a/src/box/execute.c b/src/box/execute.c
index a3d4a92..e81cc32 100644
--- a/src/box/execute.c
+++ b/src/box/execute.c
@@ -410,8 +410,7 @@ port_sql_dump_msgpack(struct port *port, struct obuf *out)
  * @retval -1 Error.
  */
 static inline int
-sql_execute(sql *db, struct sql_stmt *stmt, struct port *port,
-	    struct region *region)
+sql_execute(struct sql_stmt *stmt, struct port *port, struct region *region)
 {
 	int rc, column_count = sql_column_count(stmt);
 	if (column_count > 0) {
@@ -427,15 +426,8 @@ sql_execute(sql *db, struct sql_stmt *stmt, struct port *port,
 		rc = sql_step(stmt);
 		assert(rc != SQL_ROW && rc != SQL_OK);
 	}
-	if (rc != SQL_DONE) {
-		if (db->errCode != SQL_TARANTOOL_ERROR) {
-			const char *err = (char *)sql_value_text(db->pErr);
-			if (err == NULL)
-				err = sqlErrStr(db->errCode);
-			diag_set(ClientError, ER_SQL_EXECUTE, err);
-		}
+	if (rc != SQL_DONE)
 		return -1;
-	}
 	return 0;
 }
 
@@ -446,19 +438,12 @@ sql_prepare_and_execute(const char *sql, int len, const struct sql_bind *bind,
 {
 	struct sql_stmt *stmt;
 	struct sql *db = sql_get();
-	if (sql_prepare_v2(db, sql, len, &stmt, NULL) != SQL_OK) {
-		if (db->errCode != SQL_TARANTOOL_ERROR) {
-			const char *err = (char *)sql_value_text(db->pErr);
-			if (err == NULL)
-				err = sqlErrStr(db->errCode);
-			diag_set(ClientError, ER_SQL_EXECUTE, err);
-		}
+	if (sql_prepare_v2(db, sql, len, &stmt, NULL) != SQL_OK)
 		return -1;
-	}
 	assert(stmt != NULL);
 	port_sql_create(port, stmt);
 	if (sql_bind(stmt, bind, bind_count) == 0 &&
-	    sql_execute(db, stmt, port, region) == 0)
+	    sql_execute(stmt, port, region) == 0)
 		return 0;
 	port_destroy(port);
 	return -1;
diff --git a/src/box/sql/vdbe.c b/src/box/sql/vdbe.c
index 43d7329..5bf5e6e 100644
--- a/src/box/sql/vdbe.c
+++ b/src/box/sql/vdbe.c
@@ -986,7 +986,7 @@ case OP_Halt: {
 		p->rc = SQL_BUSY;
 	} else {
 		assert(rc==SQL_OK || (p->rc&0xff)==SQL_CONSTRAINT);
-		rc = p->rc ? SQL_ERROR : SQL_DONE;
+		rc = p->rc ? SQL_TARANTOOL_ERROR : SQL_DONE;
 	}
 	goto vdbe_return;
 }
@@ -1098,17 +1098,13 @@ case OP_NextAutoincValue: {
 	assert(pOp->p2 > 0);
 
 	struct space *space = space_by_id(pOp->p1);
-	if (space == NULL) {
-		rc = SQL_TARANTOOL_ERROR;
+	if (space == NULL)
 		goto abort_due_to_error;
-	}
 
 	int64_t value;
 	struct sequence *sequence = space->sequence;
-	if (sequence == NULL || sequence_next(sequence, &value) != 0) {
-		rc = SQL_TARANTOOL_ERROR;
+	if (sequence == NULL || sequence_next(sequence, &value) != 0)
 		goto abort_due_to_error;
-	}
 
 	pOut = out2Prerelease(p, pOp);
 	pOut->flags = MEM_Int;
@@ -1335,7 +1331,7 @@ case OP_ResultRow: {
 	 * not return the number of rows modified. And do not RELEASE the statement
 	 * transaction. It needs to be rolled back.
 	 */
-	if (SQL_OK!=(rc = sqlVdbeCheckFk(p, 0))) {
+	if (sqlVdbeCheckFk(p, 0) != SQL_OK) {
 		assert(user_session->sql_flags&SQL_CountRows);
 		goto abort_due_to_error;
 	}
@@ -1427,7 +1423,6 @@ case OP_Concat: {           /* same as TK_CONCAT, in1, in2, out3 */
 					  mem_type_to_str(pIn2);
 		diag_set(ClientError, ER_INCONSISTENT_TYPES, "TEXT or BLOB",
 			 inconsistent_type);
-		rc = SQL_TARANTOOL_ERROR;
 		goto abort_due_to_error;
 	}
 
@@ -1435,10 +1430,10 @@ case OP_Concat: {           /* same as TK_CONCAT, in1, in2, out3 */
 	if (str_type_p1 != str_type_p2) {
 		diag_set(ClientError, ER_INCONSISTENT_TYPES,
 			 mem_type_to_str(pIn2), mem_type_to_str(pIn1));
-		rc = SQL_TARANTOOL_ERROR;
 		goto abort_due_to_error;
 	}
-	if (ExpandBlob(pIn1) || ExpandBlob(pIn2)) goto no_mem;
+	if (ExpandBlob(pIn1) != SQL_OK || ExpandBlob(pIn2) != SQL_OK)
+		goto abort_due_to_error;
 	nByte = pIn1->n + pIn2->n;
 	if (nByte>db->aLimit[SQL_LIMIT_LENGTH]) {
 		goto too_big;
@@ -1551,13 +1546,11 @@ case OP_Remainder: {           /* same as TK_REM, in1, in2, out3 */
 		if (sqlVdbeRealValue(pIn1, &rA) != 0) {
 			diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
 				 sql_value_text(pIn1), "numeric");
-			rc = SQL_TARANTOOL_ERROR;
 			goto abort_due_to_error;
 		}
 		if (sqlVdbeRealValue(pIn2, &rB) != 0) {
 			diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
 				 sql_value_text(pIn2), "numeric");
-			rc = SQL_TARANTOOL_ERROR;
 			goto abort_due_to_error;
 		}
 		switch( pOp->opcode) {
@@ -1597,11 +1590,9 @@ arithmetic_result_is_null:
 
 division_by_zero:
 	diag_set(ClientError, ER_SQL_EXECUTE, "division by zero");
-	rc = SQL_TARANTOOL_ERROR;
 	goto abort_due_to_error;
 integer_overflow:
 	diag_set(ClientError, ER_SQL_EXECUTE, "integer is overflowed");
-	rc = SQL_TARANTOOL_ERROR;
 	goto abort_due_to_error;
 }
 
@@ -1721,10 +1712,8 @@ case OP_Function: {
 	(*pCtx->pFunc->xSFunc)(pCtx, pCtx->argc, pCtx->argv);/* IMP: R-24505-23230 */
 
 	/* If the function returned an error, throw an exception */
-	if (pCtx->is_aborted) {
-		rc = SQL_TARANTOOL_ERROR;
+	if (pCtx->is_aborted)
 		goto abort_due_to_error;
-	}
 
 	/* Copy the result of the function into register P3 */
 	if (pOut->flags & (MEM_Str|MEM_Blob)) {
@@ -1785,13 +1774,11 @@ case OP_ShiftRight: {           /* same as TK_RSHIFT, in1, in2, out3 */
 	if (sqlVdbeIntValue(pIn2, (int64_t *) &iA) != 0) {
 		diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
 			 sql_value_text(pIn2), "integer");
-		rc = SQL_TARANTOOL_ERROR;
 		goto abort_due_to_error;
 	}
 	if (sqlVdbeIntValue(pIn1, (int64_t *) &iB) != 0) {
 		diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
 			 sql_value_text(pIn1), "integer");
-		rc = SQL_TARANTOOL_ERROR;
 		goto abort_due_to_error;
 	}
 	op = pOp->opcode;
@@ -1860,7 +1847,6 @@ case OP_MustBeInt: {            /* jump, in1 */
 			if (pOp->p2==0) {
 				diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
 					 sql_value_text(pIn1), "integer");
-				rc = SQL_TARANTOOL_ERROR;
 				goto abort_due_to_error;
 			} else {
 				goto jump_to_p2;
@@ -1906,8 +1892,7 @@ case OP_Realify: {                  /* in1 */
  */
 case OP_Cast: {                  /* in1 */
 	pIn1 = &aMem[pOp->p1];
-	rc = ExpandBlob(pIn1);
-	if (rc != 0)
+	if (ExpandBlob(pIn1) != SQL_OK)
 		goto abort_due_to_error;
 	rc = sqlVdbeMemCast(pIn1, pOp->p2);
 	UPDATE_MAX_BLOBSIZE(pIn1);
@@ -1915,7 +1900,6 @@ case OP_Cast: {                  /* in1 */
 		break;
 	diag_set(ClientError, ER_SQL_TYPE_MISMATCH, sql_value_text(pIn1),
 		 field_type_strs[pOp->p2]);
-	rc = SQL_TARANTOOL_ERROR;
 	goto abort_due_to_error;
 }
 #endif /* SQL_OMIT_CAST */
@@ -2068,7 +2052,6 @@ case OP_Ge: {             /* same as TK_GE, jump, in1, in3 */
 						  mem_type_to_str(pIn3);
 			diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
 				 inconsistent_type, "boolean");
-			rc = SQL_TARANTOOL_ERROR;
 			goto abort_due_to_error;
 		}
 		res = sqlMemCompare(pIn3, pIn1, NULL);
@@ -2087,7 +2070,6 @@ case OP_Ge: {             /* same as TK_GE, jump, in1, in3 */
 							 ER_SQL_TYPE_MISMATCH,
 							 sql_value_text(pIn3),
 							 "numeric");
-						rc = SQL_TARANTOOL_ERROR;
 						goto abort_due_to_error;
 					}
 
@@ -2329,7 +2311,6 @@ case OP_Or: {             /* same as TK_OR, in1, in2, out3 */
 	} else {
 		diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
 			 sql_value_text(pIn1), "boolean");
-		rc = SQL_TARANTOOL_ERROR;
 		goto abort_due_to_error;
 	}
 	pIn2 = &aMem[pOp->p2];
@@ -2340,7 +2321,6 @@ case OP_Or: {             /* same as TK_OR, in1, in2, out3 */
 	} else {
 		diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
 			 sql_value_text(pIn2), "boolean");
-		rc = SQL_TARANTOOL_ERROR;
 		goto abort_due_to_error;
 	}
 	if (pOp->opcode==OP_And) {
@@ -2374,7 +2354,6 @@ case OP_Not: {                /* same as TK_NOT, in1, out2 */
 		if ((pIn1->flags & MEM_Bool) == 0) {
 			diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
 				 sql_value_text(pIn1), "boolean");
-			rc = SQL_TARANTOOL_ERROR;
 			goto abort_due_to_error;
 		}
 		mem_set_bool(pOut, ! pIn1->u.b);
@@ -2398,7 +2377,6 @@ case OP_BitNot: {             /* same as TK_BITNOT, in1, out2 */
 		if (sqlVdbeIntValue(pIn1, &i) != 0) {
 			diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
 				 sql_value_text(pIn1), "integer");
-			rc = SQL_TARANTOOL_ERROR;
 			goto abort_due_to_error;
 		}
 		pOut->flags = MEM_Int;
@@ -2446,7 +2424,6 @@ case OP_IfNot: {            /* jump, in1 */
 	} else {
 		diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
 			 sql_value_text(pIn1), "boolean");
-		rc = SQL_TARANTOOL_ERROR;
 		goto abort_due_to_error;
 	}
 	VdbeBranchTaken(c!=0, 2);
@@ -2586,8 +2563,9 @@ case OP_Column: {
 		zEnd = zData + pC->payloadSize;
 	} else {
 		memset(&sMem, 0, sizeof(sMem));
-		rc = sqlVdbeMemFromBtree(pC->uc.pCursor, 0, pC->payloadSize, &sMem);
-		if (rc!=SQL_OK) goto abort_due_to_error;
+		if (sqlVdbeMemFromBtree(pC->uc.pCursor, 0, pC->payloadSize,
+					&sMem) != SQL_OK)
+			goto abort_due_to_error;
 		zData = (u8*)sMem.z;
 		zEnd = zData + pC->payloadSize;
 	}
@@ -2646,10 +2624,8 @@ case OP_Column: {
 	}
 	uint32_t unused;
 	if (vdbe_decode_msgpack_into_mem((const char *)(zData + aOffset[p2]),
-					 pDest, &unused) != 0) {
-		rc = SQL_TARANTOOL_ERROR;
+					 pDest, &unused) != 0)
 		goto abort_due_to_error;
-	}
 	/* MsgPack map, array or extension (unsupported in sql).
 	 * Wrap it in a blob verbatim.
 	 */
@@ -2683,7 +2659,11 @@ case OP_Column: {
 	if ((pDest->flags & (MEM_Ephem | MEM_Str)) == (MEM_Ephem | MEM_Str)) {
 		int len = pDest->n;
 		if (pDest->szMalloc<len+1) {
-			if (sqlVdbeMemGrow(pDest, len+1, 1)) goto op_column_error;
+			if (sqlVdbeMemGrow(pDest, len + 1, 1)) {
+				if (zData != pC->aRow)
+					sqlVdbeMemRelease(&sMem);
+				goto abort_due_to_error;
+			}
 		} else {
 			pDest->z = memcpy(pDest->zMalloc, pDest->z, len);
 			pDest->flags &= ~MEM_Ephem;
@@ -2697,10 +2677,6 @@ case OP_Column: {
 	UPDATE_MAX_BLOBSIZE(pDest);
 	REGISTER_TRACE(pOp->p3, pDest);
 	break;
-
-			op_column_error:
-	if (zData!=pC->aRow) sqlVdbeMemRelease(&sMem);
-	goto abort_due_to_error;
 }
 
 /* Opcode: ApplyType P1 P2 * P4 *
@@ -2725,7 +2701,6 @@ case OP_ApplyType: {
 			diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
 				 sql_value_text(pIn1),
 				 field_type_strs[type]);
-			rc = SQL_TARANTOOL_ERROR;
 			goto abort_due_to_error;
 		}
 		pIn1++;
@@ -2798,10 +2773,8 @@ case OP_MakeRecord: {
 	uint32_t tuple_size;
 	char *tuple =
 		sql_vdbe_mem_encode_tuple(pData0, nField, &tuple_size, region);
-	if (tuple == NULL) {
-		rc = SQL_TARANTOOL_ERROR;
+	if (tuple == NULL)
 		goto abort_due_to_error;
-	}
 	if ((int64_t)tuple_size > db->aLimit[SQL_LIMIT_LENGTH])
 		goto too_big;
 
@@ -2856,13 +2829,14 @@ case OP_Count: {         /* out2 */
 	assert(pCrsr);
 	nEntry = 0;  /* Not needed.  Only used to silence a warning. */
 	if (pCrsr->curFlags & BTCF_TaCursor) {
-		rc = tarantoolsqlCount(pCrsr, &nEntry);
+		if (tarantoolsqlCount(pCrsr, &nEntry) != SQL_OK)
+			goto abort_due_to_error;
 	} else if (pCrsr->curFlags & BTCF_TEphemCursor) {
-		rc = tarantoolsqlEphemeralCount(pCrsr, &nEntry);
+		if (tarantoolsqlEphemeralCount(pCrsr, &nEntry) != SQL_OK)
+			goto abort_due_to_error;
 	} else {
 		unreachable();
 	}
-	if (rc) goto abort_due_to_error;
 	pOut = out2Prerelease(p, pOp);
 	pOut->u.i = nEntry;
 	break;
@@ -2886,7 +2860,6 @@ case OP_Savepoint: {
 	if (psql_txn == NULL) {
 		assert(!box_txn());
 		diag_set(ClientError, ER_NO_TRANSACTION);
-		rc = SQL_TARANTOOL_ERROR;
 		goto abort_due_to_error;
 	}
 	p1 = pOp->p1;
@@ -2914,8 +2887,8 @@ case OP_Savepoint: {
 			pSavepoint = pSavepoint->pNext
 			);
 		if (!pSavepoint) {
-			sqlVdbeError(p, "no such savepoint: %s", zName);
-			rc = SQL_ERROR;
+			diag_set(ClientError, ER_NO_SUCH_SAVEPOINT);
+			goto abort_due_to_error;
 		} else {
 
 			/* Determine whether or not this is a transaction savepoint. If so,
@@ -2932,7 +2905,8 @@ case OP_Savepoint: {
 					p->rc = rc = SQL_BUSY;
 					goto vdbe_return;
 				}
-				rc = p->rc;
+				if (p->rc != SQL_OK)
+					goto abort_due_to_error;
 			} else {
 				if (p1==SAVEPOINT_ROLLBACK)
 					box_txn_rollback_to_savepoint(pSavepoint->tnt_savepoint);
@@ -2964,7 +2938,6 @@ case OP_Savepoint: {
 			}
 		}
 	}
-	if (rc) goto abort_due_to_error;
 
 	break;
 }
@@ -2987,7 +2960,6 @@ case OP_CheckViewReferences: {
 	if (space->def->view_ref_count > 0) {
 		diag_set(ClientError, ER_DROP_SPACE, space->def->name,
 			 "other views depend on this space");
-		rc = SQL_TARANTOOL_ERROR;
 		goto abort_due_to_error;
 	}
 	break;
@@ -3000,10 +2972,8 @@ case OP_CheckViewReferences: {
  * Otherwise, raise an error with appropriate error message.
  */
 case OP_TransactionBegin: {
-	if (sql_txn_begin(p) != 0) {
-		rc = SQL_TARANTOOL_ERROR;
+	if (sql_txn_begin(p) != 0)
 		goto abort_due_to_error;
-	}
 	p->auto_commit = false	;
 	break;
 }
@@ -3019,13 +2989,11 @@ case OP_TransactionBegin: {
 case OP_TransactionCommit: {
 	struct txn *txn = in_txn();
 	if (txn != NULL) {
-		if (txn_commit(txn) != 0) {
-			rc = SQL_TARANTOOL_ERROR;
+		if (txn_commit(txn) != 0)
 			goto abort_due_to_error;
-		}
 	} else {
-		sqlVdbeError(p, "cannot commit - no transaction is active");
-		rc = SQL_ERROR;
+		diag_set(ClientError, ER_SQL_EXECUTE, "cannot commit - no "\
+			 "transaction is active");
 		goto abort_due_to_error;
 	}
 	break;
@@ -3038,14 +3006,11 @@ case OP_TransactionCommit: {
  */
 case OP_TransactionRollback: {
 	if (box_txn()) {
-		if (box_txn_rollback() != 0) {
-			rc = SQL_TARANTOOL_ERROR;
+		if (box_txn_rollback() != 0)
 			goto abort_due_to_error;
-		}
 	} else {
-		sqlVdbeError(p, "cannot rollback - no "
-				    "transaction is active");
-		rc = SQL_ERROR;
+		diag_set(ClientError, ER_SQL_EXECUTE, "cannot rollback - no "\
+			 "transaction is active");
 		goto abort_due_to_error;
 	}
 	break;
@@ -3063,16 +3028,12 @@ case OP_TransactionRollback: {
  */
 case OP_TTransaction: {
 	if (!box_txn()) {
-		if (sql_txn_begin(p) != 0) {
-			rc = SQL_TARANTOOL_ERROR;
+		if (sql_txn_begin(p) != 0)
 			goto abort_due_to_error;
-		}
 	} else {
 		p->anonymous_savepoint = sql_savepoint(p, NULL);
-		if (p->anonymous_savepoint == NULL) {
-			rc = SQL_TARANTOOL_ERROR;
+		if (p->anonymous_savepoint == NULL)
 			goto abort_due_to_error;
-		}
 	}
 	break;
 }
@@ -3111,9 +3072,8 @@ case OP_IteratorOpen:
 	if (box_schema_version() != p->schema_ver &&
 	    (pOp->p5 & OPFLAG_SYSTEMSP) == 0) {
 		p->expired = 1;
-		rc = SQL_ERROR;
-		sqlVdbeError(p, "schema version has changed: " \
-				    "need to re-compile SQL statement");
+		diag_set(ClientError, ER_SQL_EXECUTE, "schema version has "\
+			 "changed: need to re-compile SQL statement");
 		goto abort_due_to_error;
 	}
 	struct space *space;
@@ -3122,10 +3082,8 @@ case OP_IteratorOpen:
 	else
 		space = aMem[pOp->p3].u.p;
 	assert(space != NULL);
-	if (access_check_space(space, PRIV_R) != 0) {
-		rc = SQL_TARANTOOL_ERROR;
+	if (access_check_space(space, PRIV_R) != 0)
 		goto abort_due_to_error;
-	}
 
 	struct index *index = space_index(space, pOp->p2);
 	assert(index != NULL);
@@ -3148,8 +3106,6 @@ case OP_IteratorOpen:
 	cur->nullRow = 1;
 open_cursor_set_hints:
 	cur->uc.pCursor->hints = pOp->p5 & OPFLAG_SEEKEQ;
-	if (rc != 0)
-		goto abort_due_to_error;
 	break;
 }
 
@@ -3171,10 +3127,8 @@ case OP_OpenTEphemeral: {
 	struct space *space = sql_ephemeral_space_create(pOp->p2,
 							 pOp->p4.key_info);
 
-	if (space == NULL) {
-		rc = SQL_TARANTOOL_ERROR;
+	if (space == NULL)
 		goto abort_due_to_error;
-	}
 	aMem[pOp->p1].u.p = space;
 	aMem[pOp->p1].flags = MEM_Ptr;
 	break;
@@ -3200,8 +3154,8 @@ case OP_SorterOpen: {
 	pCx = allocateCursor(p, pOp->p1, pOp->p2, CURTYPE_SORTER);
 	if (pCx==0) goto no_mem;
 	pCx->key_def = def;
-	rc = sqlVdbeSorterInit(db, pCx);
-	if (rc) goto abort_due_to_error;
+	if (sqlVdbeSorterInit(db, pCx) != SQL_OK)
+		goto abort_due_to_error;
 	break;
 }
 
@@ -3433,7 +3387,6 @@ case OP_SeekGT: {       /* jump, in3 */
 		} else {
 			diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
 				 sql_value_text(pIn3), "integer");
-			rc = SQL_TARANTOOL_ERROR;
 			goto abort_due_to_error;
 		}
 		iKey = i;
@@ -3514,10 +3467,8 @@ case OP_SeekGT: {       /* jump, in3 */
 #endif
 	r.eqSeen = 0;
 	r.opcode = oc;
-	rc = sqlCursorMovetoUnpacked(pC->uc.pCursor, &r, &res);
-	if (rc!=SQL_OK) {
+	if (sqlCursorMovetoUnpacked(pC->uc.pCursor, &r, &res) != SQL_OK)
 		goto abort_due_to_error;
-	}
 	if (eqOnly && r.eqSeen==0) {
 		assert(res!=0);
 		goto seek_not_found;
@@ -3529,8 +3480,8 @@ case OP_SeekGT: {       /* jump, in3 */
 	if (oc>=OP_SeekGE) {  assert(oc==OP_SeekGE || oc==OP_SeekGT);
 		if (res<0 || (res==0 && oc==OP_SeekGT)) {
 			res = 0;
-			rc = sqlCursorNext(pC->uc.pCursor, &res);
-			if (rc!=SQL_OK) goto abort_due_to_error;
+			if (sqlCursorNext(pC->uc.pCursor, &res) != SQL_OK)
+				goto abort_due_to_error;
 		} else {
 			res = 0;
 		}
@@ -3538,8 +3489,8 @@ case OP_SeekGT: {       /* jump, in3 */
 		assert(oc==OP_SeekLT || oc==OP_SeekLE);
 		if (res>0 || (res==0 && oc==OP_SeekLT)) {
 			res = 0;
-			rc = sqlCursorPrevious(pC->uc.pCursor, &res);
-			if (rc!=SQL_OK) goto abort_due_to_error;
+			if (sqlCursorPrevious(pC->uc.pCursor, &res) != SQL_OK)
+				goto abort_due_to_error;
 		} else {
 			/* res might be negative because the table is empty.  Check to
 			 * see if this is the case.
@@ -3681,10 +3632,11 @@ case OP_Found: {        /* jump, in3 */
 		}
 	}
 	rc = sqlCursorMovetoUnpacked(pC->uc.pCursor, pIdxKey, &res);
-	if (pFree) sqlDbFree(db, pFree);
-	if (rc!=SQL_OK) {
+	if (pFree != NULL)
+		sqlDbFree(db, pFree);
+	assert(rc == SQL_OK || rc == SQL_TARANTOOL_ERROR);
+	if (rc != SQL_OK)
 		goto abort_due_to_error;
-	}
 	pC->seekResult = res;
 	alreadyExists = (res==0);
 	pC->nullRow = 1-alreadyExists;
@@ -3744,10 +3696,8 @@ case OP_NextIdEphemeral: {
 	struct space *space = (struct space*)p->aMem[pOp->p1].u.p;
 	assert(space->def->id == 0);
 	uint64_t rowid;
-	if (space->vtab->ephemeral_rowid_next(space, &rowid) != 0) {
-		rc = SQL_TARANTOOL_ERROR;
+	if (space->vtab->ephemeral_rowid_next(space, &rowid) != 0)
 		goto abort_due_to_error;
-	}
 	/*
 	 * FIXME: since memory cell can comprise only 32-bit
 	 * integer, make sure it can fit in. This check should
@@ -3756,7 +3706,6 @@ case OP_NextIdEphemeral: {
 	 */
 	if (rowid > INT32_MAX) {
 		diag_set(ClientError, ER_ROWID_OVERFLOW);
-		rc = SQL_TARANTOOL_ERROR;
 		goto abort_due_to_error;
 	}
 	pOut = &aMem[pOp->p2];
@@ -3903,7 +3852,8 @@ case OP_SorterCompare: {
 			pIn3 = &aMem[pOp->p3];
 			nKeyCol = pOp->p4.i;
 			res = 0;
-			rc = sqlVdbeSorterCompare(pC, pIn3, nKeyCol, &res);
+			if (sqlVdbeSorterCompare(pC, pIn3, nKeyCol, &res) != 0)
+				rc = SQL_TARANTOOL_ERROR;
 			VdbeBranchTaken(res!=0,2);
 			if (rc) goto abort_due_to_error;
 			if (res) goto jump_to_p2;
@@ -3928,10 +3878,10 @@ case OP_SorterData: {
 	pOut = &aMem[pOp->p2];
 	pC = p->apCsr[pOp->p1];
 	assert(isSorter(pC));
-	rc = sqlVdbeSorterRowkey(pC, pOut);
-	assert(rc!=SQL_OK || (pOut->flags & MEM_Blob));
+	if (sqlVdbeSorterRowkey(pC, pOut) != SQL_OK)
+		goto abort_due_to_error;
+	assert(pOut->flags & MEM_Blob);
 	assert(pOp->p1>=0 && pOp->p1<p->nCursor);
-	if (rc) goto abort_due_to_error;
 	p->apCsr[pOp->p3]->cacheStatus = CACHE_STALE;
 	break;
 }
@@ -3998,11 +3948,9 @@ case OP_RowData: {
 	testcase( n==0);
 
 	sqlVdbeMemRelease(pOut);
-	rc = sql_vdbe_mem_alloc_region(pOut, n);
-	if (rc)
-		goto no_mem;
-	rc = sqlCursorPayload(pCrsr, 0, n, pOut->z);
-	if (rc) goto abort_due_to_error;
+	if (sql_vdbe_mem_alloc_region(pOut, n) != SQL_OK ||
+	    sqlCursorPayload(pCrsr, 0, n, pOut->z) != SQL_OK)
+		goto abort_due_to_error;
 	UPDATE_MAX_BLOBSIZE(pOut);
 	REGISTER_TRACE(pOp->p2, pOut);
 	break;
@@ -4137,15 +4085,18 @@ case OP_Rewind: {        /* jump */
 	pC->seekOp = OP_Rewind;
 #endif
 	if (isSorter(pC)) {
-		rc = sqlVdbeSorterRewind(pC, &res);
+		if (sqlVdbeSorterRewind(pC, &res) != SQL_OK)
+			goto abort_due_to_error;
 	} else {
 		assert(pC->eCurType==CURTYPE_TARANTOOL);
 		pCrsr = pC->uc.pCursor;
 		assert(pCrsr);
-		rc = tarantoolsqlFirst(pCrsr, &res);
+		if (tarantoolsqlFirst(pCrsr, &res) != SQL_OK)
+			rc = SQL_TARANTOOL_ERROR;
 		pC->cacheStatus = CACHE_STALE;
+		if (rc != SQL_OK)
+			goto abort_due_to_error;
 	}
-	if (rc) goto abort_due_to_error;
 	pC->nullRow = (u8)res;
 	assert(pOp->p2>0 && pOp->p2<p->nOp);
 	VdbeBranchTaken(res!=0,2);
@@ -4291,11 +4242,8 @@ case OP_SorterInsert: {      /* in2 */
 	assert(isSorter(cursor));
 	pIn2 = &aMem[pOp->p2];
 	assert((pIn2->flags & MEM_Blob) != 0);
-	rc = ExpandBlob(pIn2);
-	if (rc != 0)
-		goto abort_due_to_error;
-	rc = sqlVdbeSorterWrite(cursor, pIn2);
-	if (rc != 0)
+	if (ExpandBlob(pIn2) != SQL_OK ||
+	    sqlVdbeSorterWrite(cursor, pIn2) != SQL_OK)
 		goto abort_due_to_error;
 	break;
 }
@@ -4325,8 +4273,7 @@ case OP_IdxInsert: {
 	assert((pIn2->flags & MEM_Blob) != 0);
 	if (pOp->p5 & OPFLAG_NCHANGE)
 		p->nChange++;
-	rc = ExpandBlob(pIn2);
-	if (rc != 0)
+	if (ExpandBlob(pIn2) != SQL_OK)
 		goto abort_due_to_error;
 	struct space *space;
 	if (pOp->p4type == P4_SPACEPTR)
@@ -4360,6 +4307,7 @@ case OP_IdxInsert: {
 	} else if (pOp->p5 & OPFLAG_OE_ROLLBACK) {
 		p->errorAction = ON_CONFLICT_ACTION_ROLLBACK;
 	}
+	assert(rc == SQL_OK || rc == SQL_TARANTOOL_ERROR);
 	if (rc != 0)
 		goto abort_due_to_error;
 	break;
@@ -4427,14 +4375,12 @@ case OP_Update: {
 	if (is_error) {
 		diag_set(OutOfMemory, stream.pos - stream.buf,
 			"mpstream_flush", "stream");
-		rc = SQL_TARANTOOL_ERROR;
 		goto abort_due_to_error;
 	}
 	uint32_t ops_size = region_used(region) - used;
 	const char *ops = region_join(region, ops_size);
 	if (ops == NULL) {
 		diag_set(OutOfMemory, ops_size, "region_join", "raw");
-		rc = SQL_TARANTOOL_ERROR;
 		goto abort_due_to_error;
 	}
 
@@ -4460,6 +4406,7 @@ case OP_Update: {
 	} else if (pOp->p5 & OPFLAG_OE_ROLLBACK) {
 		p->errorAction = ON_CONFLICT_ACTION_ROLLBACK;
 	}
+	assert(rc == SQL_OK || rc == SQL_TARANTOOL_ERROR);
 	if (rc != 0)
 		goto abort_due_to_error;
 	break;
@@ -4510,8 +4457,7 @@ case OP_SDelete: {
 	struct space *space = space_by_id(pOp->p1);
 	assert(space != NULL);
 	assert(space_is_system(space));
-	rc = sql_delete_by_key(space, 0, pIn2->z, pIn2->n);
-	if (rc)
+	if (sql_delete_by_key(space, 0, pIn2->z, pIn2->n) != SQL_OK)
 		goto abort_due_to_error;
 	if (pOp->p5 & OPFLAG_NCHANGE)
 		p->nChange++;
@@ -4545,18 +4491,19 @@ case OP_IdxDelete: {
 	r.default_rc = 0;
 	r.aMem = &aMem[pOp->p2];
 	r.opcode = OP_IdxDelete;
-	rc = sqlCursorMovetoUnpacked(pCrsr, &r, &res);
-	if (rc) goto abort_due_to_error;
+	if (sqlCursorMovetoUnpacked(pCrsr, &r, &res) != SQL_OK)
+		goto abort_due_to_error;
 	if (res==0) {
 		assert(pCrsr->eState == CURSOR_VALID);
 		if (pCrsr->curFlags & BTCF_TaCursor) {
-			rc = tarantoolsqlDelete(pCrsr, 0);
+			if (tarantoolsqlDelete(pCrsr, 0) != SQL_OK)
+				goto abort_due_to_error;
 		} else if (pCrsr->curFlags & BTCF_TEphemCursor) {
-			rc = tarantoolsqlEphemeralDelete(pCrsr);
+			if (tarantoolsqlEphemeralDelete(pCrsr) != SQL_OK)
+				goto abort_due_to_error;
 		} else {
 			unreachable();
 		}
-		if (rc) goto abort_due_to_error;
 	}
 	pC->cacheStatus = CACHE_STALE;
 	pC->seekResult = 0;
@@ -4668,14 +4615,14 @@ case OP_Clear: {
 	rc = 0;
 	if (pOp->p2 > 0) {
 		if (box_truncate(space_id) != 0)
-			rc = SQL_TARANTOOL_ERROR;
+			goto abort_due_to_error;
 	} else {
 		uint32_t tuple_count;
-		rc = tarantoolsqlClearTable(space, &tuple_count);
-		if (rc == 0 && (pOp->p5 & OPFLAG_NCHANGE) != 0)
+		if (tarantoolsqlClearTable(space, &tuple_count) != SQL_OK)
+			goto abort_due_to_error;
+		if ((pOp->p5 & OPFLAG_NCHANGE) != 0)
 			p->nChange += tuple_count;
 	}
-	if (rc) goto abort_due_to_error;
 	break;
 }
 
@@ -4698,8 +4645,8 @@ case OP_ResetSorter: {
 	} else {
 		assert(pC->eCurType==CURTYPE_TARANTOOL);
 		assert(pC->uc.pCursor->curFlags & BTCF_TEphemCursor);
-		rc = tarantoolsqlEphemeralClearTable(pC->uc.pCursor);
-		if (rc) goto abort_due_to_error;
+		if (tarantoolsqlEphemeralClearTable(pC->uc.pCursor) != SQL_OK)
+			goto abort_due_to_error;
 	}
 	break;
 }
@@ -4732,8 +4679,8 @@ case OP_RenameTable: {
 	zNewTableName = pOp->p4.z;
 	zOldTableName = sqlDbStrNDup(db, zOldTableName,
 					 sqlStrlen30(zOldTableName));
-	rc = sql_rename_table(space_id, zNewTableName);
-	if (rc) goto abort_due_to_error;
+	if (sql_rename_table(space_id, zNewTableName) != SQL_OK)
+		goto abort_due_to_error;
 	/*
 	 * Rebuild 'CREATE TRIGGER' expressions of all triggers
 	 * created on this table. Sure, this action is not atomic
@@ -4743,20 +4690,18 @@ case OP_RenameTable: {
 	for (struct sql_trigger *trigger = triggers; trigger != NULL; ) {
 		/* Store pointer as trigger will be destructed. */
 		struct sql_trigger *next_trigger = trigger->next;
-		rc = tarantoolsqlRenameTrigger(trigger->zName,
-						   zOldTableName, zNewTableName);
-		if (rc != SQL_OK) {
-			/*
-			 * FIXME: In the case of error,
-			 * part of triggers would have invalid
-			 * space name in tuple so can not been
-			 * persisted.
-			 * Server could be restarted.
-			 * In this case, rename table back and
-			 * try again.
-			 */
+		/*
+		 * FIXME: In the case of error,
+		 * part of triggers would have invalid
+		 * space name in tuple so can not been
+		 * persisted.
+		 * Server could be restarted.
+		 * In this case, rename table back and
+		 * try again.
+		 */
+		if (tarantoolsqlRenameTrigger(trigger->zName, zOldTableName,
+					      zNewTableName) != SQL_OK)
 			goto abort_due_to_error;
-		}
 		trigger = next_trigger;
 	}
 	sqlDbFree(db, (void*)zOldTableName);
@@ -4771,8 +4716,8 @@ case OP_RenameTable: {
  */
 case OP_LoadAnalysis: {
 	assert(pOp->p1==0 );
-	rc = sql_analysis_load(db);
-	if (rc) goto abort_due_to_error;
+	if (sql_analysis_load(db) != SQL_OK)
+		goto abort_due_to_error;
 	break;
 }
 
@@ -4828,8 +4773,8 @@ case OP_Program: {        /* jump */
 	}
 
 	if (p->nFrame>=db->aLimit[SQL_LIMIT_TRIGGER_DEPTH]) {
-		rc = SQL_ERROR;
-		sqlVdbeError(p, "too many levels of trigger recursion");
+		diag_set(ClientError, ER_SQL_EXECUTE, "too many levels of "\
+			 "trigger recursion");
 		goto abort_due_to_error;
 	}
 
@@ -5157,11 +5102,9 @@ case OP_AggStep: {
 	(pCtx->pFunc->xSFunc)(pCtx,pCtx->argc,pCtx->argv); /* IMP: R-24505-23230 */
 	if (pCtx->is_aborted) {
 		sqlVdbeMemRelease(&t);
-		rc = SQL_TARANTOOL_ERROR;
 		goto abort_due_to_error;
-	} else {
-		assert(t.flags==MEM_Null);
 	}
+	assert(t.flags==MEM_Null);
 	if (pCtx->skipFlag) {
 		assert(pOp[-1].opcode==OP_CollSeq);
 		i = pOp[-1].p1;
@@ -5188,11 +5131,8 @@ case OP_AggFinal: {
 	assert(pOp->p1>0 && pOp->p1<=(p->nMem+1 - p->nCursor));
 	pMem = &aMem[pOp->p1];
 	assert((pMem->flags & ~(MEM_Null|MEM_Agg))==0);
-	rc = sqlVdbeMemFinalize(pMem, pOp->p4.pFunc);
-	if (rc) {
-		sqlVdbeError(p, "%s", sql_value_text(pMem));
+	if (sqlVdbeMemFinalize(pMem, pOp->p4.pFunc) != 0)
 		goto abort_due_to_error;
-	}
 	UPDATE_MAX_BLOBSIZE(pMem);
 	if (sqlVdbeMemTooBig(pMem)) {
 		goto too_big;
@@ -5301,10 +5241,8 @@ case OP_IncMaxid: {
 	assert(pOp->p1 > 0);
 	pOut = &aMem[pOp->p1];
 
-	rc = tarantoolsqlIncrementMaxid((uint64_t*) &pOut->u.i);
-	if (rc!=SQL_OK) {
+	if (tarantoolsqlIncrementMaxid((uint64_t*) &pOut->u.i) != SQL_OK)
 		goto abort_due_to_error;
-	}
 	pOut->flags = MEM_Int;
 	break;
 }
@@ -5368,28 +5306,8 @@ default: {          /* This is really OP_Noop and OP_Explain */
 	 * an error of some kind.
 	 */
 abort_due_to_error:
-	if (db->mallocFailed) rc = SQL_NOMEM;
-	assert(rc);
-	if (p->zErrMsg==0 && rc!=SQL_IOERR_NOMEM) {
-		const char *msg;
-		/* Avoiding situation when Tarantool error is set,
-		 * but error message isn't.
-		 */
-		if (rc == SQL_TARANTOOL_ERROR && tarantoolErrorMessage()) {
-			msg = tarantoolErrorMessage();
-		} else {
-			msg = sqlErrStr(rc);
-		}
-		sqlVdbeError(p, "%s", msg);
-	}
+	rc = SQL_TARANTOOL_ERROR;
 	p->rc = rc;
-	sqlSystemError(db, rc);
-	testcase( sqlGlobalConfig.xLog!=0);
-	sql_log(rc, "statement aborts at %d: [%s] %s",
-		    (int)(pOp - aOp), p->zSql, p->zErrMsg);
-	sqlVdbeHalt(p);
-	if (rc==SQL_IOERR_NOMEM) sqlOomFault(db);
-	rc = SQL_ERROR;
 
 	/* This is the only way out of this procedure. */
 vdbe_return:
@@ -5398,21 +5316,20 @@ vdbe_return:
 	assert(rc!=SQL_OK || nExtraDelete==0
 		|| sql_strlike_ci("DELETE%", p->zSql, 0) != 0
 		);
+	assert(rc == SQL_OK || rc == SQL_BUSY || rc == SQL_TARANTOOL_ERROR ||
+	       rc == SQL_ROW || rc == SQL_DONE);
 	return rc;
 
 	/* Jump to here if a string or blob larger than SQL_MAX_LENGTH
 	 * is encountered.
 	 */
 too_big:
-	sqlVdbeError(p, "string or blob too big");
-	rc = SQL_TOOBIG;
+	diag_set(ClientError, ER_SQL_EXECUTE, "string or blob too big");
 	goto abort_due_to_error;
 
 	/* Jump to here if a malloc() fails.
 	 */
 no_mem:
 	sqlOomFault(db);
-	sqlVdbeError(p, "out of memory");
-	rc = SQL_NOMEM;
 	goto abort_due_to_error;
 }
diff --git a/src/box/sql/vdbeInt.h b/src/box/sql/vdbeInt.h
index ee14510..9e6a426 100644
--- a/src/box/sql/vdbeInt.h
+++ b/src/box/sql/vdbeInt.h
@@ -244,10 +244,6 @@ struct Mem {
 #define MEM_Agg       0x4000	/* Mem.z points to an agg function context */
 #define MEM_Zero      0x8000	/* Mem.i contains count of 0s appended to blob */
 #define MEM_Subtype   0x10000	/* Mem.eSubtype is valid */
-#ifdef SQL_OMIT_INCRBLOB
-#undef MEM_Zero
-#define MEM_Zero 0x0000
-#endif
 
 /**
  * In contrast to Mem_TypeMask, this one allows to get
@@ -450,7 +446,6 @@ struct Vdbe {
 /*
  * Function prototypes
  */
-void sqlVdbeError(Vdbe *, const char *, ...);
 void sqlVdbeFreeCursor(Vdbe *, VdbeCursor *);
 void sqlVdbePopStack(Vdbe *, int);
 int sqlVdbeCursorRestore(VdbeCursor *);
@@ -532,13 +527,8 @@ void sqlVdbeMemPrettyPrint(Mem * pMem, char *zBuf);
 #endif
 int sqlVdbeMemHandleBom(Mem * pMem);
 
-#ifndef SQL_OMIT_INCRBLOB
 int sqlVdbeMemExpandBlob(Mem *);
 #define ExpandBlob(P) (((P)->flags&MEM_Zero)?sqlVdbeMemExpandBlob(P):0)
-#else
-#define sqlVdbeMemExpandBlob(x) SQL_OK
-#define ExpandBlob(P) SQL_OK
-#endif
 
 /**
  * Perform comparison of two keys: one is packed and one is not.
diff --git a/src/box/sql/vdbeapi.c b/src/box/sql/vdbeapi.c
index 673ccd1..3bdfa7d 100644
--- a/src/box/sql/vdbeapi.c
+++ b/src/box/sql/vdbeapi.c
@@ -536,15 +536,6 @@ sqlStep(Vdbe * p)
 		p->rc = SQL_NOMEM;
 	}
  end_of_step:
-	/* At this point local variable rc holds the value that should be
-	 * returned if this statement was compiled using the legacy
-	 * sql_prepare() interface. According to the docs, this can only
-	 * be one of the values in the first assert() below. Variable p->rc
-	 * contains the value that would be returned if sql_finalize()
-	 * were called on statement p.
-	 */
-	assert(rc == SQL_ROW || rc == SQL_DONE || rc == SQL_ERROR
-	       || (rc & 0xff) == SQL_BUSY || rc == SQL_MISUSE);
 	if (p->isPrepareV2 && rc != SQL_ROW && rc != SQL_DONE) {
 		/* If this statement was prepared using sql_prepare_v2(), and an
 		 * error has occurred, then return the error code in p->rc to the
@@ -564,20 +555,17 @@ int
 sql_step(sql_stmt * pStmt)
 {
 	int rc;			/* Result from sqlStep() */
-	int rc2 = SQL_OK;	/* Result from sqlReprepare() */
 	Vdbe *v = (Vdbe *) pStmt;	/* the prepared statement */
 	int cnt = 0;		/* Counter to prevent infinite loop of reprepares */
-	sql *db;		/* The database connection */
 
 	if (vdbeSafetyNotNull(v)) {
 		return SQL_MISUSE;
 	}
-	db = v->db;
 	v->doingRerun = 0;
 	while ((rc = sqlStep(v)) == SQL_SCHEMA
 	       && cnt++ < SQL_MAX_SCHEMA_RETRY) {
 		int savedPc = v->pc;
-		rc2 = rc = sqlReprepare(v);
+		rc = sqlReprepare(v);
 		if (rc != SQL_OK)
 			break;
 		sql_reset(pStmt);
@@ -585,26 +573,6 @@ sql_step(sql_stmt * pStmt)
 			v->doingRerun = 1;
 		assert(v->expired == 0);
 	}
-	if (rc2 != SQL_OK) {
-		/* This case occurs after failing to recompile an sql statement.
-		 * The error message from the SQL compiler has already been loaded
-		 * into the database handle. This block copies the error message
-		 * from the database handle into the statement and sets the statement
-		 * program counter to 0 to ensure that when the statement is
-		 * finalized or reset the parser error message is available via
-		 * sql_errmsg() and sql_errcode().
-		 */
-		const char *zErr = (const char *)sql_value_text(db->pErr);
-		sqlDbFree(db, v->zErrMsg);
-		if (!db->mallocFailed) {
-			v->zErrMsg = sqlDbStrDup(db, zErr);
-			v->rc = rc2;
-		} else {
-			v->zErrMsg = 0;
-			v->rc = rc = SQL_NOMEM;
-		}
-	}
-	rc = sqlApiExit(db, rc);
 	return rc;
 }
 
diff --git a/src/box/sql/vdbeaux.c b/src/box/sql/vdbeaux.c
index 619b211..3f573d0 100644
--- a/src/box/sql/vdbeaux.c
+++ b/src/box/sql/vdbeaux.c
@@ -116,19 +116,6 @@ sql_vdbe_prepare(struct Vdbe *vdbe)
 }
 
 /*
- * Change the error string stored in Vdbe.zErrMsg
- */
-void
-sqlVdbeError(Vdbe * p, const char *zFormat, ...)
-{
-	va_list ap;
-	sqlDbFree(p->db, p->zErrMsg);
-	va_start(ap, zFormat);
-	p->zErrMsg = sqlVMPrintf(p->db, zFormat, ap);
-	va_end(ap);
-}
-
-/*
  * Remember the SQL string for a prepared statement.
  */
 void
@@ -2115,10 +2102,11 @@ sqlVdbeCheckFk(Vdbe * p, int deferred)
 	if ((deferred && txn != NULL && txn->psql_txn != NULL &&
 	     txn->psql_txn->fk_deferred_count > 0) ||
 	    (!deferred && p->nFkConstraint > 0)) {
-		p->rc = SQL_CONSTRAINT_FOREIGNKEY;
+		p->rc = SQL_TARANTOOL_ERROR;
 		p->errorAction = ON_CONFLICT_ACTION_ABORT;
-		sqlVdbeError(p, "FOREIGN KEY constraint failed");
-		return SQL_ERROR;
+		diag_set(ClientError, ER_SQL_EXECUTE, "FOREIGN KEY constraint "\
+			 "failed");
+		return SQL_TARANTOOL_ERROR;
 	}
 	return SQL_OK;
 }
diff --git a/src/box/sql/vdbemem.c b/src/box/sql/vdbemem.c
index 312c661..ea6afa6 100644
--- a/src/box/sql/vdbemem.c
+++ b/src/box/sql/vdbemem.c
@@ -210,7 +210,6 @@ sqlVdbeMemMakeWriteable(Mem * pMem)
  * If the given Mem* has a zero-filled tail, turn it into an ordinary
  * blob stored in dynamically allocated space.
  */
-#ifndef SQL_OMIT_INCRBLOB
 int
 sqlVdbeMemExpandBlob(Mem * pMem)
 {
@@ -232,7 +231,6 @@ sqlVdbeMemExpandBlob(Mem * pMem)
 	pMem->flags &= ~(MEM_Zero | MEM_Term);
 	return SQL_OK;
 }
-#endif
 
 /*
  * It is already known that pMem contains an unterminated string.
@@ -315,8 +313,7 @@ sqlVdbeMemStringify(Mem * pMem, u8 bForce)
  * This routine calls the finalize method for that function.  The
  * result of the aggregate is stored back into pMem.
  *
- * Return SQL_ERROR if the finalizer reports an error.  SQL_OK
- * otherwise.
+ * Return -1 if the finalizer reports an error. 0 otherwise.
  */
 int
 sqlVdbeMemFinalize(Mem * pMem, FuncDef * pFunc)
@@ -337,9 +334,10 @@ sqlVdbeMemFinalize(Mem * pMem, FuncDef * pFunc)
 		if (pMem->szMalloc > 0)
 			sqlDbFree(pMem->db, pMem->zMalloc);
 		memcpy(pMem, &t, sizeof(t));
-		return ctx.is_aborted ? SQL_TARANTOOL_ERROR : SQL_OK;
+		if (ctx.is_aborted)
+			return -1;
 	}
-	return SQL_OK;
+	return 0;
 }
 
 /*
diff --git a/test/sql-tap/gh-2931-savepoints.test.lua b/test/sql-tap/gh-2931-savepoints.test.lua
index 6123fc4..be499b6 100755
--- a/test/sql-tap/gh-2931-savepoints.test.lua
+++ b/test/sql-tap/gh-2931-savepoints.test.lua
@@ -39,7 +39,7 @@ local testcases = {
 		{0,{1,1}}},
 	{"5",
 		[[rollback to savepoint s1_2;]],
-		{1, "Failed to execute SQL statement: no such savepoint: S1_2"}},
+		{1, "Can not rollback to savepoint: the savepoint does not exist"}},
 	{"6",
 		[[insert into t1 values(2);
 		select * from t1 union all select * from t2;]],
diff --git a/test/sql/savepoints.result b/test/sql/savepoints.result
index bb4a296..d20e0ed 100644
--- a/test/sql/savepoints.result
+++ b/test/sql/savepoints.result
@@ -67,7 +67,7 @@ end;
 ...
 release_sv_fail();
 ---
-- error: 'Failed to execute SQL statement: no such savepoint: T1'
+- error: 'Can not rollback to savepoint: the savepoint does not exist'
 ...
 box.commit();
 ---
-- 
2.7.4

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [tarantool-patches] Re: [PATCH v1 9/9] sql: set errors in VDBE using diag_set()
  2019-05-28 11:39 ` [tarantool-patches] [PATCH v1 9/9] sql: set errors in VDBE using diag_set() imeevma
@ 2019-06-02 16:34   ` Vladislav Shpilevoy
  2019-06-03 12:10     ` Mergen Imeev
  0 siblings, 1 reply; 25+ messages in thread
From: Vladislav Shpilevoy @ 2019-06-02 16:34 UTC (permalink / raw)
  To: imeevma; +Cc: tarantool-patches


> diff --git a/src/box/sql/vdbe.c b/src/box/sql/vdbe.c
> index 43d7329..5bf5e6e 100644
> --- a/src/box/sql/vdbe.c
> +++ b/src/box/sql/vdbe.c
> @@ -3903,7 +3852,8 @@ case OP_SorterCompare: {
>  			pIn3 = &aMem[pOp->p3];
>  			nKeyCol = pOp->p4.i;
>  			res = 0;
> -			rc = sqlVdbeSorterCompare(pC, pIn3, nKeyCol, &res);
> +			if (sqlVdbeSorterCompare(pC, pIn3, nKeyCol, &res) != 0)
> +				rc = SQL_TARANTOOL_ERROR;

In all the similar places you remove SQL_TARANTOOL_ERROR,
but here you added it. Why?

>  			VdbeBranchTaken(res!=0,2);
>  			if (rc) goto abort_due_to_error;
>  			if (res) goto jump_to_p2;
> @@ -4137,15 +4085,18 @@ case OP_Rewind: {        /* jump */
>  	pC->seekOp = OP_Rewind;
>  #endif
>  	if (isSorter(pC)) {
> -		rc = sqlVdbeSorterRewind(pC, &res);
> +		if (sqlVdbeSorterRewind(pC, &res) != SQL_OK)
> +			goto abort_due_to_error;
>  	} else {
>  		assert(pC->eCurType==CURTYPE_TARANTOOL);
>  		pCrsr = pC->uc.pCursor;
>  		assert(pCrsr);
> -		rc = tarantoolsqlFirst(pCrsr, &res);
> +		if (tarantoolsqlFirst(pCrsr, &res) != SQL_OK)
> +			rc = SQL_TARANTOOL_ERROR;

The same.

Consider my review fixes on the branch and below. They are motivated
by several points:

1) in the original code there were places comparing 'rc' with 0, but
you replaced them with 'rc ==/!= SQL_OK'. I rolled back such changes,
because we move towards removal of SQL_OK. So when you need to choose
between 0 and SQL_OK - use 0.

2) there were places using SQL_OK, but very easy to fix and compare
with 0. I did it.

3) in a couple of places you kept 'rc = SQL_TARANTOOL_ERROR'. I don't
know why, but I dropped it, and the tests passed. If I was wrong, tell
me, please.

=======================================================================

commit e203a7c93132605e04931045ccc8ba4fd4bce7fa
Author: Vladislav Shpilevoy <v.shpilevoy@tarantool.org>
Date:   Sun Jun 2 18:28:25 2019 +0200

    Review fixes

diff --git a/src/box/sql.c b/src/box/sql.c
index 59a8bfbd5..d4d9d9671 100644
--- a/src/box/sql.c
+++ b/src/box/sql.c
@@ -325,21 +325,19 @@ int tarantoolsqlMovetoUnpacked(BtCursor *pCur, UnpackedRecord *pIdxKey,
  *
  * @retval SQL_OK
  */
-int tarantoolsqlEphemeralCount(struct BtCursor *pCur, i64 *pnEntry)
+int64_t
+tarantoolsqlEphemeralCount(struct BtCursor *pCur)
 {
 	assert(pCur->curFlags & BTCF_TEphemCursor);
-
 	struct index *primary_index = space_index(pCur->space, 0 /* PK */);
-	*pnEntry = index_count(primary_index, pCur->iter_type, NULL, 0);
-	return SQL_OK;
+	return index_count(primary_index, pCur->iter_type, NULL, 0);
 }
 
-int tarantoolsqlCount(BtCursor *pCur, i64 *pnEntry)
+int64_t
+tarantoolsqlCount(struct BtCursor *pCur)
 {
 	assert(pCur->curFlags & BTCF_TaCursor);
-
-	*pnEntry = index_count(pCur->index, pCur->iter_type, NULL, 0);
-	return SQL_OK;
+	return index_count(pCur->index, pCur->iter_type, NULL, 0);
 }
 
 struct space *
@@ -621,12 +619,12 @@ int tarantoolsqlRenameTrigger(const char *trig_name,
 	char *key_begin = (char*) region_alloc(&fiber()->gc, key_len);
 	if (key_begin == NULL) {
 		diag_set(OutOfMemory, key_len, "region_alloc", "key_begin");
-		return SQL_TARANTOOL_ERROR;
+		return -1;
 	}
 	char *key = mp_encode_array(key_begin, 1);
 	key = mp_encode_str(key, trig_name, trig_name_len);
 	if (box_index_get(BOX_TRIGGER_ID, 0, key_begin, key, &tuple) != 0)
-		return SQL_TARANTOOL_ERROR;
+		return -1;
 	assert(tuple != NULL);
 	assert(tuple_field_count(tuple) == 3);
 	const char *field = tuple_field(tuple, BOX_TRIGGER_FIELD_SPACE_ID);
@@ -645,7 +643,7 @@ int tarantoolsqlRenameTrigger(const char *trig_name,
 	if (trigger_stmt == NULL) {
 		diag_set(OutOfMemory, trigger_stmt_len + 1, "region_alloc",
 			 "trigger_stmt");
-		return SQL_TARANTOOL_ERROR;
+		return -1;
 	}
 	memcpy(trigger_stmt, trigger_stmt_old, trigger_stmt_len);
 	trigger_stmt[trigger_stmt_len] = '\0';
@@ -662,7 +660,7 @@ int tarantoolsqlRenameTrigger(const char *trig_name,
 	char *new_tuple = (char*)region_alloc(&fiber()->gc, key_len);
 	if (new_tuple == NULL) {
 		diag_set(OutOfMemory, key_len, "region_alloc", "new_tuple");
-		return SQL_TARANTOOL_ERROR;
+		return -1;
 	}
 	char *new_tuple_end = mp_encode_array(new_tuple, 3);
 	new_tuple_end = mp_encode_str(new_tuple_end, trig_name, trig_name_len);
@@ -672,15 +670,12 @@ int tarantoolsqlRenameTrigger(const char *trig_name,
 	new_tuple_end = mp_encode_str(new_tuple_end, trigger_stmt,
 				      trigger_stmt_new_len);
 
-	if (box_replace(BOX_TRIGGER_ID, new_tuple, new_tuple_end, NULL) != 0)
-		return SQL_TARANTOOL_ERROR;
-	else
-		return SQL_OK;
+	return box_replace(BOX_TRIGGER_ID, new_tuple, new_tuple_end, NULL);
 
 rename_fail:
 	diag_set(ClientError, ER_SQL_EXECUTE, "can't modify name of space "
 		"created not via SQL facilities");
-	return SQL_TARANTOOL_ERROR;
+	return -1;
 }
 
 int
@@ -695,7 +690,7 @@ sql_rename_table(uint32_t space_id, const char *new_name)
 	char *raw = (char *) region_alloc(region, size);
 	if (raw == NULL) {
 		diag_set(OutOfMemory, size, "region_alloc", "raw");
-		return SQL_TARANTOOL_ERROR;
+		return -1;
 	}
 	/* Encode key. */
 	char *pos = mp_encode_array(raw, 1);
@@ -709,7 +704,7 @@ sql_rename_table(uint32_t space_id, const char *new_name)
 	pos = mp_encode_uint(pos, BOX_SPACE_FIELD_NAME);
 	pos = mp_encode_str(pos, new_name, name_len);
 	if (box_update(BOX_SPACE_ID, 0, raw, ops, ops, pos, 0, NULL) != 0)
-		return SQL_TARANTOOL_ERROR;
+		return -1;
 	return 0;
 }
 
@@ -834,8 +829,8 @@ tarantoolsqlIncrementMaxid(uint64_t *space_max_id)
 	request.space_id = space_schema->def->id;
 	if (box_process_rw(&request, space_schema, &res) != 0 || res == NULL ||
 	    tuple_field_u64(res, 1, space_max_id) != 0)
-		return SQL_TARANTOOL_ERROR;
-	return SQL_OK;
+		return -1;
+	return 0;
 }
 
 /*
diff --git a/src/box/sql/analyze.c b/src/box/sql/analyze.c
index 979542948..4106bce37 100644
--- a/src/box/sql/analyze.c
+++ b/src/box/sql/analyze.c
@@ -1691,7 +1691,7 @@ sql_analysis_load(struct sql *db)
 	assert(stat_space != NULL);
 	ssize_t index_count = box_index_len(stat_space->def->id, 0);
 	if (index_count < 0)
-		return SQL_TARANTOOL_ERROR;
+		return -1;
 	if (box_txn_begin() != 0)
 		goto fail;
 	size_t stats_size = index_count * sizeof(struct index_stat);
@@ -1712,7 +1712,7 @@ sql_analysis_load(struct sql *db)
 		goto fail;
 	if (info.index_count == 0) {
 		box_txn_commit();
-		return SQL_OK;
+		return 0;
 	}
 	/*
 	 * This query is used to allocate enough memory for
@@ -1768,12 +1768,9 @@ sql_analysis_load(struct sql *db)
 	 */
 	const char *order_query = "SELECT \"tbl\",\"idx\" FROM "
 				  "\"_sql_stat4\" GROUP BY \"tbl\",\"idx\"";
-	if (load_stat_to_index(db, order_query, heap_stats) != 0)
-		goto fail;
-	if (box_txn_commit() != 0)
-		return SQL_TARANTOOL_ERROR;
-	return SQL_OK;
+	if (load_stat_to_index(db, order_query, heap_stats) == 0)
+		return box_txn_commit();
 fail:
 	box_txn_rollback();
-	return SQL_TARANTOOL_ERROR;
+	return -1;
 }
diff --git a/src/box/sql/sqlInt.h b/src/box/sql/sqlInt.h
index 9c0659bc9..777527865 100644
--- a/src/box/sql/sqlInt.h
+++ b/src/box/sql/sqlInt.h
@@ -4591,7 +4591,8 @@ sql_index_tuple_size(struct space *space, struct index *idx);
  * samples[] arrays.
  *
  * @param db Database handler.
- * @retval sql_OK on success, smth else otherwise.
+ * @retval 0 Success.
+ * @retval -1 Error.
  */
 int
 sql_analysis_load(struct sql *db);
diff --git a/src/box/sql/tarantoolInt.h b/src/box/sql/tarantoolInt.h
index f15e1472b..0474f2976 100644
--- a/src/box/sql/tarantoolInt.h
+++ b/src/box/sql/tarantoolInt.h
@@ -34,7 +34,8 @@ int tarantoolsqlNext(BtCursor * pCur, int *pRes);
 int tarantoolsqlPrevious(BtCursor * pCur, int *pRes);
 int tarantoolsqlMovetoUnpacked(BtCursor * pCur, UnpackedRecord * pIdxKey,
 				   int *pRes);
-int tarantoolsqlCount(BtCursor * pCur, i64 * pnEntry);
+int64_t
+tarantoolsqlCount(struct BtCursor *pCur);
 int tarantoolsqlInsert(struct space *space, const char *tuple,
 			   const char *tuple_end);
 int tarantoolsqlReplace(struct space *space, const char *tuple,
@@ -62,7 +63,8 @@ int tarantoolsqlClearTable(struct space *space, uint32_t *tuple_count);
  * @param space_id Table's space identifier.
  * @param new_name new name of table
  *
- * @retval 0 on success, SQL_TARANTOOL_ERROR otherwise.
+ * @retval 0 Success.
+ * @retval -1 Error.
  */
 int
 sql_rename_table(uint32_t space_id, const char *new_name);
@@ -100,7 +102,8 @@ sql_ephemeral_space_create(uint32_t filed_count, struct sql_key_info *key_info);
 int tarantoolsqlEphemeralInsert(struct space *space, const char *tuple,
 				    const char *tuple_end);
 int tarantoolsqlEphemeralDelete(BtCursor * pCur);
-int tarantoolsqlEphemeralCount(BtCursor * pCur, i64 * pnEntry);
+int64_t
+tarantoolsqlEphemeralCount(struct BtCursor *pCur);
 int tarantoolsqlEphemeralDrop(BtCursor * pCur);
 int tarantoolsqlEphemeralClearTable(BtCursor * pCur);
 
diff --git a/src/box/sql/vdbe.c b/src/box/sql/vdbe.c
index 5bf5e6e88..0b1d7888d 100644
--- a/src/box/sql/vdbe.c
+++ b/src/box/sql/vdbe.c
@@ -1432,7 +1432,7 @@ case OP_Concat: {           /* same as TK_CONCAT, in1, in2, out3 */
 			 mem_type_to_str(pIn2), mem_type_to_str(pIn1));
 		goto abort_due_to_error;
 	}
-	if (ExpandBlob(pIn1) != SQL_OK || ExpandBlob(pIn2) != SQL_OK)
+	if (ExpandBlob(pIn1) != 0 || ExpandBlob(pIn2) != 0)
 		goto abort_due_to_error;
 	nByte = pIn1->n + pIn2->n;
 	if (nByte>db->aLimit[SQL_LIMIT_LENGTH]) {
@@ -1892,7 +1892,7 @@ case OP_Realify: {                  /* in1 */
  */
 case OP_Cast: {                  /* in1 */
 	pIn1 = &aMem[pOp->p1];
-	if (ExpandBlob(pIn1) != SQL_OK)
+	if (ExpandBlob(pIn1) != 0)
 		goto abort_due_to_error;
 	rc = sqlVdbeMemCast(pIn1, pOp->p2);
 	UPDATE_MAX_BLOBSIZE(pIn1);
@@ -2659,7 +2659,7 @@ case OP_Column: {
 	if ((pDest->flags & (MEM_Ephem | MEM_Str)) == (MEM_Ephem | MEM_Str)) {
 		int len = pDest->n;
 		if (pDest->szMalloc<len+1) {
-			if (sqlVdbeMemGrow(pDest, len + 1, 1)) {
+			if (sqlVdbeMemGrow(pDest, len + 1, 1) != 0) {
 				if (zData != pC->aRow)
 					sqlVdbeMemRelease(&sMem);
 				goto abort_due_to_error;
@@ -2790,7 +2790,8 @@ case OP_MakeRecord: {
 	 * routine.
 	 */
 	if (bIsEphemeral) {
-		rc = sqlVdbeMemClearAndResize(pOut, tuple_size);
+		if (sqlVdbeMemClearAndResize(pOut, tuple_size) != 0)
+			goto abort_due_to_error;
 		pOut->flags = MEM_Blob;
 		pOut->n = tuple_size;
 		memcpy(pOut->z, tuple, tuple_size);
@@ -2805,8 +2806,6 @@ case OP_MakeRecord: {
 		pOut->n = tuple_size;
 		pOut->z = tuple;
 	}
-	if (rc)
-		goto no_mem;
 	assert(sqlVdbeCheckMemInvariants(pOut));
 	assert(pOp->p3>0 && pOp->p3<=(p->nMem+1 - p->nCursor));
 	REGISTER_TRACE(pOp->p3, pOut);
@@ -2827,15 +2826,11 @@ case OP_Count: {         /* out2 */
 	assert(p->apCsr[pOp->p1]->eCurType==CURTYPE_TARANTOOL);
 	pCrsr = p->apCsr[pOp->p1]->uc.pCursor;
 	assert(pCrsr);
-	nEntry = 0;  /* Not needed.  Only used to silence a warning. */
 	if (pCrsr->curFlags & BTCF_TaCursor) {
-		if (tarantoolsqlCount(pCrsr, &nEntry) != SQL_OK)
-			goto abort_due_to_error;
-	} else if (pCrsr->curFlags & BTCF_TEphemCursor) {
-		if (tarantoolsqlEphemeralCount(pCrsr, &nEntry) != SQL_OK)
-			goto abort_due_to_error;
+		nEntry = tarantoolsqlCount(pCrsr);
 	} else {
-		unreachable();
+		assert((pCrsr->curFlags & BTCF_TEphemCursor) != 0);
+		nEntry = tarantoolsqlEphemeralCount(pCrsr);
 	}
 	pOut = out2Prerelease(p, pOp);
 	pOut->u.i = nEntry;
@@ -2905,7 +2900,7 @@ case OP_Savepoint: {
 					p->rc = rc = SQL_BUSY;
 					goto vdbe_return;
 				}
-				if (p->rc != SQL_OK)
+				if (p->rc != 0)
 					goto abort_due_to_error;
 			} else {
 				if (p1==SAVEPOINT_ROLLBACK)
@@ -3154,7 +3149,7 @@ case OP_SorterOpen: {
 	pCx = allocateCursor(p, pOp->p1, pOp->p2, CURTYPE_SORTER);
 	if (pCx==0) goto no_mem;
 	pCx->key_def = def;
-	if (sqlVdbeSorterInit(db, pCx) != SQL_OK)
+	if (sqlVdbeSorterInit(db, pCx) != 0)
 		goto abort_due_to_error;
 	break;
 }
@@ -3851,11 +3846,9 @@ case OP_SorterCompare: {
 			assert(pOp->p4type==P4_INT32);
 			pIn3 = &aMem[pOp->p3];
 			nKeyCol = pOp->p4.i;
-			res = 0;
 			if (sqlVdbeSorterCompare(pC, pIn3, nKeyCol, &res) != 0)
-				rc = SQL_TARANTOOL_ERROR;
+				goto abort_due_to_error;
 			VdbeBranchTaken(res!=0,2);
-			if (rc) goto abort_due_to_error;
 			if (res) goto jump_to_p2;
 			break;
 		};
@@ -3878,7 +3871,7 @@ case OP_SorterData: {
 	pOut = &aMem[pOp->p2];
 	pC = p->apCsr[pOp->p1];
 	assert(isSorter(pC));
-	if (sqlVdbeSorterRowkey(pC, pOut) != SQL_OK)
+	if (sqlVdbeSorterRowkey(pC, pOut) != 0)
 		goto abort_due_to_error;
 	assert(pOut->flags & MEM_Blob);
 	assert(pOp->p1>=0 && pOp->p1<p->nCursor);
@@ -3948,8 +3941,8 @@ case OP_RowData: {
 	testcase( n==0);
 
 	sqlVdbeMemRelease(pOut);
-	if (sql_vdbe_mem_alloc_region(pOut, n) != SQL_OK ||
-	    sqlCursorPayload(pCrsr, 0, n, pOut->z) != SQL_OK)
+	if (sql_vdbe_mem_alloc_region(pOut, n) != 0 ||
+	    sqlCursorPayload(pCrsr, 0, n, pOut->z) != 0)
 		goto abort_due_to_error;
 	UPDATE_MAX_BLOBSIZE(pOut);
 	REGISTER_TRACE(pOp->p2, pOut);
@@ -4013,10 +4006,10 @@ case OP_Last: {        /* jump */
 	pC->seekOp = OP_Last;
 #endif
 	if (pOp->p3==0 || !sqlCursorIsValidNN(pCrsr)) {
-		rc = tarantoolsqlLast(pCrsr, &res);
+		if (tarantoolsqlLast(pCrsr, &res) != 0)
+			goto abort_due_to_error;
 		pC->nullRow = (u8)res;
 		pC->cacheStatus = CACHE_STALE;
-		if (rc) goto abort_due_to_error;
 		if (pOp->p2>0) {
 			VdbeBranchTaken(res!=0,2);
 			if (res) goto jump_to_p2;
@@ -4085,17 +4078,15 @@ case OP_Rewind: {        /* jump */
 	pC->seekOp = OP_Rewind;
 #endif
 	if (isSorter(pC)) {
-		if (sqlVdbeSorterRewind(pC, &res) != SQL_OK)
+		if (sqlVdbeSorterRewind(pC, &res) != 0)
 			goto abort_due_to_error;
 	} else {
 		assert(pC->eCurType==CURTYPE_TARANTOOL);
 		pCrsr = pC->uc.pCursor;
 		assert(pCrsr);
-		if (tarantoolsqlFirst(pCrsr, &res) != SQL_OK)
-			rc = SQL_TARANTOOL_ERROR;
-		pC->cacheStatus = CACHE_STALE;
-		if (rc != SQL_OK)
+		if (tarantoolsqlFirst(pCrsr, &res) != 0)
 			goto abort_due_to_error;
+		pC->cacheStatus = CACHE_STALE;
 	}
 	pC->nullRow = (u8)res;
 	assert(pOp->p2>0 && pOp->p2<p->nOp);
@@ -4179,7 +4170,8 @@ case OP_SorterNext: {  /* jump */
 	pC = p->apCsr[pOp->p1];
 	assert(isSorter(pC));
 	res = 0;
-	rc = sqlVdbeSorterNext(db, pC, &res);
+	if (sqlVdbeSorterNext(db, pC, &res) != 0)
+		goto abort_due_to_error;
 	goto next_tail;
 case OP_PrevIfOpen:    /* jump */
 case OP_NextIfOpen:    /* jump */
@@ -4210,11 +4202,11 @@ case OP_Next:          /* jump */
 	       || pC->seekOp==OP_SeekLT || pC->seekOp==OP_SeekLE
 	       || pC->seekOp==OP_Last);
 
-	rc = pOp->p4.xAdvance(pC->uc.pCursor, &res);
+	if (pOp->p4.xAdvance(pC->uc.pCursor, &res) != 0)
+		goto abort_due_to_error;
 			next_tail:
 	pC->cacheStatus = CACHE_STALE;
 	VdbeBranchTaken(res==0,2);
-	if (rc) goto abort_due_to_error;
 	if (res==0) {
 		pC->nullRow = 0;
 		p->aCounter[pOp->p5]++;
@@ -4242,8 +4234,8 @@ case OP_SorterInsert: {      /* in2 */
 	assert(isSorter(cursor));
 	pIn2 = &aMem[pOp->p2];
 	assert((pIn2->flags & MEM_Blob) != 0);
-	if (ExpandBlob(pIn2) != SQL_OK ||
-	    sqlVdbeSorterWrite(cursor, pIn2) != SQL_OK)
+	if (ExpandBlob(pIn2) != 0 ||
+	    sqlVdbeSorterWrite(cursor, pIn2) != 0)
 		goto abort_due_to_error;
 	break;
 }
@@ -4273,7 +4265,7 @@ case OP_IdxInsert: {
 	assert((pIn2->flags & MEM_Blob) != 0);
 	if (pOp->p5 & OPFLAG_NCHANGE)
 		p->nChange++;
-	if (ExpandBlob(pIn2) != SQL_OK)
+	if (ExpandBlob(pIn2) != 0)
 		goto abort_due_to_error;
 	struct space *space;
 	if (pOp->p4type == P4_SPACEPTR)
@@ -4457,7 +4449,7 @@ case OP_SDelete: {
 	struct space *space = space_by_id(pOp->p1);
 	assert(space != NULL);
 	assert(space_is_system(space));
-	if (sql_delete_by_key(space, 0, pIn2->z, pIn2->n) != SQL_OK)
+	if (sql_delete_by_key(space, 0, pIn2->z, pIn2->n) != 0)
 		goto abort_due_to_error;
 	if (pOp->p5 & OPFLAG_NCHANGE)
 		p->nChange++;
@@ -4491,15 +4483,15 @@ case OP_IdxDelete: {
 	r.default_rc = 0;
 	r.aMem = &aMem[pOp->p2];
 	r.opcode = OP_IdxDelete;
-	if (sqlCursorMovetoUnpacked(pCrsr, &r, &res) != SQL_OK)
+	if (sqlCursorMovetoUnpacked(pCrsr, &r, &res) != 0)
 		goto abort_due_to_error;
 	if (res==0) {
 		assert(pCrsr->eState == CURSOR_VALID);
 		if (pCrsr->curFlags & BTCF_TaCursor) {
-			if (tarantoolsqlDelete(pCrsr, 0) != SQL_OK)
+			if (tarantoolsqlDelete(pCrsr, 0) != 0)
 				goto abort_due_to_error;
 		} else if (pCrsr->curFlags & BTCF_TEphemCursor) {
-			if (tarantoolsqlEphemeralDelete(pCrsr) != SQL_OK)
+			if (tarantoolsqlEphemeralDelete(pCrsr) != 0)
 				goto abort_due_to_error;
 		} else {
 			unreachable();
@@ -4612,13 +4604,12 @@ case OP_Clear: {
 	uint32_t space_id = pOp->p1;
 	struct space *space = space_by_id(space_id);
 	assert(space != NULL);
-	rc = 0;
 	if (pOp->p2 > 0) {
 		if (box_truncate(space_id) != 0)
 			goto abort_due_to_error;
 	} else {
 		uint32_t tuple_count;
-		if (tarantoolsqlClearTable(space, &tuple_count) != SQL_OK)
+		if (tarantoolsqlClearTable(space, &tuple_count) != 0)
 			goto abort_due_to_error;
 		if ((pOp->p5 & OPFLAG_NCHANGE) != 0)
 			p->nChange += tuple_count;
@@ -4645,7 +4636,7 @@ case OP_ResetSorter: {
 	} else {
 		assert(pC->eCurType==CURTYPE_TARANTOOL);
 		assert(pC->uc.pCursor->curFlags & BTCF_TEphemCursor);
-		if (tarantoolsqlEphemeralClearTable(pC->uc.pCursor) != SQL_OK)
+		if (tarantoolsqlEphemeralClearTable(pC->uc.pCursor) != 0)
 			goto abort_due_to_error;
 	}
 	break;
@@ -4679,7 +4670,7 @@ case OP_RenameTable: {
 	zNewTableName = pOp->p4.z;
 	zOldTableName = sqlDbStrNDup(db, zOldTableName,
 					 sqlStrlen30(zOldTableName));
-	if (sql_rename_table(space_id, zNewTableName) != SQL_OK)
+	if (sql_rename_table(space_id, zNewTableName) != 0)
 		goto abort_due_to_error;
 	/*
 	 * Rebuild 'CREATE TRIGGER' expressions of all triggers
@@ -4691,16 +4682,13 @@ case OP_RenameTable: {
 		/* Store pointer as trigger will be destructed. */
 		struct sql_trigger *next_trigger = trigger->next;
 		/*
-		 * FIXME: In the case of error,
-		 * part of triggers would have invalid
-		 * space name in tuple so can not been
-		 * persisted.
-		 * Server could be restarted.
-		 * In this case, rename table back and
-		 * try again.
+		 * FIXME: In the case of error, part of triggers
+		 * would have invalid space name in tuple so can
+		 * not been persisted. Server could be restarted.
+		 * In this case, rename table back and try again.
 		 */
 		if (tarantoolsqlRenameTrigger(trigger->zName, zOldTableName,
-					      zNewTableName) != SQL_OK)
+					      zNewTableName) != 0)
 			goto abort_due_to_error;
 		trigger = next_trigger;
 	}
@@ -4716,7 +4704,7 @@ case OP_RenameTable: {
  */
 case OP_LoadAnalysis: {
 	assert(pOp->p1==0 );
-	if (sql_analysis_load(db) != SQL_OK)
+	if (sql_analysis_load(db) != 0)
 		goto abort_due_to_error;
 	break;
 }
@@ -5241,7 +5229,7 @@ case OP_IncMaxid: {
 	assert(pOp->p1 > 0);
 	pOut = &aMem[pOp->p1];
 
-	if (tarantoolsqlIncrementMaxid((uint64_t*) &pOut->u.i) != SQL_OK)
+	if (tarantoolsqlIncrementMaxid((uint64_t*) &pOut->u.i) != 0)
 		goto abort_due_to_error;
 	pOut->flags = MEM_Int;
 	break;

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [tarantool-patches] Re: [PATCH v1 4/9] sql: rework diag_set() in OP_Halt
  2019-05-28 11:39 ` [tarantool-patches] [PATCH v1 4/9] sql: rework diag_set() in OP_Halt imeevma
@ 2019-06-02 16:35   ` Vladislav Shpilevoy
  2019-06-03  8:41     ` Imeev Mergen
  0 siblings, 1 reply; 25+ messages in thread
From: Vladislav Shpilevoy @ 2019-06-02 16:35 UTC (permalink / raw)
  To: tarantool-patches, imeevma



On 28/05/2019 14:39, imeevma@tarantool.org wrote:
> Prior to this patch, the way to set Tarantool error in OP_Halt was
> too universal. It was possible to set a description of the error
> that does not match its errcode.

There was a concrete reason, why it was possible - because different
error codes have different arguments of various types, and the only way
to set an error at parsing stage is to allow to set arbitrary error
message to any error code. Without '...', va_arg etc. Besides, we could
use it to set correct line number and function name in future. Now you
use diag_set, which restricts us.

So why do you need that patch? We will need to revert it when an error
appears requiring more than one argument, or an argument of not
const char * type. That will definitely happen.

> This change will also make it
> easier to work with an error in OP_Halt, since you no longer need
> to create a complete error message.> 
> Example of wrong error code:
> ...
> 
> tarantool> box.execute('select 1 limit true')
> ---
> - error: Only positive integers are allowed in the LIMIT clause
> ...
> 
> tarantool> box.error.last().code
> ---
> - 0
> ...
> ---

This is not because of box_error_set usage.

tarantool> box.error({code = 123, reason = 'test'})
---
- error: test
...

tarantool> box.error.last().code
---
- 123
...

This example uses box_error_set() too, but the error
code is kept. The bug in SQL could be fixed in a few lines,
and you did it. But somewhy decided to break generic
error creation alongside.

The whole patch could be shrunk to this (+ tests):

> diff --git a/src/box/sql/select.c b/src/box/sql/select.c
> index d3472a9..3f0b540 100644
> --- a/src/box/sql/select.c
> +++ b/src/box/sql/select.c
> @@ -2116,6 +2116,7 @@ computeLimitRegisters(Parse * pParse, Select * p, int iBreak)
>  				  0, 0,
>  				  wrong_limit_error,
>  				  P4_STATIC);
> +		sqlVdbeChangeP5(v, ER_SQL_EXECUTE);>  
>  		sqlVdbeResolveLabel(v, positive_limit_label);
>  		VdbeCoverage(v);
> @@ -2178,6 +2178,7 @@ computeLimitRegisters(Parse * pParse, Select * p, int iBreak)
>  					  0, 0,
>  					  wrong_offset_error,
>  					  P4_STATIC);
> +			sqlVdbeChangeP5(v, ER_SQL_EXECUTE);
>  
>  			sqlVdbeResolveLabel(v, positive_offset_label);
>              		sqlReleaseTempReg(pParse, r1);

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [tarantool-patches] Re: [PATCH v1 8/9] sql: use diag_set() to set an error in SQL functions
  2019-05-28 11:39 ` [tarantool-patches] [PATCH v1 8/9] sql: use diag_set() to set an error in SQL functions imeevma
@ 2019-06-02 16:35   ` Vladislav Shpilevoy
  2019-06-03 11:54     ` Mergen Imeev
  0 siblings, 1 reply; 25+ messages in thread
From: Vladislav Shpilevoy @ 2019-06-02 16:35 UTC (permalink / raw)
  To: imeevma; +Cc: tarantool-patches


> diff --git a/src/box/sql/vdbeapi.c b/src/box/sql/vdbeapi.c
> index 597d37e..673ccd1 100644
> --- a/src/box/sql/vdbeapi.c
> +++ b/src/box/sql/vdbeapi.c
> @@ -762,75 +724,6 @@ sql_aggregate_context(sql_context * p, int nByte)
> -/*
> - * Set the auxiliary data pointer and delete function, for the iArg'th
> - * argument to the user-function defined by pCtx. Any previous value is
> - * deleted by calling the delete function specified when it was set.
> - */
> -void
> -sql_set_auxdata(sql_context * pCtx,
> -		    int iArg, void *pAux, void (*xDelete) (void *)
> -    )

Still is mentioned in a couple of comments.

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [tarantool-patches] Re: [PATCH v1 5/9] sql: make SQL_TARANTOOL_ERROR the only errcode of OP_Halt
  2019-05-28 11:39 ` [tarantool-patches] [PATCH v1 5/9] sql: make SQL_TARANTOOL_ERROR the only errcode of OP_Halt imeevma
@ 2019-06-02 16:35   ` Vladislav Shpilevoy
  2019-06-03 11:53     ` Mergen Imeev
  0 siblings, 1 reply; 25+ messages in thread
From: Vladislav Shpilevoy @ 2019-06-02 16:35 UTC (permalink / raw)
  To: tarantool-patches, imeevma

>   * This routine is invoked once per CTE by the parser while parsing a
> diff --git a/src/box/sql/expr.c b/src/box/sql/expr.c
> index 6ac42d7..a4a2d71 100644
> --- a/src/box/sql/expr.c
> +++ b/src/box/sql/expr.c
> @@ -4386,9 +4386,10 @@ sqlExprCodeTarget(Parse * pParse, Expr * pExpr, int target)
>  					  ON_CONFLICT_ACTION_IGNORE, 0,
>  					  pExpr->u.zToken, 0);
>  		} else {
> -			sqlHaltConstraint(pParse, SQL_CONSTRAINT_TRIGGER,
> -					      pExpr->on_conflict_action,
> -					      pExpr->u.zToken, 0, 0);
> +			sqlVdbeAddOp4(v, OP_Halt, SQL_TARANTOOL_ERROR,
> +				      pExpr->on_conflict_action, 0,
> +				      pExpr->u.zToken, 0);
> +			sqlVdbeChangeP5(v, ER_SQL_EXECUTE);

Please, remove p5 arg and store error code in p2. Now it can be done
with ease.

>  		}
>  		break;
>  	}

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [tarantool-patches] Re: [PATCH v1 4/9] sql: rework diag_set() in OP_Halt
  2019-06-02 16:35   ` [tarantool-patches] " Vladislav Shpilevoy
@ 2019-06-03  8:41     ` Imeev Mergen
  2019-06-04 19:34       ` Vladislav Shpilevoy
  0 siblings, 1 reply; 25+ messages in thread
From: Imeev Mergen @ 2019-06-03  8:41 UTC (permalink / raw)
  To: Vladislav Shpilevoy, tarantool-patches

Hi! Thank you for the review! My answers below. Also, I think I'm
going to drop this patch, since I plan to move the error code from
p5 to p2 in the next patch.

On 6/2/19 7:35 PM, Vladislav Shpilevoy wrote:
>
> On 28/05/2019 14:39, imeevma@tarantool.org wrote:
>> Prior to this patch, the way to set Tarantool error in OP_Halt was
>> too universal. It was possible to set a description of the error
>> that does not match its errcode.
> There was a concrete reason, why it was possible - because different
> error codes have different arguments of various types, and the only way
> to set an error at parsing stage is to allow to set arbitrary error
> message to any error code. Without '...', va_arg etc. Besides, we could
> use it to set correct line number and function name in future. Now you
> use diag_set, which restricts us.
>
> So why do you need that patch? We will need to revert it when an error
> appears requiring more than one argument, or an argument of not
> const char * type. That will definitely happen.
For some reason, manually creating an error message looks a bit
wrong to me. How about creating a new macro to create such
messages, for example, diag_prepare(), which takes the same
arguments as diag_set() and returns the complete error message?

>> This change will also make it
>> easier to work with an error in OP_Halt, since you no longer need
>> to create a complete error message.>
>> Example of wrong error code:
>> ...
>>
>> tarantool> box.execute('select 1 limit true')
>> ---
>> - error: Only positive integers are allowed in the LIMIT clause
>> ...
>>
>> tarantool> box.error.last().code
>> ---
>> - 0
>> ...
>> ---
> This is not because of box_error_set usage.
>
> tarantool> box.error({code = 123, reason = 'test'})
> ---
> - error: test
> ...
>
> tarantool> box.error.last().code
> ---
> - 123
> ...
>
> This example uses box_error_set() too, but the error
> code is kept. The bug in SQL could be fixed in a few lines,
> and you did it. But somewhy decided to break generic
> error creation alongside.
>
> The whole patch could be shrunk to this (+ tests):
>
>> diff --git a/src/box/sql/select.c b/src/box/sql/select.c
>> index d3472a9..3f0b540 100644
>> --- a/src/box/sql/select.c
>> +++ b/src/box/sql/select.c
>> @@ -2116,6 +2116,7 @@ computeLimitRegisters(Parse * pParse, Select * p, int iBreak)
>>   				  0, 0,
>>   				  wrong_limit_error,
>>   				  P4_STATIC);
>> +		sqlVdbeChangeP5(v, ER_SQL_EXECUTE);>
>>   		sqlVdbeResolveLabel(v, positive_limit_label);
>>   		VdbeCoverage(v);
>> @@ -2178,6 +2178,7 @@ computeLimitRegisters(Parse * pParse, Select * p, int iBreak)
>>   					  0, 0,
>>   					  wrong_offset_error,
>>   					  P4_STATIC);
>> +			sqlVdbeChangeP5(v, ER_SQL_EXECUTE);
>>   
>>   			sqlVdbeResolveLabel(v, positive_offset_label);
>>               		sqlReleaseTempReg(pParse, r1);
True, but I think I won't need this after I move errcode from p5
to p2 in the next patch.

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [tarantool-patches] Re: [PATCH v1 5/9] sql: make SQL_TARANTOOL_ERROR the only errcode of OP_Halt
  2019-06-02 16:35   ` [tarantool-patches] " Vladislav Shpilevoy
@ 2019-06-03 11:53     ` Mergen Imeev
  2019-06-04 19:34       ` Vladislav Shpilevoy
  0 siblings, 1 reply; 25+ messages in thread
From: Mergen Imeev @ 2019-06-03 11:53 UTC (permalink / raw)
  To: Vladislav Shpilevoy; +Cc: tarantool-patches

On Sun, Jun 02, 2019 at 06:35:11PM +0200, Vladislav Shpilevoy wrote:
> >   * This routine is invoked once per CTE by the parser while parsing a
> > diff --git a/src/box/sql/expr.c b/src/box/sql/expr.c
> > index 6ac42d7..a4a2d71 100644
> > --- a/src/box/sql/expr.c
> > +++ b/src/box/sql/expr.c
> > @@ -4386,9 +4386,10 @@ sqlExprCodeTarget(Parse * pParse, Expr * pExpr, int target)
> >  					  ON_CONFLICT_ACTION_IGNORE, 0,
> >  					  pExpr->u.zToken, 0);
> >  		} else {
> > -			sqlHaltConstraint(pParse, SQL_CONSTRAINT_TRIGGER,
> > -					      pExpr->on_conflict_action,
> > -					      pExpr->u.zToken, 0, 0);
> > +			sqlVdbeAddOp4(v, OP_Halt, SQL_TARANTOOL_ERROR,
> > +				      pExpr->on_conflict_action, 0,
> > +				      pExpr->u.zToken, 0);
> > +			sqlVdbeChangeP5(v, ER_SQL_EXECUTE);
> 
> Please, remove p5 arg and store error code in p2. Now it can be done
> with ease.
> 
I moved the error code from P5 to P3, since P2 is already in use.
I also replaced OP_HaltIfNull with OP_NotNull and deleted the
opcode OP_HaltIfNull.

Diff:

diff --git a/src/box/sql/build.c b/src/box/sql/build.c
index cc02e70..4c101ca 100644
--- a/src/box/sql/build.c
+++ b/src/box/sql/build.c
@@ -3106,9 +3106,8 @@ vdbe_emit_halt_with_presence_test(struct Parse *parser, int space_id,
 	if (no_error) {
 		sqlVdbeAddOp0(v, OP_Halt);
 	} else {
-		sqlVdbeAddOp4(v, OP_Halt, SQL_TARANTOOL_ERROR,0, 0, error,
-				  P4_DYNAMIC);
-		sqlVdbeChangeP5(v, tarantool_error_code);
+		sqlVdbeAddOp4(v, OP_Halt, SQL_TARANTOOL_ERROR, 0,
+			      tarantool_error_code, error, P4_DYNAMIC);
 	}
 	sqlVdbeAddOp1(v, OP_Close, cursor);
 	return 0;
diff --git a/src/box/sql/expr.c b/src/box/sql/expr.c
index 5350ed1..4fbc8f5 100644
--- a/src/box/sql/expr.c
+++ b/src/box/sql/expr.c
@@ -4390,8 +4390,8 @@ sqlExprCodeTarget(Parse * pParse, Expr * pExpr, int target)
 						     "statement: %s",
 						     pExpr->u.zToken);
 			sqlVdbeAddOp4(v, OP_Halt, SQL_TARANTOOL_ERROR,
-				      pExpr->on_conflict_action, 0, err, 0);
-			sqlVdbeChangeP5(v, ER_SQL_EXECUTE);
+				      pExpr->on_conflict_action, ER_SQL_EXECUTE,
+				      err, 0);
 		}
 		break;
 	}
diff --git a/src/box/sql/fk_constraint.c b/src/box/sql/fk_constraint.c
index 3468965..5256bec 100644
--- a/src/box/sql/fk_constraint.c
+++ b/src/box/sql/fk_constraint.c
@@ -289,9 +289,8 @@ fk_constraint_lookup_parent(struct Parse *parse_context, struct space *parent,
 		assert(incr_count == 1);
 		const char *err = "Failed to execute SQL statement: FOREIGN "\
 				  "KEY constraint failed";
-		sqlVdbeAddOp4(v, OP_Halt, SQL_TARANTOOL_ERROR, 0, 0, err,
-			      P4_STATIC);
-		sqlVdbeChangeP5(v, ER_SQL_EXECUTE);
+		sqlVdbeAddOp4(v, OP_Halt, SQL_TARANTOOL_ERROR, 0,
+			      ER_SQL_EXECUTE, err, P4_STATIC);
 	} else {
 		sqlVdbeAddOp2(v, OP_FkCounter, fk_def->is_deferred,
 				  incr_count);
diff --git a/src/box/sql/insert.c b/src/box/sql/insert.c
index eb08aae..286a721 100644
--- a/src/box/sql/insert.c
+++ b/src/box/sql/insert.c
@@ -889,10 +889,11 @@ vdbe_emit_constraint_checks(struct Parse *parse_context, struct space *space,
 			err = tt_sprintf("Failed to execute SQL statement: "\
 					 "NOT NULL constraint failed: %s.%s",
 					 def->name, def->fields[i].name);
-			sqlVdbeAddOp4(v, OP_HaltIfNull, SQL_TARANTOOL_ERROR,
-				      on_conflict_nullable, new_tuple_reg + i,
+			addr = sqlVdbeAddOp1(v, OP_NotNull, new_tuple_reg + i);
+			sqlVdbeAddOp4(v, OP_Halt, SQL_TARANTOOL_ERROR,
+				      on_conflict_nullable, ER_SQL_EXECUTE,
 				      err, P4_STATIC);
-			sqlVdbeChangeP5(v, ER_SQL_EXECUTE);
+			sqlVdbeJumpHere(v, addr);
 			break;
 		case ON_CONFLICT_ACTION_IGNORE:
 			sqlVdbeAddOp2(v, OP_IsNull, new_tuple_reg + i,
@@ -941,9 +942,8 @@ vdbe_emit_constraint_checks(struct Parse *parse_context, struct space *space,
 						   "constraint failed: %s",
 						   name);
 				sqlVdbeAddOp4(v, OP_Halt, SQL_TARANTOOL_ERROR,
-					      on_conflict_check, 0, err,
-					      P4_STATIC);
-				sqlVdbeChangeP5(v, ER_SQL_EXECUTE);
+					      on_conflict_check, ER_SQL_EXECUTE,
+					      err, P4_STATIC);
 			}
 			sqlVdbeResolveLabel(v, all_ok);
 		}
diff --git a/src/box/sql/select.c b/src/box/sql/select.c
index b5dc581..4fc59d8 100644
--- a/src/box/sql/select.c
+++ b/src/box/sql/select.c
@@ -2111,12 +2111,8 @@ computeLimitRegisters(Parse * pParse, Select * p, int iBreak)
 			"Failed to execute SQL statement: Only positive "\
 			"integers are allowed in the LIMIT clause";
 		sqlVdbeResolveLabel(v, halt_label);
-		sqlVdbeAddOp4(v, OP_Halt,
-				  SQL_TARANTOOL_ERROR,
-				  0, 0,
-				  wrong_limit_error,
-				  P4_STATIC);
-		sqlVdbeChangeP5(v, ER_SQL_EXECUTE);
+		sqlVdbeAddOp4(v, OP_Halt, SQL_TARANTOOL_ERROR, 0,
+			      ER_SQL_EXECUTE, wrong_limit_error, P4_STATIC);
 
 		sqlVdbeResolveLabel(v, positive_limit_label);
 		VdbeCoverage(v);
@@ -2147,10 +2143,9 @@ computeLimitRegisters(Parse * pParse, Select * p, int iBreak)
 					"Failed to execute SQL statement: "\
 					"Expression subquery could be limited "\
 					"only with 1";
-				sqlVdbeAddOp4(v, OP_Halt,
-						  SQL_TARANTOOL_ERROR,
-						  0, 0, error, P4_STATIC);
-				sqlVdbeChangeP5(v, ER_SQL_EXECUTE);
+				sqlVdbeAddOp4(v, OP_Halt, SQL_TARANTOOL_ERROR,
+					      0, ER_SQL_EXECUTE, error,
+					      P4_STATIC);
 				sqlVdbeResolveLabel(v, no_err);
 				sqlReleaseTempReg(pParse, r1);
 
@@ -2176,12 +2171,9 @@ computeLimitRegisters(Parse * pParse, Select * p, int iBreak)
 				"positive integers are allowed in the OFFSET "\
 				"clause";
 			sqlVdbeResolveLabel(v, offset_error_label);
-			sqlVdbeAddOp4(v, OP_Halt,
-					  SQL_TARANTOOL_ERROR,
-					  0, 0,
-					  wrong_offset_error,
-					  P4_STATIC);
-			sqlVdbeChangeP5(v, ER_SQL_EXECUTE);
+			sqlVdbeAddOp4(v, OP_Halt, SQL_TARANTOOL_ERROR, 0,
+				      ER_SQL_EXECUTE, wrong_offset_error,
+				      P4_STATIC);
 
 			sqlVdbeResolveLabel(v, positive_offset_label);
             		sqlReleaseTempReg(pParse, r1);
@@ -5453,9 +5445,8 @@ vdbe_code_raise_on_multiple_rows(struct Parse *parser, int limit_reg, int end_ma
 	const char *error =
 		"Failed to execute SQL statement: Expression subquery "\
 		"returned more than 1 row";
-	sqlVdbeAddOp4(v, OP_Halt, SQL_TARANTOOL_ERROR, 0, 0, error,
-			  P4_STATIC);
-	sqlVdbeChangeP5(v, ER_SQL_EXECUTE);
+	sqlVdbeAddOp4(v, OP_Halt, SQL_TARANTOOL_ERROR, 0, ER_SQL_EXECUTE, error,
+		      P4_STATIC);
 	sqlReleaseTempReg(parser, r1);
 }
 
diff --git a/src/box/sql/vdbe.c b/src/box/sql/vdbe.c
index d07c671..33484c5 100644
--- a/src/box/sql/vdbe.c
+++ b/src/box/sql/vdbe.c
@@ -950,29 +950,14 @@ case OP_Yield: {            /* in1, jump */
 	break;
 }
 
-/* Opcode:  HaltIfNull  P1 P2 P3 P4 P5
- * Synopsis: if r[P3]=null halt
- *
- * Check the value in register P3.  If it is NULL then Halt using
- * parameter P1, P2, and P4 as if this were a Halt instruction.  If the
- * value in register P3 is not NULL, then this routine is a no-op.
- * The P5 parameter should be 1.
- */
-case OP_HaltIfNull: {      /* in3 */
-	pIn3 = &aMem[pOp->p3];
-	if ((pIn3->flags & MEM_Null)==0) break;
-	/* Fall through into OP_Halt */
-	FALLTHROUGH;
-}
-
-/* Opcode:  Halt P1 P2 * P4 P5
+/* Opcode:  Halt P1 P2 P3 P4 *
  *
  * Exit immediately.  All open cursors, etc are closed
  * automatically.
  *
  * P1 is the result code returned by sql_exec(),
  * sql_reset(), or sql_finalize().  For a normal halt,
- * this should be SQL_OK (0).
+ * this should be 0.
  * For errors, it can be some other value.  If P1!=0 then P2 will
  * determine whether or not to rollback the current transaction.
  * Do not rollback if P2==ON_CONFLICT_ACTION_FAIL. Do the rollback
@@ -983,18 +968,8 @@ case OP_HaltIfNull: {      /* in3 */
  *
  * If P4 is not null then it is an error message string.
  *
- * If P1 is SQL_TARANTOOL_ERROR then P5 is a ClientError code and
- * P4 is error message to set. Else P5 is a value between 0 and 4,
- * inclusive, that modifies the P4 string.
- *
- *    0:  (no change)
- *    1:  NOT NULL contraint failed: P4
- *    2:  UNIQUE constraint failed: P4
- *    3:  CHECK constraint failed: P4
- *    4:  FOREIGN KEY constraint failed: P4
- *
- * If P5 is not zero and  P4 is  NULL, then everything after the
- * ":" is omitted.
+ * If P1 is SQL_TARANTOOL_ERROR then P3 is a ClientError code and
+ * P4 is error message to set.
  *
  * There is an implied "Halt 0 0 0" instruction inserted at the
  * very end of every program.  So a jump past the last instruction
@@ -1033,7 +1008,7 @@ case OP_Halt: {
 	if (p->rc) {
 		assert(p->rc == SQL_TARANTOOL_ERROR);
 		if (pOp->p4.z != NULL)
-			box_error_set(__FILE__, __LINE__, pOp->p5, pOp->p4.z);
+			box_error_set(__FILE__, __LINE__, pOp->p3, pOp->p4.z);
 		assert(! diag_is_empty(diag_get()));
 	}
 	rc = sqlVdbeHalt(p);


New patch:

From 58bb9420e5532868759056503ebe5a2af361aa60 Mon Sep 17 00:00:00 2001
Date: Fri, 12 Apr 2019 14:16:18 +0300
Subject: [PATCH] sql: make SQL_TARANTOOL_ERROR the only errcode of OP_Halt

Currently, in OP_Halt, you can get a SQL error other than
SQL_TARANTOOL_ERROR, for example, the SQL_CONSTRAINT error. After
this patch, all errors going through OP_Halt will have SQL error
code SQL_TARANTOOL_ERROR and have diag set.

Part of #4074

diff --git a/src/box/sql/build.c b/src/box/sql/build.c
index 73748f5..4c101ca 100644
--- a/src/box/sql/build.c
+++ b/src/box/sql/build.c
@@ -2998,26 +2998,6 @@ sql_set_multi_write(struct Parse *parse_context, bool is_set)
 	pToplevel->isMultiWrite |= is_set;
 }
 
-/*
- * Code an OP_Halt that causes the vdbe to return an SQL_CONSTRAINT
- * error. The onError parameter determines which (if any) of the statement
- * and/or current transaction is rolled back.
- */
-void
-sqlHaltConstraint(Parse * pParse,	/* Parsing context */
-		      int errCode,	/* extended error code */
-		      int onError,	/* Constraint type */
-		      char *p4,	/* Error message */
-		      i8 p4type,	/* P4_STATIC or P4_TRANSIENT */
-		      u8 p5Errmsg	/* P5_ErrMsg type */
-    )
-{
-	Vdbe *v = sqlGetVdbe(pParse);
-	assert((errCode & 0xff) == SQL_CONSTRAINT);
-	sqlVdbeAddOp4(v, OP_Halt, errCode, onError, 0, p4, p4type);
-	sqlVdbeChangeP5(v, p5Errmsg);
-}
-
 #ifndef SQL_OMIT_CTE
 /*
  * This routine is invoked once per CTE by the parser while parsing a
@@ -3126,9 +3106,8 @@ vdbe_emit_halt_with_presence_test(struct Parse *parser, int space_id,
 	if (no_error) {
 		sqlVdbeAddOp0(v, OP_Halt);
 	} else {
-		sqlVdbeAddOp4(v, OP_Halt, SQL_TARANTOOL_ERROR,0, 0, error,
-				  P4_DYNAMIC);
-		sqlVdbeChangeP5(v, tarantool_error_code);
+		sqlVdbeAddOp4(v, OP_Halt, SQL_TARANTOOL_ERROR, 0,
+			      tarantool_error_code, error, P4_DYNAMIC);
 	}
 	sqlVdbeAddOp1(v, OP_Close, cursor);
 	return 0;
diff --git a/src/box/sql/expr.c b/src/box/sql/expr.c
index 6ac42d7..4fbc8f5 100644
--- a/src/box/sql/expr.c
+++ b/src/box/sql/expr.c
@@ -4386,9 +4386,12 @@ sqlExprCodeTarget(Parse * pParse, Expr * pExpr, int target)
 					  ON_CONFLICT_ACTION_IGNORE, 0,
 					  pExpr->u.zToken, 0);
 		} else {
-			sqlHaltConstraint(pParse, SQL_CONSTRAINT_TRIGGER,
-					      pExpr->on_conflict_action,
-					      pExpr->u.zToken, 0, 0);
+			const char *err = tt_sprintf("Failed to execute SQL "\
+						     "statement: %s",
+						     pExpr->u.zToken);
+			sqlVdbeAddOp4(v, OP_Halt, SQL_TARANTOOL_ERROR,
+				      pExpr->on_conflict_action, ER_SQL_EXECUTE,
+				      err, 0);
 		}
 		break;
 	}
diff --git a/src/box/sql/fk_constraint.c b/src/box/sql/fk_constraint.c
index 7d36edc..5256bec 100644
--- a/src/box/sql/fk_constraint.c
+++ b/src/box/sql/fk_constraint.c
@@ -287,10 +287,10 @@ fk_constraint_lookup_parent(struct Parse *parse_context, struct space *parent,
 		 * transaction.
 		 */
 		assert(incr_count == 1);
-		sqlHaltConstraint(parse_context,
-				      SQL_CONSTRAINT_FOREIGNKEY,
-				      ON_CONFLICT_ACTION_ABORT, 0, P4_STATIC,
-				      P5_ConstraintFK);
+		const char *err = "Failed to execute SQL statement: FOREIGN "\
+				  "KEY constraint failed";
+		sqlVdbeAddOp4(v, OP_Halt, SQL_TARANTOOL_ERROR, 0,
+			      ER_SQL_EXECUTE, err, P4_STATIC);
 	} else {
 		sqlVdbeAddOp2(v, OP_FkCounter, fk_def->is_deferred,
 				  incr_count);
diff --git a/src/box/sql/insert.c b/src/box/sql/insert.c
index 2950240..286a721 100644
--- a/src/box/sql/insert.c
+++ b/src/box/sql/insert.c
@@ -851,7 +851,6 @@ vdbe_emit_constraint_checks(struct Parse *parse_context, struct space *space,
 			    enum on_conflict_action on_conflict,
 			    int ignore_label, int *upd_cols)
 {
-	struct sql *db = parse_context->db;
 	struct Vdbe *v = sqlGetVdbe(parse_context);
 	assert(v != NULL);
 	bool is_update = upd_cols != NULL;
@@ -881,20 +880,20 @@ vdbe_emit_constraint_checks(struct Parse *parse_context, struct space *space,
 		if (on_conflict_nullable == ON_CONFLICT_ACTION_REPLACE &&
 		    dflt == NULL)
 			on_conflict_nullable = ON_CONFLICT_ACTION_ABORT;
-		char *err_msg;
+		const char *err;
 		int addr;
 		switch (on_conflict_nullable) {
 		case ON_CONFLICT_ACTION_ABORT:
 		case ON_CONFLICT_ACTION_ROLLBACK:
 		case ON_CONFLICT_ACTION_FAIL:
-			err_msg = sqlMPrintf(db, "%s.%s", def->name,
-						 def->fields[i].name);
-			sqlVdbeAddOp3(v, OP_HaltIfNull,
-					  SQL_CONSTRAINT_NOTNULL,
-					  on_conflict_nullable,
-					  new_tuple_reg + i);
-			sqlVdbeAppendP4(v, err_msg, P4_DYNAMIC);
-			sqlVdbeChangeP5(v, P5_ConstraintNotNull);
+			err = tt_sprintf("Failed to execute SQL statement: "\
+					 "NOT NULL constraint failed: %s.%s",
+					 def->name, def->fields[i].name);
+			addr = sqlVdbeAddOp1(v, OP_NotNull, new_tuple_reg + i);
+			sqlVdbeAddOp4(v, OP_Halt, SQL_TARANTOOL_ERROR,
+				      on_conflict_nullable, ER_SQL_EXECUTE,
+				      err, P4_STATIC);
+			sqlVdbeJumpHere(v, addr);
 			break;
 		case ON_CONFLICT_ACTION_IGNORE:
 			sqlVdbeAddOp2(v, OP_IsNull, new_tuple_reg + i,
@@ -937,11 +936,14 @@ vdbe_emit_constraint_checks(struct Parse *parse_context, struct space *space,
 				char *name = checks->a[i].zName;
 				if (name == NULL)
 					name = def->name;
-				sqlHaltConstraint(parse_context,
-						      SQL_CONSTRAINT_CHECK,
-						      on_conflict_check, name,
-						      P4_TRANSIENT,
-						      P5_ConstraintCheck);
+				const char *err =
+					tt_sprintf("Failed to execute SQL "\
+						   "statement: CHECK "\
+						   "constraint failed: %s",
+						   name);
+				sqlVdbeAddOp4(v, OP_Halt, SQL_TARANTOOL_ERROR,
+					      on_conflict_check, ER_SQL_EXECUTE,
+					      err, P4_STATIC);
 			}
 			sqlVdbeResolveLabel(v, all_ok);
 		}
diff --git a/src/box/sql/select.c b/src/box/sql/select.c
index d3472a9..4fc59d8 100644
--- a/src/box/sql/select.c
+++ b/src/box/sql/select.c
@@ -2108,14 +2108,11 @@ computeLimitRegisters(Parse * pParse, Select * p, int iBreak)
 		sqlVdbeAddOp3(v, OP_Ge, r1, positive_limit_label, iLimit);
 		/* Otherwise return an error and stop */
 		const char *wrong_limit_error =
-			"Only positive integers are allowed "
-			"in the LIMIT clause";
+			"Failed to execute SQL statement: Only positive "\
+			"integers are allowed in the LIMIT clause";
 		sqlVdbeResolveLabel(v, halt_label);
-		sqlVdbeAddOp4(v, OP_Halt,
-				  SQL_TARANTOOL_ERROR,
-				  0, 0,
-				  wrong_limit_error,
-				  P4_STATIC);
+		sqlVdbeAddOp4(v, OP_Halt, SQL_TARANTOOL_ERROR, 0,
+			      ER_SQL_EXECUTE, wrong_limit_error, P4_STATIC);
 
 		sqlVdbeResolveLabel(v, positive_limit_label);
 		VdbeCoverage(v);
@@ -2143,12 +2140,12 @@ computeLimitRegisters(Parse * pParse, Select * p, int iBreak)
 				int no_err = sqlVdbeMakeLabel(v);
 				sqlVdbeAddOp3(v, OP_Eq, iLimit, no_err, r1);
 				const char *error =
-					"SQL error: Expression subquery could "
-					"be limited only with 1";
-				sqlVdbeAddOp4(v, OP_Halt,
-						  SQL_TARANTOOL_ERROR,
-						  0, 0, error, P4_STATIC);
-				sqlVdbeChangeP5(v, ER_SQL_EXECUTE);
+					"Failed to execute SQL statement: "\
+					"Expression subquery could be limited "\
+					"only with 1";
+				sqlVdbeAddOp4(v, OP_Halt, SQL_TARANTOOL_ERROR,
+					      0, ER_SQL_EXECUTE, error,
+					      P4_STATIC);
 				sqlVdbeResolveLabel(v, no_err);
 				sqlReleaseTempReg(pParse, r1);
 
@@ -2170,14 +2167,13 @@ computeLimitRegisters(Parse * pParse, Select * p, int iBreak)
             		sqlVdbeAddOp3(v, OP_Ge, r1, positive_offset_label, iOffset);
 			/* Otherwise return an error and stop */
 			const char *wrong_offset_error =
-				"Only positive integers are allowed "
-				"in the OFFSET clause";
+				"Failed to execute SQL statement: Only "\
+				"positive integers are allowed in the OFFSET "\
+				"clause";
 			sqlVdbeResolveLabel(v, offset_error_label);
-			sqlVdbeAddOp4(v, OP_Halt,
-					  SQL_TARANTOOL_ERROR,
-					  0, 0,
-					  wrong_offset_error,
-					  P4_STATIC);
+			sqlVdbeAddOp4(v, OP_Halt, SQL_TARANTOOL_ERROR, 0,
+				      ER_SQL_EXECUTE, wrong_offset_error,
+				      P4_STATIC);
 
 			sqlVdbeResolveLabel(v, positive_offset_label);
             		sqlReleaseTempReg(pParse, r1);
@@ -5447,10 +5443,10 @@ vdbe_code_raise_on_multiple_rows(struct Parse *parser, int limit_reg, int end_ma
 	sqlVdbeAddOp2(v, OP_Integer, 0, r1);
 	sqlVdbeAddOp3(v, OP_Ne, r1, end_mark, limit_reg);
 	const char *error =
-		"SQL error: Expression subquery returned more than 1 row";
-	sqlVdbeAddOp4(v, OP_Halt, SQL_TARANTOOL_ERROR, 0, 0, error,
-			  P4_STATIC);
-	sqlVdbeChangeP5(v, ER_SQL_EXECUTE);
+		"Failed to execute SQL statement: Expression subquery "\
+		"returned more than 1 row";
+	sqlVdbeAddOp4(v, OP_Halt, SQL_TARANTOOL_ERROR, 0, ER_SQL_EXECUTE, error,
+		      P4_STATIC);
 	sqlReleaseTempReg(parser, r1);
 }
 
diff --git a/src/box/sql/sqlInt.h b/src/box/sql/sqlInt.h
index 05a4042..5c71c51 100644
--- a/src/box/sql/sqlInt.h
+++ b/src/box/sql/sqlInt.h
@@ -3912,7 +3912,6 @@ vdbe_emit_insertion_completion(struct Vdbe *v, struct space *space,
 
 void
 sql_set_multi_write(Parse *, bool);
-void sqlHaltConstraint(Parse *, int, int, char *, i8, u8);
 
 Expr *sqlExprDup(sql *, Expr *, int);
 SrcList *sqlSrcListDup(sql *, SrcList *, int);
diff --git a/src/box/sql/vdbe.c b/src/box/sql/vdbe.c
index a64c846..33484c5 100644
--- a/src/box/sql/vdbe.c
+++ b/src/box/sql/vdbe.c
@@ -950,29 +950,14 @@ case OP_Yield: {            /* in1, jump */
 	break;
 }
 
-/* Opcode:  HaltIfNull  P1 P2 P3 P4 P5
- * Synopsis: if r[P3]=null halt
- *
- * Check the value in register P3.  If it is NULL then Halt using
- * parameter P1, P2, and P4 as if this were a Halt instruction.  If the
- * value in register P3 is not NULL, then this routine is a no-op.
- * The P5 parameter should be 1.
- */
-case OP_HaltIfNull: {      /* in3 */
-	pIn3 = &aMem[pOp->p3];
-	if ((pIn3->flags & MEM_Null)==0) break;
-	/* Fall through into OP_Halt */
-	FALLTHROUGH;
-}
-
-/* Opcode:  Halt P1 P2 * P4 P5
+/* Opcode:  Halt P1 P2 P3 P4 *
  *
  * Exit immediately.  All open cursors, etc are closed
  * automatically.
  *
  * P1 is the result code returned by sql_exec(),
  * sql_reset(), or sql_finalize().  For a normal halt,
- * this should be SQL_OK (0).
+ * this should be 0.
  * For errors, it can be some other value.  If P1!=0 then P2 will
  * determine whether or not to rollback the current transaction.
  * Do not rollback if P2==ON_CONFLICT_ACTION_FAIL. Do the rollback
@@ -983,18 +968,8 @@ case OP_HaltIfNull: {      /* in3 */
  *
  * If P4 is not null then it is an error message string.
  *
- * If P1 is SQL_TARANTOOL_ERROR then P5 is a ClientError code and
- * P4 is error message to set. Else P5 is a value between 0 and 4,
- * inclusive, that modifies the P4 string.
- *
- *    0:  (no change)
- *    1:  NOT NULL contraint failed: P4
- *    2:  UNIQUE constraint failed: P4
- *    3:  CHECK constraint failed: P4
- *    4:  FOREIGN KEY constraint failed: P4
- *
- * If P5 is not zero and  P4 is  NULL, then everything after the
- * ":" is omitted.
+ * If P1 is SQL_TARANTOOL_ERROR then P3 is a ClientError code and
+ * P4 is error message to set.
  *
  * There is an implied "Halt 0 0 0" instruction inserted at the
  * very end of every program.  So a jump past the last instruction
@@ -1031,28 +1006,10 @@ case OP_Halt: {
 	p->errorAction = (u8)pOp->p2;
 	p->pc = pcx;
 	if (p->rc) {
-		if (p->rc == SQL_TARANTOOL_ERROR) {
-			if (pOp->p4.z == NULL) {
-				assert(! diag_is_empty(diag_get()));
-			} else {
-				box_error_set(__FILE__, __LINE__, pOp->p5,
-					      pOp->p4.z);
-			}
-		} else if (pOp->p5 != 0) {
-			static const char * const azType[] = { "NOT NULL", "UNIQUE", "CHECK",
-							       "FOREIGN KEY" };
-			testcase( pOp->p5==1);
-			testcase( pOp->p5==2);
-			testcase( pOp->p5==3);
-			testcase( pOp->p5==4);
-			sqlVdbeError(p, "%s constraint failed", azType[pOp->p5-1]);
-			if (pOp->p4.z) {
-				p->zErrMsg = sqlMPrintf(db, "%z: %s", p->zErrMsg, pOp->p4.z);
-			}
-		} else {
-			sqlVdbeError(p, "%s", pOp->p4.z);
-		}
-		sql_log(pOp->p1, "abort at %d in [%s]: %s", pcx, p->zSql, p->zErrMsg);
+		assert(p->rc == SQL_TARANTOOL_ERROR);
+		if (pOp->p4.z != NULL)
+			box_error_set(__FILE__, __LINE__, pOp->p3, pOp->p4.z);
+		assert(! diag_is_empty(diag_get()));
 	}
 	rc = sqlVdbeHalt(p);
 	assert(rc==SQL_BUSY || rc==SQL_OK || rc==SQL_ERROR);
diff --git a/test/sql-tap/e_select1.test.lua b/test/sql-tap/e_select1.test.lua
index 6f17471..9968038 100755
--- a/test/sql-tap/e_select1.test.lua
+++ b/test/sql-tap/e_select1.test.lua
@@ -2170,7 +2170,7 @@ for _, val in ipairs({
         "e_select-9.2."..tn,
         select,
         {
-            1, "Only positive integers are allowed in the LIMIT clause"})
+            1, "Failed to execute SQL statement: Only positive integers are allowed in the LIMIT clause"})
 end
 
 -- EVIDENCE-OF: R-03014-26414 If the LIMIT expression evaluates to a
@@ -2224,7 +2224,7 @@ for _, val in ipairs({
     test:do_catchsql_test(
         "e_select-9.7."..tn,
         select, {
-            1, "Only positive integers are allowed in the OFFSET clause"
+            1, "Failed to execute SQL statement: Only positive integers are allowed in the OFFSET clause"
         })
 
 end
diff --git a/test/sql-tap/limit.test.lua b/test/sql-tap/limit.test.lua
index 9b728d8..40b787b 100755
--- a/test/sql-tap/limit.test.lua
+++ b/test/sql-tap/limit.test.lua
@@ -84,7 +84,7 @@ test:do_catchsql_test(
         SELECT x FROM t1 ORDER BY x+1 LIMIT 5 OFFSET -2
     ]], {
         -- <limit-1.2.13>
-        1 ,"Only positive integers are allowed in the OFFSET clause"
+        1 ,"Failed to execute SQL statement: Only positive integers are allowed in the OFFSET clause"
         -- </limit-1.2.13>
     })
 
@@ -94,7 +94,7 @@ test:do_catchsql_test(
         SELECT x FROM t1 ORDER BY x+1 LIMIT 2, -5
     ]], {
         -- <limit-1.2.4>
-        1, "Only positive integers are allowed in the LIMIT clause"
+        1, "Failed to execute SQL statement: Only positive integers are allowed in the LIMIT clause"
         -- </limit-1.2.4>
     })
 
@@ -115,7 +115,7 @@ test:do_catchsql_test(
         SELECT x FROM t1 ORDER BY x+1 LIMIT -2, 5
     ]], {
         -- <limit-1.2.6>
-        1, "Only positive integers are allowed in the OFFSET clause"
+        1, "Failed to execute SQL statement: Only positive integers are allowed in the OFFSET clause"
         -- </limit-1.2.6>
     })
 
@@ -135,7 +135,7 @@ test:do_catchsql_test(
         SELECT x FROM t1 ORDER BY x+1 LIMIT -2, -5
     ]], {
         -- <limit-1.2.8>
-        1, "Only positive integers are allowed in the LIMIT clause"
+        1, "Failed to execute SQL statement: Only positive integers are allowed in the LIMIT clause"
         -- </limit-1.2.8>
     })
 
@@ -384,7 +384,7 @@ test:do_catchsql_test(
         SELECT * FROM t6 LIMIT -1 OFFSET -1;
     ]], {
         -- <limit-6.2>
-        1, "Only positive integers are allowed in the LIMIT clause"
+        1, "Failed to execute SQL statement: Only positive integers are allowed in the LIMIT clause"
         -- </limit-6.2>
     })
 
@@ -394,7 +394,7 @@ test:do_catchsql_test(
         SELECT * FROM t6 LIMIT 2 OFFSET -123;
     ]], {
         -- <limit-6.3>
-        1, "Only positive integers are allowed in the OFFSET clause"
+        1, "Failed to execute SQL statement: Only positive integers are allowed in the OFFSET clause"
         -- </limit-6.3>
     })
 
@@ -414,7 +414,7 @@ test:do_catchsql_test(
         SELECT * FROM t6 LIMIT -432 OFFSET 2;
     ]], {
         -- <limit-6.4>
-        1, "Only positive integers are allowed in the LIMIT clause"
+        1, "Failed to execute SQL statement: Only positive integers are allowed in the LIMIT clause"
         -- </limit-6.4>
     })
 
@@ -434,7 +434,7 @@ test:do_catchsql_test(
         SELECT * FROM t6 LIMIT -1
     ]], {
         -- <limit-6.5>
-        1, "Only positive integers are allowed in the LIMIT clause"
+        1, "Failed to execute SQL statement: Only positive integers are allowed in the LIMIT clause"
         -- </limit-6.5>
     })
 
@@ -454,7 +454,7 @@ test:do_catchsql_test(
         SELECT * FROM t6 LIMIT -1 OFFSET 1
     ]], {
         -- <limit-6.6>
-        1, "Only positive integers are allowed in the LIMIT clause"
+        1, "Failed to execute SQL statement: Only positive integers are allowed in the LIMIT clause"
         -- </limit-6.6>
     })
 
@@ -734,7 +734,7 @@ test:do_test(
         return test:catchsql("SELECT x FROM t1 WHERE x<10 LIMIT "..limit)
     end, {
         -- <limit-10.4>
-        1, "Only positive integers are allowed in the LIMIT clause"
+        1, "Failed to execute SQL statement: Only positive integers are allowed in the LIMIT clause"
         -- </limit-10.4>
     })
 
@@ -745,7 +745,7 @@ test:do_test(
         return test:catchsql("SELECT x FROM t1 WHERE x<10 LIMIT "..limit)
     end, {
         -- <limit-10.5>
-        1, "Only positive integers are allowed in the LIMIT clause"
+        1, "Failed to execute SQL statement: Only positive integers are allowed in the LIMIT clause"
         -- </limit-10.5>
     })
 
@@ -1320,7 +1320,7 @@ test:do_catchsql_test(
         SELECT 123 LIMIT -1 OFFSET 0
     ]], {
         -- <limit-14.6.1>
-        1, "Only positive integers are allowed in the LIMIT clause"
+        1, "Failed to execute SQL statement: Only positive integers are allowed in the LIMIT clause"
         -- </limit-14.6.1>
     })
 
@@ -1340,7 +1340,7 @@ test:do_catchsql_test(
         SELECT 123 LIMIT -1 OFFSET 1
     ]], {
         -- <limit-14.7.1>
-        1, "Only positive integers are allowed in the LIMIT clause"
+        1, "Failed to execute SQL statement: Only positive integers are allowed in the LIMIT clause"
         -- </limit-14.7.1>
     })
 
diff --git a/test/sql-tap/select4.test.lua b/test/sql-tap/select4.test.lua
index b78091b..1c0804b 100755
--- a/test/sql-tap/select4.test.lua
+++ b/test/sql-tap/select4.test.lua
@@ -990,7 +990,7 @@ test:do_catchsql_test(
         SELECT DISTINCT log FROM t1 ORDER BY log LIMIT -1
     ]], {
         -- <select4-10.4.1>
-    1,"Only positive integers are allowed in the LIMIT clause"
+    1,"Failed to execute SQL statement: Only positive integers are allowed in the LIMIT clause"
         -- </select4-10.4.1>
     })
 test:do_execsql_test(
@@ -1009,7 +1009,7 @@ test:do_catchsql_test(
         SELECT DISTINCT log FROM t1 ORDER BY log LIMIT -1 OFFSET 2
     ]], {
         -- <select4-10.5.1>
-        1,"Only positive integers are allowed in the LIMIT clause"
+        1,"Failed to execute SQL statement: Only positive integers are allowed in the LIMIT clause"
         -- </select4-10.5.1>
     })
 test:do_execsql_test(
@@ -1402,7 +1402,7 @@ test:do_catchsql_test(
         SELECT (VALUES(1),(2),(3),(4))
     ]], {
         -- <select4-14.10>
-        1, "SQL error: Expression subquery returned more than 1 row"
+        1, "Failed to execute SQL statement: Expression subquery returned more than 1 row"
         -- </select4-14.10>
     })
 
@@ -1412,7 +1412,7 @@ test:do_catchsql_test(
         SELECT (SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4)
     ]], {
         -- <select4-14.11>
-        1, "SQL error: Expression subquery returned more than 1 row"
+        1, "Failed to execute SQL statement: Expression subquery returned more than 1 row"
         -- </select4-14.11>
     })
 
diff --git a/test/sql-tap/subselect.test.lua b/test/sql-tap/subselect.test.lua
index 5b71390..ebfdf43 100755
--- a/test/sql-tap/subselect.test.lua
+++ b/test/sql-tap/subselect.test.lua
@@ -350,7 +350,7 @@ test:do_catchsql_test(
         SELECT (SELECT a FROM t5);
     ]], {
     -- <subselect-5.1>
-    1, "SQL error: Expression subquery returned more than 1 row"
+    1, "Failed to execute SQL statement: Expression subquery returned more than 1 row"
     -- </subselect-5.1>
 })
 
@@ -360,7 +360,7 @@ test:do_catchsql_test(
         SELECT b FROM t5 WHERE a = (SELECT a FROM t5 WHERE b=6);
     ]], {
     -- <subselect-5.2>
-    1, "SQL error: Expression subquery returned more than 1 row"
+    1, "Failed to execute SQL statement: Expression subquery returned more than 1 row"
     -- </subselect-5.2>
 })
 
@@ -380,7 +380,7 @@ test:do_catchsql_test(
         SELECT b FROM t1 WHERE a = (SELECT a FROM t1 WHERE b=6 LIMIT (SELECT b FROM t1 WHERE a =1));
     ]], {
     -- <subselect-5.2>
-    1, "SQL error: Expression subquery could be limited only with 1"
+    1, "Failed to execute SQL statement: Expression subquery could be limited only with 1"
     -- </subselect-5.2>
 })
 
diff --git a/test/sql-tap/tkt1473.test.lua b/test/sql-tap/tkt1473.test.lua
index 3e93203..ada18d0 100755
--- a/test/sql-tap/tkt1473.test.lua
+++ b/test/sql-tap/tkt1473.test.lua
@@ -125,7 +125,7 @@ test:do_catchsql_test(
         SELECT (SELECT 1 FROM t1 WHERE a=1 UNION ALL SELECT 2 FROM t1 WHERE b=0)
     ]], {
         -- <tkt1473-2.2>
-        1, "SQL error: Expression subquery returned more than 1 row"
+        1, "Failed to execute SQL statement: Expression subquery returned more than 1 row"
         -- </tkt1473-2.2>
     })
 
@@ -145,7 +145,7 @@ test:do_catchsql_test(
         SELECT (SELECT 1 FROM t1 WHERE a=1 UNION ALL SELECT 2 FROM t1 WHERE b=4)
     ]], {
         -- <tkt1473-2.4>
-        1, "SQL error: Expression subquery returned more than 1 row"
+        1, "Failed to execute SQL statement: Expression subquery returned more than 1 row"
         -- </tkt1473-2.4>
     })
 
@@ -155,7 +155,7 @@ test:do_catchsql_test(
         SELECT (SELECT 1 FROM t1 WHERE a=1 UNION SELECT 2 FROM t1 WHERE b=4)
     ]], {
         -- <tkt1473-2.5>
-        1, "SQL error: Expression subquery returned more than 1 row"
+        1, "Failed to execute SQL statement: Expression subquery returned more than 1 row"
         -- </tkt1473-2.5>
     })
 
@@ -165,7 +165,7 @@ test:do_catchsql_test(
         SELECT (SELECT 1 FROM t1 WHERE a=0 UNION ALL SELECT 2 FROM t1 WHERE b=4)
     ]], {
         -- <tkt1473-2.6>
-        1, "SQL error: Expression subquery returned more than 1 row"
+        1, "Failed to execute SQL statement: Expression subquery returned more than 1 row"
         -- </tkt1473-2.6>
     })
 
@@ -206,7 +206,7 @@ test:do_catchsql_test(
           (SELECT 1 FROM t1 WHERE a=1 UNION ALL SELECT 2 FROM t1 WHERE b=0)
     ]], {
         -- <tkt1473-3.2>
-        1, "SQL error: Expression subquery returned more than 1 row"
+        1, "Failed to execute SQL statement: Expression subquery returned more than 1 row"
         -- </tkt1473-3.2>
     })
 
@@ -228,7 +228,7 @@ test:do_catchsql_test(
           (SELECT 1 FROM t1 WHERE a=1 UNION ALL SELECT 2 FROM t1 WHERE b=4)
     ]], {
         -- <tkt1473-3.4>
-        1, "SQL error: Expression subquery returned more than 1 row"
+        1, "Failed to execute SQL statement: Expression subquery returned more than 1 row"
         -- </tkt1473-3.4>
     })
 
@@ -239,7 +239,7 @@ test:do_catchsql_test(
           (SELECT 1 FROM t1 WHERE a=1 UNION SELECT 2 FROM t1 WHERE b=4)
     ]], {
         -- <tkt1473-3.5>
-        1, "SQL error: Expression subquery returned more than 1 row"
+        1, "Failed to execute SQL statement: Expression subquery returned more than 1 row"
         -- </tkt1473-3.5>
     })
 
@@ -250,7 +250,7 @@ test:do_catchsql_test(
           (SELECT 1 FROM t1 WHERE a=0 UNION ALL SELECT 2 FROM t1 WHERE b=4)
     ]], {
         -- <tkt1473-3.6>
-        1, "SQL error: Expression subquery returned more than 1 row"
+        1, "Failed to execute SQL statement: Expression subquery returned more than 1 row"
         -- </tkt1473-3.6>
     })
 
@@ -359,7 +359,7 @@ test:do_catchsql_test(
         )
     ]], {
         -- <tkt1473-4.3>
-        1, "SQL error: Expression subquery returned more than 1 row"
+        1, "Failed to execute SQL statement: Expression subquery returned more than 1 row"
         -- </tkt1473-4.3>
     })
 
@@ -389,7 +389,7 @@ test:do_catchsql_test(
         )
     ]], {
         -- <tkt1473-4.4>
-        1, "SQL error: Expression subquery returned more than 1 row"
+        1, "Failed to execute SQL statement: Expression subquery returned more than 1 row"
         -- </tkt1473-4.4>
     })
 
@@ -419,7 +419,7 @@ test:do_catchsql_test(
         )
     ]], {
         -- <tkt1473-4.5>
-        1, "SQL error: Expression subquery returned more than 1 row"
+        1, "Failed to execute SQL statement: Expression subquery returned more than 1 row"
         -- </tkt1473-4.5>
     })
 
@@ -449,7 +449,7 @@ test:do_catchsql_test(
         )
     ]], {
         -- <tkt1473-4.6>
-        1, "SQL error: Expression subquery returned more than 1 row"
+        1, "Failed to execute SQL statement: Expression subquery returned more than 1 row"
         -- </tkt1473-4.6>
     })
 
@@ -509,7 +509,7 @@ test:do_catchsql_test(
         )
     ]], {
         -- <tkt1473-5.3>
-        1, "SQL error: Expression subquery returned more than 1 row"
+        1, "Failed to execute SQL statement: Expression subquery returned more than 1 row"
         -- </tkt1473-5.3>
     })
 
@@ -539,7 +539,7 @@ test:do_catchsql_test(
         )
     ]], {
         -- <tkt1473-5.4>
-        1, "SQL error: Expression subquery returned more than 1 row"
+        1, "Failed to execute SQL statement: Expression subquery returned more than 1 row"
         -- </tkt1473-5.4>
     })
 
@@ -569,7 +569,7 @@ test:do_catchsql_test(
         )
     ]], {
         -- <tkt1473-5.5>
-        1, "SQL error: Expression subquery returned more than 1 row"
+        1, "Failed to execute SQL statement: Expression subquery returned more than 1 row"
         -- </tkt1473-5.5>
     })
 
@@ -599,7 +599,7 @@ test:do_catchsql_test(
         )
     ]], {
         -- <tkt1473-5.6>
-        1, "SQL error: Expression subquery returned more than 1 row"
+        1, "Failed to execute SQL statement: Expression subquery returned more than 1 row"
         -- </tkt1473-5.6>
     })
 
@@ -659,7 +659,7 @@ test:do_catchsql_test(
         )
     ]], {
         -- <tkt1473-6.3>
-        1, "SQL error: Expression subquery returned more than 1 row"
+        1, "Failed to execute SQL statement: Expression subquery returned more than 1 row"
         -- </tkt1473-6.3>
     })
 
@@ -689,7 +689,7 @@ test:do_catchsql_test(
         )
     ]], {
         -- <tkt1473-6.4>
-        1, "SQL error: Expression subquery returned more than 1 row"
+        1, "Failed to execute SQL statement: Expression subquery returned more than 1 row"
         -- </tkt1473-6.4>
     })
 
diff --git a/test/sql/iproto.result b/test/sql/iproto.result
index 73497b4..9639ba7 100644
--- a/test/sql/iproto.result
+++ b/test/sql/iproto.result
@@ -164,15 +164,18 @@ cn:execute('select * from test limit ?', {2})
 ...
 cn:execute('select * from test limit ?', {-2})
 ---
-- error: Only positive integers are allowed in the LIMIT clause
+- error: 'Failed to execute SQL statement: Only positive integers are allowed in the
+    LIMIT clause'
 ...
 cn:execute('select * from test limit ?', {2.7})
 ---
-- error: Only positive integers are allowed in the LIMIT clause
+- error: 'Failed to execute SQL statement: Only positive integers are allowed in the
+    LIMIT clause'
 ...
 cn:execute('select * from test limit ?', {'Hello'})
 ---
-- error: Only positive integers are allowed in the LIMIT clause
+- error: 'Failed to execute SQL statement: Only positive integers are allowed in the
+    LIMIT clause'
 ...
 cn:execute('select * from test limit 1 offset ?', {2})
 ---
@@ -188,15 +191,18 @@ cn:execute('select * from test limit 1 offset ?', {2})
 ...
 cn:execute('select * from test limit 1 offset ?', {-2})
 ---
-- error: Only positive integers are allowed in the OFFSET clause
+- error: 'Failed to execute SQL statement: Only positive integers are allowed in the
+    OFFSET clause'
 ...
 cn:execute('select * from test limit 1 offset ?', {2.7})
 ---
-- error: Only positive integers are allowed in the OFFSET clause
+- error: 'Failed to execute SQL statement: Only positive integers are allowed in the
+    OFFSET clause'
 ...
 cn:execute('select * from test limit 1 offset ?', {'Hello'})
 ---
-- error: Only positive integers are allowed in the OFFSET clause
+- error: 'Failed to execute SQL statement: Only positive integers are allowed in the
+    OFFSET clause'
 ...
 -- gh-2608 SQL iproto DDL
 cn:execute('create table test2(id int primary key, a int, b int, c int)')
diff --git a/test/sql/types.result b/test/sql/types.result
index a53d6f7..572a83c 100644
--- a/test/sql/types.result
+++ b/test/sql/types.result
@@ -383,11 +383,13 @@ box.execute("SELECT true IN (1, 'abc', false)")
 ...
 box.execute("SELECT 1 LIMIT true;")
 ---
-- error: Only positive integers are allowed in the LIMIT clause
+- error: 'Failed to execute SQL statement: Only positive integers are allowed in the
+    LIMIT clause'
 ...
 box.execute("SELECT 1 LIMIT 1 OFFSET true;")
 ---
-- error: Only positive integers are allowed in the OFFSET clause
+- error: 'Failed to execute SQL statement: Only positive integers are allowed in the
+    OFFSET clause'
 ...
 box.execute("SELECT 'abc' || true;")
 ---
@@ -551,7 +553,8 @@ box.execute("SELECT b FROM t GROUP BY b LIMIT 1;")
 ...
 box.execute("SELECT b FROM t LIMIT true;")
 ---
-- error: Only positive integers are allowed in the LIMIT clause
+- error: 'Failed to execute SQL statement: Only positive integers are allowed in the
+    LIMIT clause'
 ...
 -- Most of aggregates don't accept boolean arguments.
 --

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [tarantool-patches] Re: [PATCH v1 8/9] sql: use diag_set() to set an error in SQL functions
  2019-06-02 16:35   ` [tarantool-patches] " Vladislav Shpilevoy
@ 2019-06-03 11:54     ` Mergen Imeev
  0 siblings, 0 replies; 25+ messages in thread
From: Mergen Imeev @ 2019-06-03 11:54 UTC (permalink / raw)
  To: Vladislav Shpilevoy; +Cc: tarantool-patches

On Sun, Jun 02, 2019 at 06:35:08PM +0200, Vladislav Shpilevoy wrote:
> 
> > diff --git a/src/box/sql/vdbeapi.c b/src/box/sql/vdbeapi.c
> > index 597d37e..673ccd1 100644
> > --- a/src/box/sql/vdbeapi.c
> > +++ b/src/box/sql/vdbeapi.c
> > @@ -762,75 +724,6 @@ sql_aggregate_context(sql_context * p, int nByte)
> > -/*
> > - * Set the auxiliary data pointer and delete function, for the iArg'th
> > - * argument to the user-function defined by pCtx. Any previous value is
> > - * deleted by calling the delete function specified when it was set.
> > - */
> > -void
> > -sql_set_auxdata(sql_context * pCtx,
> > -		    int iArg, void *pAux, void (*xDelete) (void *)
> > -    )
> 
> Still is mentioned in a couple of comments.
Fixed.

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [tarantool-patches] Re: [PATCH v1 9/9] sql: set errors in VDBE using diag_set()
  2019-06-02 16:34   ` [tarantool-patches] " Vladislav Shpilevoy
@ 2019-06-03 12:10     ` Mergen Imeev
  2019-06-03 12:20       ` Mergen Imeev
  0 siblings, 1 reply; 25+ messages in thread
From: Mergen Imeev @ 2019-06-03 12:10 UTC (permalink / raw)
  To: Vladislav Shpilevoy; +Cc: tarantool-patches

On Sun, Jun 02, 2019 at 06:34:12PM +0200, Vladislav Shpilevoy wrote:
> 
> > diff --git a/src/box/sql/vdbe.c b/src/box/sql/vdbe.c
> > index 43d7329..5bf5e6e 100644
> > --- a/src/box/sql/vdbe.c
> > +++ b/src/box/sql/vdbe.c
> > @@ -3903,7 +3852,8 @@ case OP_SorterCompare: {
> >  			pIn3 = &aMem[pOp->p3];
> >  			nKeyCol = pOp->p4.i;
> >  			res = 0;
> > -			rc = sqlVdbeSorterCompare(pC, pIn3, nKeyCol, &res);
> > +			if (sqlVdbeSorterCompare(pC, pIn3, nKeyCol, &res) != 0)
> > +				rc = SQL_TARANTOOL_ERROR;
> 
> In all the similar places you remove SQL_TARANTOOL_ERROR,
> but here you added it. Why?
> 
I thought the next command was doing something useful and
should be executed in any case. Now I see that I was wrong.

> >  			VdbeBranchTaken(res!=0,2);
> >  			if (rc) goto abort_due_to_error;
> >  			if (res) goto jump_to_p2;
> > @@ -4137,15 +4085,18 @@ case OP_Rewind: {        /* jump */
> >  	pC->seekOp = OP_Rewind;
> >  #endif
> >  	if (isSorter(pC)) {
> > -		rc = sqlVdbeSorterRewind(pC, &res);
> > +		if (sqlVdbeSorterRewind(pC, &res) != SQL_OK)
> > +			goto abort_due_to_error;
> >  	} else {
> >  		assert(pC->eCurType==CURTYPE_TARANTOOL);
> >  		pCrsr = pC->uc.pCursor;
> >  		assert(pCrsr);
> > -		rc = tarantoolsqlFirst(pCrsr, &res);
> > +		if (tarantoolsqlFirst(pCrsr, &res) != SQL_OK)
> > +			rc = SQL_TARANTOOL_ERROR;
> 
> The same.
> 
As in the previous case, I thought that pC->cacheStatus
should be set, but now I see that it is checked only in
OP_Column, and in case of an error, it will not be
checked at all.

> Consider my review fixes on the branch and below. They are motivated
> by several points:
> 
> 1) in the original code there were places comparing 'rc' with 0, but
> you replaced them with 'rc ==/!= SQL_OK'. I rolled back such changes,
> because we move towards removal of SQL_OK. So when you need to choose
> between 0 and SQL_OK - use 0.
> 
> 2) there were places using SQL_OK, but very easy to fix and compare
> with 0. I did it.
> 
> 3) in a couple of places you kept 'rc = SQL_TARANTOOL_ERROR'. I don't
> know why, but I dropped it, and the tests passed. If I was wrong, tell
> me, please.
> 
Thank you, I squashed your patch. Actually, all of SQL
errcodes are removed in the follow-up patch-set.

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [tarantool-patches] Re: [PATCH v1 9/9] sql: set errors in VDBE using diag_set()
  2019-06-03 12:10     ` Mergen Imeev
@ 2019-06-03 12:20       ` Mergen Imeev
  0 siblings, 0 replies; 25+ messages in thread
From: Mergen Imeev @ 2019-06-03 12:20 UTC (permalink / raw)
  To: Vladislav Shpilevoy; +Cc: tarantool-patches

Did not include a new patch in the previous letter, sorry.
New patch below.

On Mon, Jun 03, 2019 at 03:10:10PM +0300, Mergen Imeev wrote:
> On Sun, Jun 02, 2019 at 06:34:12PM +0200, Vladislav Shpilevoy wrote:
> > 
> > > diff --git a/src/box/sql/vdbe.c b/src/box/sql/vdbe.c
> > > index 43d7329..5bf5e6e 100644
> > > --- a/src/box/sql/vdbe.c
> > > +++ b/src/box/sql/vdbe.c
> > > @@ -3903,7 +3852,8 @@ case OP_SorterCompare: {
> > >  			pIn3 = &aMem[pOp->p3];
> > >  			nKeyCol = pOp->p4.i;
> > >  			res = 0;
> > > -			rc = sqlVdbeSorterCompare(pC, pIn3, nKeyCol, &res);
> > > +			if (sqlVdbeSorterCompare(pC, pIn3, nKeyCol, &res) != 0)
> > > +				rc = SQL_TARANTOOL_ERROR;
> > 
> > In all the similar places you remove SQL_TARANTOOL_ERROR,
> > but here you added it. Why?
> > 
> I thought the next command was doing something useful and
> should be executed in any case. Now I see that I was wrong.
> 
> > >  			VdbeBranchTaken(res!=0,2);
> > >  			if (rc) goto abort_due_to_error;
> > >  			if (res) goto jump_to_p2;
> > > @@ -4137,15 +4085,18 @@ case OP_Rewind: {        /* jump */
> > >  	pC->seekOp = OP_Rewind;
> > >  #endif
> > >  	if (isSorter(pC)) {
> > > -		rc = sqlVdbeSorterRewind(pC, &res);
> > > +		if (sqlVdbeSorterRewind(pC, &res) != SQL_OK)
> > > +			goto abort_due_to_error;
> > >  	} else {
> > >  		assert(pC->eCurType==CURTYPE_TARANTOOL);
> > >  		pCrsr = pC->uc.pCursor;
> > >  		assert(pCrsr);
> > > -		rc = tarantoolsqlFirst(pCrsr, &res);
> > > +		if (tarantoolsqlFirst(pCrsr, &res) != SQL_OK)
> > > +			rc = SQL_TARANTOOL_ERROR;
> > 
> > The same.
> > 
> As in the previous case, I thought that pC->cacheStatus
> should be set, but now I see that it is checked only in
> OP_Column, and in case of an error, it will not be
> checked at all.
> 
> > Consider my review fixes on the branch and below. They are motivated
> > by several points:
> > 
> > 1) in the original code there were places comparing 'rc' with 0, but
> > you replaced them with 'rc ==/!= SQL_OK'. I rolled back such changes,
> > because we move towards removal of SQL_OK. So when you need to choose
> > between 0 and SQL_OK - use 0.
> > 
> > 2) there were places using SQL_OK, but very easy to fix and compare
> > with 0. I did it.
> > 
> > 3) in a couple of places you kept 'rc = SQL_TARANTOOL_ERROR'. I don't
> > know why, but I dropped it, and the tests passed. If I was wrong, tell
> > me, please.
> > 
> Thank you, I squashed your patch. Actually, all of SQL
> errcodes are removed in the follow-up patch-set.
>

New patch:

From 1bbdbe48b600e93ef88d8cfb0b5264e5ec41c753 Mon Sep 17 00:00:00 2001
Date: Mon, 22 Apr 2019 19:41:46 +0300
Subject: [PATCH] sql: set errors in VDBE using diag_set()

After this patch, all errors in VDBE will be set using diag_set().

Closes #4074

diff --git a/src/box/execute.c b/src/box/execute.c
index a3d4a92..e81cc32 100644
--- a/src/box/execute.c
+++ b/src/box/execute.c
@@ -410,8 +410,7 @@ port_sql_dump_msgpack(struct port *port, struct obuf *out)
  * @retval -1 Error.
  */
 static inline int
-sql_execute(sql *db, struct sql_stmt *stmt, struct port *port,
-	    struct region *region)
+sql_execute(struct sql_stmt *stmt, struct port *port, struct region *region)
 {
 	int rc, column_count = sql_column_count(stmt);
 	if (column_count > 0) {
@@ -427,15 +426,8 @@ sql_execute(sql *db, struct sql_stmt *stmt, struct port *port,
 		rc = sql_step(stmt);
 		assert(rc != SQL_ROW && rc != SQL_OK);
 	}
-	if (rc != SQL_DONE) {
-		if (db->errCode != SQL_TARANTOOL_ERROR) {
-			const char *err = (char *)sql_value_text(db->pErr);
-			if (err == NULL)
-				err = sqlErrStr(db->errCode);
-			diag_set(ClientError, ER_SQL_EXECUTE, err);
-		}
+	if (rc != SQL_DONE)
 		return -1;
-	}
 	return 0;
 }
 
@@ -446,19 +438,12 @@ sql_prepare_and_execute(const char *sql, int len, const struct sql_bind *bind,
 {
 	struct sql_stmt *stmt;
 	struct sql *db = sql_get();
-	if (sql_prepare_v2(db, sql, len, &stmt, NULL) != SQL_OK) {
-		if (db->errCode != SQL_TARANTOOL_ERROR) {
-			const char *err = (char *)sql_value_text(db->pErr);
-			if (err == NULL)
-				err = sqlErrStr(db->errCode);
-			diag_set(ClientError, ER_SQL_EXECUTE, err);
-		}
+	if (sql_prepare_v2(db, sql, len, &stmt, NULL) != SQL_OK)
 		return -1;
-	}
 	assert(stmt != NULL);
 	port_sql_create(port, stmt);
 	if (sql_bind(stmt, bind, bind_count) == 0 &&
-	    sql_execute(db, stmt, port, region) == 0)
+	    sql_execute(stmt, port, region) == 0)
 		return 0;
 	port_destroy(port);
 	return -1;
diff --git a/src/box/sql.c b/src/box/sql.c
index 59a8bfb..d4d9d96 100644
--- a/src/box/sql.c
+++ b/src/box/sql.c
@@ -325,21 +325,19 @@ int tarantoolsqlMovetoUnpacked(BtCursor *pCur, UnpackedRecord *pIdxKey,
  *
  * @retval SQL_OK
  */
-int tarantoolsqlEphemeralCount(struct BtCursor *pCur, i64 *pnEntry)
+int64_t
+tarantoolsqlEphemeralCount(struct BtCursor *pCur)
 {
 	assert(pCur->curFlags & BTCF_TEphemCursor);
-
 	struct index *primary_index = space_index(pCur->space, 0 /* PK */);
-	*pnEntry = index_count(primary_index, pCur->iter_type, NULL, 0);
-	return SQL_OK;
+	return index_count(primary_index, pCur->iter_type, NULL, 0);
 }
 
-int tarantoolsqlCount(BtCursor *pCur, i64 *pnEntry)
+int64_t
+tarantoolsqlCount(struct BtCursor *pCur)
 {
 	assert(pCur->curFlags & BTCF_TaCursor);
-
-	*pnEntry = index_count(pCur->index, pCur->iter_type, NULL, 0);
-	return SQL_OK;
+	return index_count(pCur->index, pCur->iter_type, NULL, 0);
 }
 
 struct space *
@@ -621,12 +619,12 @@ int tarantoolsqlRenameTrigger(const char *trig_name,
 	char *key_begin = (char*) region_alloc(&fiber()->gc, key_len);
 	if (key_begin == NULL) {
 		diag_set(OutOfMemory, key_len, "region_alloc", "key_begin");
-		return SQL_TARANTOOL_ERROR;
+		return -1;
 	}
 	char *key = mp_encode_array(key_begin, 1);
 	key = mp_encode_str(key, trig_name, trig_name_len);
 	if (box_index_get(BOX_TRIGGER_ID, 0, key_begin, key, &tuple) != 0)
-		return SQL_TARANTOOL_ERROR;
+		return -1;
 	assert(tuple != NULL);
 	assert(tuple_field_count(tuple) == 3);
 	const char *field = tuple_field(tuple, BOX_TRIGGER_FIELD_SPACE_ID);
@@ -645,7 +643,7 @@ int tarantoolsqlRenameTrigger(const char *trig_name,
 	if (trigger_stmt == NULL) {
 		diag_set(OutOfMemory, trigger_stmt_len + 1, "region_alloc",
 			 "trigger_stmt");
-		return SQL_TARANTOOL_ERROR;
+		return -1;
 	}
 	memcpy(trigger_stmt, trigger_stmt_old, trigger_stmt_len);
 	trigger_stmt[trigger_stmt_len] = '\0';
@@ -662,7 +660,7 @@ int tarantoolsqlRenameTrigger(const char *trig_name,
 	char *new_tuple = (char*)region_alloc(&fiber()->gc, key_len);
 	if (new_tuple == NULL) {
 		diag_set(OutOfMemory, key_len, "region_alloc", "new_tuple");
-		return SQL_TARANTOOL_ERROR;
+		return -1;
 	}
 	char *new_tuple_end = mp_encode_array(new_tuple, 3);
 	new_tuple_end = mp_encode_str(new_tuple_end, trig_name, trig_name_len);
@@ -672,15 +670,12 @@ int tarantoolsqlRenameTrigger(const char *trig_name,
 	new_tuple_end = mp_encode_str(new_tuple_end, trigger_stmt,
 				      trigger_stmt_new_len);
 
-	if (box_replace(BOX_TRIGGER_ID, new_tuple, new_tuple_end, NULL) != 0)
-		return SQL_TARANTOOL_ERROR;
-	else
-		return SQL_OK;
+	return box_replace(BOX_TRIGGER_ID, new_tuple, new_tuple_end, NULL);
 
 rename_fail:
 	diag_set(ClientError, ER_SQL_EXECUTE, "can't modify name of space "
 		"created not via SQL facilities");
-	return SQL_TARANTOOL_ERROR;
+	return -1;
 }
 
 int
@@ -695,7 +690,7 @@ sql_rename_table(uint32_t space_id, const char *new_name)
 	char *raw = (char *) region_alloc(region, size);
 	if (raw == NULL) {
 		diag_set(OutOfMemory, size, "region_alloc", "raw");
-		return SQL_TARANTOOL_ERROR;
+		return -1;
 	}
 	/* Encode key. */
 	char *pos = mp_encode_array(raw, 1);
@@ -709,7 +704,7 @@ sql_rename_table(uint32_t space_id, const char *new_name)
 	pos = mp_encode_uint(pos, BOX_SPACE_FIELD_NAME);
 	pos = mp_encode_str(pos, new_name, name_len);
 	if (box_update(BOX_SPACE_ID, 0, raw, ops, ops, pos, 0, NULL) != 0)
-		return SQL_TARANTOOL_ERROR;
+		return -1;
 	return 0;
 }
 
@@ -834,8 +829,8 @@ tarantoolsqlIncrementMaxid(uint64_t *space_max_id)
 	request.space_id = space_schema->def->id;
 	if (box_process_rw(&request, space_schema, &res) != 0 || res == NULL ||
 	    tuple_field_u64(res, 1, space_max_id) != 0)
-		return SQL_TARANTOOL_ERROR;
-	return SQL_OK;
+		return -1;
+	return 0;
 }
 
 /*
diff --git a/src/box/sql/analyze.c b/src/box/sql/analyze.c
index 9795429..4106bce 100644
--- a/src/box/sql/analyze.c
+++ b/src/box/sql/analyze.c
@@ -1691,7 +1691,7 @@ sql_analysis_load(struct sql *db)
 	assert(stat_space != NULL);
 	ssize_t index_count = box_index_len(stat_space->def->id, 0);
 	if (index_count < 0)
-		return SQL_TARANTOOL_ERROR;
+		return -1;
 	if (box_txn_begin() != 0)
 		goto fail;
 	size_t stats_size = index_count * sizeof(struct index_stat);
@@ -1712,7 +1712,7 @@ sql_analysis_load(struct sql *db)
 		goto fail;
 	if (info.index_count == 0) {
 		box_txn_commit();
-		return SQL_OK;
+		return 0;
 	}
 	/*
 	 * This query is used to allocate enough memory for
@@ -1768,12 +1768,9 @@ sql_analysis_load(struct sql *db)
 	 */
 	const char *order_query = "SELECT \"tbl\",\"idx\" FROM "
 				  "\"_sql_stat4\" GROUP BY \"tbl\",\"idx\"";
-	if (load_stat_to_index(db, order_query, heap_stats) != 0)
-		goto fail;
-	if (box_txn_commit() != 0)
-		return SQL_TARANTOOL_ERROR;
-	return SQL_OK;
+	if (load_stat_to_index(db, order_query, heap_stats) == 0)
+		return box_txn_commit();
 fail:
 	box_txn_rollback();
-	return SQL_TARANTOOL_ERROR;
+	return -1;
 }
diff --git a/src/box/sql/sqlInt.h b/src/box/sql/sqlInt.h
index 9c0659b..7775278 100644
--- a/src/box/sql/sqlInt.h
+++ b/src/box/sql/sqlInt.h
@@ -4591,7 +4591,8 @@ sql_index_tuple_size(struct space *space, struct index *idx);
  * samples[] arrays.
  *
  * @param db Database handler.
- * @retval sql_OK on success, smth else otherwise.
+ * @retval 0 Success.
+ * @retval -1 Error.
  */
 int
 sql_analysis_load(struct sql *db);
diff --git a/src/box/sql/tarantoolInt.h b/src/box/sql/tarantoolInt.h
index f15e147..0474f29 100644
--- a/src/box/sql/tarantoolInt.h
+++ b/src/box/sql/tarantoolInt.h
@@ -34,7 +34,8 @@ int tarantoolsqlNext(BtCursor * pCur, int *pRes);
 int tarantoolsqlPrevious(BtCursor * pCur, int *pRes);
 int tarantoolsqlMovetoUnpacked(BtCursor * pCur, UnpackedRecord * pIdxKey,
 				   int *pRes);
-int tarantoolsqlCount(BtCursor * pCur, i64 * pnEntry);
+int64_t
+tarantoolsqlCount(struct BtCursor *pCur);
 int tarantoolsqlInsert(struct space *space, const char *tuple,
 			   const char *tuple_end);
 int tarantoolsqlReplace(struct space *space, const char *tuple,
@@ -62,7 +63,8 @@ int tarantoolsqlClearTable(struct space *space, uint32_t *tuple_count);
  * @param space_id Table's space identifier.
  * @param new_name new name of table
  *
- * @retval 0 on success, SQL_TARANTOOL_ERROR otherwise.
+ * @retval 0 Success.
+ * @retval -1 Error.
  */
 int
 sql_rename_table(uint32_t space_id, const char *new_name);
@@ -100,7 +102,8 @@ sql_ephemeral_space_create(uint32_t filed_count, struct sql_key_info *key_info);
 int tarantoolsqlEphemeralInsert(struct space *space, const char *tuple,
 				    const char *tuple_end);
 int tarantoolsqlEphemeralDelete(BtCursor * pCur);
-int tarantoolsqlEphemeralCount(BtCursor * pCur, i64 * pnEntry);
+int64_t
+tarantoolsqlEphemeralCount(struct BtCursor *pCur);
 int tarantoolsqlEphemeralDrop(BtCursor * pCur);
 int tarantoolsqlEphemeralClearTable(BtCursor * pCur);
 
diff --git a/src/box/sql/vdbe.c b/src/box/sql/vdbe.c
index b5909b6..86ad180 100644
--- a/src/box/sql/vdbe.c
+++ b/src/box/sql/vdbe.c
@@ -961,7 +961,7 @@ case OP_Halt: {
 		p->rc = SQL_BUSY;
 	} else {
 		assert(rc==SQL_OK || (p->rc&0xff)==SQL_CONSTRAINT);
-		rc = p->rc ? SQL_ERROR : SQL_DONE;
+		rc = p->rc ? SQL_TARANTOOL_ERROR : SQL_DONE;
 	}
 	goto vdbe_return;
 }
@@ -1073,17 +1073,13 @@ case OP_NextAutoincValue: {
 	assert(pOp->p2 > 0);
 
 	struct space *space = space_by_id(pOp->p1);
-	if (space == NULL) {
-		rc = SQL_TARANTOOL_ERROR;
+	if (space == NULL)
 		goto abort_due_to_error;
-	}
 
 	int64_t value;
 	struct sequence *sequence = space->sequence;
-	if (sequence == NULL || sequence_next(sequence, &value) != 0) {
-		rc = SQL_TARANTOOL_ERROR;
+	if (sequence == NULL || sequence_next(sequence, &value) != 0)
 		goto abort_due_to_error;
-	}
 
 	pOut = out2Prerelease(p, pOp);
 	pOut->flags = MEM_Int;
@@ -1310,7 +1306,7 @@ case OP_ResultRow: {
 	 * not return the number of rows modified. And do not RELEASE the statement
 	 * transaction. It needs to be rolled back.
 	 */
-	if (SQL_OK!=(rc = sqlVdbeCheckFk(p, 0))) {
+	if (sqlVdbeCheckFk(p, 0) != SQL_OK) {
 		assert(user_session->sql_flags&SQL_CountRows);
 		goto abort_due_to_error;
 	}
@@ -1402,7 +1398,6 @@ case OP_Concat: {           /* same as TK_CONCAT, in1, in2, out3 */
 					  mem_type_to_str(pIn2);
 		diag_set(ClientError, ER_INCONSISTENT_TYPES, "TEXT or BLOB",
 			 inconsistent_type);
-		rc = SQL_TARANTOOL_ERROR;
 		goto abort_due_to_error;
 	}
 
@@ -1410,10 +1405,10 @@ case OP_Concat: {           /* same as TK_CONCAT, in1, in2, out3 */
 	if (str_type_p1 != str_type_p2) {
 		diag_set(ClientError, ER_INCONSISTENT_TYPES,
 			 mem_type_to_str(pIn2), mem_type_to_str(pIn1));
-		rc = SQL_TARANTOOL_ERROR;
 		goto abort_due_to_error;
 	}
-	if (ExpandBlob(pIn1) || ExpandBlob(pIn2)) goto no_mem;
+	if (ExpandBlob(pIn1) != 0 || ExpandBlob(pIn2) != 0)
+		goto abort_due_to_error;
 	nByte = pIn1->n + pIn2->n;
 	if (nByte>db->aLimit[SQL_LIMIT_LENGTH]) {
 		goto too_big;
@@ -1526,13 +1521,11 @@ case OP_Remainder: {           /* same as TK_REM, in1, in2, out3 */
 		if (sqlVdbeRealValue(pIn1, &rA) != 0) {
 			diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
 				 sql_value_text(pIn1), "numeric");
-			rc = SQL_TARANTOOL_ERROR;
 			goto abort_due_to_error;
 		}
 		if (sqlVdbeRealValue(pIn2, &rB) != 0) {
 			diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
 				 sql_value_text(pIn2), "numeric");
-			rc = SQL_TARANTOOL_ERROR;
 			goto abort_due_to_error;
 		}
 		switch( pOp->opcode) {
@@ -1572,11 +1565,9 @@ arithmetic_result_is_null:
 
 division_by_zero:
 	diag_set(ClientError, ER_SQL_EXECUTE, "division by zero");
-	rc = SQL_TARANTOOL_ERROR;
 	goto abort_due_to_error;
 integer_overflow:
 	diag_set(ClientError, ER_SQL_EXECUTE, "integer is overflowed");
-	rc = SQL_TARANTOOL_ERROR;
 	goto abort_due_to_error;
 }
 
@@ -1690,10 +1681,8 @@ case OP_Function: {
 	(*pCtx->pFunc->xSFunc)(pCtx, pCtx->argc, pCtx->argv);/* IMP: R-24505-23230 */
 
 	/* If the function returned an error, throw an exception */
-	if (pCtx->is_aborted) {
-		rc = SQL_TARANTOOL_ERROR;
+	if (pCtx->is_aborted)
 		goto abort_due_to_error;
-	}
 
 	/* Copy the result of the function into register P3 */
 	if (pOut->flags & (MEM_Str|MEM_Blob)) {
@@ -1754,13 +1743,11 @@ case OP_ShiftRight: {           /* same as TK_RSHIFT, in1, in2, out3 */
 	if (sqlVdbeIntValue(pIn2, (int64_t *) &iA) != 0) {
 		diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
 			 sql_value_text(pIn2), "integer");
-		rc = SQL_TARANTOOL_ERROR;
 		goto abort_due_to_error;
 	}
 	if (sqlVdbeIntValue(pIn1, (int64_t *) &iB) != 0) {
 		diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
 			 sql_value_text(pIn1), "integer");
-		rc = SQL_TARANTOOL_ERROR;
 		goto abort_due_to_error;
 	}
 	op = pOp->opcode;
@@ -1829,7 +1816,6 @@ case OP_MustBeInt: {            /* jump, in1 */
 			if (pOp->p2==0) {
 				diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
 					 sql_value_text(pIn1), "integer");
-				rc = SQL_TARANTOOL_ERROR;
 				goto abort_due_to_error;
 			} else {
 				goto jump_to_p2;
@@ -1875,8 +1861,7 @@ case OP_Realify: {                  /* in1 */
  */
 case OP_Cast: {                  /* in1 */
 	pIn1 = &aMem[pOp->p1];
-	rc = ExpandBlob(pIn1);
-	if (rc != 0)
+	if (ExpandBlob(pIn1) != 0)
 		goto abort_due_to_error;
 	rc = sqlVdbeMemCast(pIn1, pOp->p2);
 	UPDATE_MAX_BLOBSIZE(pIn1);
@@ -1884,7 +1869,6 @@ case OP_Cast: {                  /* in1 */
 		break;
 	diag_set(ClientError, ER_SQL_TYPE_MISMATCH, sql_value_text(pIn1),
 		 field_type_strs[pOp->p2]);
-	rc = SQL_TARANTOOL_ERROR;
 	goto abort_due_to_error;
 }
 #endif /* SQL_OMIT_CAST */
@@ -2037,7 +2021,6 @@ case OP_Ge: {             /* same as TK_GE, jump, in1, in3 */
 						  mem_type_to_str(pIn3);
 			diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
 				 inconsistent_type, "boolean");
-			rc = SQL_TARANTOOL_ERROR;
 			goto abort_due_to_error;
 		}
 		res = sqlMemCompare(pIn3, pIn1, NULL);
@@ -2056,7 +2039,6 @@ case OP_Ge: {             /* same as TK_GE, jump, in1, in3 */
 							 ER_SQL_TYPE_MISMATCH,
 							 sql_value_text(pIn3),
 							 "numeric");
-						rc = SQL_TARANTOOL_ERROR;
 						goto abort_due_to_error;
 					}
 
@@ -2298,7 +2280,6 @@ case OP_Or: {             /* same as TK_OR, in1, in2, out3 */
 	} else {
 		diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
 			 sql_value_text(pIn1), "boolean");
-		rc = SQL_TARANTOOL_ERROR;
 		goto abort_due_to_error;
 	}
 	pIn2 = &aMem[pOp->p2];
@@ -2309,7 +2290,6 @@ case OP_Or: {             /* same as TK_OR, in1, in2, out3 */
 	} else {
 		diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
 			 sql_value_text(pIn2), "boolean");
-		rc = SQL_TARANTOOL_ERROR;
 		goto abort_due_to_error;
 	}
 	if (pOp->opcode==OP_And) {
@@ -2343,7 +2323,6 @@ case OP_Not: {                /* same as TK_NOT, in1, out2 */
 		if ((pIn1->flags & MEM_Bool) == 0) {
 			diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
 				 sql_value_text(pIn1), "boolean");
-			rc = SQL_TARANTOOL_ERROR;
 			goto abort_due_to_error;
 		}
 		mem_set_bool(pOut, ! pIn1->u.b);
@@ -2367,7 +2346,6 @@ case OP_BitNot: {             /* same as TK_BITNOT, in1, out2 */
 		if (sqlVdbeIntValue(pIn1, &i) != 0) {
 			diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
 				 sql_value_text(pIn1), "integer");
-			rc = SQL_TARANTOOL_ERROR;
 			goto abort_due_to_error;
 		}
 		pOut->flags = MEM_Int;
@@ -2415,7 +2393,6 @@ case OP_IfNot: {            /* jump, in1 */
 	} else {
 		diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
 			 sql_value_text(pIn1), "boolean");
-		rc = SQL_TARANTOOL_ERROR;
 		goto abort_due_to_error;
 	}
 	VdbeBranchTaken(c!=0, 2);
@@ -2555,8 +2532,9 @@ case OP_Column: {
 		zEnd = zData + pC->payloadSize;
 	} else {
 		memset(&sMem, 0, sizeof(sMem));
-		rc = sqlVdbeMemFromBtree(pC->uc.pCursor, 0, pC->payloadSize, &sMem);
-		if (rc!=SQL_OK) goto abort_due_to_error;
+		if (sqlVdbeMemFromBtree(pC->uc.pCursor, 0, pC->payloadSize,
+					&sMem) != SQL_OK)
+			goto abort_due_to_error;
 		zData = (u8*)sMem.z;
 		zEnd = zData + pC->payloadSize;
 	}
@@ -2615,10 +2593,8 @@ case OP_Column: {
 	}
 	uint32_t unused;
 	if (vdbe_decode_msgpack_into_mem((const char *)(zData + aOffset[p2]),
-					 pDest, &unused) != 0) {
-		rc = SQL_TARANTOOL_ERROR;
+					 pDest, &unused) != 0)
 		goto abort_due_to_error;
-	}
 	/* MsgPack map, array or extension (unsupported in sql).
 	 * Wrap it in a blob verbatim.
 	 */
@@ -2652,7 +2628,11 @@ case OP_Column: {
 	if ((pDest->flags & (MEM_Ephem | MEM_Str)) == (MEM_Ephem | MEM_Str)) {
 		int len = pDest->n;
 		if (pDest->szMalloc<len+1) {
-			if (sqlVdbeMemGrow(pDest, len+1, 1)) goto op_column_error;
+			if (sqlVdbeMemGrow(pDest, len + 1, 1) != 0) {
+				if (zData != pC->aRow)
+					sqlVdbeMemRelease(&sMem);
+				goto abort_due_to_error;
+			}
 		} else {
 			pDest->z = memcpy(pDest->zMalloc, pDest->z, len);
 			pDest->flags &= ~MEM_Ephem;
@@ -2666,10 +2646,6 @@ case OP_Column: {
 	UPDATE_MAX_BLOBSIZE(pDest);
 	REGISTER_TRACE(pOp->p3, pDest);
 	break;
-
-			op_column_error:
-	if (zData!=pC->aRow) sqlVdbeMemRelease(&sMem);
-	goto abort_due_to_error;
 }
 
 /* Opcode: ApplyType P1 P2 * P4 *
@@ -2694,7 +2670,6 @@ case OP_ApplyType: {
 			diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
 				 sql_value_text(pIn1),
 				 field_type_strs[type]);
-			rc = SQL_TARANTOOL_ERROR;
 			goto abort_due_to_error;
 		}
 		pIn1++;
@@ -2767,10 +2742,8 @@ case OP_MakeRecord: {
 	uint32_t tuple_size;
 	char *tuple =
 		sql_vdbe_mem_encode_tuple(pData0, nField, &tuple_size, region);
-	if (tuple == NULL) {
-		rc = SQL_TARANTOOL_ERROR;
+	if (tuple == NULL)
 		goto abort_due_to_error;
-	}
 	if ((int64_t)tuple_size > db->aLimit[SQL_LIMIT_LENGTH])
 		goto too_big;
 
@@ -2786,7 +2759,8 @@ case OP_MakeRecord: {
 	 * routine.
 	 */
 	if (bIsEphemeral) {
-		rc = sqlVdbeMemClearAndResize(pOut, tuple_size);
+		if (sqlVdbeMemClearAndResize(pOut, tuple_size) != 0)
+			goto abort_due_to_error;
 		pOut->flags = MEM_Blob;
 		pOut->n = tuple_size;
 		memcpy(pOut->z, tuple, tuple_size);
@@ -2801,8 +2775,6 @@ case OP_MakeRecord: {
 		pOut->n = tuple_size;
 		pOut->z = tuple;
 	}
-	if (rc)
-		goto no_mem;
 	assert(sqlVdbeCheckMemInvariants(pOut));
 	assert(pOp->p3>0 && pOp->p3<=(p->nMem+1 - p->nCursor));
 	REGISTER_TRACE(pOp->p3, pOut);
@@ -2823,15 +2795,12 @@ case OP_Count: {         /* out2 */
 	assert(p->apCsr[pOp->p1]->eCurType==CURTYPE_TARANTOOL);
 	pCrsr = p->apCsr[pOp->p1]->uc.pCursor;
 	assert(pCrsr);
-	nEntry = 0;  /* Not needed.  Only used to silence a warning. */
 	if (pCrsr->curFlags & BTCF_TaCursor) {
-		rc = tarantoolsqlCount(pCrsr, &nEntry);
-	} else if (pCrsr->curFlags & BTCF_TEphemCursor) {
-		rc = tarantoolsqlEphemeralCount(pCrsr, &nEntry);
+		nEntry = tarantoolsqlCount(pCrsr);
 	} else {
-		unreachable();
+		assert((pCrsr->curFlags & BTCF_TEphemCursor) != 0);
+		nEntry = tarantoolsqlEphemeralCount(pCrsr);
 	}
-	if (rc) goto abort_due_to_error;
 	pOut = out2Prerelease(p, pOp);
 	pOut->u.i = nEntry;
 	break;
@@ -2855,7 +2824,6 @@ case OP_Savepoint: {
 	if (psql_txn == NULL) {
 		assert(!box_txn());
 		diag_set(ClientError, ER_NO_TRANSACTION);
-		rc = SQL_TARANTOOL_ERROR;
 		goto abort_due_to_error;
 	}
 	p1 = pOp->p1;
@@ -2883,8 +2851,8 @@ case OP_Savepoint: {
 			pSavepoint = pSavepoint->pNext
 			);
 		if (!pSavepoint) {
-			sqlVdbeError(p, "no such savepoint: %s", zName);
-			rc = SQL_ERROR;
+			diag_set(ClientError, ER_NO_SUCH_SAVEPOINT);
+			goto abort_due_to_error;
 		} else {
 
 			/* Determine whether or not this is a transaction savepoint. If so,
@@ -2901,7 +2869,8 @@ case OP_Savepoint: {
 					p->rc = rc = SQL_BUSY;
 					goto vdbe_return;
 				}
-				rc = p->rc;
+				if (p->rc != 0)
+					goto abort_due_to_error;
 			} else {
 				if (p1==SAVEPOINT_ROLLBACK)
 					box_txn_rollback_to_savepoint(pSavepoint->tnt_savepoint);
@@ -2933,7 +2902,6 @@ case OP_Savepoint: {
 			}
 		}
 	}
-	if (rc) goto abort_due_to_error;
 
 	break;
 }
@@ -2956,7 +2924,6 @@ case OP_CheckViewReferences: {
 	if (space->def->view_ref_count > 0) {
 		diag_set(ClientError, ER_DROP_SPACE, space->def->name,
 			 "other views depend on this space");
-		rc = SQL_TARANTOOL_ERROR;
 		goto abort_due_to_error;
 	}
 	break;
@@ -2969,10 +2936,8 @@ case OP_CheckViewReferences: {
  * Otherwise, raise an error with appropriate error message.
  */
 case OP_TransactionBegin: {
-	if (sql_txn_begin(p) != 0) {
-		rc = SQL_TARANTOOL_ERROR;
+	if (sql_txn_begin(p) != 0)
 		goto abort_due_to_error;
-	}
 	p->auto_commit = false	;
 	break;
 }
@@ -2988,13 +2953,11 @@ case OP_TransactionBegin: {
 case OP_TransactionCommit: {
 	struct txn *txn = in_txn();
 	if (txn != NULL) {
-		if (txn_commit(txn) != 0) {
-			rc = SQL_TARANTOOL_ERROR;
+		if (txn_commit(txn) != 0)
 			goto abort_due_to_error;
-		}
 	} else {
-		sqlVdbeError(p, "cannot commit - no transaction is active");
-		rc = SQL_ERROR;
+		diag_set(ClientError, ER_SQL_EXECUTE, "cannot commit - no "\
+			 "transaction is active");
 		goto abort_due_to_error;
 	}
 	break;
@@ -3007,14 +2970,11 @@ case OP_TransactionCommit: {
  */
 case OP_TransactionRollback: {
 	if (box_txn()) {
-		if (box_txn_rollback() != 0) {
-			rc = SQL_TARANTOOL_ERROR;
+		if (box_txn_rollback() != 0)
 			goto abort_due_to_error;
-		}
 	} else {
-		sqlVdbeError(p, "cannot rollback - no "
-				    "transaction is active");
-		rc = SQL_ERROR;
+		diag_set(ClientError, ER_SQL_EXECUTE, "cannot rollback - no "\
+			 "transaction is active");
 		goto abort_due_to_error;
 	}
 	break;
@@ -3032,16 +2992,12 @@ case OP_TransactionRollback: {
  */
 case OP_TTransaction: {
 	if (!box_txn()) {
-		if (sql_txn_begin(p) != 0) {
-			rc = SQL_TARANTOOL_ERROR;
+		if (sql_txn_begin(p) != 0)
 			goto abort_due_to_error;
-		}
 	} else {
 		p->anonymous_savepoint = sql_savepoint(p, NULL);
-		if (p->anonymous_savepoint == NULL) {
-			rc = SQL_TARANTOOL_ERROR;
+		if (p->anonymous_savepoint == NULL)
 			goto abort_due_to_error;
-		}
 	}
 	break;
 }
@@ -3080,9 +3036,8 @@ case OP_IteratorOpen:
 	if (box_schema_version() != p->schema_ver &&
 	    (pOp->p5 & OPFLAG_SYSTEMSP) == 0) {
 		p->expired = 1;
-		rc = SQL_ERROR;
-		sqlVdbeError(p, "schema version has changed: " \
-				    "need to re-compile SQL statement");
+		diag_set(ClientError, ER_SQL_EXECUTE, "schema version has "\
+			 "changed: need to re-compile SQL statement");
 		goto abort_due_to_error;
 	}
 	struct space *space;
@@ -3091,10 +3046,8 @@ case OP_IteratorOpen:
 	else
 		space = aMem[pOp->p3].u.p;
 	assert(space != NULL);
-	if (access_check_space(space, PRIV_R) != 0) {
-		rc = SQL_TARANTOOL_ERROR;
+	if (access_check_space(space, PRIV_R) != 0)
 		goto abort_due_to_error;
-	}
 
 	struct index *index = space_index(space, pOp->p2);
 	assert(index != NULL);
@@ -3117,8 +3070,6 @@ case OP_IteratorOpen:
 	cur->nullRow = 1;
 open_cursor_set_hints:
 	cur->uc.pCursor->hints = pOp->p5 & OPFLAG_SEEKEQ;
-	if (rc != 0)
-		goto abort_due_to_error;
 	break;
 }
 
@@ -3140,10 +3091,8 @@ case OP_OpenTEphemeral: {
 	struct space *space = sql_ephemeral_space_create(pOp->p2,
 							 pOp->p4.key_info);
 
-	if (space == NULL) {
-		rc = SQL_TARANTOOL_ERROR;
+	if (space == NULL)
 		goto abort_due_to_error;
-	}
 	aMem[pOp->p1].u.p = space;
 	aMem[pOp->p1].flags = MEM_Ptr;
 	break;
@@ -3169,8 +3118,8 @@ case OP_SorterOpen: {
 	pCx = allocateCursor(p, pOp->p1, pOp->p2, CURTYPE_SORTER);
 	if (pCx==0) goto no_mem;
 	pCx->key_def = def;
-	rc = sqlVdbeSorterInit(db, pCx);
-	if (rc) goto abort_due_to_error;
+	if (sqlVdbeSorterInit(db, pCx) != 0)
+		goto abort_due_to_error;
 	break;
 }
 
@@ -3402,7 +3351,6 @@ case OP_SeekGT: {       /* jump, in3 */
 		} else {
 			diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
 				 sql_value_text(pIn3), "integer");
-			rc = SQL_TARANTOOL_ERROR;
 			goto abort_due_to_error;
 		}
 		iKey = i;
@@ -3483,10 +3431,8 @@ case OP_SeekGT: {       /* jump, in3 */
 #endif
 	r.eqSeen = 0;
 	r.opcode = oc;
-	rc = sqlCursorMovetoUnpacked(pC->uc.pCursor, &r, &res);
-	if (rc!=SQL_OK) {
+	if (sqlCursorMovetoUnpacked(pC->uc.pCursor, &r, &res) != SQL_OK)
 		goto abort_due_to_error;
-	}
 	if (eqOnly && r.eqSeen==0) {
 		assert(res!=0);
 		goto seek_not_found;
@@ -3498,8 +3444,8 @@ case OP_SeekGT: {       /* jump, in3 */
 	if (oc>=OP_SeekGE) {  assert(oc==OP_SeekGE || oc==OP_SeekGT);
 		if (res<0 || (res==0 && oc==OP_SeekGT)) {
 			res = 0;
-			rc = sqlCursorNext(pC->uc.pCursor, &res);
-			if (rc!=SQL_OK) goto abort_due_to_error;
+			if (sqlCursorNext(pC->uc.pCursor, &res) != SQL_OK)
+				goto abort_due_to_error;
 		} else {
 			res = 0;
 		}
@@ -3507,8 +3453,8 @@ case OP_SeekGT: {       /* jump, in3 */
 		assert(oc==OP_SeekLT || oc==OP_SeekLE);
 		if (res>0 || (res==0 && oc==OP_SeekLT)) {
 			res = 0;
-			rc = sqlCursorPrevious(pC->uc.pCursor, &res);
-			if (rc!=SQL_OK) goto abort_due_to_error;
+			if (sqlCursorPrevious(pC->uc.pCursor, &res) != SQL_OK)
+				goto abort_due_to_error;
 		} else {
 			/* res might be negative because the table is empty.  Check to
 			 * see if this is the case.
@@ -3650,10 +3596,11 @@ case OP_Found: {        /* jump, in3 */
 		}
 	}
 	rc = sqlCursorMovetoUnpacked(pC->uc.pCursor, pIdxKey, &res);
-	if (pFree) sqlDbFree(db, pFree);
-	if (rc!=SQL_OK) {
+	if (pFree != NULL)
+		sqlDbFree(db, pFree);
+	assert(rc == SQL_OK || rc == SQL_TARANTOOL_ERROR);
+	if (rc != SQL_OK)
 		goto abort_due_to_error;
-	}
 	pC->seekResult = res;
 	alreadyExists = (res==0);
 	pC->nullRow = 1-alreadyExists;
@@ -3713,10 +3660,8 @@ case OP_NextIdEphemeral: {
 	struct space *space = (struct space*)p->aMem[pOp->p1].u.p;
 	assert(space->def->id == 0);
 	uint64_t rowid;
-	if (space->vtab->ephemeral_rowid_next(space, &rowid) != 0) {
-		rc = SQL_TARANTOOL_ERROR;
+	if (space->vtab->ephemeral_rowid_next(space, &rowid) != 0)
 		goto abort_due_to_error;
-	}
 	/*
 	 * FIXME: since memory cell can comprise only 32-bit
 	 * integer, make sure it can fit in. This check should
@@ -3725,7 +3670,6 @@ case OP_NextIdEphemeral: {
 	 */
 	if (rowid > INT32_MAX) {
 		diag_set(ClientError, ER_ROWID_OVERFLOW);
-		rc = SQL_TARANTOOL_ERROR;
 		goto abort_due_to_error;
 	}
 	pOut = &aMem[pOp->p2];
@@ -3871,10 +3815,9 @@ case OP_SorterCompare: {
 			assert(pOp->p4type==P4_INT32);
 			pIn3 = &aMem[pOp->p3];
 			nKeyCol = pOp->p4.i;
-			res = 0;
-			rc = sqlVdbeSorterCompare(pC, pIn3, nKeyCol, &res);
+			if (sqlVdbeSorterCompare(pC, pIn3, nKeyCol, &res) != 0)
+				goto abort_due_to_error;
 			VdbeBranchTaken(res!=0,2);
-			if (rc) goto abort_due_to_error;
 			if (res) goto jump_to_p2;
 			break;
 		};
@@ -3897,10 +3840,10 @@ case OP_SorterData: {
 	pOut = &aMem[pOp->p2];
 	pC = p->apCsr[pOp->p1];
 	assert(isSorter(pC));
-	rc = sqlVdbeSorterRowkey(pC, pOut);
-	assert(rc!=SQL_OK || (pOut->flags & MEM_Blob));
+	if (sqlVdbeSorterRowkey(pC, pOut) != 0)
+		goto abort_due_to_error;
+	assert(pOut->flags & MEM_Blob);
 	assert(pOp->p1>=0 && pOp->p1<p->nCursor);
-	if (rc) goto abort_due_to_error;
 	p->apCsr[pOp->p3]->cacheStatus = CACHE_STALE;
 	break;
 }
@@ -3967,11 +3910,9 @@ case OP_RowData: {
 	testcase( n==0);
 
 	sqlVdbeMemRelease(pOut);
-	rc = sql_vdbe_mem_alloc_region(pOut, n);
-	if (rc)
-		goto no_mem;
-	rc = sqlCursorPayload(pCrsr, 0, n, pOut->z);
-	if (rc) goto abort_due_to_error;
+	if (sql_vdbe_mem_alloc_region(pOut, n) != 0 ||
+	    sqlCursorPayload(pCrsr, 0, n, pOut->z) != 0)
+		goto abort_due_to_error;
 	UPDATE_MAX_BLOBSIZE(pOut);
 	REGISTER_TRACE(pOp->p2, pOut);
 	break;
@@ -4034,10 +3975,10 @@ case OP_Last: {        /* jump */
 	pC->seekOp = OP_Last;
 #endif
 	if (pOp->p3==0 || !sqlCursorIsValidNN(pCrsr)) {
-		rc = tarantoolsqlLast(pCrsr, &res);
+		if (tarantoolsqlLast(pCrsr, &res) != 0)
+			goto abort_due_to_error;
 		pC->nullRow = (u8)res;
 		pC->cacheStatus = CACHE_STALE;
-		if (rc) goto abort_due_to_error;
 		if (pOp->p2>0) {
 			VdbeBranchTaken(res!=0,2);
 			if (res) goto jump_to_p2;
@@ -4106,15 +4047,16 @@ case OP_Rewind: {        /* jump */
 	pC->seekOp = OP_Rewind;
 #endif
 	if (isSorter(pC)) {
-		rc = sqlVdbeSorterRewind(pC, &res);
+		if (sqlVdbeSorterRewind(pC, &res) != 0)
+			goto abort_due_to_error;
 	} else {
 		assert(pC->eCurType==CURTYPE_TARANTOOL);
 		pCrsr = pC->uc.pCursor;
 		assert(pCrsr);
-		rc = tarantoolsqlFirst(pCrsr, &res);
+		if (tarantoolsqlFirst(pCrsr, &res) != 0)
+			goto abort_due_to_error;
 		pC->cacheStatus = CACHE_STALE;
 	}
-	if (rc) goto abort_due_to_error;
 	pC->nullRow = (u8)res;
 	assert(pOp->p2>0 && pOp->p2<p->nOp);
 	VdbeBranchTaken(res!=0,2);
@@ -4197,7 +4139,8 @@ case OP_SorterNext: {  /* jump */
 	pC = p->apCsr[pOp->p1];
 	assert(isSorter(pC));
 	res = 0;
-	rc = sqlVdbeSorterNext(db, pC, &res);
+	if (sqlVdbeSorterNext(db, pC, &res) != 0)
+		goto abort_due_to_error;
 	goto next_tail;
 case OP_PrevIfOpen:    /* jump */
 case OP_NextIfOpen:    /* jump */
@@ -4228,11 +4171,11 @@ case OP_Next:          /* jump */
 	       || pC->seekOp==OP_SeekLT || pC->seekOp==OP_SeekLE
 	       || pC->seekOp==OP_Last);
 
-	rc = pOp->p4.xAdvance(pC->uc.pCursor, &res);
+	if (pOp->p4.xAdvance(pC->uc.pCursor, &res) != 0)
+		goto abort_due_to_error;
 			next_tail:
 	pC->cacheStatus = CACHE_STALE;
 	VdbeBranchTaken(res==0,2);
-	if (rc) goto abort_due_to_error;
 	if (res==0) {
 		pC->nullRow = 0;
 		p->aCounter[pOp->p5]++;
@@ -4260,11 +4203,8 @@ case OP_SorterInsert: {      /* in2 */
 	assert(isSorter(cursor));
 	pIn2 = &aMem[pOp->p2];
 	assert((pIn2->flags & MEM_Blob) != 0);
-	rc = ExpandBlob(pIn2);
-	if (rc != 0)
-		goto abort_due_to_error;
-	rc = sqlVdbeSorterWrite(cursor, pIn2);
-	if (rc != 0)
+	if (ExpandBlob(pIn2) != 0 ||
+	    sqlVdbeSorterWrite(cursor, pIn2) != 0)
 		goto abort_due_to_error;
 	break;
 }
@@ -4294,8 +4234,7 @@ case OP_IdxInsert: {
 	assert((pIn2->flags & MEM_Blob) != 0);
 	if (pOp->p5 & OPFLAG_NCHANGE)
 		p->nChange++;
-	rc = ExpandBlob(pIn2);
-	if (rc != 0)
+	if (ExpandBlob(pIn2) != 0)
 		goto abort_due_to_error;
 	struct space *space;
 	if (pOp->p4type == P4_SPACEPTR)
@@ -4329,6 +4268,7 @@ case OP_IdxInsert: {
 	} else if (pOp->p5 & OPFLAG_OE_ROLLBACK) {
 		p->errorAction = ON_CONFLICT_ACTION_ROLLBACK;
 	}
+	assert(rc == SQL_OK || rc == SQL_TARANTOOL_ERROR);
 	if (rc != 0)
 		goto abort_due_to_error;
 	break;
@@ -4396,14 +4336,12 @@ case OP_Update: {
 	if (is_error) {
 		diag_set(OutOfMemory, stream.pos - stream.buf,
 			"mpstream_flush", "stream");
-		rc = SQL_TARANTOOL_ERROR;
 		goto abort_due_to_error;
 	}
 	uint32_t ops_size = region_used(region) - used;
 	const char *ops = region_join(region, ops_size);
 	if (ops == NULL) {
 		diag_set(OutOfMemory, ops_size, "region_join", "raw");
-		rc = SQL_TARANTOOL_ERROR;
 		goto abort_due_to_error;
 	}
 
@@ -4429,6 +4367,7 @@ case OP_Update: {
 	} else if (pOp->p5 & OPFLAG_OE_ROLLBACK) {
 		p->errorAction = ON_CONFLICT_ACTION_ROLLBACK;
 	}
+	assert(rc == SQL_OK || rc == SQL_TARANTOOL_ERROR);
 	if (rc != 0)
 		goto abort_due_to_error;
 	break;
@@ -4479,8 +4418,7 @@ case OP_SDelete: {
 	struct space *space = space_by_id(pOp->p1);
 	assert(space != NULL);
 	assert(space_is_system(space));
-	rc = sql_delete_by_key(space, 0, pIn2->z, pIn2->n);
-	if (rc)
+	if (sql_delete_by_key(space, 0, pIn2->z, pIn2->n) != 0)
 		goto abort_due_to_error;
 	if (pOp->p5 & OPFLAG_NCHANGE)
 		p->nChange++;
@@ -4514,18 +4452,19 @@ case OP_IdxDelete: {
 	r.default_rc = 0;
 	r.aMem = &aMem[pOp->p2];
 	r.opcode = OP_IdxDelete;
-	rc = sqlCursorMovetoUnpacked(pCrsr, &r, &res);
-	if (rc) goto abort_due_to_error;
+	if (sqlCursorMovetoUnpacked(pCrsr, &r, &res) != 0)
+		goto abort_due_to_error;
 	if (res==0) {
 		assert(pCrsr->eState == CURSOR_VALID);
 		if (pCrsr->curFlags & BTCF_TaCursor) {
-			rc = tarantoolsqlDelete(pCrsr, 0);
+			if (tarantoolsqlDelete(pCrsr, 0) != 0)
+				goto abort_due_to_error;
 		} else if (pCrsr->curFlags & BTCF_TEphemCursor) {
-			rc = tarantoolsqlEphemeralDelete(pCrsr);
+			if (tarantoolsqlEphemeralDelete(pCrsr) != 0)
+				goto abort_due_to_error;
 		} else {
 			unreachable();
 		}
-		if (rc) goto abort_due_to_error;
 	}
 	pC->cacheStatus = CACHE_STALE;
 	pC->seekResult = 0;
@@ -4634,17 +4573,16 @@ case OP_Clear: {
 	uint32_t space_id = pOp->p1;
 	struct space *space = space_by_id(space_id);
 	assert(space != NULL);
-	rc = 0;
 	if (pOp->p2 > 0) {
 		if (box_truncate(space_id) != 0)
-			rc = SQL_TARANTOOL_ERROR;
+			goto abort_due_to_error;
 	} else {
 		uint32_t tuple_count;
-		rc = tarantoolsqlClearTable(space, &tuple_count);
-		if (rc == 0 && (pOp->p5 & OPFLAG_NCHANGE) != 0)
+		if (tarantoolsqlClearTable(space, &tuple_count) != 0)
+			goto abort_due_to_error;
+		if ((pOp->p5 & OPFLAG_NCHANGE) != 0)
 			p->nChange += tuple_count;
 	}
-	if (rc) goto abort_due_to_error;
 	break;
 }
 
@@ -4667,8 +4605,8 @@ case OP_ResetSorter: {
 	} else {
 		assert(pC->eCurType==CURTYPE_TARANTOOL);
 		assert(pC->uc.pCursor->curFlags & BTCF_TEphemCursor);
-		rc = tarantoolsqlEphemeralClearTable(pC->uc.pCursor);
-		if (rc) goto abort_due_to_error;
+		if (tarantoolsqlEphemeralClearTable(pC->uc.pCursor) != 0)
+			goto abort_due_to_error;
 	}
 	break;
 }
@@ -4701,8 +4639,8 @@ case OP_RenameTable: {
 	zNewTableName = pOp->p4.z;
 	zOldTableName = sqlDbStrNDup(db, zOldTableName,
 					 sqlStrlen30(zOldTableName));
-	rc = sql_rename_table(space_id, zNewTableName);
-	if (rc) goto abort_due_to_error;
+	if (sql_rename_table(space_id, zNewTableName) != 0)
+		goto abort_due_to_error;
 	/*
 	 * Rebuild 'CREATE TRIGGER' expressions of all triggers
 	 * created on this table. Sure, this action is not atomic
@@ -4712,20 +4650,15 @@ case OP_RenameTable: {
 	for (struct sql_trigger *trigger = triggers; trigger != NULL; ) {
 		/* Store pointer as trigger will be destructed. */
 		struct sql_trigger *next_trigger = trigger->next;
-		rc = tarantoolsqlRenameTrigger(trigger->zName,
-						   zOldTableName, zNewTableName);
-		if (rc != SQL_OK) {
-			/*
-			 * FIXME: In the case of error,
-			 * part of triggers would have invalid
-			 * space name in tuple so can not been
-			 * persisted.
-			 * Server could be restarted.
-			 * In this case, rename table back and
-			 * try again.
-			 */
+		/*
+		 * FIXME: In the case of error, part of triggers
+		 * would have invalid space name in tuple so can
+		 * not been persisted. Server could be restarted.
+		 * In this case, rename table back and try again.
+		 */
+		if (tarantoolsqlRenameTrigger(trigger->zName, zOldTableName,
+					      zNewTableName) != 0)
 			goto abort_due_to_error;
-		}
 		trigger = next_trigger;
 	}
 	sqlDbFree(db, (void*)zOldTableName);
@@ -4740,8 +4673,8 @@ case OP_RenameTable: {
  */
 case OP_LoadAnalysis: {
 	assert(pOp->p1==0 );
-	rc = sql_analysis_load(db);
-	if (rc) goto abort_due_to_error;
+	if (sql_analysis_load(db) != 0)
+		goto abort_due_to_error;
 	break;
 }
 
@@ -4797,8 +4730,8 @@ case OP_Program: {        /* jump */
 	}
 
 	if (p->nFrame>=db->aLimit[SQL_LIMIT_TRIGGER_DEPTH]) {
-		rc = SQL_ERROR;
-		sqlVdbeError(p, "too many levels of trigger recursion");
+		diag_set(ClientError, ER_SQL_EXECUTE, "too many levels of "\
+			 "trigger recursion");
 		goto abort_due_to_error;
 	}
 
@@ -5126,11 +5059,9 @@ case OP_AggStep: {
 	(pCtx->pFunc->xSFunc)(pCtx,pCtx->argc,pCtx->argv); /* IMP: R-24505-23230 */
 	if (pCtx->is_aborted) {
 		sqlVdbeMemRelease(&t);
-		rc = SQL_TARANTOOL_ERROR;
 		goto abort_due_to_error;
-	} else {
-		assert(t.flags==MEM_Null);
 	}
+	assert(t.flags==MEM_Null);
 	if (pCtx->skipFlag) {
 		assert(pOp[-1].opcode==OP_CollSeq);
 		i = pOp[-1].p1;
@@ -5157,11 +5088,8 @@ case OP_AggFinal: {
 	assert(pOp->p1>0 && pOp->p1<=(p->nMem+1 - p->nCursor));
 	pMem = &aMem[pOp->p1];
 	assert((pMem->flags & ~(MEM_Null|MEM_Agg))==0);
-	rc = sqlVdbeMemFinalize(pMem, pOp->p4.pFunc);
-	if (rc) {
-		sqlVdbeError(p, "%s", sql_value_text(pMem));
+	if (sqlVdbeMemFinalize(pMem, pOp->p4.pFunc) != 0)
 		goto abort_due_to_error;
-	}
 	UPDATE_MAX_BLOBSIZE(pMem);
 	if (sqlVdbeMemTooBig(pMem)) {
 		goto too_big;
@@ -5270,10 +5198,8 @@ case OP_IncMaxid: {
 	assert(pOp->p1 > 0);
 	pOut = &aMem[pOp->p1];
 
-	rc = tarantoolsqlIncrementMaxid((uint64_t*) &pOut->u.i);
-	if (rc!=SQL_OK) {
+	if (tarantoolsqlIncrementMaxid((uint64_t*) &pOut->u.i) != 0)
 		goto abort_due_to_error;
-	}
 	pOut->flags = MEM_Int;
 	break;
 }
@@ -5337,28 +5263,8 @@ default: {          /* This is really OP_Noop and OP_Explain */
 	 * an error of some kind.
 	 */
 abort_due_to_error:
-	if (db->mallocFailed) rc = SQL_NOMEM;
-	assert(rc);
-	if (p->zErrMsg==0 && rc!=SQL_IOERR_NOMEM) {
-		const char *msg;
-		/* Avoiding situation when Tarantool error is set,
-		 * but error message isn't.
-		 */
-		if (rc == SQL_TARANTOOL_ERROR && tarantoolErrorMessage()) {
-			msg = tarantoolErrorMessage();
-		} else {
-			msg = sqlErrStr(rc);
-		}
-		sqlVdbeError(p, "%s", msg);
-	}
+	rc = SQL_TARANTOOL_ERROR;
 	p->rc = rc;
-	sqlSystemError(db, rc);
-	testcase( sqlGlobalConfig.xLog!=0);
-	sql_log(rc, "statement aborts at %d: [%s] %s",
-		    (int)(pOp - aOp), p->zSql, p->zErrMsg);
-	sqlVdbeHalt(p);
-	if (rc==SQL_IOERR_NOMEM) sqlOomFault(db);
-	rc = SQL_ERROR;
 
 	/* This is the only way out of this procedure. */
 vdbe_return:
@@ -5367,21 +5273,20 @@ vdbe_return:
 	assert(rc!=SQL_OK || nExtraDelete==0
 		|| sql_strlike_ci("DELETE%", p->zSql, 0) != 0
 		);
+	assert(rc == SQL_OK || rc == SQL_BUSY || rc == SQL_TARANTOOL_ERROR ||
+	       rc == SQL_ROW || rc == SQL_DONE);
 	return rc;
 
 	/* Jump to here if a string or blob larger than SQL_MAX_LENGTH
 	 * is encountered.
 	 */
 too_big:
-	sqlVdbeError(p, "string or blob too big");
-	rc = SQL_TOOBIG;
+	diag_set(ClientError, ER_SQL_EXECUTE, "string or blob too big");
 	goto abort_due_to_error;
 
 	/* Jump to here if a malloc() fails.
 	 */
 no_mem:
 	sqlOomFault(db);
-	sqlVdbeError(p, "out of memory");
-	rc = SQL_NOMEM;
 	goto abort_due_to_error;
 }
diff --git a/src/box/sql/vdbeInt.h b/src/box/sql/vdbeInt.h
index ee14510..9e6a426 100644
--- a/src/box/sql/vdbeInt.h
+++ b/src/box/sql/vdbeInt.h
@@ -244,10 +244,6 @@ struct Mem {
 #define MEM_Agg       0x4000	/* Mem.z points to an agg function context */
 #define MEM_Zero      0x8000	/* Mem.i contains count of 0s appended to blob */
 #define MEM_Subtype   0x10000	/* Mem.eSubtype is valid */
-#ifdef SQL_OMIT_INCRBLOB
-#undef MEM_Zero
-#define MEM_Zero 0x0000
-#endif
 
 /**
  * In contrast to Mem_TypeMask, this one allows to get
@@ -450,7 +446,6 @@ struct Vdbe {
 /*
  * Function prototypes
  */
-void sqlVdbeError(Vdbe *, const char *, ...);
 void sqlVdbeFreeCursor(Vdbe *, VdbeCursor *);
 void sqlVdbePopStack(Vdbe *, int);
 int sqlVdbeCursorRestore(VdbeCursor *);
@@ -532,13 +527,8 @@ void sqlVdbeMemPrettyPrint(Mem * pMem, char *zBuf);
 #endif
 int sqlVdbeMemHandleBom(Mem * pMem);
 
-#ifndef SQL_OMIT_INCRBLOB
 int sqlVdbeMemExpandBlob(Mem *);
 #define ExpandBlob(P) (((P)->flags&MEM_Zero)?sqlVdbeMemExpandBlob(P):0)
-#else
-#define sqlVdbeMemExpandBlob(x) SQL_OK
-#define ExpandBlob(P) SQL_OK
-#endif
 
 /**
  * Perform comparison of two keys: one is packed and one is not.
diff --git a/src/box/sql/vdbeapi.c b/src/box/sql/vdbeapi.c
index 673ccd1..3bdfa7d 100644
--- a/src/box/sql/vdbeapi.c
+++ b/src/box/sql/vdbeapi.c
@@ -536,15 +536,6 @@ sqlStep(Vdbe * p)
 		p->rc = SQL_NOMEM;
 	}
  end_of_step:
-	/* At this point local variable rc holds the value that should be
-	 * returned if this statement was compiled using the legacy
-	 * sql_prepare() interface. According to the docs, this can only
-	 * be one of the values in the first assert() below. Variable p->rc
-	 * contains the value that would be returned if sql_finalize()
-	 * were called on statement p.
-	 */
-	assert(rc == SQL_ROW || rc == SQL_DONE || rc == SQL_ERROR
-	       || (rc & 0xff) == SQL_BUSY || rc == SQL_MISUSE);
 	if (p->isPrepareV2 && rc != SQL_ROW && rc != SQL_DONE) {
 		/* If this statement was prepared using sql_prepare_v2(), and an
 		 * error has occurred, then return the error code in p->rc to the
@@ -564,20 +555,17 @@ int
 sql_step(sql_stmt * pStmt)
 {
 	int rc;			/* Result from sqlStep() */
-	int rc2 = SQL_OK;	/* Result from sqlReprepare() */
 	Vdbe *v = (Vdbe *) pStmt;	/* the prepared statement */
 	int cnt = 0;		/* Counter to prevent infinite loop of reprepares */
-	sql *db;		/* The database connection */
 
 	if (vdbeSafetyNotNull(v)) {
 		return SQL_MISUSE;
 	}
-	db = v->db;
 	v->doingRerun = 0;
 	while ((rc = sqlStep(v)) == SQL_SCHEMA
 	       && cnt++ < SQL_MAX_SCHEMA_RETRY) {
 		int savedPc = v->pc;
-		rc2 = rc = sqlReprepare(v);
+		rc = sqlReprepare(v);
 		if (rc != SQL_OK)
 			break;
 		sql_reset(pStmt);
@@ -585,26 +573,6 @@ sql_step(sql_stmt * pStmt)
 			v->doingRerun = 1;
 		assert(v->expired == 0);
 	}
-	if (rc2 != SQL_OK) {
-		/* This case occurs after failing to recompile an sql statement.
-		 * The error message from the SQL compiler has already been loaded
-		 * into the database handle. This block copies the error message
-		 * from the database handle into the statement and sets the statement
-		 * program counter to 0 to ensure that when the statement is
-		 * finalized or reset the parser error message is available via
-		 * sql_errmsg() and sql_errcode().
-		 */
-		const char *zErr = (const char *)sql_value_text(db->pErr);
-		sqlDbFree(db, v->zErrMsg);
-		if (!db->mallocFailed) {
-			v->zErrMsg = sqlDbStrDup(db, zErr);
-			v->rc = rc2;
-		} else {
-			v->zErrMsg = 0;
-			v->rc = rc = SQL_NOMEM;
-		}
-	}
-	rc = sqlApiExit(db, rc);
 	return rc;
 }
 
diff --git a/src/box/sql/vdbeaux.c b/src/box/sql/vdbeaux.c
index 619b211..3f573d0 100644
--- a/src/box/sql/vdbeaux.c
+++ b/src/box/sql/vdbeaux.c
@@ -116,19 +116,6 @@ sql_vdbe_prepare(struct Vdbe *vdbe)
 }
 
 /*
- * Change the error string stored in Vdbe.zErrMsg
- */
-void
-sqlVdbeError(Vdbe * p, const char *zFormat, ...)
-{
-	va_list ap;
-	sqlDbFree(p->db, p->zErrMsg);
-	va_start(ap, zFormat);
-	p->zErrMsg = sqlVMPrintf(p->db, zFormat, ap);
-	va_end(ap);
-}
-
-/*
  * Remember the SQL string for a prepared statement.
  */
 void
@@ -2115,10 +2102,11 @@ sqlVdbeCheckFk(Vdbe * p, int deferred)
 	if ((deferred && txn != NULL && txn->psql_txn != NULL &&
 	     txn->psql_txn->fk_deferred_count > 0) ||
 	    (!deferred && p->nFkConstraint > 0)) {
-		p->rc = SQL_CONSTRAINT_FOREIGNKEY;
+		p->rc = SQL_TARANTOOL_ERROR;
 		p->errorAction = ON_CONFLICT_ACTION_ABORT;
-		sqlVdbeError(p, "FOREIGN KEY constraint failed");
-		return SQL_ERROR;
+		diag_set(ClientError, ER_SQL_EXECUTE, "FOREIGN KEY constraint "\
+			 "failed");
+		return SQL_TARANTOOL_ERROR;
 	}
 	return SQL_OK;
 }
diff --git a/src/box/sql/vdbemem.c b/src/box/sql/vdbemem.c
index 312c661..ea6afa6 100644
--- a/src/box/sql/vdbemem.c
+++ b/src/box/sql/vdbemem.c
@@ -210,7 +210,6 @@ sqlVdbeMemMakeWriteable(Mem * pMem)
  * If the given Mem* has a zero-filled tail, turn it into an ordinary
  * blob stored in dynamically allocated space.
  */
-#ifndef SQL_OMIT_INCRBLOB
 int
 sqlVdbeMemExpandBlob(Mem * pMem)
 {
@@ -232,7 +231,6 @@ sqlVdbeMemExpandBlob(Mem * pMem)
 	pMem->flags &= ~(MEM_Zero | MEM_Term);
 	return SQL_OK;
 }
-#endif
 
 /*
  * It is already known that pMem contains an unterminated string.
@@ -315,8 +313,7 @@ sqlVdbeMemStringify(Mem * pMem, u8 bForce)
  * This routine calls the finalize method for that function.  The
  * result of the aggregate is stored back into pMem.
  *
- * Return SQL_ERROR if the finalizer reports an error.  SQL_OK
- * otherwise.
+ * Return -1 if the finalizer reports an error. 0 otherwise.
  */
 int
 sqlVdbeMemFinalize(Mem * pMem, FuncDef * pFunc)
@@ -337,9 +334,10 @@ sqlVdbeMemFinalize(Mem * pMem, FuncDef * pFunc)
 		if (pMem->szMalloc > 0)
 			sqlDbFree(pMem->db, pMem->zMalloc);
 		memcpy(pMem, &t, sizeof(t));
-		return ctx.is_aborted ? SQL_TARANTOOL_ERROR : SQL_OK;
+		if (ctx.is_aborted)
+			return -1;
 	}
-	return SQL_OK;
+	return 0;
 }
 
 /*
diff --git a/test/sql-tap/gh-2931-savepoints.test.lua b/test/sql-tap/gh-2931-savepoints.test.lua
index 6123fc4..be499b6 100755
--- a/test/sql-tap/gh-2931-savepoints.test.lua
+++ b/test/sql-tap/gh-2931-savepoints.test.lua
@@ -39,7 +39,7 @@ local testcases = {
 		{0,{1,1}}},
 	{"5",
 		[[rollback to savepoint s1_2;]],
-		{1, "Failed to execute SQL statement: no such savepoint: S1_2"}},
+		{1, "Can not rollback to savepoint: the savepoint does not exist"}},
 	{"6",
 		[[insert into t1 values(2);
 		select * from t1 union all select * from t2;]],
diff --git a/test/sql/savepoints.result b/test/sql/savepoints.result
index bb4a296..d20e0ed 100644
--- a/test/sql/savepoints.result
+++ b/test/sql/savepoints.result
@@ -67,7 +67,7 @@ end;
 ...
 release_sv_fail();
 ---
-- error: 'Failed to execute SQL statement: no such savepoint: T1'
+- error: 'Can not rollback to savepoint: the savepoint does not exist'
 ...
 box.commit();
 ---
 

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [tarantool-patches] Re: [PATCH v1 4/9] sql: rework diag_set() in OP_Halt
  2019-06-03  8:41     ` Imeev Mergen
@ 2019-06-04 19:34       ` Vladislav Shpilevoy
  2019-06-08 12:11         ` Mergen Imeev
  0 siblings, 1 reply; 25+ messages in thread
From: Vladislav Shpilevoy @ 2019-06-04 19:34 UTC (permalink / raw)
  To: tarantool-patches, Imeev Mergen



On 03/06/2019 11:41, Imeev Mergen wrote:
> Hi! Thank you for the review! My answers below. Also, I think I'm
> going to drop this patch, since I plan to move the error code from
> p5 to p2 in the next patch.
> 
> On 6/2/19 7:35 PM, Vladislav Shpilevoy wrote:
>>
>> On 28/05/2019 14:39, imeevma@tarantool.org wrote:
>>> Prior to this patch, the way to set Tarantool error in OP_Halt was
>>> too universal. It was possible to set a description of the error
>>> that does not match its errcode.
>> There was a concrete reason, why it was possible - because different
>> error codes have different arguments of various types, and the only way
>> to set an error at parsing stage is to allow to set arbitrary error
>> message to any error code. Without '...', va_arg etc. Besides, we could
>> use it to set correct line number and function name in future. Now you
>> use diag_set, which restricts us.
>>
>> So why do you need that patch? We will need to revert it when an error
>> appears requiring more than one argument, or an argument of not
>> const char * type. That will definitely happen.
> For some reason, manually creating an error message looks a bit
> wrong to me. How about creating a new macro to create such
> messages, for example, diag_prepare(), which takes the same
> arguments as diag_set() and returns the complete error message?

Perhaps. Sounds good to me. You can do it, if you want. But I
would suggest name "diag_prepare_msg", because it won't create a
struct error object. Only create a message.

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [tarantool-patches] Re: [PATCH v1 5/9] sql: make SQL_TARANTOOL_ERROR the only errcode of OP_Halt
  2019-06-03 11:53     ` Mergen Imeev
@ 2019-06-04 19:34       ` Vladislav Shpilevoy
  2019-06-08 12:15         ` Mergen Imeev
  0 siblings, 1 reply; 25+ messages in thread
From: Vladislav Shpilevoy @ 2019-06-04 19:34 UTC (permalink / raw)
  To: Mergen Imeev; +Cc: tarantool-patches

Hi! Thanks for the fixes!

I noticed, that in many places you copy-pasted ER_SQL_EXECUTE
error message. It should not be so. Consider my fixes below and
on the branch:

==============================================================================

commit b7b929b7cfd3f45a26be797bfbe1cdc7e7379edc
Author: Vladislav Shpilevoy <v.shpilevoy@tarantool.org>
Date:   Tue Jun 4 21:20:22 2019 +0200

    Review fixes

diff --git a/src/box/sql/expr.c b/src/box/sql/expr.c
index 4fbc8f53f..652e5a273 100644
--- a/src/box/sql/expr.c
+++ b/src/box/sql/expr.c
@@ -4386,9 +4386,9 @@ sqlExprCodeTarget(Parse * pParse, Expr * pExpr, int target)
 					  ON_CONFLICT_ACTION_IGNORE, 0,
 					  pExpr->u.zToken, 0);
 		} else {
-			const char *err = tt_sprintf("Failed to execute SQL "\
-						     "statement: %s",
-						     pExpr->u.zToken);
+			const char *err =
+				tt_sprintf(tnt_errcode_desc(ER_SQL_EXECUTE),
+					   pExpr->u.zToken);
 			sqlVdbeAddOp4(v, OP_Halt, SQL_TARANTOOL_ERROR,
 				      pExpr->on_conflict_action, ER_SQL_EXECUTE,
 				      err, 0);
diff --git a/src/box/sql/fk_constraint.c b/src/box/sql/fk_constraint.c
index 5256bec82..660674122 100644
--- a/src/box/sql/fk_constraint.c
+++ b/src/box/sql/fk_constraint.c
@@ -287,8 +287,8 @@ fk_constraint_lookup_parent(struct Parse *parse_context, struct space *parent,
 		 * transaction.
 		 */
 		assert(incr_count == 1);
-		const char *err = "Failed to execute SQL statement: FOREIGN "\
-				  "KEY constraint failed";
+		const char *err = tt_sprintf(tnt_errcode_desc(ER_SQL_EXECUTE),
+					     "FOREIGN KEY constraint failed");
 		sqlVdbeAddOp4(v, OP_Halt, SQL_TARANTOOL_ERROR, 0,
 			      ER_SQL_EXECUTE, err, P4_STATIC);
 	} else {
diff --git a/src/box/sql/insert.c b/src/box/sql/insert.c
index 286a72134..4e93a83e3 100644
--- a/src/box/sql/insert.c
+++ b/src/box/sql/insert.c
@@ -856,6 +856,7 @@ vdbe_emit_constraint_checks(struct Parse *parse_context, struct space *space,
 	bool is_update = upd_cols != NULL;
 	assert(space != NULL);
 	struct space_def *def = space->def;
+	const char *err;
 	/* Insertion into VIEW is prohibited. */
 	assert(!def->opts.is_view);
 	uint32_t autoinc_fieldno = sql_space_autoinc_fieldno(space);
@@ -880,15 +881,15 @@ vdbe_emit_constraint_checks(struct Parse *parse_context, struct space *space,
 		if (on_conflict_nullable == ON_CONFLICT_ACTION_REPLACE &&
 		    dflt == NULL)
 			on_conflict_nullable = ON_CONFLICT_ACTION_ABORT;
-		const char *err;
 		int addr;
 		switch (on_conflict_nullable) {
 		case ON_CONFLICT_ACTION_ABORT:
 		case ON_CONFLICT_ACTION_ROLLBACK:
 		case ON_CONFLICT_ACTION_FAIL:
-			err = tt_sprintf("Failed to execute SQL statement: "\
-					 "NOT NULL constraint failed: %s.%s",
-					 def->name, def->fields[i].name);
+			err = tt_sprintf(tnt_errcode_desc(ER_SQL_EXECUTE),
+					 tt_sprintf("NOT NULL constraint "\
+						    "failed: %s.%s", def->name,
+						    def->fields[i].name));
 			addr = sqlVdbeAddOp1(v, OP_NotNull, new_tuple_reg + i);
 			sqlVdbeAddOp4(v, OP_Halt, SQL_TARANTOOL_ERROR,
 				      on_conflict_nullable, ER_SQL_EXECUTE,
@@ -936,11 +937,10 @@ vdbe_emit_constraint_checks(struct Parse *parse_context, struct space *space,
 				char *name = checks->a[i].zName;
 				if (name == NULL)
 					name = def->name;
-				const char *err =
-					tt_sprintf("Failed to execute SQL "\
-						   "statement: CHECK "\
-						   "constraint failed: %s",
-						   name);
+				err = tnt_errcode_desc(ER_SQL_EXECUTE);
+				err = tt_sprintf(err, tt_sprintf("CHECK "\
+						 "constraint failed: %s",
+						 name));
 				sqlVdbeAddOp4(v, OP_Halt, SQL_TARANTOOL_ERROR,
 					      on_conflict_check, ER_SQL_EXECUTE,
 					      err, P4_STATIC);
diff --git a/src/box/sql/select.c b/src/box/sql/select.c
index 4fc59d8b9..9a01c438c 100644
--- a/src/box/sql/select.c
+++ b/src/box/sql/select.c
@@ -2107,12 +2107,12 @@ computeLimitRegisters(Parse * pParse, Select * p, int iBreak)
 		sqlVdbeAddOp2(v, OP_Integer, 0, r1);
 		sqlVdbeAddOp3(v, OP_Ge, r1, positive_limit_label, iLimit);
 		/* Otherwise return an error and stop */
-		const char *wrong_limit_error =
-			"Failed to execute SQL statement: Only positive "\
-			"integers are allowed in the LIMIT clause";
+		const char *err = tt_sprintf(tnt_errcode_desc(ER_SQL_EXECUTE),
+					     "Only positive integers are "\
+					     "allowed in the LIMIT clause");
 		sqlVdbeResolveLabel(v, halt_label);
 		sqlVdbeAddOp4(v, OP_Halt, SQL_TARANTOOL_ERROR, 0,
-			      ER_SQL_EXECUTE, wrong_limit_error, P4_STATIC);
+			      ER_SQL_EXECUTE, err, P4_STATIC);
 
 		sqlVdbeResolveLabel(v, positive_limit_label);
 		VdbeCoverage(v);
@@ -2139,12 +2139,12 @@ computeLimitRegisters(Parse * pParse, Select * p, int iBreak)
 				sqlVdbeAddOp2(v, OP_Integer, 1, r1);
 				int no_err = sqlVdbeMakeLabel(v);
 				sqlVdbeAddOp3(v, OP_Eq, iLimit, no_err, r1);
-				const char *error =
-					"Failed to execute SQL statement: "\
-					"Expression subquery could be limited "\
-					"only with 1";
+				err = tnt_errcode_desc(ER_SQL_EXECUTE);
+				err = tt_sprintf(err, "Expression subquery "\
+						 "could be limited only "\
+						 "with 1");
 				sqlVdbeAddOp4(v, OP_Halt, SQL_TARANTOOL_ERROR,
-					      0, ER_SQL_EXECUTE, error,
+					      0, ER_SQL_EXECUTE, err,
 					      P4_STATIC);
 				sqlVdbeResolveLabel(v, no_err);
 				sqlReleaseTempReg(pParse, r1);
@@ -2166,14 +2166,12 @@ computeLimitRegisters(Parse * pParse, Select * p, int iBreak)
 
             		sqlVdbeAddOp3(v, OP_Ge, r1, positive_offset_label, iOffset);
 			/* Otherwise return an error and stop */
-			const char *wrong_offset_error =
-				"Failed to execute SQL statement: Only "\
-				"positive integers are allowed in the OFFSET "\
-				"clause";
+			err = tt_sprintf(tnt_errcode_desc(ER_SQL_EXECUTE),
+					 "Only positive integers are allowed "\
+					 "in the OFFSET clause");
 			sqlVdbeResolveLabel(v, offset_error_label);
 			sqlVdbeAddOp4(v, OP_Halt, SQL_TARANTOOL_ERROR, 0,
-				      ER_SQL_EXECUTE, wrong_offset_error,
-				      P4_STATIC);
+				      ER_SQL_EXECUTE, err, P4_STATIC);
 
 			sqlVdbeResolveLabel(v, positive_offset_label);
             		sqlReleaseTempReg(pParse, r1);
@@ -5442,9 +5440,9 @@ vdbe_code_raise_on_multiple_rows(struct Parse *parser, int limit_reg, int end_ma
 	int r1 = sqlGetTempReg(parser);
 	sqlVdbeAddOp2(v, OP_Integer, 0, r1);
 	sqlVdbeAddOp3(v, OP_Ne, r1, end_mark, limit_reg);
-	const char *error =
-		"Failed to execute SQL statement: Expression subquery "\
-		"returned more than 1 row";
+	const char *error = tt_sprintf(tnt_errcode_desc(ER_SQL_EXECUTE),
+				       "Expression subquery returned more "\
+				       "than 1 row");
 	sqlVdbeAddOp4(v, OP_Halt, SQL_TARANTOOL_ERROR, 0, ER_SQL_EXECUTE, error,
 		      P4_STATIC);
 	sqlReleaseTempReg(parser, r1);

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [tarantool-patches] Re: [PATCH v1 4/9] sql: rework diag_set() in OP_Halt
  2019-06-04 19:34       ` Vladislav Shpilevoy
@ 2019-06-08 12:11         ` Mergen Imeev
  0 siblings, 0 replies; 25+ messages in thread
From: Mergen Imeev @ 2019-06-08 12:11 UTC (permalink / raw)
  To: Vladislav Shpilevoy; +Cc: tarantool-patches

Thank you for review! My answer below.

On Tue, Jun 04, 2019 at 09:34:45PM +0200, Vladislav Shpilevoy wrote:
> 
> 
> On 03/06/2019 11:41, Imeev Mergen wrote:
> > Hi! Thank you for the review! My answers below. Also, I think I'm
> > going to drop this patch, since I plan to move the error code from
> > p5 to p2 in the next patch.
> > 
> > On 6/2/19 7:35 PM, Vladislav Shpilevoy wrote:
> >>
> >> On 28/05/2019 14:39, imeevma@tarantool.org wrote:
> >>> Prior to this patch, the way to set Tarantool error in OP_Halt was
> >>> too universal. It was possible to set a description of the error
> >>> that does not match its errcode.
> >> There was a concrete reason, why it was possible - because different
> >> error codes have different arguments of various types, and the only way
> >> to set an error at parsing stage is to allow to set arbitrary error
> >> message to any error code. Without '...', va_arg etc. Besides, we could
> >> use it to set correct line number and function name in future. Now you
> >> use diag_set, which restricts us.
> >>
> >> So why do you need that patch? We will need to revert it when an error
> >> appears requiring more than one argument, or an argument of not
> >> const char * type. That will definitely happen.
> > For some reason, manually creating an error message looks a bit
> > wrong to me. How about creating a new macro to create such
> > messages, for example, diag_prepare(), which takes the same
> > arguments as diag_set() and returns the complete error message?
> 
> Perhaps. Sounds good to me. You can do it, if you want. But I
> would suggest name "diag_prepare_msg", because it won't create a
> struct error object. Only create a message.
>
Thanks. I'm going to do this as an follow-up patch to the
current patch-set.

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [tarantool-patches] Re: [PATCH v1 5/9] sql: make SQL_TARANTOOL_ERROR the only errcode of OP_Halt
  2019-06-04 19:34       ` Vladislav Shpilevoy
@ 2019-06-08 12:15         ` Mergen Imeev
  0 siblings, 0 replies; 25+ messages in thread
From: Mergen Imeev @ 2019-06-08 12:15 UTC (permalink / raw)
  To: Vladislav Shpilevoy; +Cc: tarantool-patches

On Tue, Jun 04, 2019 at 09:34:52PM +0200, Vladislav Shpilevoy wrote:
> Hi! Thanks for the fixes!
> 
> I noticed, that in many places you copy-pasted ER_SQL_EXECUTE
> error message. It should not be so. Consider my fixes below and
> on the branch:
> 
Thank you! I squashed this commit.

New patch:

From 86a6577357b8597ce9d4162bbdac5841cf65aef3 Mon Sep 17 00:00:00 2001
Date: Fri, 12 Apr 2019 14:16:18 +0300
Subject: [PATCH] sql: make SQL_TARANTOOL_ERROR the only errcode of OP_Halt

Currently, in OP_Halt, you can get a SQL error other than
SQL_TARANTOOL_ERROR, for example, the SQL_CONSTRAINT error. After
this patch, all errors going through OP_Halt will have SQL error
code SQL_TARANTOOL_ERROR and have diag set.

Part of #4074

diff --git a/src/box/sql/build.c b/src/box/sql/build.c
index cf958fd..b6cec65 100644
--- a/src/box/sql/build.c
+++ b/src/box/sql/build.c
@@ -3178,26 +3178,6 @@ sql_set_multi_write(struct Parse *parse_context, bool is_set)
 	pToplevel->isMultiWrite |= is_set;
 }
 
-/*
- * Code an OP_Halt that causes the vdbe to return an SQL_CONSTRAINT
- * error. The onError parameter determines which (if any) of the statement
- * and/or current transaction is rolled back.
- */
-void
-sqlHaltConstraint(Parse * pParse,	/* Parsing context */
-		      int errCode,	/* extended error code */
-		      int onError,	/* Constraint type */
-		      char *p4,	/* Error message */
-		      i8 p4type,	/* P4_STATIC or P4_TRANSIENT */
-		      u8 p5Errmsg	/* P5_ErrMsg type */
-    )
-{
-	Vdbe *v = sqlGetVdbe(pParse);
-	assert((errCode & 0xff) == SQL_CONSTRAINT);
-	sqlVdbeAddOp4(v, OP_Halt, errCode, onError, 0, p4, p4type);
-	sqlVdbeChangeP5(v, p5Errmsg);
-}
-
 #ifndef SQL_OMIT_CTE
 /*
  * This routine is invoked once per CTE by the parser while parsing a
@@ -3306,9 +3286,8 @@ vdbe_emit_halt_with_presence_test(struct Parse *parser, int space_id,
 	if (no_error) {
 		sqlVdbeAddOp0(v, OP_Halt);
 	} else {
-		sqlVdbeAddOp4(v, OP_Halt, SQL_TARANTOOL_ERROR,0, 0, error,
-				  P4_DYNAMIC);
-		sqlVdbeChangeP5(v, tarantool_error_code);
+		sqlVdbeAddOp4(v, OP_Halt, SQL_TARANTOOL_ERROR, 0,
+			      tarantool_error_code, error, P4_DYNAMIC);
 	}
 	sqlVdbeAddOp1(v, OP_Close, cursor);
 	return 0;
diff --git a/src/box/sql/expr.c b/src/box/sql/expr.c
index e662448..694edea 100644
--- a/src/box/sql/expr.c
+++ b/src/box/sql/expr.c
@@ -4391,9 +4391,12 @@ sqlExprCodeTarget(Parse * pParse, Expr * pExpr, int target)
 					  ON_CONFLICT_ACTION_IGNORE, 0,
 					  pExpr->u.zToken, 0);
 		} else {
-			sqlHaltConstraint(pParse, SQL_CONSTRAINT_TRIGGER,
-					      pExpr->on_conflict_action,
-					      pExpr->u.zToken, 0, 0);
+			const char *err =
+				tt_sprintf(tnt_errcode_desc(ER_SQL_EXECUTE),
+					   pExpr->u.zToken);
+			sqlVdbeAddOp4(v, OP_Halt, SQL_TARANTOOL_ERROR,
+				      pExpr->on_conflict_action, ER_SQL_EXECUTE,
+				      err, 0);
 		}
 		break;
 	}
diff --git a/src/box/sql/fk_constraint.c b/src/box/sql/fk_constraint.c
index 04c694a..08e7f62 100644
--- a/src/box/sql/fk_constraint.c
+++ b/src/box/sql/fk_constraint.c
@@ -285,10 +285,10 @@ fk_constraint_lookup_parent(struct Parse *parse_context, struct space *parent,
 		 * transaction.
 		 */
 		assert(incr_count == 1);
-		sqlHaltConstraint(parse_context,
-				      SQL_CONSTRAINT_FOREIGNKEY,
-				      ON_CONFLICT_ACTION_ABORT, 0, P4_STATIC,
-				      P5_ConstraintFK);
+		const char *err = tt_sprintf(tnt_errcode_desc(ER_SQL_EXECUTE),
+					     "FOREIGN KEY constraint failed");
+		sqlVdbeAddOp4(v, OP_Halt, SQL_TARANTOOL_ERROR, 0,
+			      ER_SQL_EXECUTE, err, P4_STATIC);
 	} else {
 		sqlVdbeAddOp2(v, OP_FkCounter, fk_def->is_deferred,
 				  incr_count);
diff --git a/src/box/sql/insert.c b/src/box/sql/insert.c
index 084bec7..f096629 100644
--- a/src/box/sql/insert.c
+++ b/src/box/sql/insert.c
@@ -825,12 +825,12 @@ vdbe_emit_constraint_checks(struct Parse *parse_context, struct space *space,
 			    enum on_conflict_action on_conflict,
 			    int ignore_label, int *upd_cols)
 {
-	struct sql *db = parse_context->db;
 	struct Vdbe *v = sqlGetVdbe(parse_context);
 	assert(v != NULL);
 	bool is_update = upd_cols != NULL;
 	assert(space != NULL);
 	struct space_def *def = space->def;
+	const char *err;
 	/* Insertion into VIEW is prohibited. */
 	assert(!def->opts.is_view);
 	uint32_t autoinc_fieldno = sql_space_autoinc_fieldno(space);
@@ -855,20 +855,20 @@ vdbe_emit_constraint_checks(struct Parse *parse_context, struct space *space,
 		if (on_conflict_nullable == ON_CONFLICT_ACTION_REPLACE &&
 		    dflt == NULL)
 			on_conflict_nullable = ON_CONFLICT_ACTION_ABORT;
-		char *err_msg;
 		int addr;
 		switch (on_conflict_nullable) {
 		case ON_CONFLICT_ACTION_ABORT:
 		case ON_CONFLICT_ACTION_ROLLBACK:
 		case ON_CONFLICT_ACTION_FAIL:
-			err_msg = sqlMPrintf(db, "%s.%s", def->name,
-						 def->fields[i].name);
-			sqlVdbeAddOp3(v, OP_HaltIfNull,
-					  SQL_CONSTRAINT_NOTNULL,
-					  on_conflict_nullable,
-					  new_tuple_reg + i);
-			sqlVdbeAppendP4(v, err_msg, P4_DYNAMIC);
-			sqlVdbeChangeP5(v, P5_ConstraintNotNull);
+			err = tt_sprintf(tnt_errcode_desc(ER_SQL_EXECUTE),
+					 tt_sprintf("NOT NULL constraint "\
+						    "failed: %s.%s", def->name,
+						    def->fields[i].name));
+			addr = sqlVdbeAddOp1(v, OP_NotNull, new_tuple_reg + i);
+			sqlVdbeAddOp4(v, OP_Halt, SQL_TARANTOOL_ERROR,
+				      on_conflict_nullable, ER_SQL_EXECUTE,
+				      err, P4_STATIC);
+			sqlVdbeJumpHere(v, addr);
 			break;
 		case ON_CONFLICT_ACTION_IGNORE:
 			sqlVdbeAddOp2(v, OP_IsNull, new_tuple_reg + i,
diff --git a/src/box/sql/select.c b/src/box/sql/select.c
index 22aa628..b675293 100644
--- a/src/box/sql/select.c
+++ b/src/box/sql/select.c
@@ -2102,15 +2102,12 @@ computeLimitRegisters(Parse * pParse, Select * p, int iBreak)
 		sqlVdbeAddOp2(v, OP_Integer, 0, r1);
 		sqlVdbeAddOp3(v, OP_Ge, r1, positive_limit_label, iLimit);
 		/* Otherwise return an error and stop */
-		const char *wrong_limit_error =
-			"Only positive integers are allowed "
-			"in the LIMIT clause";
+		const char *err = tt_sprintf(tnt_errcode_desc(ER_SQL_EXECUTE),
+					     "Only positive integers are "\
+					     "allowed in the LIMIT clause");
 		sqlVdbeResolveLabel(v, halt_label);
-		sqlVdbeAddOp4(v, OP_Halt,
-				  SQL_TARANTOOL_ERROR,
-				  0, 0,
-				  wrong_limit_error,
-				  P4_STATIC);
+		sqlVdbeAddOp4(v, OP_Halt, SQL_TARANTOOL_ERROR, 0,
+			      ER_SQL_EXECUTE, err, P4_STATIC);
 
 		sqlVdbeResolveLabel(v, positive_limit_label);
 		VdbeCoverage(v);
@@ -2137,13 +2134,13 @@ computeLimitRegisters(Parse * pParse, Select * p, int iBreak)
 				sqlVdbeAddOp2(v, OP_Integer, 1, r1);
 				int no_err = sqlVdbeMakeLabel(v);
 				sqlVdbeAddOp3(v, OP_Eq, iLimit, no_err, r1);
-				const char *error =
-					"SQL error: Expression subquery could "
-					"be limited only with 1";
-				sqlVdbeAddOp4(v, OP_Halt,
-						  SQL_TARANTOOL_ERROR,
-						  0, 0, error, P4_STATIC);
-				sqlVdbeChangeP5(v, ER_SQL_EXECUTE);
+				err = tnt_errcode_desc(ER_SQL_EXECUTE);
+				err = tt_sprintf(err, "Expression subquery "\
+						 "could be limited only "\
+						 "with 1");
+				sqlVdbeAddOp4(v, OP_Halt, SQL_TARANTOOL_ERROR,
+					      0, ER_SQL_EXECUTE, err,
+					      P4_STATIC);
 				sqlVdbeResolveLabel(v, no_err);
 				sqlReleaseTempReg(pParse, r1);
 
@@ -2164,15 +2161,12 @@ computeLimitRegisters(Parse * pParse, Select * p, int iBreak)
 
             		sqlVdbeAddOp3(v, OP_Ge, r1, positive_offset_label, iOffset);
 			/* Otherwise return an error and stop */
-			const char *wrong_offset_error =
-				"Only positive integers are allowed "
-				"in the OFFSET clause";
+			err = tt_sprintf(tnt_errcode_desc(ER_SQL_EXECUTE),
+					 "Only positive integers are allowed "\
+					 "in the OFFSET clause");
 			sqlVdbeResolveLabel(v, offset_error_label);
-			sqlVdbeAddOp4(v, OP_Halt,
-					  SQL_TARANTOOL_ERROR,
-					  0, 0,
-					  wrong_offset_error,
-					  P4_STATIC);
+			sqlVdbeAddOp4(v, OP_Halt, SQL_TARANTOOL_ERROR, 0,
+				      ER_SQL_EXECUTE, err, P4_STATIC);
 
 			sqlVdbeResolveLabel(v, positive_offset_label);
             		sqlReleaseTempReg(pParse, r1);
@@ -5440,11 +5434,11 @@ vdbe_code_raise_on_multiple_rows(struct Parse *parser, int limit_reg, int end_ma
 	int r1 = sqlGetTempReg(parser);
 	sqlVdbeAddOp2(v, OP_Integer, 0, r1);
 	sqlVdbeAddOp3(v, OP_Ne, r1, end_mark, limit_reg);
-	const char *error =
-		"SQL error: Expression subquery returned more than 1 row";
-	sqlVdbeAddOp4(v, OP_Halt, SQL_TARANTOOL_ERROR, 0, 0, error,
-			  P4_STATIC);
-	sqlVdbeChangeP5(v, ER_SQL_EXECUTE);
+	const char *error = tt_sprintf(tnt_errcode_desc(ER_SQL_EXECUTE),
+				       "Expression subquery returned more "\
+				       "than 1 row");
+	sqlVdbeAddOp4(v, OP_Halt, SQL_TARANTOOL_ERROR, 0, ER_SQL_EXECUTE, error,
+		      P4_STATIC);
 	sqlReleaseTempReg(parser, r1);
 }
 
diff --git a/src/box/sql/sqlInt.h b/src/box/sql/sqlInt.h
index a6e4552..30b1d84 100644
--- a/src/box/sql/sqlInt.h
+++ b/src/box/sql/sqlInt.h
@@ -3952,7 +3952,6 @@ vdbe_emit_insertion_completion(struct Vdbe *v, struct space *space,
 
 void
 sql_set_multi_write(Parse *, bool);
-void sqlHaltConstraint(Parse *, int, int, char *, i8, u8);
 
 Expr *sqlExprDup(sql *, Expr *, int);
 SrcList *sqlSrcListDup(sql *, SrcList *, int);
diff --git a/src/box/sql/vdbe.c b/src/box/sql/vdbe.c
index 67ab42f..8ab9fcf 100644
--- a/src/box/sql/vdbe.c
+++ b/src/box/sql/vdbe.c
@@ -1062,29 +1062,14 @@ case OP_Yield: {            /* in1, jump */
 	break;
 }
 
-/* Opcode:  HaltIfNull  P1 P2 P3 P4 P5
- * Synopsis: if r[P3]=null halt
- *
- * Check the value in register P3.  If it is NULL then Halt using
- * parameter P1, P2, and P4 as if this were a Halt instruction.  If the
- * value in register P3 is not NULL, then this routine is a no-op.
- * The P5 parameter should be 1.
- */
-case OP_HaltIfNull: {      /* in3 */
-	pIn3 = &aMem[pOp->p3];
-	if ((pIn3->flags & MEM_Null)==0) break;
-	/* Fall through into OP_Halt */
-	FALLTHROUGH;
-}
-
-/* Opcode:  Halt P1 P2 * P4 P5
+/* Opcode:  Halt P1 P2 P3 P4 *
  *
  * Exit immediately.  All open cursors, etc are closed
  * automatically.
  *
  * P1 is the result code returned by sql_exec(),
  * sql_reset(), or sql_finalize().  For a normal halt,
- * this should be SQL_OK (0).
+ * this should be 0.
  * For errors, it can be some other value.  If P1!=0 then P2 will
  * determine whether or not to rollback the current transaction.
  * Do not rollback if P2==ON_CONFLICT_ACTION_FAIL. Do the rollback
@@ -1095,18 +1080,8 @@ case OP_HaltIfNull: {      /* in3 */
  *
  * If P4 is not null then it is an error message string.
  *
- * If P1 is SQL_TARANTOOL_ERROR then P5 is a ClientError code and
- * P4 is error message to set. Else P5 is a value between 0 and 4,
- * inclusive, that modifies the P4 string.
- *
- *    0:  (no change)
- *    1:  NOT NULL contraint failed: P4
- *    2:  UNIQUE constraint failed: P4
- *    3:  CHECK constraint failed: P4
- *    4:  FOREIGN KEY constraint failed: P4
- *
- * If P5 is not zero and  P4 is  NULL, then everything after the
- * ":" is omitted.
+ * If P1 is SQL_TARANTOOL_ERROR then P3 is a ClientError code and
+ * P4 is error message to set.
  *
  * There is an implied "Halt 0 0 0" instruction inserted at the
  * very end of every program.  So a jump past the last instruction
@@ -1143,28 +1118,10 @@ case OP_Halt: {
 	p->errorAction = (u8)pOp->p2;
 	p->pc = pcx;
 	if (p->rc) {
-		if (p->rc == SQL_TARANTOOL_ERROR) {
-			if (pOp->p4.z == NULL) {
-				assert(! diag_is_empty(diag_get()));
-			} else {
-				box_error_set(__FILE__, __LINE__, pOp->p5,
-					      pOp->p4.z);
-			}
-		} else if (pOp->p5 != 0) {
-			static const char * const azType[] = { "NOT NULL", "UNIQUE", "CHECK",
-							       "FOREIGN KEY" };
-			testcase( pOp->p5==1);
-			testcase( pOp->p5==2);
-			testcase( pOp->p5==3);
-			testcase( pOp->p5==4);
-			sqlVdbeError(p, "%s constraint failed", azType[pOp->p5-1]);
-			if (pOp->p4.z) {
-				p->zErrMsg = sqlMPrintf(db, "%z: %s", p->zErrMsg, pOp->p4.z);
-			}
-		} else {
-			sqlVdbeError(p, "%s", pOp->p4.z);
-		}
-		sql_log(pOp->p1, "abort at %d in [%s]: %s", pcx, p->zSql, p->zErrMsg);
+		assert(p->rc == SQL_TARANTOOL_ERROR);
+		if (pOp->p4.z != NULL)
+			box_error_set(__FILE__, __LINE__, pOp->p3, pOp->p4.z);
+		assert(! diag_is_empty(diag_get()));
 	}
 	rc = sqlVdbeHalt(p);
 	assert(rc==SQL_BUSY || rc==SQL_OK || rc==SQL_ERROR);
diff --git a/test/sql-tap/e_select1.test.lua b/test/sql-tap/e_select1.test.lua
index 6f17471..9968038 100755
--- a/test/sql-tap/e_select1.test.lua
+++ b/test/sql-tap/e_select1.test.lua
@@ -2170,7 +2170,7 @@ for _, val in ipairs({
         "e_select-9.2."..tn,
         select,
         {
-            1, "Only positive integers are allowed in the LIMIT clause"})
+            1, "Failed to execute SQL statement: Only positive integers are allowed in the LIMIT clause"})
 end
 
 -- EVIDENCE-OF: R-03014-26414 If the LIMIT expression evaluates to a
@@ -2224,7 +2224,7 @@ for _, val in ipairs({
     test:do_catchsql_test(
         "e_select-9.7."..tn,
         select, {
-            1, "Only positive integers are allowed in the OFFSET clause"
+            1, "Failed to execute SQL statement: Only positive integers are allowed in the OFFSET clause"
         })
 
 end
diff --git a/test/sql-tap/limit.test.lua b/test/sql-tap/limit.test.lua
index 9b728d8..40b787b 100755
--- a/test/sql-tap/limit.test.lua
+++ b/test/sql-tap/limit.test.lua
@@ -84,7 +84,7 @@ test:do_catchsql_test(
         SELECT x FROM t1 ORDER BY x+1 LIMIT 5 OFFSET -2
     ]], {
         -- <limit-1.2.13>
-        1 ,"Only positive integers are allowed in the OFFSET clause"
+        1 ,"Failed to execute SQL statement: Only positive integers are allowed in the OFFSET clause"
         -- </limit-1.2.13>
     })
 
@@ -94,7 +94,7 @@ test:do_catchsql_test(
         SELECT x FROM t1 ORDER BY x+1 LIMIT 2, -5
     ]], {
         -- <limit-1.2.4>
-        1, "Only positive integers are allowed in the LIMIT clause"
+        1, "Failed to execute SQL statement: Only positive integers are allowed in the LIMIT clause"
         -- </limit-1.2.4>
     })
 
@@ -115,7 +115,7 @@ test:do_catchsql_test(
         SELECT x FROM t1 ORDER BY x+1 LIMIT -2, 5
     ]], {
         -- <limit-1.2.6>
-        1, "Only positive integers are allowed in the OFFSET clause"
+        1, "Failed to execute SQL statement: Only positive integers are allowed in the OFFSET clause"
         -- </limit-1.2.6>
     })
 
@@ -135,7 +135,7 @@ test:do_catchsql_test(
         SELECT x FROM t1 ORDER BY x+1 LIMIT -2, -5
     ]], {
         -- <limit-1.2.8>
-        1, "Only positive integers are allowed in the LIMIT clause"
+        1, "Failed to execute SQL statement: Only positive integers are allowed in the LIMIT clause"
         -- </limit-1.2.8>
     })
 
@@ -384,7 +384,7 @@ test:do_catchsql_test(
         SELECT * FROM t6 LIMIT -1 OFFSET -1;
     ]], {
         -- <limit-6.2>
-        1, "Only positive integers are allowed in the LIMIT clause"
+        1, "Failed to execute SQL statement: Only positive integers are allowed in the LIMIT clause"
         -- </limit-6.2>
     })
 
@@ -394,7 +394,7 @@ test:do_catchsql_test(
         SELECT * FROM t6 LIMIT 2 OFFSET -123;
     ]], {
         -- <limit-6.3>
-        1, "Only positive integers are allowed in the OFFSET clause"
+        1, "Failed to execute SQL statement: Only positive integers are allowed in the OFFSET clause"
         -- </limit-6.3>
     })
 
@@ -414,7 +414,7 @@ test:do_catchsql_test(
         SELECT * FROM t6 LIMIT -432 OFFSET 2;
     ]], {
         -- <limit-6.4>
-        1, "Only positive integers are allowed in the LIMIT clause"
+        1, "Failed to execute SQL statement: Only positive integers are allowed in the LIMIT clause"
         -- </limit-6.4>
     })
 
@@ -434,7 +434,7 @@ test:do_catchsql_test(
         SELECT * FROM t6 LIMIT -1
     ]], {
         -- <limit-6.5>
-        1, "Only positive integers are allowed in the LIMIT clause"
+        1, "Failed to execute SQL statement: Only positive integers are allowed in the LIMIT clause"
         -- </limit-6.5>
     })
 
@@ -454,7 +454,7 @@ test:do_catchsql_test(
         SELECT * FROM t6 LIMIT -1 OFFSET 1
     ]], {
         -- <limit-6.6>
-        1, "Only positive integers are allowed in the LIMIT clause"
+        1, "Failed to execute SQL statement: Only positive integers are allowed in the LIMIT clause"
         -- </limit-6.6>
     })
 
@@ -734,7 +734,7 @@ test:do_test(
         return test:catchsql("SELECT x FROM t1 WHERE x<10 LIMIT "..limit)
     end, {
         -- <limit-10.4>
-        1, "Only positive integers are allowed in the LIMIT clause"
+        1, "Failed to execute SQL statement: Only positive integers are allowed in the LIMIT clause"
         -- </limit-10.4>
     })
 
@@ -745,7 +745,7 @@ test:do_test(
         return test:catchsql("SELECT x FROM t1 WHERE x<10 LIMIT "..limit)
     end, {
         -- <limit-10.5>
-        1, "Only positive integers are allowed in the LIMIT clause"
+        1, "Failed to execute SQL statement: Only positive integers are allowed in the LIMIT clause"
         -- </limit-10.5>
     })
 
@@ -1320,7 +1320,7 @@ test:do_catchsql_test(
         SELECT 123 LIMIT -1 OFFSET 0
     ]], {
         -- <limit-14.6.1>
-        1, "Only positive integers are allowed in the LIMIT clause"
+        1, "Failed to execute SQL statement: Only positive integers are allowed in the LIMIT clause"
         -- </limit-14.6.1>
     })
 
@@ -1340,7 +1340,7 @@ test:do_catchsql_test(
         SELECT 123 LIMIT -1 OFFSET 1
     ]], {
         -- <limit-14.7.1>
-        1, "Only positive integers are allowed in the LIMIT clause"
+        1, "Failed to execute SQL statement: Only positive integers are allowed in the LIMIT clause"
         -- </limit-14.7.1>
     })
 
diff --git a/test/sql-tap/select4.test.lua b/test/sql-tap/select4.test.lua
index b78091b..1c0804b 100755
--- a/test/sql-tap/select4.test.lua
+++ b/test/sql-tap/select4.test.lua
@@ -990,7 +990,7 @@ test:do_catchsql_test(
         SELECT DISTINCT log FROM t1 ORDER BY log LIMIT -1
     ]], {
         -- <select4-10.4.1>
-    1,"Only positive integers are allowed in the LIMIT clause"
+    1,"Failed to execute SQL statement: Only positive integers are allowed in the LIMIT clause"
         -- </select4-10.4.1>
     })
 test:do_execsql_test(
@@ -1009,7 +1009,7 @@ test:do_catchsql_test(
         SELECT DISTINCT log FROM t1 ORDER BY log LIMIT -1 OFFSET 2
     ]], {
         -- <select4-10.5.1>
-        1,"Only positive integers are allowed in the LIMIT clause"
+        1,"Failed to execute SQL statement: Only positive integers are allowed in the LIMIT clause"
         -- </select4-10.5.1>
     })
 test:do_execsql_test(
@@ -1402,7 +1402,7 @@ test:do_catchsql_test(
         SELECT (VALUES(1),(2),(3),(4))
     ]], {
         -- <select4-14.10>
-        1, "SQL error: Expression subquery returned more than 1 row"
+        1, "Failed to execute SQL statement: Expression subquery returned more than 1 row"
         -- </select4-14.10>
     })
 
@@ -1412,7 +1412,7 @@ test:do_catchsql_test(
         SELECT (SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4)
     ]], {
         -- <select4-14.11>
-        1, "SQL error: Expression subquery returned more than 1 row"
+        1, "Failed to execute SQL statement: Expression subquery returned more than 1 row"
         -- </select4-14.11>
     })
 
diff --git a/test/sql-tap/subselect.test.lua b/test/sql-tap/subselect.test.lua
index 5b71390..ebfdf43 100755
--- a/test/sql-tap/subselect.test.lua
+++ b/test/sql-tap/subselect.test.lua
@@ -350,7 +350,7 @@ test:do_catchsql_test(
         SELECT (SELECT a FROM t5);
     ]], {
     -- <subselect-5.1>
-    1, "SQL error: Expression subquery returned more than 1 row"
+    1, "Failed to execute SQL statement: Expression subquery returned more than 1 row"
     -- </subselect-5.1>
 })
 
@@ -360,7 +360,7 @@ test:do_catchsql_test(
         SELECT b FROM t5 WHERE a = (SELECT a FROM t5 WHERE b=6);
     ]], {
     -- <subselect-5.2>
-    1, "SQL error: Expression subquery returned more than 1 row"
+    1, "Failed to execute SQL statement: Expression subquery returned more than 1 row"
     -- </subselect-5.2>
 })
 
@@ -380,7 +380,7 @@ test:do_catchsql_test(
         SELECT b FROM t1 WHERE a = (SELECT a FROM t1 WHERE b=6 LIMIT (SELECT b FROM t1 WHERE a =1));
     ]], {
     -- <subselect-5.2>
-    1, "SQL error: Expression subquery could be limited only with 1"
+    1, "Failed to execute SQL statement: Expression subquery could be limited only with 1"
     -- </subselect-5.2>
 })
 
diff --git a/test/sql-tap/tkt1473.test.lua b/test/sql-tap/tkt1473.test.lua
index 3e93203..ada18d0 100755
--- a/test/sql-tap/tkt1473.test.lua
+++ b/test/sql-tap/tkt1473.test.lua
@@ -125,7 +125,7 @@ test:do_catchsql_test(
         SELECT (SELECT 1 FROM t1 WHERE a=1 UNION ALL SELECT 2 FROM t1 WHERE b=0)
     ]], {
         -- <tkt1473-2.2>
-        1, "SQL error: Expression subquery returned more than 1 row"
+        1, "Failed to execute SQL statement: Expression subquery returned more than 1 row"
         -- </tkt1473-2.2>
     })
 
@@ -145,7 +145,7 @@ test:do_catchsql_test(
         SELECT (SELECT 1 FROM t1 WHERE a=1 UNION ALL SELECT 2 FROM t1 WHERE b=4)
     ]], {
         -- <tkt1473-2.4>
-        1, "SQL error: Expression subquery returned more than 1 row"
+        1, "Failed to execute SQL statement: Expression subquery returned more than 1 row"
         -- </tkt1473-2.4>
     })
 
@@ -155,7 +155,7 @@ test:do_catchsql_test(
         SELECT (SELECT 1 FROM t1 WHERE a=1 UNION SELECT 2 FROM t1 WHERE b=4)
     ]], {
         -- <tkt1473-2.5>
-        1, "SQL error: Expression subquery returned more than 1 row"
+        1, "Failed to execute SQL statement: Expression subquery returned more than 1 row"
         -- </tkt1473-2.5>
     })
 
@@ -165,7 +165,7 @@ test:do_catchsql_test(
         SELECT (SELECT 1 FROM t1 WHERE a=0 UNION ALL SELECT 2 FROM t1 WHERE b=4)
     ]], {
         -- <tkt1473-2.6>
-        1, "SQL error: Expression subquery returned more than 1 row"
+        1, "Failed to execute SQL statement: Expression subquery returned more than 1 row"
         -- </tkt1473-2.6>
     })
 
@@ -206,7 +206,7 @@ test:do_catchsql_test(
           (SELECT 1 FROM t1 WHERE a=1 UNION ALL SELECT 2 FROM t1 WHERE b=0)
     ]], {
         -- <tkt1473-3.2>
-        1, "SQL error: Expression subquery returned more than 1 row"
+        1, "Failed to execute SQL statement: Expression subquery returned more than 1 row"
         -- </tkt1473-3.2>
     })
 
@@ -228,7 +228,7 @@ test:do_catchsql_test(
           (SELECT 1 FROM t1 WHERE a=1 UNION ALL SELECT 2 FROM t1 WHERE b=4)
     ]], {
         -- <tkt1473-3.4>
-        1, "SQL error: Expression subquery returned more than 1 row"
+        1, "Failed to execute SQL statement: Expression subquery returned more than 1 row"
         -- </tkt1473-3.4>
     })
 
@@ -239,7 +239,7 @@ test:do_catchsql_test(
           (SELECT 1 FROM t1 WHERE a=1 UNION SELECT 2 FROM t1 WHERE b=4)
     ]], {
         -- <tkt1473-3.5>
-        1, "SQL error: Expression subquery returned more than 1 row"
+        1, "Failed to execute SQL statement: Expression subquery returned more than 1 row"
         -- </tkt1473-3.5>
     })
 
@@ -250,7 +250,7 @@ test:do_catchsql_test(
           (SELECT 1 FROM t1 WHERE a=0 UNION ALL SELECT 2 FROM t1 WHERE b=4)
     ]], {
         -- <tkt1473-3.6>
-        1, "SQL error: Expression subquery returned more than 1 row"
+        1, "Failed to execute SQL statement: Expression subquery returned more than 1 row"
         -- </tkt1473-3.6>
     })
 
@@ -359,7 +359,7 @@ test:do_catchsql_test(
         )
     ]], {
         -- <tkt1473-4.3>
-        1, "SQL error: Expression subquery returned more than 1 row"
+        1, "Failed to execute SQL statement: Expression subquery returned more than 1 row"
         -- </tkt1473-4.3>
     })
 
@@ -389,7 +389,7 @@ test:do_catchsql_test(
         )
     ]], {
         -- <tkt1473-4.4>
-        1, "SQL error: Expression subquery returned more than 1 row"
+        1, "Failed to execute SQL statement: Expression subquery returned more than 1 row"
         -- </tkt1473-4.4>
     })
 
@@ -419,7 +419,7 @@ test:do_catchsql_test(
         )
     ]], {
         -- <tkt1473-4.5>
-        1, "SQL error: Expression subquery returned more than 1 row"
+        1, "Failed to execute SQL statement: Expression subquery returned more than 1 row"
         -- </tkt1473-4.5>
     })
 
@@ -449,7 +449,7 @@ test:do_catchsql_test(
         )
     ]], {
         -- <tkt1473-4.6>
-        1, "SQL error: Expression subquery returned more than 1 row"
+        1, "Failed to execute SQL statement: Expression subquery returned more than 1 row"
         -- </tkt1473-4.6>
     })
 
@@ -509,7 +509,7 @@ test:do_catchsql_test(
         )
     ]], {
         -- <tkt1473-5.3>
-        1, "SQL error: Expression subquery returned more than 1 row"
+        1, "Failed to execute SQL statement: Expression subquery returned more than 1 row"
         -- </tkt1473-5.3>
     })
 
@@ -539,7 +539,7 @@ test:do_catchsql_test(
         )
     ]], {
         -- <tkt1473-5.4>
-        1, "SQL error: Expression subquery returned more than 1 row"
+        1, "Failed to execute SQL statement: Expression subquery returned more than 1 row"
         -- </tkt1473-5.4>
     })
 
@@ -569,7 +569,7 @@ test:do_catchsql_test(
         )
     ]], {
         -- <tkt1473-5.5>
-        1, "SQL error: Expression subquery returned more than 1 row"
+        1, "Failed to execute SQL statement: Expression subquery returned more than 1 row"
         -- </tkt1473-5.5>
     })
 
@@ -599,7 +599,7 @@ test:do_catchsql_test(
         )
     ]], {
         -- <tkt1473-5.6>
-        1, "SQL error: Expression subquery returned more than 1 row"
+        1, "Failed to execute SQL statement: Expression subquery returned more than 1 row"
         -- </tkt1473-5.6>
     })
 
@@ -659,7 +659,7 @@ test:do_catchsql_test(
         )
     ]], {
         -- <tkt1473-6.3>
-        1, "SQL error: Expression subquery returned more than 1 row"
+        1, "Failed to execute SQL statement: Expression subquery returned more than 1 row"
         -- </tkt1473-6.3>
     })
 
@@ -689,7 +689,7 @@ test:do_catchsql_test(
         )
     ]], {
         -- <tkt1473-6.4>
-        1, "SQL error: Expression subquery returned more than 1 row"
+        1, "Failed to execute SQL statement: Expression subquery returned more than 1 row"
         -- </tkt1473-6.4>
     })
 
diff --git a/test/sql/iproto.result b/test/sql/iproto.result
index 73497b4..9639ba7 100644
--- a/test/sql/iproto.result
+++ b/test/sql/iproto.result
@@ -164,15 +164,18 @@ cn:execute('select * from test limit ?', {2})
 ...
 cn:execute('select * from test limit ?', {-2})
 ---
-- error: Only positive integers are allowed in the LIMIT clause
+- error: 'Failed to execute SQL statement: Only positive integers are allowed in the
+    LIMIT clause'
 ...
 cn:execute('select * from test limit ?', {2.7})
 ---
-- error: Only positive integers are allowed in the LIMIT clause
+- error: 'Failed to execute SQL statement: Only positive integers are allowed in the
+    LIMIT clause'
 ...
 cn:execute('select * from test limit ?', {'Hello'})
 ---
-- error: Only positive integers are allowed in the LIMIT clause
+- error: 'Failed to execute SQL statement: Only positive integers are allowed in the
+    LIMIT clause'
 ...
 cn:execute('select * from test limit 1 offset ?', {2})
 ---
@@ -188,15 +191,18 @@ cn:execute('select * from test limit 1 offset ?', {2})
 ...
 cn:execute('select * from test limit 1 offset ?', {-2})
 ---
-- error: Only positive integers are allowed in the OFFSET clause
+- error: 'Failed to execute SQL statement: Only positive integers are allowed in the
+    OFFSET clause'
 ...
 cn:execute('select * from test limit 1 offset ?', {2.7})
 ---
-- error: Only positive integers are allowed in the OFFSET clause
+- error: 'Failed to execute SQL statement: Only positive integers are allowed in the
+    OFFSET clause'
 ...
 cn:execute('select * from test limit 1 offset ?', {'Hello'})
 ---
-- error: Only positive integers are allowed in the OFFSET clause
+- error: 'Failed to execute SQL statement: Only positive integers are allowed in the
+    OFFSET clause'
 ...
 -- gh-2608 SQL iproto DDL
 cn:execute('create table test2(id int primary key, a int, b int, c int)')
diff --git a/test/sql/types.result b/test/sql/types.result
index d2786ff..cdfb1e7 100644
--- a/test/sql/types.result
+++ b/test/sql/types.result
@@ -383,11 +383,13 @@ box.execute("SELECT true IN (1, 'abc', false)")
 ...
 box.execute("SELECT 1 LIMIT true;")
 ---
-- error: Only positive integers are allowed in the LIMIT clause
+- error: 'Failed to execute SQL statement: Only positive integers are allowed in the
+    LIMIT clause'
 ...
 box.execute("SELECT 1 LIMIT 1 OFFSET true;")
 ---
-- error: Only positive integers are allowed in the OFFSET clause
+- error: 'Failed to execute SQL statement: Only positive integers are allowed in the
+    OFFSET clause'
 ...
 box.execute("SELECT 'abc' || true;")
 ---
@@ -551,7 +553,8 @@ box.execute("SELECT b FROM t GROUP BY b LIMIT 1;")
 ...
 box.execute("SELECT b FROM t LIMIT true;")
 ---
-- error: Only positive integers are allowed in the LIMIT clause
+- error: 'Failed to execute SQL statement: Only positive integers are allowed in the
+    LIMIT clause'
 ...
 -- Most of aggregates don't accept boolean arguments.
 --

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [tarantool-patches] Re: [PATCH v1 0/9] sql: set errors in VDBE using diag_set()
  2019-05-28 11:39 [tarantool-patches] [PATCH v1 0/9] sql: set errors in VDBE using diag_set() imeevma
                   ` (8 preceding siblings ...)
  2019-05-28 11:39 ` [tarantool-patches] [PATCH v1 9/9] sql: set errors in VDBE using diag_set() imeevma
@ 2019-06-09 17:14 ` Vladislav Shpilevoy
  2019-06-13  9:44 ` Kirill Yukhin
  10 siblings, 0 replies; 25+ messages in thread
From: Vladislav Shpilevoy @ 2019-06-09 17:14 UTC (permalink / raw)
  To: imeevma; +Cc: tarantool-patches, Kirill Yukhin

LGTM.

On 28/05/2019 14:39, imeevma@tarantool.org wrote:
> The main purpose of this patch-set is to replace the SQL error
> system with the Tarantool error system.
> 
> https://github.com/tarantool/tarantool/issues/4074
> https://github.com/tarantool/tarantool/tree/imeevma/gh-4074-diag_set-in-vdbe
> 
> Mergen Imeev (9):
>   sql: remove mayAbort field from struct Parse
>   sql: remove error codes SQL_TARANTOOL_*_FAIL
>   sql: remove error ER_SQL
>   sql: rework diag_set() in OP_Halt
>   sql: make SQL_TARANTOOL_ERROR the only errcode of OP_Halt
>   sql: remove error SQL_INTERRUPT
>   sql: remove error SQL_MISMATCH
>   sql: use diag_set() to set an error in SQL functions
>   sql: set errors in VDBE using diag_set()
> 
>  src/box/alter.cc                                   |   4 +-
>  src/box/errcode.h                                  |   2 +-
>  src/box/execute.c                                  |  23 +-
>  src/box/lua/lua_sql.c                              |  13 +-
>  src/box/sql.c                                      |  37 +-
>  src/box/sql/analyze.c                              |   6 +-
>  src/box/sql/build.c                                |  59 +--
>  src/box/sql/date.c                                 |   8 +-
>  src/box/sql/delete.c                               |   4 +-
>  src/box/sql/expr.c                                 |   9 +-
>  src/box/sql/fk_constraint.c                        |  42 +-
>  src/box/sql/func.c                                 | 102 +++--
>  src/box/sql/insert.c                               |  31 +-
>  src/box/sql/main.c                                 |   5 -
>  src/box/sql/malloc.c                               |   4 -
>  src/box/sql/resolve.c                              |   2 +-
>  src/box/sql/select.c                               |  13 +-
>  src/box/sql/sqlInt.h                               |  32 --
>  src/box/sql/tarantoolInt.h                         |   5 +-
>  src/box/sql/tokenize.c                             |   3 -
>  src/box/sql/trigger.c                              |  18 +-
>  src/box/sql/vdbe.c                                 | 431 ++++++---------------
>  src/box/sql/vdbe.h                                 |   3 -
>  src/box/sql/vdbeInt.h                              |  38 +-
>  src/box/sql/vdbeapi.c                              | 170 +-------
>  src/box/sql/vdbeaux.c                              | 234 +----------
>  src/box/sql/vdbemem.c                              |  15 +-
>  test/box/misc.result                               |   1 -
>  test/sql-tap/autoinc.test.lua                      |   4 +-
>  test/sql-tap/e_select1.test.lua                    |   4 +-
>  test/sql-tap/func.test.lua                         |   2 +-
>  test/sql-tap/gh-2931-savepoints.test.lua           |   6 +-
>  .../gh-3307-xfer-optimization-issue.test.lua       |  10 +-
>  test/sql-tap/gh2259-in-stmt-trans.test.lua         |   8 +-
>  test/sql-tap/gh2964-abort.test.lua                 |   2 +-
>  test/sql-tap/intpkey.test.lua                      |   2 +-
>  test/sql-tap/limit.test.lua                        |  26 +-
>  test/sql-tap/misc1.test.lua                        |   2 +-
>  test/sql-tap/select3.test.lua                      |   2 +-
>  test/sql-tap/select4.test.lua                      |   8 +-
>  test/sql-tap/select5.test.lua                      |  10 +-
>  test/sql-tap/subselect.test.lua                    |   6 +-
>  test/sql-tap/table.test.lua                        |   8 +-
>  test/sql-tap/tkt-4a03edc4c8.test.lua               |   2 +-
>  test/sql-tap/tkt1473.test.lua                      |  36 +-
>  test/sql-tap/trigger1.test.lua                     |   6 +-
>  test/sql-tap/unique.test.lua                       |  10 +-
>  test/sql/collation.result                          |  18 +-
>  test/sql/delete.result                             |   7 +-
>  test/sql/errinj.result                             |   6 +-
>  test/sql/foreign-keys.result                       |   3 +-
>  test/sql/insert-unique.result                      |   6 +-
>  test/sql/iproto.result                             |  21 +-
>  test/sql/on-conflict.result                        |   4 +-
>  test/sql/persistency.result                        |   6 +-
>  test/sql/savepoints.result                         |   2 +-
>  test/sql/transition.result                         |   6 +-
>  test/sql/triggers.result                           |  21 +-
>  test/sql/types.result                              |   9 +-
>  59 files changed, 420 insertions(+), 1157 deletions(-)
> 

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [tarantool-patches] Re: [PATCH v1 0/9] sql: set errors in VDBE using diag_set()
  2019-05-28 11:39 [tarantool-patches] [PATCH v1 0/9] sql: set errors in VDBE using diag_set() imeevma
                   ` (9 preceding siblings ...)
  2019-06-09 17:14 ` [tarantool-patches] Re: [PATCH v1 0/9] " Vladislav Shpilevoy
@ 2019-06-13  9:44 ` Kirill Yukhin
  10 siblings, 0 replies; 25+ messages in thread
From: Kirill Yukhin @ 2019-06-13  9:44 UTC (permalink / raw)
  To: tarantool-patches; +Cc: v.shpilevoy

Hello,

On 28 May 14:39, imeevma@tarantool.org wrote:
> The main purpose of this patch-set is to replace the SQL error
> system with the Tarantool error system.
> 
> https://github.com/tarantool/tarantool/issues/4074
> https://github.com/tarantool/tarantool/tree/imeevma/gh-4074-diag_set-in-vdbe

I've checked your patch set into master.

--
Regards, Kirill Yukhin

^ permalink raw reply	[flat|nested] 25+ messages in thread

end of thread, other threads:[~2019-06-13  9:44 UTC | newest]

Thread overview: 25+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-05-28 11:39 [tarantool-patches] [PATCH v1 0/9] sql: set errors in VDBE using diag_set() imeevma
2019-05-28 11:39 ` [tarantool-patches] [PATCH v1 1/9] sql: remove mayAbort field from struct Parse imeevma
2019-05-28 11:39 ` [tarantool-patches] [PATCH v1 2/9] sql: remove error codes SQL_TARANTOOL_*_FAIL imeevma
2019-05-28 11:39 ` [tarantool-patches] [PATCH v1 3/9] sql: remove error ER_SQL imeevma
2019-05-28 11:39 ` [tarantool-patches] [PATCH v1 4/9] sql: rework diag_set() in OP_Halt imeevma
2019-06-02 16:35   ` [tarantool-patches] " Vladislav Shpilevoy
2019-06-03  8:41     ` Imeev Mergen
2019-06-04 19:34       ` Vladislav Shpilevoy
2019-06-08 12:11         ` Mergen Imeev
2019-05-28 11:39 ` [tarantool-patches] [PATCH v1 5/9] sql: make SQL_TARANTOOL_ERROR the only errcode of OP_Halt imeevma
2019-06-02 16:35   ` [tarantool-patches] " Vladislav Shpilevoy
2019-06-03 11:53     ` Mergen Imeev
2019-06-04 19:34       ` Vladislav Shpilevoy
2019-06-08 12:15         ` Mergen Imeev
2019-05-28 11:39 ` [tarantool-patches] [PATCH v1 6/9] sql: remove error SQL_INTERRUPT imeevma
2019-05-28 11:39 ` [tarantool-patches] [PATCH v1 7/9] sql: remove error SQL_MISMATCH imeevma
2019-05-28 11:39 ` [tarantool-patches] [PATCH v1 8/9] sql: use diag_set() to set an error in SQL functions imeevma
2019-06-02 16:35   ` [tarantool-patches] " Vladislav Shpilevoy
2019-06-03 11:54     ` Mergen Imeev
2019-05-28 11:39 ` [tarantool-patches] [PATCH v1 9/9] sql: set errors in VDBE using diag_set() imeevma
2019-06-02 16:34   ` [tarantool-patches] " Vladislav Shpilevoy
2019-06-03 12:10     ` Mergen Imeev
2019-06-03 12:20       ` Mergen Imeev
2019-06-09 17:14 ` [tarantool-patches] Re: [PATCH v1 0/9] " Vladislav Shpilevoy
2019-06-13  9:44 ` Kirill Yukhin

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox