Tarantool development patches archive
 help / color / mirror / Atom feed
* [tarantool-patches] [PATCH v1 00/12] sql: set errors in VDBE using diag_set()
@ 2019-05-05 12:17 imeevma
  2019-05-05 12:17 ` [tarantool-patches] [PATCH v1 01/12] sql: remove errors SQL_TARANTOOL_*_FAIL imeevma
                   ` (11 more replies)
  0 siblings, 12 replies; 31+ messages in thread
From: imeevma @ 2019-05-05 12:17 UTC (permalink / raw)
  To: korablev; +Cc: tarantool-patches

This set of patches partially replaces the SQL error system with
the Tarantool error system. There are still some parts of the SQL
error system in the code, the most notable of which are the rc
field in struct sql and struct Vdbe and the mallocFailed field in
struct sql. I tried to remove the rc field from struct Vdbe, but
it still has too many connections to the SQL code. I think this
should be done in a different set of patches.

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

Mergen Imeev (12):
  sql: remove errors 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: set errors in VDBE using diag_set()
  sql: remove field zErrMsg from struct Vdbe
  sql: remove field pErr from struct sql
  sql: remove field errCode from struct sql
  sql: remove sqlError() and remove sqlErrorWithMsg()
  sql: use diag_set() to set an error in SQL functions

 src/box/alter.cc                                   |   4 +-
 src/box/errcode.h                                  |   2 +-
 src/box/execute.c                                  |  23 +-
 src/box/lua/lua_sql.c                              |  15 +-
 src/box/sql.c                                      |  37 +-
 src/box/sql/analyze.c                              |   6 +-
 src/box/sql/build.c                                |  31 +-
 src/box/sql/delete.c                               |   4 +-
 src/box/sql/expr.c                                 |   7 +-
 src/box/sql/fk_constraint.c                        |   7 +-
 src/box/sql/func.c                                 | 104 +++--
 src/box/sql/insert.c                               |  29 +-
 src/box/sql/legacy.c                               |   2 -
 src/box/sql/main.c                                 | 106 +----
 src/box/sql/malloc.c                               |   5 -
 src/box/sql/prepare.c                              |   8 +-
 src/box/sql/resolve.c                              |   2 +-
 src/box/sql/select.c                               |  13 +-
 src/box/sql/sqlInt.h                               |  38 --
 src/box/sql/tarantoolInt.h                         |   5 +-
 src/box/sql/tokenize.c                             |   3 -
 src/box/sql/trigger.c                              |  18 +-
 src/box/sql/util.c                                 |  81 ----
 src/box/sql/vdbe.c                                 | 449 +++++++--------------
 src/box/sql/vdbeInt.h                              |  40 +-
 src/box/sql/vdbeapi.c                              | 178 +-------
 src/box/sql/vdbeaux.c                              | 163 ++------
 src/box/sql/vdbemem.c                              |   9 +-
 test/box/misc.result                               |   1 -
 test/sql-tap/autoinc.test.lua                      |   4 +-
 test/sql-tap/e_select1.test.lua                    |   4 +-
 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/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/func-recreate.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/transition.result                         |   6 +-
 test/sql/triggers.result                           |  21 +-
 test/sql/types.result                              |   9 +-
 59 files changed, 458 insertions(+), 1192 deletions(-)

-- 
2.7.4

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

* [tarantool-patches] [PATCH v1 01/12] sql: remove errors SQL_TARANTOOL_*_FAIL
  2019-05-05 12:17 [tarantool-patches] [PATCH v1 00/12] sql: set errors in VDBE using diag_set() imeevma
@ 2019-05-05 12:17 ` imeevma
  2019-05-15 13:18   ` [tarantool-patches] " n.pettik
  2019-05-05 12:17 ` [tarantool-patches] [PATCH v1 02/12] sql: remove error ER_SQL imeevma
                   ` (10 subsequent siblings)
  11 siblings, 1 reply; 31+ messages in thread
From: imeevma @ 2019-05-05 12:17 UTC (permalink / raw)
  To: korablev; +Cc: tarantool-patches

Errors SQL_TARANTOOL_DELETE_FAIL, SQL_TARANTOOL_ITERATOR_FAIL and
SQL_TARANTOOL_INSERT_FAIL have almost no functionality, but can
lead to incorrect behavior. This patch replaces them with
SQL_TARANTOOL_ERROR. It will simplify work with the 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 1fb93e1..3593242 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,
 				&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,
 				&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)
 					&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,
 						&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)++;
 	}
@@ -899,7 +890,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;
@@ -913,7 +904,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);
@@ -940,7 +931,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 3bd8223..5222a4e 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 cd0e103..dbc0699 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 6f14d1e..5a931b8 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 77b88f4..16df1fb 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] 31+ messages in thread

* [tarantool-patches] [PATCH v1 02/12] sql: remove error ER_SQL
  2019-05-05 12:17 [tarantool-patches] [PATCH v1 00/12] sql: set errors in VDBE using diag_set() imeevma
  2019-05-05 12:17 ` [tarantool-patches] [PATCH v1 01/12] sql: remove errors SQL_TARANTOOL_*_FAIL imeevma
@ 2019-05-05 12:17 ` imeevma
  2019-05-15 13:18   ` [tarantool-patches] " n.pettik
  2019-05-05 12:17 ` [tarantool-patches] [PATCH v1 03/12] sql: rework diag_set() in OP_Halt imeevma
                   ` (9 subsequent siblings)
  11 siblings, 1 reply; 31+ messages in thread
From: imeevma @ 2019-05-05 12:17 UTC (permalink / raw)
  To: korablev; +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 9279426..fbcff69 100644
--- a/src/box/alter.cc
+++ b/src/box/alter.cc
@@ -3550,7 +3550,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");
 		}
@@ -3558,7 +3558,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 3f8cb8e..6c9bcc4 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 72be410..1151425 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 14e4198..4fdbb60 100644
--- a/src/box/sql/trigger.c
+++ b/src/box/sql/trigger.c
@@ -445,7 +445,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;
 		}
@@ -454,7 +454,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",
@@ -462,7 +462,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 a1f7a09..8eabc57 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 16df1fb..a4c927c 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] 31+ messages in thread

* [tarantool-patches] [PATCH v1 03/12] sql: rework diag_set() in OP_Halt
  2019-05-05 12:17 [tarantool-patches] [PATCH v1 00/12] sql: set errors in VDBE using diag_set() imeevma
  2019-05-05 12:17 ` [tarantool-patches] [PATCH v1 01/12] sql: remove errors SQL_TARANTOOL_*_FAIL imeevma
  2019-05-05 12:17 ` [tarantool-patches] [PATCH v1 02/12] sql: remove error ER_SQL imeevma
@ 2019-05-05 12:17 ` imeevma
  2019-05-15 13:18   ` [tarantool-patches] " n.pettik
  2019-05-05 12:17 ` [tarantool-patches] [PATCH v1 04/12] sql: make SQL_TARANTOOL_ERROR the only errcode of OP_Halt imeevma
                   ` (8 subsequent siblings)
  11 siblings, 1 reply; 31+ messages in thread
From: imeevma @ 2019-05-05 12:17 UTC (permalink / raw)
  To: korablev; +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 1151425..28dcbc3 100644
--- a/src/box/sql/build.c
+++ b/src/box/sql/build.c
@@ -1004,12 +1004,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);
@@ -1392,13 +1390,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 4fdbb60..3005362 100644
--- a/src/box/sql/trigger.c
+++ b/src/box/sql/trigger.c
@@ -100,9 +100,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;
@@ -113,7 +110,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;
 	}
@@ -412,9 +410,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;
@@ -422,7 +417,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 5222a4e..9f0d760 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 c4724e6..0c626c9 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 bc4518c..f05b856 100644
--- a/test/sql/types.result
+++ b/test/sql/types.result
@@ -351,11 +351,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;")
 ---
@@ -519,7 +521,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] 31+ messages in thread

* [tarantool-patches] [PATCH v1 04/12] sql: make SQL_TARANTOOL_ERROR the only errcode of OP_Halt
  2019-05-05 12:17 [tarantool-patches] [PATCH v1 00/12] sql: set errors in VDBE using diag_set() imeevma
                   ` (2 preceding siblings ...)
  2019-05-05 12:17 ` [tarantool-patches] [PATCH v1 03/12] sql: rework diag_set() in OP_Halt imeevma
@ 2019-05-05 12:17 ` imeevma
  2019-05-15 13:18   ` [tarantool-patches] " n.pettik
  2019-05-05 12:17 ` [tarantool-patches] [PATCH v1 05/12] sql: remove error SQL_INTERRUPT imeevma
                   ` (7 subsequent siblings)
  11 siblings, 1 reply; 31+ messages in thread
From: imeevma @ 2019-05-05 12:17 UTC (permalink / raw)
  To: korablev; +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 28dcbc3..32c101d 100644
--- a/src/box/sql/build.c
+++ b/src/box/sql/build.c
@@ -2972,26 +2972,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 f725478..dcadd7c 100644
--- a/src/box/sql/insert.c
+++ b/src/box/sql/insert.c
@@ -865,7 +865,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;
@@ -895,20 +894,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,
@@ -951,11 +948,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 9f0d760..85cec85 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] 31+ messages in thread

* [tarantool-patches] [PATCH v1 05/12] sql: remove error SQL_INTERRUPT
  2019-05-05 12:17 [tarantool-patches] [PATCH v1 00/12] sql: set errors in VDBE using diag_set() imeevma
                   ` (3 preceding siblings ...)
  2019-05-05 12:17 ` [tarantool-patches] [PATCH v1 04/12] sql: make SQL_TARANTOOL_ERROR the only errcode of OP_Halt imeevma
@ 2019-05-05 12:17 ` imeevma
  2019-05-15 13:18   ` [tarantool-patches] " n.pettik
  2019-05-05 12:17 ` [tarantool-patches] [PATCH v1 06/12] sql: remove error SQL_MISMATCH imeevma
                   ` (6 subsequent siblings)
  11 siblings, 1 reply; 31+ messages in thread
From: imeevma @ 2019-05-05 12:17 UTC (permalink / raw)
  To: korablev; +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 85cec85..c2eec93 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 d286856..909db8c 100644
--- a/src/box/sql/vdbeapi.c
+++ b/src/box/sql/vdbeapi.c
@@ -537,13 +537,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] 31+ messages in thread

* [tarantool-patches] [PATCH v1 06/12] sql: remove error SQL_MISMATCH
  2019-05-05 12:17 [tarantool-patches] [PATCH v1 00/12] sql: set errors in VDBE using diag_set() imeevma
                   ` (4 preceding siblings ...)
  2019-05-05 12:17 ` [tarantool-patches] [PATCH v1 05/12] sql: remove error SQL_INTERRUPT imeevma
@ 2019-05-05 12:17 ` imeevma
  2019-05-15 13:19   ` [tarantool-patches] " n.pettik
  2019-05-05 12:17 ` [tarantool-patches] [PATCH v1 07/12] sql: set errors in VDBE using diag_set() imeevma
                   ` (5 subsequent siblings)
  11 siblings, 1 reply; 31+ messages in thread
From: imeevma @ 2019-05-05 12:17 UTC (permalink / raw)
  To: korablev; +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 c2eec93..bdf7429 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] 31+ messages in thread

* [tarantool-patches] [PATCH v1 07/12] sql: set errors in VDBE using diag_set()
  2019-05-05 12:17 [tarantool-patches] [PATCH v1 00/12] sql: set errors in VDBE using diag_set() imeevma
                   ` (5 preceding siblings ...)
  2019-05-05 12:17 ` [tarantool-patches] [PATCH v1 06/12] sql: remove error SQL_MISMATCH imeevma
@ 2019-05-05 12:17 ` imeevma
  2019-05-15 13:26   ` [tarantool-patches] " n.pettik
  2019-05-05 12:17 ` [tarantool-patches] [PATCH v1 08/12] sql: remove field zErrMsg from struct Vdbe imeevma
                   ` (4 subsequent siblings)
  11 siblings, 1 reply; 31+ messages in thread
From: imeevma @ 2019-05-05 12:17 UTC (permalink / raw)
  To: korablev; +Cc: tarantool-patches

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

Part of #4074
---
 src/box/execute.c     |  23 +---
 src/box/sql/vdbe.c    | 331 +++++++++++++++++++++-----------------------------
 src/box/sql/vdbeInt.h |  10 --
 src/box/sql/vdbeapi.c |  34 +-----
 src/box/sql/vdbeaux.c |  20 +--
 5 files changed, 148 insertions(+), 270 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 bdf7429..115f22e 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,8 @@ 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))) {
+	rc = sqlVdbeCheckFk(p, 0);
+	if (rc != SQL_OK) {
 		assert(user_session->sql_flags&SQL_CountRows);
 		goto abort_due_to_error;
 	}
@@ -1427,7 +1424,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 +1431,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 +1547,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 +1591,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;
 }
 
@@ -1723,11 +1715,15 @@ case OP_Function: {
 	/* 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;
+			if (pCtx->isError != SQL_TARANTOOL_ERROR) {
+				diag_set(ClientError, ER_SQL_EXECUTE,
+					 sql_value_text(pCtx->pOut));
+			}
+			rc = SQL_TARANTOOL_ERROR;
 		}
 		sqlVdbeDeleteAuxData(db, &p->pAuxData, pCtx->iOp, pOp->p1);
-		if (rc) goto abort_due_to_error;
+		if (rc != SQL_OK)
+			goto abort_due_to_error;
 	}
 
 	/* Copy the result of the function into register P3 */
@@ -1789,13 +1785,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;
@@ -1864,7 +1858,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;
@@ -1910,8 +1903,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);
@@ -1919,7 +1911,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 */
@@ -2072,7 +2063,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);
@@ -2091,7 +2081,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;
 					}
 
@@ -2333,7 +2322,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];
@@ -2344,7 +2332,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) {
@@ -2378,7 +2365,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);
@@ -2402,7 +2388,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;
@@ -2450,7 +2435,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);
@@ -2590,8 +2574,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;
 	}
@@ -2650,10 +2635,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.
 	 */
@@ -2687,7 +2670,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;
@@ -2701,10 +2688,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 *
@@ -2729,7 +2712,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++;
@@ -2802,10 +2784,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;
 
@@ -2860,13 +2840,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;
@@ -2890,7 +2871,6 @@ case OP_Savepoint: {
 	if (psql_txn == NULL) {
 		assert(!box_txn());
 		diag_set(ClientError, ER_SAVEPOINT_NO_TRANSACTION);
-		rc = SQL_TARANTOOL_ERROR;
 		goto abort_due_to_error;
 	}
 	p1 = pOp->p1;
@@ -2918,8 +2898,10 @@ case OP_Savepoint: {
 			pSavepoint = pSavepoint->pNext
 			);
 		if (!pSavepoint) {
-			sqlVdbeError(p, "no such savepoint: %s", zName);
-			rc = SQL_ERROR;
+			const char *err =
+				tt_sprintf("no such savepoint: %s", zName);
+			diag_set(ClientError, ER_SQL_EXECUTE, err);
+			goto abort_due_to_error;
 		} else {
 
 			/* Determine whether or not this is a transaction savepoint. If so,
@@ -2936,7 +2918,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);
@@ -2968,7 +2951,6 @@ case OP_Savepoint: {
 			}
 		}
 	}
-	if (rc) goto abort_due_to_error;
 
 	break;
 }
@@ -2991,7 +2973,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;
@@ -3004,10 +2985,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;
 }
@@ -3023,13 +3002,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;
@@ -3042,14 +3019,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;
@@ -3067,16 +3041,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;
 }
@@ -3115,9 +3085,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;
@@ -3126,10 +3095,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);
@@ -3152,8 +3119,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;
 }
 
@@ -3175,10 +3140,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;
@@ -3204,8 +3167,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;
 }
 
@@ -3437,7 +3400,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;
@@ -3518,10 +3480,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;
@@ -3533,8 +3493,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;
 		}
@@ -3542,8 +3502,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.
@@ -3685,10 +3645,11 @@ case OP_Found: {        /* jump, in3 */
 		}
 	}
 	rc = sqlCursorMovetoUnpacked(pC->uc.pCursor, pIdxKey, &res);
-	if (pFree) sqlDbFree(db, pFree);
-	if (rc!=SQL_OK) {
+	if (pFree)
+		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;
@@ -3748,10 +3709,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
@@ -3760,7 +3719,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];
@@ -3860,7 +3818,9 @@ case OP_Delete: {
 	}
 	pC->cacheStatus = CACHE_STALE;
 	pC->seekResult = 0;
-	if (rc) goto abort_due_to_error;
+	assert(rc == SQL_OK || rc == SQL_TARANTOOL_ERROR);
+	if (rc != SQL_OK)
+		goto abort_due_to_error;
 
 	if (opflags & OPFLAG_NCHANGE)
 		p->nChange++;
@@ -3907,9 +3867,12 @@ 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;
+			assert(rc == SQL_OK || rc == SQL_TARANTOOL_ERROR);
+			if (rc != SQL_OK)
+				goto abort_due_to_error;
 			if (res) goto jump_to_p2;
 			break;
 		};
@@ -3932,10 +3895,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;
 }
@@ -4002,11 +3965,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;
@@ -4072,7 +4033,9 @@ case OP_Last: {        /* jump */
 		rc = tarantoolsqlLast(pCrsr, &res);
 		pC->nullRow = (u8)res;
 		pC->cacheStatus = CACHE_STALE;
-		if (rc) goto abort_due_to_error;
+		assert(rc == SQL_OK || rc == SQL_TARANTOOL_ERROR);
+		if (rc != SQL_OK)
+			goto abort_due_to_error;
 		if (pOp->p2>0) {
 			VdbeBranchTaken(res!=0,2);
 			if (res) goto jump_to_p2;
@@ -4141,15 +4104,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);
@@ -4267,7 +4233,9 @@ case OP_Next:          /* jump */
 			next_tail:
 	pC->cacheStatus = CACHE_STALE;
 	VdbeBranchTaken(res==0,2);
-	if (rc) goto abort_due_to_error;
+	assert(rc == SQL_OK || rc == SQL_TARANTOOL_ERROR);
+	if (rc != SQL_OK)
+		goto abort_due_to_error;
 	if (res==0) {
 		pC->nullRow = 0;
 		p->aCounter[pOp->p5]++;
@@ -4295,11 +4263,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;
 }
@@ -4329,8 +4294,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)
@@ -4364,6 +4328,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;
@@ -4431,14 +4396,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;
 	}
 
@@ -4464,6 +4427,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;
@@ -4514,8 +4478,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++;
@@ -4549,18 +4512,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;
@@ -4672,14 +4636,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;
 }
 
@@ -4702,8 +4666,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;
 }
@@ -4736,8 +4700,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
@@ -4747,20 +4711,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);
@@ -4775,8 +4737,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;
 }
 
@@ -4832,8 +4794,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;
 	}
 
@@ -5164,11 +5126,16 @@ case OP_AggStep: {
 	(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->isError != SQL_TARANTOOL_ERROR) {
+				diag_set(ClientError, ER_SQL_EXECUTE,
+					 sql_value_text(&t));
+			}
+			rc = SQL_TARANTOOL_ERROR;
 		}
 		sqlVdbeMemRelease(&t);
-		if (rc) goto abort_due_to_error;
+		assert(rc == SQL_OK || rc == SQL_TARANTOOL_ERROR);
+		if (rc != SQL_OK)
+			goto abort_due_to_error;
 	} else {
 		assert(t.flags==MEM_Null);
 	}
@@ -5199,8 +5166,11 @@ case OP_AggFinal: {
 	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 (rc != SQL_OK) {
+		if (rc != SQL_TARANTOOL_ERROR) {
+			diag_set(ClientError, ER_SQL_EXECUTE,
+				 sql_value_text(pMem));
+		}
 		goto abort_due_to_error;
 	}
 	UPDATE_MAX_BLOBSIZE(pMem);
@@ -5311,10 +5281,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;
 }
@@ -5378,28 +5346,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:
@@ -5408,21 +5356,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 a3100e5..b655b5a 100644
--- a/src/box/sql/vdbeInt.h
+++ b/src/box/sql/vdbeInt.h
@@ -248,10 +248,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
@@ -467,7 +463,6 @@ struct Vdbe {
 /*
  * Function prototypes
  */
-void sqlVdbeError(Vdbe *, const char *, ...);
 void sqlVdbeFreeCursor(Vdbe *, VdbeCursor *);
 void sqlVdbePopStack(Vdbe *, int);
 int sqlVdbeCursorRestore(VdbeCursor *);
@@ -550,13 +545,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 909db8c..34fa5c8 100644
--- a/src/box/sql/vdbeapi.c
+++ b/src/box/sql/vdbeapi.c
@@ -569,15 +569,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
@@ -597,20 +588,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);
@@ -618,26 +606,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 27fa5b2..48c2a81 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
@@ -2124,10 +2111,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;
 }
-- 
2.7.4

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

* [tarantool-patches] [PATCH v1 08/12] sql: remove field zErrMsg from struct Vdbe
  2019-05-05 12:17 [tarantool-patches] [PATCH v1 00/12] sql: set errors in VDBE using diag_set() imeevma
                   ` (6 preceding siblings ...)
  2019-05-05 12:17 ` [tarantool-patches] [PATCH v1 07/12] sql: set errors in VDBE using diag_set() imeevma
@ 2019-05-05 12:17 ` imeevma
  2019-05-15 13:30   ` [tarantool-patches] " n.pettik
  2019-05-05 12:17 ` [tarantool-patches] [PATCH v1 09/12] sql: remove field pErr from struct sql imeevma
                   ` (3 subsequent siblings)
  11 siblings, 1 reply; 31+ messages in thread
From: imeevma @ 2019-05-05 12:17 UTC (permalink / raw)
  To: korablev; +Cc: tarantool-patches

This field become unused and should be removed.
---
 src/box/sql/vdbeInt.h |  1 -
 src/box/sql/vdbeaux.c | 29 ++++-------------------------
 2 files changed, 4 insertions(+), 26 deletions(-)

diff --git a/src/box/sql/vdbeInt.h b/src/box/sql/vdbeInt.h
index b655b5a..de9dbd6 100644
--- a/src/box/sql/vdbeInt.h
+++ b/src/box/sql/vdbeInt.h
@@ -404,7 +404,6 @@ struct Vdbe {
 	Mem **apArg;		/* Arguments to currently executing user function */
 	Mem *aColName;		/* Column names to return */
 	Mem *pResultSet;	/* Pointer to an array of results */
-	char *zErrMsg;		/* Error message written here */
 	VdbeCursor **apCsr;	/* One element of this array for each open cursor */
 	Mem *aVar;		/* Values for the OP_Variable opcode. */
 	/**
diff --git a/src/box/sql/vdbeaux.c b/src/box/sql/vdbeaux.c
index 48c2a81..300a44b 100644
--- a/src/box/sql/vdbeaux.c
+++ b/src/box/sql/vdbeaux.c
@@ -1966,7 +1966,6 @@ closeCursorsAndFree(Vdbe * p)
 static void
 Cleanup(Vdbe * p)
 {
-	sql *db = p->db;
 
 #ifdef SQL_DEBUG
 	/* Execute assert() statements to ensure that the Vdbe.apCsr[] and
@@ -1982,8 +1981,6 @@ Cleanup(Vdbe * p)
 	}
 #endif
 
-	sqlDbFree(db, p->zErrMsg);
-	p->zErrMsg = 0;
 	p->pResultSet = 0;
 }
 
@@ -2326,8 +2323,6 @@ sqlVdbeHalt(Vdbe * p)
 				if (p->rc == SQL_OK
 				    || (p->rc & 0xff) == SQL_CONSTRAINT) {
 					p->rc = rc;
-					sqlDbFree(db, p->zErrMsg);
-					p->zErrMsg = 0;
 				}
 				closeCursorsAndFree(p);
 				sqlRollbackAll(p);
@@ -2390,24 +2385,13 @@ sqlVdbeTransferError(Vdbe * p)
 {
 	sql *db = p->db;
 	int rc = p->rc;
-	if (p->zErrMsg) {
-		db->bBenignMalloc++;
-		sqlBeginBenignMalloc();
-		if (db->pErr == 0)
-			db->pErr = sqlValueNew(db);
-		sqlValueSetStr(db->pErr, -1, p->zErrMsg, SQL_TRANSIENT);
-		sqlEndBenignMalloc();
-		db->bBenignMalloc--;
-		db->errCode = rc;
-	} else {
-		sqlError(db, rc);
-	}
+	sqlError(db, rc);
 	return rc;
 }
 
 /*
  * Clean up a VDBE after execution but do not delete the VDBE just yet.
- * Write any error messages into *pzErrMsg.  Return the result code.
+ * Return the result code.
  *
  * After this routine is run, the VDBE should be ready to be executed
  * again.
@@ -2435,8 +2419,6 @@ sqlVdbeReset(Vdbe * p)
 	 */
 	if (p->pc >= 0) {
 		sqlVdbeTransferError(p);
-		sqlDbFree(db, p->zErrMsg);
-		p->zErrMsg = 0;
 		if (p->runOnlyOnce)
 			p->expired = 1;
 	} else if (p->rc && p->expired) {
@@ -2444,10 +2426,7 @@ sqlVdbeReset(Vdbe * p)
 		 * to sql_step(). For consistency (since sql_step() was
 		 * called), set the database error in this case as well.
 		 */
-		sqlErrorWithMsg(db, p->rc, p->zErrMsg ? "%s" : 0,
-				    p->zErrMsg);
-		sqlDbFree(db, p->zErrMsg);
-		p->zErrMsg = 0;
+		sqlErrorWithMsg(db, p->rc, NULL);
 	}
 
 	/* Reclaim all memory used by the VDBE
@@ -2501,7 +2480,7 @@ sqlVdbeReset(Vdbe * p)
 
 /*
  * Clean up and delete a VDBE after execution.  Return an integer which is
- * the result code.  Write any error message text into *pzErrMsg.
+ * the result code.
  */
 int
 sqlVdbeFinalize(Vdbe * p)
-- 
2.7.4

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

* [tarantool-patches] [PATCH v1 09/12] sql: remove field pErr from struct sql
  2019-05-05 12:17 [tarantool-patches] [PATCH v1 00/12] sql: set errors in VDBE using diag_set() imeevma
                   ` (7 preceding siblings ...)
  2019-05-05 12:17 ` [tarantool-patches] [PATCH v1 08/12] sql: remove field zErrMsg from struct Vdbe imeevma
@ 2019-05-05 12:17 ` imeevma
  2019-05-05 12:17 ` [tarantool-patches] [PATCH v1 10/12] sql: remove field errCode " imeevma
                   ` (2 subsequent siblings)
  11 siblings, 0 replies; 31+ messages in thread
From: imeevma @ 2019-05-05 12:17 UTC (permalink / raw)
  To: korablev; +Cc: tarantool-patches

This field became unused and should be removed.
---
 src/box/sql/sqlInt.h |  1 -
 src/box/sql/util.c   | 14 ++------------
 2 files changed, 2 insertions(+), 13 deletions(-)

diff --git a/src/box/sql/sqlInt.h b/src/box/sql/sqlInt.h
index 3981fbf..1af5457 100644
--- a/src/box/sql/sqlInt.h
+++ b/src/box/sql/sqlInt.h
@@ -1463,7 +1463,6 @@ struct sql {
 	void *pUpdateArg;
 	void (*xUpdateCallback) (void *, int, const char *, const char *,
 				 sql_int64);
-	sql_value *pErr;	/* Most recent error message */
 	Lookaside lookaside;	/* Lookaside malloc configuration */
 	Hash aFunc;		/* Hash table of connection functions */
 	int *pnBytesFreed;	/* If not NULL, increment this in DbFree() */
diff --git a/src/box/sql/util.c b/src/box/sql/util.c
index d5c93f8..62c29ce 100644
--- a/src/box/sql/util.c
+++ b/src/box/sql/util.c
@@ -138,8 +138,6 @@ sqlStrlen30(const char *z)
 static SQL_NOINLINE void
 sqlErrorFinish(sql * db, int err_code)
 {
-	if (db->pErr)
-		sqlValueSetNull(db->pErr);
 	sqlSystemError(db, err_code);
 }
 
@@ -153,7 +151,7 @@ sqlError(sql * db, int err_code)
 {
 	assert(db != 0);
 	db->errCode = err_code;
-	if (err_code || db->pErr)
+	if (err_code)
 		sqlErrorFinish(db, err_code);
 }
 
@@ -199,16 +197,8 @@ sqlErrorWithMsg(sql * db, int err_code, const char *zFormat, ...)
 	assert(db != 0);
 	db->errCode = err_code;
 	sqlSystemError(db, err_code);
-	if (zFormat == 0) {
+	if (zFormat == 0)
 		sqlError(db, err_code);
-	} else if (db->pErr || (db->pErr = sqlValueNew(db)) != 0) {
-		char *z;
-		va_list ap;
-		va_start(ap, zFormat);
-		z = sqlVMPrintf(db, zFormat, ap);
-		va_end(ap);
-		sqlValueSetStr(db->pErr, -1, z, SQL_DYNAMIC);
-	}
 }
 
 /*
-- 
2.7.4

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

* [tarantool-patches] [PATCH v1 10/12] sql: remove field errCode from struct sql
  2019-05-05 12:17 [tarantool-patches] [PATCH v1 00/12] sql: set errors in VDBE using diag_set() imeevma
                   ` (8 preceding siblings ...)
  2019-05-05 12:17 ` [tarantool-patches] [PATCH v1 09/12] sql: remove field pErr from struct sql imeevma
@ 2019-05-05 12:17 ` imeevma
  2019-05-15 13:32   ` [tarantool-patches] " n.pettik
  2019-05-05 12:17 ` [tarantool-patches] [PATCH v1 11/12] sql: remove sqlError() and remove sqlErrorWithMsg() imeevma
  2019-05-05 12:17 ` [tarantool-patches] [PATCH v1 12/12] sql: use diag_set() to set an error in SQL functions imeevma
  11 siblings, 1 reply; 31+ messages in thread
From: imeevma @ 2019-05-05 12:17 UTC (permalink / raw)
  To: korablev; +Cc: tarantool-patches

This field became unusued and should be removed.
---
 src/box/sql/main.c    | 18 ------------------
 src/box/sql/prepare.c |  2 --
 src/box/sql/sqlInt.h  |  1 -
 src/box/sql/util.c    |  2 --
 src/box/sql/vdbeapi.c |  1 -
 5 files changed, 24 deletions(-)

diff --git a/src/box/sql/main.c b/src/box/sql/main.c
index a3c6aa1..155cbcc 100644
--- a/src/box/sql/main.c
+++ b/src/box/sql/main.c
@@ -568,22 +568,6 @@ sqlTempInMemory(const sql * db)
 }
 
 /*
- * Return the most recent error code generated by an sql routine. If NULL is
- * passed to this function, we assume a malloc() failed during sql_open().
- */
-int
-sql_errcode(sql * db)
-{
-	if (db && !sqlSafetyCheckSickOrOk(db)) {
-		return SQL_MISUSE;
-	}
-	if (!db || db->mallocFailed) {
-		return SQL_NOMEM;
-	}
-	return db->errCode & db->errMask;
-}
-
-/*
  * This array defines hard upper bounds on limit values.  The
  * initializer must be kept in sync with the SQL_LIMIT_*
  * #defines in sql.h.
@@ -734,7 +718,6 @@ sql_init_db(sql **out_db)
 	 */
 	sqlError(db, SQL_OK);
 	sqlRegisterPerConnectionBuiltinFunctions(db);
-	rc = sql_errcode(db);
 
 	if (rc)
 		sqlError(db, rc);
@@ -744,7 +727,6 @@ sql_init_db(sql **out_db)
 		       sqlGlobalConfig.nLookaside);
 
 opendb_out:
-	rc = sql_errcode(db);
 	assert(db != 0 || rc == SQL_NOMEM);
 	if (rc == SQL_NOMEM) {
 		sql_close(db);
diff --git a/src/box/sql/prepare.c b/src/box/sql/prepare.c
index 3df6b5c..3f1e1e0 100644
--- a/src/box/sql/prepare.c
+++ b/src/box/sql/prepare.c
@@ -166,8 +166,6 @@ sqlPrepare(sql * db,	/* Database handle. */
 		*ppStmt = (sql_stmt *) sParse.pVdbe;
 	}
 
-	db->errCode = rc;
-
 	/* Delete any TriggerPrg structures allocated while parsing this statement. */
 	while (sParse.pTriggerPrg) {
 		TriggerPrg *pT = sParse.pTriggerPrg;
diff --git a/src/box/sql/sqlInt.h b/src/box/sql/sqlInt.h
index 1af5457..e6de71c 100644
--- a/src/box/sql/sqlInt.h
+++ b/src/box/sql/sqlInt.h
@@ -1428,7 +1428,6 @@ struct sql {
 	struct Vdbe *pVdbe;	/* List of active virtual machines */
 	struct coll *pDfltColl;	/* The default collating sequence (BINARY) */
 	i64 szMmap;		/* Default mmap_size setting */
-	int errCode;		/* Most recent error code (sql_*) */
 	int errMask;		/* & result codes with this before returning */
 	int iSysErrno;		/* Errno value from last system error */
 	u16 dbOptFlags;		/* Flags to enable/disable optimizations */
diff --git a/src/box/sql/util.c b/src/box/sql/util.c
index 62c29ce..819f7fa 100644
--- a/src/box/sql/util.c
+++ b/src/box/sql/util.c
@@ -150,7 +150,6 @@ void
 sqlError(sql * db, int err_code)
 {
 	assert(db != 0);
-	db->errCode = err_code;
 	if (err_code)
 		sqlErrorFinish(db, err_code);
 }
@@ -195,7 +194,6 @@ void
 sqlErrorWithMsg(sql * db, int err_code, const char *zFormat, ...)
 {
 	assert(db != 0);
-	db->errCode = err_code;
 	sqlSystemError(db, err_code);
 	if (zFormat == 0)
 		sqlError(db, err_code);
diff --git a/src/box/sql/vdbeapi.c b/src/box/sql/vdbeapi.c
index 34fa5c8..5a859fe 100644
--- a/src/box/sql/vdbeapi.c
+++ b/src/box/sql/vdbeapi.c
@@ -564,7 +564,6 @@ sqlStep(Vdbe * p)
 		checkProfileCallback(db, p);
 #endif
 
-	db->errCode = rc;
 	if (SQL_NOMEM == sqlApiExit(p->db, p->rc)) {
 		p->rc = SQL_NOMEM;
 	}
-- 
2.7.4

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

* [tarantool-patches] [PATCH v1 11/12] sql: remove sqlError() and remove sqlErrorWithMsg()
  2019-05-05 12:17 [tarantool-patches] [PATCH v1 00/12] sql: set errors in VDBE using diag_set() imeevma
                   ` (9 preceding siblings ...)
  2019-05-05 12:17 ` [tarantool-patches] [PATCH v1 10/12] sql: remove field errCode " imeevma
@ 2019-05-05 12:17 ` imeevma
  2019-05-05 12:17 ` [tarantool-patches] [PATCH v1 12/12] sql: use diag_set() to set an error in SQL functions imeevma
  11 siblings, 0 replies; 31+ messages in thread
From: imeevma @ 2019-05-05 12:17 UTC (permalink / raw)
  To: korablev; +Cc: tarantool-patches

These functions are part of the SQL error system, which is
replaced by the Tarantool error system. They are not needed now,
so they will be deleted.
---
 src/box/lua/lua_sql.c         |  2 +-
 src/box/sql/legacy.c          |  2 --
 src/box/sql/main.c            | 83 +++++++------------------------------------
 src/box/sql/malloc.c          |  1 -
 src/box/sql/prepare.c         |  6 ++--
 src/box/sql/sqlInt.h          |  6 ----
 src/box/sql/util.c            | 69 -----------------------------------
 src/box/sql/vdbeInt.h         |  1 -
 src/box/sql/vdbeapi.c         |  7 +---
 src/box/sql/vdbeaux.c         | 31 +++++-----------
 test/sql/func-recreate.result |  3 +-
 11 files changed, 27 insertions(+), 184 deletions(-)

diff --git a/src/box/lua/lua_sql.c b/src/box/lua/lua_sql.c
index 36b75ff..d28045a 100644
--- a/src/box/lua/lua_sql.c
+++ b/src/box/lua/lua_sql.c
@@ -196,6 +196,6 @@ lbox_sql_create_function(struct lua_State *L)
 					   func_info, lua_sql_call, NULL, NULL,
 					   lua_sql_destroy);
 	if (rc != 0)
-		return luaL_error(L, sqlErrStr(rc));
+		return luaT_error(L);
 	return 0;
 }
diff --git a/src/box/sql/legacy.c b/src/box/sql/legacy.c
index ee680ef..b6e8f6e 100644
--- a/src/box/sql/legacy.c
+++ b/src/box/sql/legacy.c
@@ -70,7 +70,6 @@ sql_exec(sql * db,	/* The database on which the SQL executes */
 	if (zSql == 0)
 		zSql = "";
 
-	sqlError(db, SQL_OK);
 	while (rc == SQL_OK && zSql[0]) {
 		int nCol;
 		char **azVals = 0;
@@ -145,7 +144,6 @@ sql_exec(sql * db,	/* The database on which the SQL executes */
 					rc = SQL_ABORT;
 					sqlVdbeFinalize((Vdbe *) pStmt);
 					pStmt = 0;
-					sqlError(db, SQL_ABORT);
 					goto exec_out;
 				}
 			}
diff --git a/src/box/sql/main.c b/src/box/sql/main.c
index 155cbcc..f35c84f 100644
--- a/src/box/sql/main.c
+++ b/src/box/sql/main.c
@@ -284,61 +284,6 @@ functionDestroy(sql * db, FuncDef * p)
 }
 
 /*
- * Return TRUE if database connection db has unfinalized prepared
- * statement.
- */
-static int
-connectionIsBusy(sql * db)
-{
-	if (db->pVdbe)
-		return 1;
-	return 0;
-}
-
-/*
- * Close an existing sql database
- */
-static int
-sqlClose(sql * db, int forceZombie)
-{
-	assert(db);
-	if (!sqlSafetyCheckSickOrOk(db)) {
-		return SQL_MISUSE;
-	}
-	if (db->mTrace & SQL_TRACE_CLOSE) {
-		db->xTrace(SQL_TRACE_CLOSE, db->pTraceArg, db, 0);
-	}
-
-	/* Legacy behavior (sql_close() behavior) is to return
-	 * SQL_BUSY if the connection can not be closed immediately.
-	 */
-	if (!forceZombie && connectionIsBusy(db)) {
-		sqlErrorWithMsg(db, SQL_BUSY,
-				    "unable to close due to unfinalized "
-				    "statements");
-		return SQL_BUSY;
-	}
-
-	/* Convert the connection into a zombie and then close it.
-	 */
-	db->magic = SQL_MAGIC_ZOMBIE;
-
-	return SQL_OK;
-}
-
-/*
- * Two variations on the public interface for closing a database
- * connection. The sql_close() version returns SQL_BUSY and
- * leaves the connection option if there are unfinalized prepared
- * statements.
- */
-int
-sql_close(sql * db)
-{
-	return sqlClose(db, 0);
-}
-
-/*
  * Rollback all database files.  If tripCode is not SQL_OK, then
  * any write cursors are invalidated ("tripped" - as in "tripping a circuit
  * breaker") and made to return tripCode if there are any further
@@ -417,7 +362,9 @@ sqlCreateFunc(sql * db,
 	    (!xSFunc && (!xFinal && xStep)) ||
 	    (nArg < -1 || nArg > SQL_MAX_FUNCTION_ARG) ||
 	    (255 < (sqlStrlen30(zFunctionName)))) {
-		return SQL_MISUSE;
+		diag_set(ClientError, ER_CREATE_FUNCTION, zFunctionName,
+			 "wrong function definition");
+		return SQL_TARANTOOL_ERROR;
 	}
 
 	assert(SQL_FUNC_CONSTANT == SQL_DETERMINISTIC);
@@ -432,10 +379,10 @@ sqlCreateFunc(sql * db,
 	p = sqlFindFunction(db, zFunctionName, nArg, 0);
 	if (p && p->nArg == nArg) {
 		if (db->nVdbeActive) {
-			sqlErrorWithMsg(db, SQL_BUSY,
-					    "unable to delete/modify user-function due to active statements");
-			assert(!db->mallocFailed);
-			return SQL_BUSY;
+			diag_set(ClientError, ER_CREATE_FUNCTION, zFunctionName,
+				 "unable to create function due to active "\
+				 "statements");
+			return SQL_TARANTOOL_ERROR;
 		} else {
 			sqlExpirePreparedStatements(db);
 		}
@@ -443,9 +390,8 @@ sqlCreateFunc(sql * db,
 
 	p = sqlFindFunction(db, zFunctionName, nArg, 1);
 	assert(p || db->mallocFailed);
-	if (!p) {
-		return SQL_NOMEM;
-	}
+	if (p == NULL)
+		return SQL_TARANTOOL_ERROR;
 
 	/* If an older version of the function with a configured destructor is
 	 * being replaced invoke the destructor function here.
@@ -716,22 +662,17 @@ sql_init_db(sql **out_db)
 	 * database schema yet. This is delayed until the first time the database
 	 * is accessed.
 	 */
-	sqlError(db, SQL_OK);
 	sqlRegisterPerConnectionBuiltinFunctions(db);
 
-	if (rc)
-		sqlError(db, rc);
-
 	/* Enable the lookaside-malloc subsystem */
 	setupLookaside(db, 0, sqlGlobalConfig.szLookaside,
 		       sqlGlobalConfig.nLookaside);
 
 opendb_out:
 	assert(db != 0 || rc == SQL_NOMEM);
-	if (rc == SQL_NOMEM) {
-		sql_close(db);
-		db = 0;
-	} else if (rc != SQL_OK)
+	if (rc == SQL_NOMEM)
+		db = NULL;
+	else if (rc != SQL_OK)
 		db->magic = SQL_MAGIC_SICK;
 
 	*out_db = db;
diff --git a/src/box/sql/malloc.c b/src/box/sql/malloc.c
index dbc6846..a531a8c 100644
--- a/src/box/sql/malloc.c
+++ b/src/box/sql/malloc.c
@@ -926,7 +926,6 @@ static SQL_NOINLINE int
 apiOomError(sql * db)
 {
 	sqlOomClear(db);
-	sqlError(db, SQL_NOMEM);
 	return SQL_NOMEM;
 }
 
diff --git a/src/box/sql/prepare.c b/src/box/sql/prepare.c
index 3f1e1e0..5e0faa1 100644
--- a/src/box/sql/prepare.c
+++ b/src/box/sql/prepare.c
@@ -81,9 +81,9 @@ sqlPrepare(sql * db,	/* Database handle. */
 		testcase(nBytes == mxLen);
 		testcase(nBytes == mxLen + 1);
 		if (nBytes > mxLen) {
-			sqlErrorWithMsg(db, SQL_TOOBIG,
-					    "statement too long");
-			rc = sqlApiExit(db, SQL_TOOBIG);
+			diag_set(ClientError, ER_SQL_PARSER_LIMIT,
+				 "SQL command length", nBytes, mxLen);
+			rc = SQL_TARANTOOL_ERROR;
 			goto end_prepare;
 		}
 		zSqlCopy = sqlDbStrNDup(db, zSql, nBytes);
diff --git a/src/box/sql/sqlInt.h b/src/box/sql/sqlInt.h
index e6de71c..c757fb5 100644
--- a/src/box/sql/sqlInt.h
+++ b/src/box/sql/sqlInt.h
@@ -922,9 +922,6 @@ sql_stmt_busy(sql_stmt *);
 int
 sql_init_db(sql **db);
 
-int
-sql_close(sql *);
-
 
 /**
  * Get number of the named parameter in the prepared sql
@@ -1429,7 +1426,6 @@ struct sql {
 	struct coll *pDfltColl;	/* The default collating sequence (BINARY) */
 	i64 szMmap;		/* Default mmap_size setting */
 	int errMask;		/* & result codes with this before returning */
-	int iSysErrno;		/* Errno value from last system error */
 	u16 dbOptFlags;		/* Flags to enable/disable optimizations */
 	u8 enc;			/* Text encoding */
 	u8 temp_store;		/* 1: file 2: memory 0: default */
@@ -4431,8 +4427,6 @@ sql_atoi64(const char *z, int64_t *val, int length);
 int
 sql_dec_or_hex_to_i64(const char *z, int64_t *val);
 
-void sqlErrorWithMsg(sql *, int, const char *, ...);
-void sqlError(sql *, int);
 void sqlSystemError(sql *, int);
 void *sqlHexToBlob(sql *, const char *z, int n);
 u8 sqlHexToInt(int h);
diff --git a/src/box/sql/util.c b/src/box/sql/util.c
index 819f7fa..d5f6447 100644
--- a/src/box/sql/util.c
+++ b/src/box/sql/util.c
@@ -131,75 +131,6 @@ sqlStrlen30(const char *z)
 }
 
 /*
- * Helper function for sqlError() - called rarely.  Broken out into
- * a separate routine to avoid unnecessary register saves on entry to
- * sqlError().
- */
-static SQL_NOINLINE void
-sqlErrorFinish(sql * db, int err_code)
-{
-	sqlSystemError(db, err_code);
-}
-
-/*
- * Set the current error code to err_code and clear any prior error message.
- * Also set iSysErrno (by calling sqlSystem) if the err_code indicates
- * that would be appropriate.
- */
-void
-sqlError(sql * db, int err_code)
-{
-	assert(db != 0);
-	if (err_code)
-		sqlErrorFinish(db, err_code);
-}
-
-/*
- * Load the sql.iSysErrno field if that is an appropriate thing
- * to do based on the sql error code in rc.
- */
-void
-sqlSystemError(sql * db, int rc)
-{
-	if (rc == SQL_IOERR_NOMEM)
-		return;
-	rc &= 0xff;
-	if (rc == SQL_CANTOPEN || rc == SQL_IOERR) {
-		db->iSysErrno = sqlOsGetLastError(db->pVfs);
-	}
-}
-
-/*
- * Set the most recent error code and error string for the sql
- * handle "db". The error code is set to "err_code".
- *
- * If it is not NULL, string zFormat specifies the format of the
- * error string in the style of the printf functions: The following
- * format characters are allowed:
- *
- *      %s      Insert a string
- *      %z      A string that should be freed after use
- *      %d      Insert an integer
- *      %T      Insert a token
- *      %S      Insert the first element of a SrcList
- *
- * zFormat and any string tokens that follow it are assumed to be
- * encoded in UTF-8.
- *
- * To clear the most recent error for sql handle "db", sqlError
- * should be called with err_code set to SQL_OK and zFormat set
- * to NULL.
- */
-void
-sqlErrorWithMsg(sql * db, int err_code, const char *zFormat, ...)
-{
-	assert(db != 0);
-	sqlSystemError(db, err_code);
-	if (zFormat == 0)
-		sqlError(db, err_code);
-}
-
-/*
  * Convert an SQL-style quoted string into a normal string by removing
  * the quote characters.  The conversion is done in-place.  If the
  * input does not begin with a quote character, then this routine
diff --git a/src/box/sql/vdbeInt.h b/src/box/sql/vdbeInt.h
index de9dbd6..6aadca2 100644
--- a/src/box/sql/vdbeInt.h
+++ b/src/box/sql/vdbeInt.h
@@ -519,7 +519,6 @@ int sqlVdbeMemClearAndResize(Mem * pMem, int n);
 int sqlVdbeCloseStatement(Vdbe *, int);
 void sqlVdbeFrameDelete(VdbeFrame *);
 int sqlVdbeFrameRestore(VdbeFrame *);
-int sqlVdbeTransferError(Vdbe * p);
 
 int sqlVdbeSorterInit(struct sql *db, struct VdbeCursor *cursor);
 void sqlVdbeSorterReset(sql *, VdbeSorter *);
diff --git a/src/box/sql/vdbeapi.c b/src/box/sql/vdbeapi.c
index 5a859fe..d9dd28f 100644
--- a/src/box/sql/vdbeapi.c
+++ b/src/box/sql/vdbeapi.c
@@ -573,7 +573,7 @@ sqlStep(Vdbe * p)
 		 * error has occurred, then return the error code in p->rc to the
 		 * caller. Set the error code in the database handle to the same value.
 		 */
-		rc = sqlVdbeTransferError(p);
+		rc = p->rc;
 	}
 	return (rc & db->errMask);
 }
@@ -877,7 +877,6 @@ columnMem(sql_stmt * pStmt, int i)
 	if (pVm->pResultSet != 0 && i < pVm->nResColumn && i >= 0) {
 		pOut = &pVm->pResultSet[i];
 	} else {
-		sqlError(pVm->db, SQL_RANGE);
 		pOut = (Mem *) columnNullValue();
 	}
 	return pOut;
@@ -1148,20 +1147,17 @@ vdbeUnbind(Vdbe * p, int i)
 		return SQL_MISUSE;
 	}
 	if (p->magic != VDBE_MAGIC_RUN || p->pc >= 0) {
-		sqlError(p->db, SQL_MISUSE);
 		sql_log(SQL_MISUSE,
 			    "bind on a busy prepared statement: [%s]", p->zSql);
 		return SQL_MISUSE;
 	}
 	if (i < 1 || i > p->nVar) {
-		sqlError(p->db, SQL_RANGE);
 		return SQL_RANGE;
 	}
 	i--;
 	pVar = &p->aVar[i];
 	sqlVdbeMemRelease(pVar);
 	pVar->flags = MEM_Null;
-	sqlError(p->db, SQL_OK);
 
 	/* If the bit corresponding to this variable in Vdbe.expmask is set, then
 	 * binding a new value to this variable invalidates the current query plan.
@@ -1247,7 +1243,6 @@ bindText(sql_stmt * pStmt,	/* The statement to bind against */
 			rc = sqlVdbeMemSetStr(pVar, zData, nData, 1, xDel);
 			if (rc == SQL_OK)
 				rc = sql_bind_type(p, i, "TEXT");
-			sqlError(p->db, rc);
 			rc = sqlApiExit(p->db, rc);
 		}
 	} else if (xDel != SQL_STATIC && xDel != SQL_TRANSIENT) {
diff --git a/src/box/sql/vdbeaux.c b/src/box/sql/vdbeaux.c
index 300a44b..38cd195 100644
--- a/src/box/sql/vdbeaux.c
+++ b/src/box/sql/vdbeaux.c
@@ -2373,23 +2373,6 @@ sqlVdbeResetStepResult(Vdbe * p)
 }
 
 /*
- * Copy the error code and error message belonging to the VDBE passed
- * as the first argument to its database handle (so that they will be
- * returned by calls to sql_errcode() and sql_errmsg()).
- *
- * This function does not clear the VDBE error code or message, just
- * copies them to the database handle.
- */
-int
-sqlVdbeTransferError(Vdbe * p)
-{
-	sql *db = p->db;
-	int rc = p->rc;
-	sqlError(db, rc);
-	return rc;
-}
-
-/*
  * Clean up a VDBE after execution but do not delete the VDBE just yet.
  * Return the result code.
  *
@@ -2418,15 +2401,17 @@ sqlVdbeReset(Vdbe * p)
 	 * instructions yet, leave the main database error information unchanged.
 	 */
 	if (p->pc >= 0) {
-		sqlVdbeTransferError(p);
 		if (p->runOnlyOnce)
 			p->expired = 1;
-	} else if (p->rc && p->expired) {
-		/* The expired flag was set on the VDBE before the first call
-		 * to sql_step(). For consistency (since sql_step() was
-		 * called), set the database error in this case as well.
+	} else {
+		/*
+		 * An error should be thrown here if the expired
+		 * flag is set on the VDBE flag with the first
+		 * call to sql_step(). However, the expired flag
+		 * is currently disabled, so this error has been
+		 * replaced with assert.
 		 */
-		sqlErrorWithMsg(db, p->rc, NULL);
+		assert(p->rc == 0 || p->expired == 0);
 	}
 
 	/* Reclaim all memory used by the VDBE
diff --git a/test/sql/func-recreate.result b/test/sql/func-recreate.result
index d713292..73fb03c 100644
--- a/test/sql/func-recreate.result
+++ b/test/sql/func-recreate.result
@@ -26,7 +26,8 @@ fiber.sleep(0.1)
 ...
 box.internal.sql_create_function('WAITFOR', 'INT', function (n) require('fiber').sleep(n) return n end)
 ---
-- error: database is locked
+- error: 'Failed to create function ''WAITFOR'': unable to create function due to
+    active statements'
 ...
 ch:get()
 ---
-- 
2.7.4

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

* [tarantool-patches] [PATCH v1 12/12] sql: use diag_set() to set an error in SQL functions
  2019-05-05 12:17 [tarantool-patches] [PATCH v1 00/12] sql: set errors in VDBE using diag_set() imeevma
                   ` (10 preceding siblings ...)
  2019-05-05 12:17 ` [tarantool-patches] [PATCH v1 11/12] sql: remove sqlError() and remove sqlErrorWithMsg() imeevma
@ 2019-05-05 12:17 ` imeevma
  2019-05-15 14:12   ` [tarantool-patches] " n.pettik
  11 siblings, 1 reply; 31+ messages in thread
From: imeevma @ 2019-05-05 12:17 UTC (permalink / raw)
  To: korablev; +Cc: tarantool-patches

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

Closes #4074
---
 src/box/lua/lua_sql.c |  13 +++--
 src/box/sql/analyze.c |   6 +--
 src/box/sql/func.c    | 104 ++++++++++++++++++----------------------
 src/box/sql/sqlInt.h  |  13 -----
 src/box/sql/vdbe.c    |  34 +++----------
 src/box/sql/vdbeInt.h |  28 ++---------
 src/box/sql/vdbeapi.c | 129 +++++---------------------------------------------
 src/box/sql/vdbeaux.c |  46 ------------------
 src/box/sql/vdbemem.c |   9 ++--
 9 files changed, 84 insertions(+), 298 deletions(-)

diff --git a/src/box/lua/lua_sql.c b/src/box/lua/lua_sql.c
index d28045a..afe4732 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_error = 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_error = 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_error = true;
 		goto error;
 	}
 error:
diff --git a/src/box/sql/analyze.c b/src/box/sql/analyze.c
index 0c02050..46ea10e 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_error = 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_error = 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_error = true;
 	} else {
 		int i;
 		char *z = zRet;
diff --git a/src/box/sql/func.c b/src/box/sql/func.c
index bb7405e..16c02f1 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 overflow");
+					context->is_error = 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_error = 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_error = 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_error = 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_error = true;
 		z = 0;
 	} else {
 		z = sqlMalloc(nByte);
-		if (!z) {
-			sql_result_error_nomem(context);
-		}
+		if (z == NULL)
+			context->is_error = true;
 	}
 	return z;
 }
@@ -591,11 +577,11 @@ case_type##ICUFunc(sql_context *context, int argc, sql_value **argv)   \
 	 * does not invalidate the _text() pointer.                            \
 	 */                                                                    \
 	assert(z2 == (char *)sql_value_text(argv[0]));                     \
-	if (!z2)                                                               \
+	if (z2 == NULL)                                                        \
 		return;                                                        \
 	z1 = contextMalloc(context, ((i64) n) + 1);                            \
-	if (!z1) {                                                             \
-		sql_result_error_nomem(context);                           \
+	if (z1 == NULL) {                                                      \
+		context->is_error = 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_error = 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_error = 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_error = 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_error = 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_error = 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_error = 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_error = 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_error = true;
 				sql_free(zOut);
 				return;
 			}
 			zOld = zOut;
 			zOut = sql_realloc64(zOut, (int)nOut);
 			if (zOut == 0) {
-				sql_result_error_nomem(context);
+				context->is_error = 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_error = 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_error = 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_error = true;
 		} else if (pAccum->accError == STRACCUM_NOMEM) {
-			sql_result_error_nomem(context);
+			context->is_error = true;
 		} else {
 			sql_result_text(context,
 					    sqlStrAccumFinish(pAccum),
diff --git a/src/box/sql/sqlInt.h b/src/box/sql/sqlInt.h
index c757fb5..511f504 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 115f22e..a4d82e1 100644
--- a/src/box/sql/vdbe.c
+++ b/src/box/sql/vdbe.c
@@ -1709,22 +1709,12 @@ case OP_Function: {
 	}
 #endif
 	MemSetTypeFlag(pCtx->pOut, MEM_Null);
-	pCtx->fErrorOrAux = 0;
+	pCtx->is_error = 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) {
-			if (pCtx->isError != SQL_TARANTOOL_ERROR) {
-				diag_set(ClientError, ER_SQL_EXECUTE,
-					 sql_value_text(pCtx->pOut));
-			}
-			rc = SQL_TARANTOOL_ERROR;
-		}
-		sqlVdbeDeleteAuxData(db, &p->pAuxData, pCtx->iOp, pOp->p1);
-		if (rc != SQL_OK)
-			goto abort_due_to_error;
-	}
+	if (pCtx->is_error)
+		goto abort_due_to_error;
 
 	/* Copy the result of the function into register P3 */
 	if (pOut->flags & (MEM_Str|MEM_Blob)) {
@@ -4856,9 +4846,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);
@@ -5121,21 +5108,12 @@ case OP_AggStep: {
 	pMem->n++;
 	sqlVdbeMemInit(&t, db, MEM_Null);
 	pCtx->pOut = &t;
-	pCtx->fErrorOrAux = 0;
+	pCtx->is_error = false;
 	pCtx->skipFlag = 0;
 	(pCtx->pFunc->xSFunc)(pCtx,pCtx->argc,pCtx->argv); /* IMP: R-24505-23230 */
-	if (pCtx->fErrorOrAux) {
-		if (pCtx->isError) {
-			if (pCtx->isError != SQL_TARANTOOL_ERROR) {
-				diag_set(ClientError, ER_SQL_EXECUTE,
-					 sql_value_text(&t));
-			}
-			rc = SQL_TARANTOOL_ERROR;
-		}
+	if (pCtx->is_error) {
 		sqlVdbeMemRelease(&t);
-		assert(rc == SQL_OK || rc == SQL_TARANTOOL_ERROR);
-		if (rc != SQL_OK)
-			goto abort_due_to_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 6aadca2..70a0bab 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 */
@@ -300,21 +296,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.
@@ -333,9 +314,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_error;
 	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 */
 };
@@ -440,7 +424,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
@@ -472,7 +455,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 d9dd28f..cf96e2d 100644
--- a/src/box/sql/vdbeapi.c
+++ b/src/box/sql/vdbeapi.c
@@ -319,7 +319,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_error = true;
 	}
 }
 
@@ -337,8 +338,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_error = true;
+	}
 	return SQL_TOOBIG;
 }
 
@@ -349,7 +352,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_error = true;
 	}
 }
 
@@ -373,14 +377,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);
@@ -449,37 +445,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.
@@ -677,13 +642,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_error = true;
 }
 
 /*
@@ -727,75 +689,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 38cd195..697dffd 100644
--- a/src/box/sql/vdbeaux.c
+++ b/src/box/sql/vdbeaux.c
@@ -1388,7 +1388,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);
 }
 
@@ -1907,9 +1906,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;
 }
 
@@ -1953,11 +1949,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);
 }
 
 /*
@@ -2480,43 +2471,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 f73ea0a..ce0c641 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_error ? SQL_TARANTOOL_ERROR : SQL_OK;
 	}
-	return rc;
+	return SQL_OK;
 }
 
 /*
@@ -1281,7 +1280,7 @@ valueFromFunction(sql * db,	/* The database connection */
 	ctx.pOut = pVal;
 	ctx.pFunc = pFunc;
 	pFunc->xSFunc(&ctx, nVal, apVal);
-	assert(!ctx.isError);
+	assert(!ctx.is_error);
 	sql_value_apply_type(pVal, type);
 	assert(rc == SQL_OK);
 
@@ -1486,7 +1485,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_error = true;
 	} else {
 		aRet[0] = nSerial + 1;
 		putVarint32(&aRet[1], iSerial);
-- 
2.7.4

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

* [tarantool-patches] Re: [PATCH v1 01/12] sql: remove errors SQL_TARANTOOL_*_FAIL
  2019-05-05 12:17 ` [tarantool-patches] [PATCH v1 01/12] sql: remove errors SQL_TARANTOOL_*_FAIL imeevma
@ 2019-05-15 13:18   ` n.pettik
  2019-05-25  9:16     ` Imeev Mergen
  0 siblings, 1 reply; 31+ messages in thread
From: n.pettik @ 2019-05-15 13:18 UTC (permalink / raw)
  To: tarantool-patches; +Cc: Imeev Mergen



> On 5 May 2019, at 15:17, imeevma@tarantool.org wrote:
> 
> Errors SQL_TARANTOOL_DELETE_FAIL, SQL_TARANTOOL_ITERATOR_FAIL and
> SQL_TARANTOOL_INSERT_FAIL have almost no functionality, but can

Nit: they are not errors, but rather error codes.

> diff --git a/src/box/sql.c b/src/box/sql.c
> index 1fb93e1..3593242 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());
> }
> 
> 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;

Let’s return -1 and set tarantool_error only in VDBE.
Later, we are going to replace tarantool_error with -1 everywhere.
The same concerns other tarantool_error usages in sql.c

> 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 3bd8223..5222a4e 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()) {

Isn’t tarantoolErrorMessage redundant check? Is it possible
to use SQL_TARANTOOL_ERROR without set diag?

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

* [tarantool-patches] Re: [PATCH v1 02/12] sql: remove error ER_SQL
  2019-05-05 12:17 ` [tarantool-patches] [PATCH v1 02/12] sql: remove error ER_SQL imeevma
@ 2019-05-15 13:18   ` n.pettik
  0 siblings, 0 replies; 31+ messages in thread
From: n.pettik @ 2019-05-15 13:18 UTC (permalink / raw)
  To: tarantool-patches; +Cc: Imeev Mergen

LGTM

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

* [tarantool-patches] Re: [PATCH v1 03/12] sql: rework diag_set() in OP_Halt
  2019-05-05 12:17 ` [tarantool-patches] [PATCH v1 03/12] sql: rework diag_set() in OP_Halt imeevma
@ 2019-05-15 13:18   ` n.pettik
  0 siblings, 0 replies; 31+ messages in thread
From: n.pettik @ 2019-05-15 13:18 UTC (permalink / raw)
  To: tarantool-patches; +Cc: Imeev Mergen

AFAIR I’ve already seen this patch.

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

* [tarantool-patches] Re: [PATCH v1 04/12] sql: make SQL_TARANTOOL_ERROR the only errcode of OP_Halt
  2019-05-05 12:17 ` [tarantool-patches] [PATCH v1 04/12] sql: make SQL_TARANTOOL_ERROR the only errcode of OP_Halt imeevma
@ 2019-05-15 13:18   ` n.pettik
  2019-05-25  9:18     ` Imeev Mergen
  0 siblings, 1 reply; 31+ messages in thread
From: n.pettik @ 2019-05-15 13:18 UTC (permalink / raw)
  To: tarantool-patches; +Cc: Imeev Mergen



> On 5 May 2019, at 15:17, imeevma@tarantool.org wrote:
> 
> 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.
> 
> diff --git a/src/box/sql/vdbe.c b/src/box/sql/vdbe.c
> index 9f0d760..85cec85 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);

Still don’t understand why can’t we use only 0/-1 for rc.

> +		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] 31+ messages in thread

* [tarantool-patches] Re: [PATCH v1 05/12] sql: remove error SQL_INTERRUPT
  2019-05-05 12:17 ` [tarantool-patches] [PATCH v1 05/12] sql: remove error SQL_INTERRUPT imeevma
@ 2019-05-15 13:18   ` n.pettik
  0 siblings, 0 replies; 31+ messages in thread
From: n.pettik @ 2019-05-15 13:18 UTC (permalink / raw)
  To: tarantool-patches; +Cc: Imeev Mergen

Patch is OK.

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

* [tarantool-patches] Re: [PATCH v1 06/12] sql: remove error SQL_MISMATCH
  2019-05-05 12:17 ` [tarantool-patches] [PATCH v1 06/12] sql: remove error SQL_MISMATCH imeevma
@ 2019-05-15 13:19   ` n.pettik
  0 siblings, 0 replies; 31+ messages in thread
From: n.pettik @ 2019-05-15 13:19 UTC (permalink / raw)
  To: tarantool-patches; +Cc: Imeev Mergen

LGTM

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

* [tarantool-patches] Re: [PATCH v1 07/12] sql: set errors in VDBE using diag_set()
  2019-05-05 12:17 ` [tarantool-patches] [PATCH v1 07/12] sql: set errors in VDBE using diag_set() imeevma
@ 2019-05-15 13:26   ` n.pettik
  2019-05-25 10:24     ` Mergen Imeev
  0 siblings, 1 reply; 31+ messages in thread
From: n.pettik @ 2019-05-15 13:26 UTC (permalink / raw)
  To: tarantool-patches; +Cc: Imeev Mergen



> On 5 May 2019, at 15:17, imeevma@tarantool.org wrote:
> 
> After this patch, all errors in VDBE will be set using diag_set().
> 
> Part of #4074
> ---
> src/box/execute.c     |  23 +---
> src/box/sql/vdbe.c    | 331 +++++++++++++++++++++-----------------------------
> src/box/sql/vdbeInt.h |  10 --
> src/box/sql/vdbeapi.c |  34 +-----
> src/box/sql/vdbeaux.c |  20 +--
> 5 files changed, 148 insertions(+), 270 deletions(-)

Please, remove whole sqlErrStr(), tarantoolErrorMessage() -
they are unused now. The same concerns sql_ret_code() -
I see no reason keeping it. Please, remove all legacy routines
connected with error codes.

> 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
> 
> @@ -1335,7 +1331,8 @@ 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))) {
> +	rc = sqlVdbeCheckFk(p, 0);
> +	if (rc != SQL_OK) {

-> if (sqlVdbeCheckFk() != 0)

> 		assert(user_session->sql_flags&SQL_CountRows);
> 		goto abort_due_to_error;
> 	}
> 
> @@ -1435,10 +1431,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;

!= 0
Still need to call sqlOomFault(db); by jumping to no_mem label.

> 	nByte = pIn1->n + pIn2->n;
> 	if (nByte>db->aLimit[SQL_LIMIT_LENGTH]) {
> 		goto too_big;
> 
> 
> @@ -1723,11 +1715,15 @@ case OP_Function: {
> 	/* 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;
> +			if (pCtx->isError != SQL_TARANTOOL_ERROR) {

How it can be different from SQL_TARANTOOL_ERROR?

> +				diag_set(ClientError, ER_SQL_EXECUTE,
> +					 sql_value_text(pCtx->pOut));
> +			}
> +			rc = SQL_TARANTOOL_ERROR;
> 		}
> 		sqlVdbeDeleteAuxData(db, &p->pAuxData, pCtx->iOp, pOp->p1);
> -		if (rc) goto abort_due_to_error;
> +		if (rc != SQL_OK)
> +			goto abort_due_to_error;

This diff seems to be redundant

> @@ -1910,8 +1903,7 @@ case OP_Realify: {                  /* in1 */
>  */
> case OP_Cast: {                  /* in1 */
> 	pIn1 = &aMem[pOp->p1];
> -	rc = ExpandBlob(pIn1);
> -	if (rc != 0)
> +	if (ExpandBlob(pIn1) != SQL_OK)

!= 0
Please, don’t use SQL_OK value anywhere.

> 
> @@ -2802,10 +2784,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;
> 
> 
> @@ -2918,8 +2898,10 @@ case OP_Savepoint: {
> 			pSavepoint = pSavepoint->pNext
> 			);
> 		if (!pSavepoint) {
> -			sqlVdbeError(p, "no such savepoint: %s", zName);
> -			rc = SQL_ERROR;
> +			const char *err =
> +				tt_sprintf("no such savepoint: %s", zName);
> +			diag_set(ClientError, ER_SQL_EXECUTE, err);

We already have ER_NO_SUCH_SAVEPOINT.

> @@ -3685,10 +3645,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

> 
> @@ -5164,11 +5126,16 @@ case OP_AggStep: {
> 	(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->isError != SQL_TARANTOOL_ERROR) {
> +				diag_set(ClientError, ER_SQL_EXECUTE,
> +					 sql_value_text(&t));
> +			}
> +			rc = SQL_TARANTOOL_ERROR;
> 		}
> 		sqlVdbeMemRelease(&t);
> -		if (rc) goto abort_due_to_error;
> +		assert(rc == SQL_OK || rc == SQL_TARANTOOL_ERROR);
> +		if (rc != SQL_OK)
> +			goto abort_due_to_error;

Looks like redundant diff

> 	} else {
> 		assert(t.flags==MEM_Null);
> 	}
> @@ -5199,8 +5166,11 @@ case OP_AggFinal: {
> 	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 (rc != SQL_OK) {
> +		if (rc != SQL_TARANTOOL_ERROR) {
> +			diag_set(ClientError, ER_SQL_EXECUTE,
> +				 sql_value_text(pMem));

Could you please clarify what does this error mean?
It would just print value of memory to string…
The same relates to error in OP_AggStep.

> @@ -5311,10 +5281,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;
> }
> 
> too_big:
> -	sqlVdbeError(p, "string or blob too big");
> -	rc = SQL_TOOBIG;
> +	diag_set(ClientError, ER_SQL_EXECUTE, "string or blob too big”);

-> is 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 a3100e5..b655b5a 100644
> --- a/src/box/sql/vdbeInt.h
> +++ b/src/box/sql/vdbeInt.h
> @@ -248,10 +248,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
> 
> 
> @@ -550,13 +545,8 @@ void sqlVdbeMemPrettyPrint(Mem * pMem, char *zBuf);
> #endif
> int sqlVdbeMemHandleBom(Mem * pMem);
> 
> -#ifndef SQL_OMIT_INCRBLOB

Still see usage of this macro in code: vdbemem.c : 213

> 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/vdbeaux.c b/src/box/sql/vdbeaux.c
> index 27fa5b2..48c2a81 100644
> --- a/src/box/sql/vdbeaux.c
> +++ b/src/box/sql/vdbeaux.c
> void
> @@ -2124,10 +2111,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”);

Please, reserve separate error code for this violation.

> +		return SQL_TARANTOOL_ERROR;
> 	}
> 	return SQL_OK;

Return 0/-1

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

* [tarantool-patches] Re: [PATCH v1 08/12] sql: remove field zErrMsg from struct Vdbe
  2019-05-05 12:17 ` [tarantool-patches] [PATCH v1 08/12] sql: remove field zErrMsg from struct Vdbe imeevma
@ 2019-05-15 13:30   ` n.pettik
  2019-05-25  9:25     ` Imeev Mergen
  0 siblings, 1 reply; 31+ messages in thread
From: n.pettik @ 2019-05-15 13:30 UTC (permalink / raw)
  To: tarantool-patches; +Cc: Imeev Mergen



> On 5 May 2019, at 15:17, imeevma@tarantool.org wrote:
> 
> This field become unused and should be removed.

-> became/has become

Patch is OK.

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

* [tarantool-patches] Re: [PATCH v1 10/12] sql: remove field errCode from struct sql
  2019-05-05 12:17 ` [tarantool-patches] [PATCH v1 10/12] sql: remove field errCode " imeevma
@ 2019-05-15 13:32   ` n.pettik
  2019-05-25  9:25     ` Imeev Mergen
  0 siblings, 1 reply; 31+ messages in thread
From: n.pettik @ 2019-05-15 13:32 UTC (permalink / raw)
  To: tarantool-patches; +Cc: Imeev Mergen



> On 5 May 2019, at 15:17, imeevma@tarantool.org wrote:
> 
> This field became unusued and should be removed.
> ---
> 
> diff --git a/src/box/sql/main.c b/src/box/sql/main.c
> index a3c6aa1..155cbcc 100644
> --- a/src/box/sql/main.c
> +++ b/src/box/sql/main.c
> @@ -568,22 +568,6 @@ sqlTempInMemory(const sql * db)
> }
> 
> /*
> - * Return the most recent error code generated by an sql routine. If NULL is
> - * passed to this function, we assume a malloc() failed during sql_open().
> - */
> -int
> -sql_errcode(sql * db)

Still see several mentions of this function in comments.

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

* [tarantool-patches] Re: [PATCH v1 12/12] sql: use diag_set() to set an error in SQL functions
  2019-05-05 12:17 ` [tarantool-patches] [PATCH v1 12/12] sql: use diag_set() to set an error in SQL functions imeevma
@ 2019-05-15 14:12   ` n.pettik
  2019-05-25  9:45     ` Mergen Imeev
  0 siblings, 1 reply; 31+ messages in thread
From: n.pettik @ 2019-05-15 14:12 UTC (permalink / raw)
  To: tarantool-patches; +Cc: Imeev Mergen


> After this patch, all errors in the SQL functions will be set
> using diag_set().
> 
> Closes #4074
> ---
> src/box/lua/lua_sql.c |  13 +++--
> src/box/sql/analyze.c |   6 +--
> src/box/sql/func.c    | 104 ++++++++++++++++++----------------------
> src/box/sql/sqlInt.h  |  13 -----
> src/box/sql/vdbe.c    |  34 +++----------
> src/box/sql/vdbeInt.h |  28 ++---------
> src/box/sql/vdbeapi.c | 129 +++++---------------------------------------------
> src/box/sql/vdbeaux.c |  46 ------------------
> src/box/sql/vdbemem.c |   9 ++--
> 9 files changed, 84 insertions(+), 298 deletions(-)
> 
> diff --git a/src/box/lua/lua_sql.c b/src/box/lua/lua_sql.c
> index d28045a..afe4732 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);

Please, remove sql_result_error at all: I grepped several
usages among dead code.

> +			diag_set(ClientError, ER_SQL_EXECUTE, "Unsupported "\
> +				 "type passed to Lua");
> +			pCtx->is_error = true;
> 			goto error;
> 		}
> 
> diff --git a/src/box/sql/func.c b/src/box/sql/func.c
> index bb7405e..16c02f1 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 overflow”);

-> integer is overflowed.

> +					context->is_error = true;
> 					return;
> 				}
> 				iVal = -iVal;
> 
> 
> 
> @@ -591,11 +577,11 @@ case_type##ICUFunc(sql_context *context, int argc, sql_value **argv)   \
> 	 * does not invalidate the _text() pointer.                            \
> 	 */                                                                    \
> 	assert(z2 == (char *)sql_value_text(argv[0]));                     \
> -	if (!z2)                                                               \
> +	if (z2 == NULL)                                                        \
> 		return;                                                        \

Redundant diff.

> src/box/sql/vdbeInt.h b/src/box/sql/vdbeInt.h
> index 6aadca2..70a0bab 100644
> --- a/src/box/sql/vdbeInt.h
> +++ b/src/box/sql/vdbeInt.h
> 
> @@ -300,21 +296,6 @@ mem_apply_numeric_type(struct Mem *record);
> #endif
> 
> 
> -/*
>  * 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.
> @@ -333,9 +314,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_error;

I’d better use is_abotred name.

> diff --git a/src/box/sql/vdbemem.c b/src/box/sql/vdbemem.c
> index f73ea0a..ce0c641 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_error ? SQL_TARANTOOL_ERROR : SQL_OK;
> 	}
> -	return rc;
> +	return SQL_OK;

Return 0/-1

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

* [tarantool-patches] Re: [PATCH v1 01/12] sql: remove errors SQL_TARANTOOL_*_FAIL
  2019-05-15 13:18   ` [tarantool-patches] " n.pettik
@ 2019-05-25  9:16     ` Imeev Mergen
  0 siblings, 0 replies; 31+ messages in thread
From: Imeev Mergen @ 2019-05-25  9:16 UTC (permalink / raw)
  To: n.pettik, tarantool-patches

Hi! Thank you for review! My answers below.

On 5/15/19 4:18 PM, n.pettik wrote:
>
>> On 5 May 2019, at 15:17, imeevma@tarantool.org wrote:
>>
>> Errors SQL_TARANTOOL_DELETE_FAIL, SQL_TARANTOOL_ITERATOR_FAIL and
>> SQL_TARANTOOL_INSERT_FAIL have almost no functionality, but can
> Nit: they are not errors, but rather error codes.
Fixed.
>
>> diff --git a/src/box/sql.c b/src/box/sql.c
>> index 1fb93e1..3593242 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());
>> }
>>
>> 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;
> Let’s return -1 and set tarantool_error only in VDBE.
> Later, we are going to replace tarantool_error with -1 everywhere.
> The same concerns other tarantool_error usages in sql.c
I think it's better to leave it as it is. A bit later there will
be a patch-set, in which all SQL error codes will be replaced with
either 0 or -1.

>
>> 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 3bd8223..5222a4e 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()) {
> Isn’t tarantoolErrorMessage redundant check? Is it possible
> to use SQL_TARANTOOL_ERROR without set diag?
It is technically possible to install SQL_TARANTOOL_ERROR without
set diag. This code will be fixed in one of the following patches
of this patch-set.

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

* [tarantool-patches] Re: [PATCH v1 04/12] sql: make SQL_TARANTOOL_ERROR the only errcode of OP_Halt
  2019-05-15 13:18   ` [tarantool-patches] " n.pettik
@ 2019-05-25  9:18     ` Imeev Mergen
  0 siblings, 0 replies; 31+ messages in thread
From: Imeev Mergen @ 2019-05-25  9:18 UTC (permalink / raw)
  To: n.pettik, tarantool-patches


On 5/15/19 4:18 PM, n.pettik wrote:
>
>> On 5 May 2019, at 15:17, imeevma@tarantool.org wrote:
>>
>> 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.
>>
>> diff --git a/src/box/sql/vdbe.c b/src/box/sql/vdbe.c
>> index 9f0d760..85cec85 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);
> Still don’t understand why can’t we use only 0/-1 for rc.
This is done in one of the following patches.

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

* [tarantool-patches] Re: [PATCH v1 08/12] sql: remove field zErrMsg from struct Vdbe
  2019-05-15 13:30   ` [tarantool-patches] " n.pettik
@ 2019-05-25  9:25     ` Imeev Mergen
  0 siblings, 0 replies; 31+ messages in thread
From: Imeev Mergen @ 2019-05-25  9:25 UTC (permalink / raw)
  To: n.pettik, tarantool-patches


On 5/15/19 4:30 PM, n.pettik wrote:
>
>> On 5 May 2019, at 15:17, imeevma@tarantool.org wrote:
>>
>> This field become unused and should be removed.
> -> became/has become
Fixed.
>
> Patch is OK.
>
>

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

* [tarantool-patches] Re: [PATCH v1 10/12] sql: remove field errCode from struct sql
  2019-05-15 13:32   ` [tarantool-patches] " n.pettik
@ 2019-05-25  9:25     ` Imeev Mergen
  0 siblings, 0 replies; 31+ messages in thread
From: Imeev Mergen @ 2019-05-25  9:25 UTC (permalink / raw)
  To: n.pettik, tarantool-patches


On 5/15/19 4:32 PM, n.pettik wrote:
>
>> On 5 May 2019, at 15:17, imeevma@tarantool.org wrote:
>>
>> This field became unusued and should be removed.
>> ---
>>
>> diff --git a/src/box/sql/main.c b/src/box/sql/main.c
>> index a3c6aa1..155cbcc 100644
>> --- a/src/box/sql/main.c
>> +++ b/src/box/sql/main.c
>> @@ -568,22 +568,6 @@ sqlTempInMemory(const sql * db)
>> }
>>
>> /*
>> - * Return the most recent error code generated by an sql routine. If NULL is
>> - * passed to this function, we assume a malloc() failed during sql_open().
>> - */
>> -int
>> -sql_errcode(sql * db)
> Still see several mentions of this function in comments.
Fixed.
>

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

* [tarantool-patches] Re: [PATCH v1 12/12] sql: use diag_set() to set an error in SQL functions
  2019-05-15 14:12   ` [tarantool-patches] " n.pettik
@ 2019-05-25  9:45     ` Mergen Imeev
  2019-05-25 10:36       ` Imeev Mergen
  0 siblings, 1 reply; 31+ messages in thread
From: Mergen Imeev @ 2019-05-25  9:45 UTC (permalink / raw)
  To: n.pettik; +Cc: tarantool-patches

I moved this patch to the position before "sql: set errors
in VDBE using diag_set()". New patch below.

On Wed, May 15, 2019 at 05:12:09PM +0300, n.pettik wrote:
> 
> > After this patch, all errors in the SQL functions will be set
> > using diag_set().
> > 
> > Closes #4074
> > ---
> > src/box/lua/lua_sql.c |  13 +++--
> > src/box/sql/analyze.c |   6 +--
> > src/box/sql/func.c    | 104 ++++++++++++++++++----------------------
> > src/box/sql/sqlInt.h  |  13 -----
> > src/box/sql/vdbe.c    |  34 +++----------
> > src/box/sql/vdbeInt.h |  28 ++---------
> > src/box/sql/vdbeapi.c | 129 +++++---------------------------------------------
> > src/box/sql/vdbeaux.c |  46 ------------------
> > src/box/sql/vdbemem.c |   9 ++--
> > 9 files changed, 84 insertions(+), 298 deletions(-)
> > 
> > diff --git a/src/box/lua/lua_sql.c b/src/box/lua/lua_sql.c
> > index d28045a..afe4732 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);
> 
> Please, remove sql_result_error at all: I grepped several
> usages among dead code.
> 
Fixed.

> > +			diag_set(ClientError, ER_SQL_EXECUTE, "Unsupported "\
> > +				 "type passed to Lua");
> > +			pCtx->is_error = true;
> > 			goto error;
> > 		}
> > 
> > diff --git a/src/box/sql/func.c b/src/box/sql/func.c
> > index bb7405e..16c02f1 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 overflow”);
> 
> -> integer is overflowed.
> 
Fixed.

> > +					context->is_error = true;
> > 					return;
> > 				}
> > 				iVal = -iVal;
> > 
> > 
> > 
> > @@ -591,11 +577,11 @@ case_type##ICUFunc(sql_context *context, int argc, sql_value **argv)   \
> > 	 * does not invalidate the _text() pointer.                            \
> > 	 */                                                                    \
> > 	assert(z2 == (char *)sql_value_text(argv[0]));                     \
> > -	if (!z2)                                                               \
> > +	if (z2 == NULL)                                                        \
> > 		return;                                                        \
> 
> Redundant diff.
> 
Fixed.

> > src/box/sql/vdbeInt.h b/src/box/sql/vdbeInt.h
> > index 6aadca2..70a0bab 100644
> > --- a/src/box/sql/vdbeInt.h
> > +++ b/src/box/sql/vdbeInt.h
> > 
> > @@ -300,21 +296,6 @@ mem_apply_numeric_type(struct Mem *record);
> > #endif
> > 
> > 
> > -/*
> >  * 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.
> > @@ -333,9 +314,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_error;
> 
> I’d better use is_abotred name.
> 
FIxed. Renamed to is_aborted.

> > diff --git a/src/box/sql/vdbemem.c b/src/box/sql/vdbemem.c
> > index f73ea0a..ce0c641 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_error ? SQL_TARANTOOL_ERROR : SQL_OK;
> > 	}
> > -	return rc;
> > +	return SQL_OK;
> 
> Return 0/-1
> 
It is fixed in one of following patches.


New patch:

From bb66ac8360ee312cf8d2047143139bb46441ddf0 Mon Sep 17 00:00:00 2001
Date: Sat, 27 Apr 2019 21:17:19 +0300
Subject: [PATCH] sql: use diag_set() to set an error in SQL functions

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

Closes #4074

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 1559f01..7d85959 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 f73ea0a..585dc21 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;
 }
 
 /*
@@ -1281,7 +1280,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);
 
@@ -1486,7 +1485,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>
     })
 

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

* [tarantool-patches] Re: [PATCH v1 07/12] sql: set errors in VDBE using diag_set()
  2019-05-15 13:26   ` [tarantool-patches] " n.pettik
@ 2019-05-25 10:24     ` Mergen Imeev
  2019-05-25 10:36       ` Imeev Mergen
  0 siblings, 1 reply; 31+ messages in thread
From: Mergen Imeev @ 2019-05-25 10:24 UTC (permalink / raw)
  To: n.pettik; +Cc: tarantool-patches

I moved patch "sql: use diag_set() to set an error in SQL
functions" to position before this patch. It allowed to
simplify this patch. New patch below.

On Wed, May 15, 2019 at 04:26:54PM +0300, n.pettik wrote:
> 
> 
> > On 5 May 2019, at 15:17, imeevma@tarantool.org wrote:
> > 
> > After this patch, all errors in VDBE will be set using diag_set().
> > 
> > Part of #4074
> > ---
> > src/box/execute.c     |  23 +---
> > src/box/sql/vdbe.c    | 331 +++++++++++++++++++++-----------------------------
> > src/box/sql/vdbeInt.h |  10 --
> > src/box/sql/vdbeapi.c |  34 +-----
> > src/box/sql/vdbeaux.c |  20 +--
> > 5 files changed, 148 insertions(+), 270 deletions(-)
> 
> Please, remove whole sqlErrStr(), tarantoolErrorMessage() -
> they are unused now. The same concerns sql_ret_code() -
> I see no reason keeping it. Please, remove all legacy routines
> connected with error codes.
> 
These functions are removed in the following patches.

> > 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
> > 
> > @@ -1335,7 +1331,8 @@ 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))) {
> > +	rc = sqlVdbeCheckFk(p, 0);
> > +	if (rc != SQL_OK) {
> 
> -> if (sqlVdbeCheckFk() != 0)
> 
Fixed. I used SQL_OK but it will be replaced by 0 in the
following patches.

> > 		assert(user_session->sql_flags&SQL_CountRows);
> > 		goto abort_due_to_error;
> > 	}
> > 
> > @@ -1435,10 +1431,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;
> 
> != 0
> Still need to call sqlOomFault(db); by jumping to no_mem label.
> 
Fixed.

> > 	nByte = pIn1->n + pIn2->n;
> > 	if (nByte>db->aLimit[SQL_LIMIT_LENGTH]) {
> > 		goto too_big;
> > 
> > 
> > @@ -1723,11 +1715,15 @@ case OP_Function: {
> > 	/* 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;
> > +			if (pCtx->isError != SQL_TARANTOOL_ERROR) {
> 
> How it can be different from SQL_TARANTOOL_ERROR?
> 
It was possible, but this part of code was completely
changed after i moved patch "sql: use diag_set() to set an
error in SQL functions" to position before this patch.

> > +				diag_set(ClientError, ER_SQL_EXECUTE,
> > +					 sql_value_text(pCtx->pOut));
> > +			}
> > +			rc = SQL_TARANTOOL_ERROR;
> > 		}
> > 		sqlVdbeDeleteAuxData(db, &p->pAuxData, pCtx->iOp, pOp->p1);
> > -		if (rc) goto abort_due_to_error;
> > +		if (rc != SQL_OK)
> > +			goto abort_due_to_error;
> 
> This diff seems to be redundant
> 
Fixed.

> > @@ -1910,8 +1903,7 @@ case OP_Realify: {                  /* in1 */
> >  */
> > case OP_Cast: {                  /* in1 */
> > 	pIn1 = &aMem[pOp->p1];
> > -	rc = ExpandBlob(pIn1);
> > -	if (rc != 0)
> > +	if (ExpandBlob(pIn1) != SQL_OK)
> 
> != 0
> Please, don’t use SQL_OK value anywhere.
> 
I think it's better to use SQL_OK here for integrity. It is
replaced with 0 in one of the following patches.

> > 
> > @@ -2802,10 +2784,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;
> > 
> > 
> > @@ -2918,8 +2898,10 @@ case OP_Savepoint: {
> > 			pSavepoint = pSavepoint->pNext
> > 			);
> > 		if (!pSavepoint) {
> > -			sqlVdbeError(p, "no such savepoint: %s", zName);
> > -			rc = SQL_ERROR;
> > +			const char *err =
> > +				tt_sprintf("no such savepoint: %s", zName);
> > +			diag_set(ClientError, ER_SQL_EXECUTE, err);
> 
> We already have ER_NO_SUCH_SAVEPOINT.
> 
Fixed.

> > @@ -3685,10 +3645,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
> 
Fixed.
> > 
> > @@ -5164,11 +5126,16 @@ case OP_AggStep: {
> > 	(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->isError != SQL_TARANTOOL_ERROR) {
> > +				diag_set(ClientError, ER_SQL_EXECUTE,
> > +					 sql_value_text(&t));
> > +			}
> > +			rc = SQL_TARANTOOL_ERROR;
> > 		}
> > 		sqlVdbeMemRelease(&t);
> > -		if (rc) goto abort_due_to_error;
> > +		assert(rc == SQL_OK || rc == SQL_TARANTOOL_ERROR);
> > +		if (rc != SQL_OK)
> > +			goto abort_due_to_error;
> 
> Looks like redundant diff
> 
Fixed.

> > 	} else {
> > 		assert(t.flags==MEM_Null);
> > 	}
> > @@ -5199,8 +5166,11 @@ case OP_AggFinal: {
> > 	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 (rc != SQL_OK) {
> > +		if (rc != SQL_TARANTOOL_ERROR) {
> > +			diag_set(ClientError, ER_SQL_EXECUTE,
> > +				 sql_value_text(pMem));
> 
> Could you please clarify what does this error mean?
> It would just print value of memory to string…
> The same relates to error in OP_AggStep.
> 
If result was returned using sql_result_error() then it was
possible that diag is not set. This was fixed in patch that
now right before this patch.

> > @@ -5311,10 +5281,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;
> > }
> > 
> > too_big:
> > -	sqlVdbeError(p, "string or blob too big");
> > -	rc = SQL_TOOBIG;
> > +	diag_set(ClientError, ER_SQL_EXECUTE, "string or blob too big”);
> 
> -> is too big
> 
Fixed here. Still, it is possible to find this error in
other places. I think it will be fixed when we create error
code for such errors.

> > 	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 a3100e5..b655b5a 100644
> > --- a/src/box/sql/vdbeInt.h
> > +++ b/src/box/sql/vdbeInt.h
> > @@ -248,10 +248,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
> > 
> > 
> > @@ -550,13 +545,8 @@ void sqlVdbeMemPrettyPrint(Mem * pMem, char *zBuf);
> > #endif
> > int sqlVdbeMemHandleBom(Mem * pMem);
> > 
> > -#ifndef SQL_OMIT_INCRBLOB
> 
> Still see usage of this macro in code: vdbemem.c : 213
> 
Fixed.

> > 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/vdbeaux.c b/src/box/sql/vdbeaux.c
> > index 27fa5b2..48c2a81 100644
> > --- a/src/box/sql/vdbeaux.c
> > +++ b/src/box/sql/vdbeaux.c
> > void
> > @@ -2124,10 +2111,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”);
> 
> Please, reserve separate error code for this violation.
> 
I am going to do this a bit later, in a different patch.

> > +		return SQL_TARANTOOL_ERROR;
> > 	}
> > 	return SQL_OK;
> 
> Return 0/-1
> 
> 
Left as it as for now, will be fixed in following patches.


New patch:

From 85cfbe96609b66379631c8d4534c8a9329fb3a47 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().

Part of #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/vdbe.c b/src/box/sql/vdbe.c
index 7d85959..b64293a 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 585dc21..d6375a6 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] 31+ messages in thread

* [tarantool-patches] Re: [PATCH v1 07/12] sql: set errors in VDBE using diag_set()
  2019-05-25 10:24     ` Mergen Imeev
@ 2019-05-25 10:36       ` Imeev Mergen
  0 siblings, 0 replies; 31+ messages in thread
From: Imeev Mergen @ 2019-05-25 10:36 UTC (permalink / raw)
  To: n.pettik; +Cc: tarantool-patches

[-- Attachment #1: Type: text/plain, Size: 47689 bytes --]

Fixed commit-message:

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

Closes  #4074  <https://github.com/tarantool/tarantool/issues/4074>

On 5/25/19 1:24 PM, Mergen Imeev wrote:
> I moved patch "sql: use diag_set() to set an error in SQL
> functions" to position before this patch. It allowed to
> simplify this patch. New patch below.
>
> On Wed, May 15, 2019 at 04:26:54PM +0300, n.pettik wrote:
>>
>>> On 5 May 2019, at 15:17, imeevma@tarantool.org wrote:
>>>
>>> After this patch, all errors in VDBE will be set using diag_set().
>>>
>>> Part of #4074
>>> ---
>>> src/box/execute.c     |  23 +---
>>> src/box/sql/vdbe.c    | 331 +++++++++++++++++++++-----------------------------
>>> src/box/sql/vdbeInt.h |  10 --
>>> src/box/sql/vdbeapi.c |  34 +-----
>>> src/box/sql/vdbeaux.c |  20 +--
>>> 5 files changed, 148 insertions(+), 270 deletions(-)
>> Please, remove whole sqlErrStr(), tarantoolErrorMessage() -
>> they are unused now. The same concerns sql_ret_code() -
>> I see no reason keeping it. Please, remove all legacy routines
>> connected with error codes.
>>
> These functions are removed in the following patches.
>
>>> 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
>>>
>>> @@ -1335,7 +1331,8 @@ 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))) {
>>> +	rc = sqlVdbeCheckFk(p, 0);
>>> +	if (rc != SQL_OK) {
>> -> if (sqlVdbeCheckFk() != 0)
>>
> Fixed. I used SQL_OK but it will be replaced by 0 in the
> following patches.
>
>>> 		assert(user_session->sql_flags&SQL_CountRows);
>>> 		goto abort_due_to_error;
>>> 	}
>>>
>>> @@ -1435,10 +1431,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;
>> != 0
>> Still need to call sqlOomFault(db); by jumping to no_mem label.
>>
> Fixed.
>
>>> 	nByte = pIn1->n + pIn2->n;
>>> 	if (nByte>db->aLimit[SQL_LIMIT_LENGTH]) {
>>> 		goto too_big;
>>>
>>>
>>> @@ -1723,11 +1715,15 @@ case OP_Function: {
>>> 	/* 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;
>>> +			if (pCtx->isError != SQL_TARANTOOL_ERROR) {
>> How it can be different from SQL_TARANTOOL_ERROR?
>>
> It was possible, but this part of code was completely
> changed after i moved patch "sql: use diag_set() to set an
> error in SQL functions" to position before this patch.
>
>>> +				diag_set(ClientError, ER_SQL_EXECUTE,
>>> +					 sql_value_text(pCtx->pOut));
>>> +			}
>>> +			rc = SQL_TARANTOOL_ERROR;
>>> 		}
>>> 		sqlVdbeDeleteAuxData(db, &p->pAuxData, pCtx->iOp, pOp->p1);
>>> -		if (rc) goto abort_due_to_error;
>>> +		if (rc != SQL_OK)
>>> +			goto abort_due_to_error;
>> This diff seems to be redundant
>>
> Fixed.
>
>>> @@ -1910,8 +1903,7 @@ case OP_Realify: {                  /* in1 */
>>>   */
>>> case OP_Cast: {                  /* in1 */
>>> 	pIn1 = &aMem[pOp->p1];
>>> -	rc = ExpandBlob(pIn1);
>>> -	if (rc != 0)
>>> +	if (ExpandBlob(pIn1) != SQL_OK)
>> != 0
>> Please, don’t use SQL_OK value anywhere.
>>
> I think it's better to use SQL_OK here for integrity. It is
> replaced with 0 in one of the following patches.
>
>>> @@ -2802,10 +2784,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;
>>>
>>>
>>> @@ -2918,8 +2898,10 @@ case OP_Savepoint: {
>>> 			pSavepoint = pSavepoint->pNext
>>> 			);
>>> 		if (!pSavepoint) {
>>> -			sqlVdbeError(p, "no such savepoint: %s", zName);
>>> -			rc = SQL_ERROR;
>>> +			const char *err =
>>> +				tt_sprintf("no such savepoint: %s", zName);
>>> +			diag_set(ClientError, ER_SQL_EXECUTE, err);
>> We already have ER_NO_SUCH_SAVEPOINT.
>>
> Fixed.
>
>>> @@ -3685,10 +3645,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
>>
> Fixed.
>>> @@ -5164,11 +5126,16 @@ case OP_AggStep: {
>>> 	(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->isError != SQL_TARANTOOL_ERROR) {
>>> +				diag_set(ClientError, ER_SQL_EXECUTE,
>>> +					 sql_value_text(&t));
>>> +			}
>>> +			rc = SQL_TARANTOOL_ERROR;
>>> 		}
>>> 		sqlVdbeMemRelease(&t);
>>> -		if (rc) goto abort_due_to_error;
>>> +		assert(rc == SQL_OK || rc == SQL_TARANTOOL_ERROR);
>>> +		if (rc != SQL_OK)
>>> +			goto abort_due_to_error;
>> Looks like redundant diff
>>
> Fixed.
>
>>> 	} else {
>>> 		assert(t.flags==MEM_Null);
>>> 	}
>>> @@ -5199,8 +5166,11 @@ case OP_AggFinal: {
>>> 	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 (rc != SQL_OK) {
>>> +		if (rc != SQL_TARANTOOL_ERROR) {
>>> +			diag_set(ClientError, ER_SQL_EXECUTE,
>>> +				 sql_value_text(pMem));
>> Could you please clarify what does this error mean?
>> It would just print value of memory to string…
>> The same relates to error in OP_AggStep.
>>
> If result was returned using sql_result_error() then it was
> possible that diag is not set. This was fixed in patch that
> now right before this patch.
>
>>> @@ -5311,10 +5281,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;
>>> }
>>>
>>> too_big:
>>> -	sqlVdbeError(p, "string or blob too big");
>>> -	rc = SQL_TOOBIG;
>>> +	diag_set(ClientError, ER_SQL_EXECUTE, "string or blob too big”);
>> -> is too big
>>
> Fixed here. Still, it is possible to find this error in
> other places. I think it will be fixed when we create error
> code for such errors.
>
>>> 	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 a3100e5..b655b5a 100644
>>> --- a/src/box/sql/vdbeInt.h
>>> +++ b/src/box/sql/vdbeInt.h
>>> @@ -248,10 +248,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
>>>
>>>
>>> @@ -550,13 +545,8 @@ void sqlVdbeMemPrettyPrint(Mem * pMem, char *zBuf);
>>> #endif
>>> int sqlVdbeMemHandleBom(Mem * pMem);
>>>
>>> -#ifndef SQL_OMIT_INCRBLOB
>> Still see usage of this macro in code: vdbemem.c : 213
>>
> Fixed.
>
>>> 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/vdbeaux.c b/src/box/sql/vdbeaux.c
>>> index 27fa5b2..48c2a81 100644
>>> --- a/src/box/sql/vdbeaux.c
>>> +++ b/src/box/sql/vdbeaux.c
>>> void
>>> @@ -2124,10 +2111,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”);
>> Please, reserve separate error code for this violation.
>>
> I am going to do this a bit later, in a different patch.
>
>>> +		return SQL_TARANTOOL_ERROR;
>>> 	}
>>> 	return SQL_OK;
>> Return 0/-1
>>
>>
> Left as it as for now, will be fixed in following patches.
>
>
> New patch:
>
>  From 85cfbe96609b66379631c8d4534c8a9329fb3a47 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().
>
> Part of #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/vdbe.c b/src/box/sql/vdbe.c
> index 7d85959..b64293a 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 585dc21..d6375a6 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();
>   ---
>
>
>
>

[-- Attachment #2: Type: text/html, Size: 49753 bytes --]

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

* [tarantool-patches] Re: [PATCH v1 12/12] sql: use diag_set() to set an error in SQL functions
  2019-05-25  9:45     ` Mergen Imeev
@ 2019-05-25 10:36       ` Imeev Mergen
  0 siblings, 0 replies; 31+ messages in thread
From: Imeev Mergen @ 2019-05-25 10:36 UTC (permalink / raw)
  To: n.pettik; +Cc: tarantool-patches

[-- Attachment #1: Type: text/plain, Size: 33695 bytes --]

Fixed commit-message:

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

Part of#4074  <https://github.com/tarantool/tarantool/issues/4074>

On 5/25/19 12:45 PM, Mergen Imeev wrote:
> I moved this patch to the position before "sql: set errors
> in VDBE using diag_set()". New patch below.
>
> On Wed, May 15, 2019 at 05:12:09PM +0300, n.pettik wrote:
>>> After this patch, all errors in the SQL functions will be set
>>> using diag_set().
>>>
>>> Closes #4074
>>> ---
>>> src/box/lua/lua_sql.c |  13 +++--
>>> src/box/sql/analyze.c |   6 +--
>>> src/box/sql/func.c    | 104 ++++++++++++++++++----------------------
>>> src/box/sql/sqlInt.h  |  13 -----
>>> src/box/sql/vdbe.c    |  34 +++----------
>>> src/box/sql/vdbeInt.h |  28 ++---------
>>> src/box/sql/vdbeapi.c | 129 +++++---------------------------------------------
>>> src/box/sql/vdbeaux.c |  46 ------------------
>>> src/box/sql/vdbemem.c |   9 ++--
>>> 9 files changed, 84 insertions(+), 298 deletions(-)
>>>
>>> diff --git a/src/box/lua/lua_sql.c b/src/box/lua/lua_sql.c
>>> index d28045a..afe4732 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);
>> Please, remove sql_result_error at all: I grepped several
>> usages among dead code.
>>
> Fixed.
>
>>> +			diag_set(ClientError, ER_SQL_EXECUTE, "Unsupported "\
>>> +				 "type passed to Lua");
>>> +			pCtx->is_error = true;
>>> 			goto error;
>>> 		}
>>>
>>> diff --git a/src/box/sql/func.c b/src/box/sql/func.c
>>> index bb7405e..16c02f1 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 overflow”);
>> -> integer is overflowed.
>>
> Fixed.
>
>>> +					context->is_error = true;
>>> 					return;
>>> 				}
>>> 				iVal = -iVal;
>>>
>>>
>>>
>>> @@ -591,11 +577,11 @@ case_type##ICUFunc(sql_context *context, int argc, sql_value **argv)   \
>>> 	 * does not invalidate the _text() pointer.                            \
>>> 	 */                                                                    \
>>> 	assert(z2 == (char *)sql_value_text(argv[0]));                     \
>>> -	if (!z2)                                                               \
>>> +	if (z2 == NULL)                                                        \
>>> 		return;                                                        \
>> Redundant diff.
>>
> Fixed.
>
>>> src/box/sql/vdbeInt.h b/src/box/sql/vdbeInt.h
>>> index 6aadca2..70a0bab 100644
>>> --- a/src/box/sql/vdbeInt.h
>>> +++ b/src/box/sql/vdbeInt.h
>>>
>>> @@ -300,21 +296,6 @@ mem_apply_numeric_type(struct Mem *record);
>>> #endif
>>>
>>>
>>> -/*
>>>   * 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.
>>> @@ -333,9 +314,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_error;
>> I’d better use is_abotred name.
>>
> FIxed. Renamed to is_aborted.
>
>>> diff --git a/src/box/sql/vdbemem.c b/src/box/sql/vdbemem.c
>>> index f73ea0a..ce0c641 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_error ? SQL_TARANTOOL_ERROR : SQL_OK;
>>> 	}
>>> -	return rc;
>>> +	return SQL_OK;
>> Return 0/-1
>>
> It is fixed in one of following patches.
>
>
> New patch:
>
>  From bb66ac8360ee312cf8d2047143139bb46441ddf0 Mon Sep 17 00:00:00 2001
> Date: Sat, 27 Apr 2019 21:17:19 +0300
> Subject: [PATCH] sql: use diag_set() to set an error in SQL functions
>
> After this patch, all errors in the SQL functions will be set
> using diag_set().
>
> Closes #4074
>
> 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 1559f01..7d85959 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 f73ea0a..585dc21 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;
>   }
>   
>   /*
> @@ -1281,7 +1280,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);
>   
> @@ -1486,7 +1485,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>
>       })
>   
>
>

[-- Attachment #2: Type: text/html, Size: 34029 bytes --]

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

end of thread, other threads:[~2019-05-25 10:36 UTC | newest]

Thread overview: 31+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-05-05 12:17 [tarantool-patches] [PATCH v1 00/12] sql: set errors in VDBE using diag_set() imeevma
2019-05-05 12:17 ` [tarantool-patches] [PATCH v1 01/12] sql: remove errors SQL_TARANTOOL_*_FAIL imeevma
2019-05-15 13:18   ` [tarantool-patches] " n.pettik
2019-05-25  9:16     ` Imeev Mergen
2019-05-05 12:17 ` [tarantool-patches] [PATCH v1 02/12] sql: remove error ER_SQL imeevma
2019-05-15 13:18   ` [tarantool-patches] " n.pettik
2019-05-05 12:17 ` [tarantool-patches] [PATCH v1 03/12] sql: rework diag_set() in OP_Halt imeevma
2019-05-15 13:18   ` [tarantool-patches] " n.pettik
2019-05-05 12:17 ` [tarantool-patches] [PATCH v1 04/12] sql: make SQL_TARANTOOL_ERROR the only errcode of OP_Halt imeevma
2019-05-15 13:18   ` [tarantool-patches] " n.pettik
2019-05-25  9:18     ` Imeev Mergen
2019-05-05 12:17 ` [tarantool-patches] [PATCH v1 05/12] sql: remove error SQL_INTERRUPT imeevma
2019-05-15 13:18   ` [tarantool-patches] " n.pettik
2019-05-05 12:17 ` [tarantool-patches] [PATCH v1 06/12] sql: remove error SQL_MISMATCH imeevma
2019-05-15 13:19   ` [tarantool-patches] " n.pettik
2019-05-05 12:17 ` [tarantool-patches] [PATCH v1 07/12] sql: set errors in VDBE using diag_set() imeevma
2019-05-15 13:26   ` [tarantool-patches] " n.pettik
2019-05-25 10:24     ` Mergen Imeev
2019-05-25 10:36       ` Imeev Mergen
2019-05-05 12:17 ` [tarantool-patches] [PATCH v1 08/12] sql: remove field zErrMsg from struct Vdbe imeevma
2019-05-15 13:30   ` [tarantool-patches] " n.pettik
2019-05-25  9:25     ` Imeev Mergen
2019-05-05 12:17 ` [tarantool-patches] [PATCH v1 09/12] sql: remove field pErr from struct sql imeevma
2019-05-05 12:17 ` [tarantool-patches] [PATCH v1 10/12] sql: remove field errCode " imeevma
2019-05-15 13:32   ` [tarantool-patches] " n.pettik
2019-05-25  9:25     ` Imeev Mergen
2019-05-05 12:17 ` [tarantool-patches] [PATCH v1 11/12] sql: remove sqlError() and remove sqlErrorWithMsg() imeevma
2019-05-05 12:17 ` [tarantool-patches] [PATCH v1 12/12] sql: use diag_set() to set an error in SQL functions imeevma
2019-05-15 14:12   ` [tarantool-patches] " n.pettik
2019-05-25  9:45     ` Mergen Imeev
2019-05-25 10:36       ` Imeev Mergen

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