Tarantool development patches archive
 help / color / mirror / Atom feed
* [tarantool-patches] [PATCH v1 1/1] sql: rework "no such object" and "object exists" errors
@ 2019-02-15 10:06 imeevma
  2019-02-15 12:44 ` [tarantool-patches] " n.pettik
  0 siblings, 1 reply; 4+ messages in thread
From: imeevma @ 2019-02-15 10:06 UTC (permalink / raw)
  To: korablev; +Cc: tarantool-patches

This patch reworks SQL errors of types "no such object" and
"object exists". After this patch, these error will be set as
Tarantool errors.

Part of #3965
---
 src/box/errcode.h                              |  7 ++---
 src/box/lua/schema.lua                         |  4 +--
 src/box/space.h                                |  2 +-
 src/box/sql/build.c                            | 37 +++++++++++++-------------
 src/box/sql/delete.c                           |  3 ++-
 src/box/sql/expr.c                             |  5 ++--
 src/box/sql/pragma.c                           |  3 ++-
 src/box/sql/resolve.c                          | 19 +++++++------
 src/box/sql/select.c                           | 12 +++++----
 src/box/sql/sqlInt.h                           |  8 ++++++
 src/box/sql/update.c                           |  5 ++--
 src/box/sql/util.c                             | 10 +++++++
 test/box/misc.result                           |  5 +++-
 test/sql-tap/alter.test.lua                    |  2 +-
 test/sql-tap/analyzeF.test.lua                 |  4 +--
 test/sql-tap/check.test.lua                    |  4 +--
 test/sql-tap/fkey2.test.lua                    |  2 +-
 test/sql-tap/func.test.lua                     |  2 +-
 test/sql-tap/gh-2367-pragma.test.lua           |  2 +-
 test/sql-tap/gh-2996-indexed-by.test.lua       | 12 ++++-----
 test/sql-tap/gh2130-index-refer-table.test.lua |  4 +--
 test/sql-tap/identifier_case.test.lua          |  2 +-
 test/sql-tap/in1.test.lua                      |  2 +-
 test/sql-tap/in3.test.lua                      |  2 +-
 test/sql-tap/index-info.test.lua               |  2 +-
 test/sql-tap/index1.test.lua                   |  6 ++---
 test/sql-tap/insert1.test.lua                  |  6 ++---
 test/sql-tap/insert3.test.lua                  |  4 +--
 test/sql-tap/join.test.lua                     |  2 +-
 test/sql-tap/limit.test.lua                    |  4 +--
 test/sql-tap/lua-tables.test.lua               |  2 +-
 test/sql-tap/lua_sql.test.lua                  |  2 +-
 test/sql-tap/misc1.test.lua                    |  4 +--
 test/sql-tap/select1.test.lua                  | 12 ++++-----
 test/sql-tap/select4.test.lua                  |  2 +-
 test/sql-tap/select5.test.lua                  |  8 +++---
 test/sql-tap/table.test.lua                    | 16 +++++------
 test/sql-tap/tkt-4ef7e3cfca.test.lua           |  2 +-
 test/sql-tap/tkt3346.test.lua                  |  2 +-
 test/sql-tap/tkt3442.test.lua                  |  2 +-
 test/sql-tap/triggerB.test.lua                 |  6 ++---
 test/sql-tap/update.test.lua                   | 16 +++++------
 test/sql-tap/view.test.lua                     |  6 ++---
 test/sql-tap/with2.test.lua                    |  4 +--
 test/sql/checks.result                         |  4 +--
 test/sql/delete.result                         |  4 +--
 test/sql/drop-table.result                     |  4 +--
 test/sql/gh-2929-primary-key.result            |  2 +-
 test/sql/gh-3613-idx-alter-update.result       |  2 +-
 test/sql/gh-3888-values-blob-assert.result     |  4 +--
 test/sql/icu-upper-lower.result                |  2 +-
 test/sql/iproto.result                         |  2 +-
 52 files changed, 161 insertions(+), 129 deletions(-)

diff --git a/src/box/errcode.h b/src/box/errcode.h
index f7dbb94..e25e05c 100644
--- a/src/box/errcode.h
+++ b/src/box/errcode.h
@@ -87,7 +87,7 @@ struct errcode_record {
 	/* 32 */_(ER_PROC_LUA,			"%s") \
 	/* 33 */_(ER_NO_SUCH_PROC,		"Procedure '%.*s' is not defined") \
 	/* 34 */_(ER_NO_SUCH_TRIGGER,		"Trigger '%s' doesn't exist") \
-	/* 35 */_(ER_NO_SUCH_INDEX,		"No index #%u is defined in space '%s'") \
+	/* 35 */_(ER_NO_SUCH_INDEX_ID,		"No index #%u is defined in space '%s'") \
 	/* 36 */_(ER_NO_SUCH_SPACE,		"Space '%s' does not exist") \
 	/* 37 */_(ER_NO_SUCH_FIELD,		"Field %d was not found in the tuple") \
 	/* 38 */_(ER_EXACT_FIELD_COUNT,		"Tuple field count %u does not match space field count %u") \
@@ -200,12 +200,12 @@ struct errcode_record {
 	/*145 */_(ER_NO_SUCH_SEQUENCE,		"Sequence '%s' does not exist") \
 	/*146 */_(ER_SEQUENCE_EXISTS,		"Sequence '%s' already exists") \
 	/*147 */_(ER_SEQUENCE_OVERFLOW,		"Sequence '%s' has overflowed") \
-	/*148 */_(ER_UNUSED5,			"") \
+	/*148 */_(ER_NO_SUCH_INDEX_NAME,	"No index '%s' is defined in space '%s'") \
 	/*149 */_(ER_SPACE_FIELD_IS_DUPLICATE,	"Space field '%s' is duplicate") \
 	/*150 */_(ER_CANT_CREATE_COLLATION,	"Failed to initialize collation: %s.") \
 	/*151 */_(ER_WRONG_COLLATION_OPTIONS,	"Wrong collation options (field %u): %s") \
 	/*152 */_(ER_NULLABLE_PRIMARY,		"Primary index of the space '%s' can not contain nullable parts") \
-	/*153 */_(ER_UNUSED,			"") \
+	/*153 */_(ER_NO_SUCH_FIELD_NAME,	"Field '%s' doesn't exist") \
 	/*154 */_(ER_TRANSACTION_YIELD,		"Transaction has been aborted by a fiber yield") \
 	/*155 */_(ER_NO_SUCH_GROUP,		"Replication group '%s' does not exist") \
 	/*156 */_(ER_SQL_BIND_VALUE,            "Bind value for parameter %s is out of range for type %s") \
@@ -227,6 +227,7 @@ struct errcode_record {
 	/*172 */_(ER_ROWID_OVERFLOW,            "Rowid is overflowed: too many entries in ephemeral space") \
 	/*173 */_(ER_DROP_COLLATION,		"Can't drop collation %s : %s") \
 	/*174 */_(ER_ILLEGAL_COLLATION_MIX,	"Illegal mix of collations") \
+	/*175 */_(ER_SQL_NO_SUCH_PRAGMA,	"Pragma '%s' does not exist") \
 
 /*
  * !IMPORTANT! Please follow instructions at start of the file
diff --git a/src/box/lua/schema.lua b/src/box/lua/schema.lua
index 0daf484..6049931 100644
--- a/src/box/lua/schema.lua
+++ b/src/box/lua/schema.lua
@@ -947,7 +947,7 @@ box.schema.index.alter = function(space_id, index_id, options)
         box.error(box.error.NO_SUCH_SPACE, '#'..tostring(space_id))
     end
     if space.index[index_id] == nil then
-        box.error(box.error.NO_SUCH_INDEX, index_id, space.name)
+        box.error(box.error.NO_SUCH_INDEX_ID, index_id, space.name)
     end
     if options == nil then
         return
@@ -1175,7 +1175,7 @@ box.internal.check_index_arg = check_index_arg -- for net.box
 local function check_primary_index(space)
     local pk = space.index[0]
     if pk == nil then
-        box.error(box.error.NO_SUCH_INDEX, 0, space.name)
+        box.error(box.error.NO_SUCH_INDEX_ID, 0, space.name)
     end
     return pk
 end
diff --git a/src/box/space.h b/src/box/space.h
index 7eb7ae2..ee5ffe6 100644
--- a/src/box/space.h
+++ b/src/box/space.h
@@ -263,7 +263,7 @@ index_find(struct space *space, uint32_t index_id)
 {
 	struct index *index = space_index(space, index_id);
 	if (index == NULL) {
-		diag_set(ClientError, ER_NO_SUCH_INDEX, index_id,
+		diag_set(ClientError, ER_NO_SUCH_INDEX_ID, index_id,
 			 space_name(space));
 		diag_log();
 	}
diff --git a/src/box/sql/build.c b/src/box/sql/build.c
index 5dc3d02..e471dba 100644
--- a/src/box/sql/build.c
+++ b/src/box/sql/build.c
@@ -415,8 +415,8 @@ sqlStartTable(Parse *pParse, Token *pName, int noErr)
 	struct space *space = space_by_name(zName);
 	if (space != NULL) {
 		if (!noErr) {
-			sqlErrorMsg(pParse, "table %s already exists",
-					zName);
+			diag_set(ClientError, ER_SPACE_EXISTS, zName);
+			sql_parser_error(pParse);
 		} else {
 			assert(!db->init.busy || CORRUPT_DB);
 		}
@@ -533,7 +533,8 @@ sqlAddColumn(Parse * pParse, Token * pName, struct type_def *type_def)
 	sqlNormalizeName(z);
 	for (i = 0; i < (int)p->def->field_count; i++) {
 		if (strcmp(z, p->def->fields[i].name) == 0) {
-			sqlErrorMsg(pParse, "duplicate column name: %s", z);
+			diag_set(ClientError, ER_SPACE_FIELD_IS_DUPLICATE, z);
+			sql_parser_error(pParse);
 			return;
 		}
 	}
@@ -1697,12 +1698,10 @@ sql_drop_table(struct Parse *parse_context, struct SrcList *table_name_list,
 	const char *space_name = table_name_list->a[0].zName;
 	struct space *space = space_by_name(space_name);
 	if (space == NULL) {
-		if (!is_view && !if_exists)
-			sqlErrorMsg(parse_context, "no such table: %s",
-					space_name);
-		if (is_view && !if_exists)
-			sqlErrorMsg(parse_context, "no such view: %s",
-					space_name);
+		if (!if_exists) {
+			diag_set(ClientError, ER_NO_SUCH_SPACE, space_name);
+			sql_parser_error(parse_context);
+		}
 		goto exit_drop_table;
 	}
 	/*
@@ -2287,9 +2286,8 @@ sql_create_index(struct Parse *parse, struct Token *token,
 			goto exit_create_index;
 		if (sql_space_index_by_name(space, name) != NULL) {
 			if (!if_not_exist) {
-				sqlErrorMsg(parse,
-						"index %s.%s already exists",
-						def->name, name);
+				diag_set(ClientError, ER_INDEX_EXISTS, name);
+				sql_parser_error(parse);
 			}
 			goto exit_create_index;
 		}
@@ -2548,18 +2546,21 @@ sql_drop_index(struct Parse *parse_context, struct SrcList *index_name_list,
 	assert(table_token->n > 0);
 	struct space *space = space_by_name(table_name);
 	if (space == NULL) {
-		if (!if_exists)
-			sqlErrorMsg(parse_context, "no such space: %s",
-					table_name);
+		if (!if_exists) {
+			diag_set(ClientError, ER_NO_SUCH_SPACE, table_name);
+			sql_parser_error(parse_context);
+		}
 		goto exit_drop_index;
 	}
 	const char *index_name = index_name_list->a[0].zName;
 	uint32_t index_id = box_index_id_by_name(space->def->id, index_name,
 						 strlen(index_name));
 	if (index_id == BOX_ID_NIL) {
-		if (!if_exists)
-			sqlErrorMsg(parse_context, "no such index: %s.%s",
-					table_name, index_name);
+		if (!if_exists) {
+			diag_set(ClientError, ER_NO_SUCH_INDEX_NAME,
+				 index_name, table_name);
+			sql_parser_error(parse_context);
+		}
 		goto exit_drop_index;
 	}
 	struct index *index = space_index(space, index_id);
diff --git a/src/box/sql/delete.c b/src/box/sql/delete.c
index 41daa44..1f5aa79 100644
--- a/src/box/sql/delete.c
+++ b/src/box/sql/delete.c
@@ -42,7 +42,8 @@ sql_lookup_table(struct Parse *parse, struct SrcList_item *tbl_name)
 	assert(tbl_name->pTab == NULL);
 	struct space *space = space_by_name(tbl_name->zName);
 	if (space == NULL) {
-		sqlErrorMsg(parse, "no such table: %s", tbl_name->zName);
+		diag_set(ClientError, ER_NO_SUCH_SPACE, tbl_name->zName);
+		sql_parser_error(parse);
 		return NULL;
 	}
 	assert(space != NULL);
diff --git a/src/box/sql/expr.c b/src/box/sql/expr.c
index 4450ac7..ef272f9 100644
--- a/src/box/sql/expr.c
+++ b/src/box/sql/expr.c
@@ -3940,8 +3940,9 @@ sqlExprCodeTarget(Parse * pParse, Expr * pExpr, int target)
 			}
 #endif
 			if (pDef == 0 || pDef->xFinalize != 0) {
-				sqlErrorMsg(pParse,
-						"unknown function: %s()", zId);
+				diag_set(ClientError, ER_NO_SUCH_FUNCTION,
+					 zId);
+				sql_parser_error(pParse);
 				break;
 			}
 
diff --git a/src/box/sql/pragma.c b/src/box/sql/pragma.c
index f3e66f5..a82ec9b 100644
--- a/src/box/sql/pragma.c
+++ b/src/box/sql/pragma.c
@@ -453,7 +453,8 @@ sqlPragma(Parse * pParse, Token * pId,	/* First part of [schema.]id field */
 	/* Locate the pragma in the lookup table */
 	pPragma = pragmaLocate(zLeft);
 	if (pPragma == 0) {
-		sqlErrorMsg(pParse, "no such pragma: %s", zLeft);
+		diag_set(ClientError, ER_SQL_NO_SUCH_PRAGMA, zLeft);
+		sql_parser_error(pParse);
 		goto pragma_out;
 	}
 	/* Register the result column names for pragmas that return results */
diff --git a/src/box/sql/resolve.c b/src/box/sql/resolve.c
index 029eb40..a3ff5b2 100644
--- a/src/box/sql/resolve.c
+++ b/src/box/sql/resolve.c
@@ -426,16 +426,20 @@ lookupName(Parse * pParse,	/* The parsing context */
 	 * cnt==0 means there was not match.  cnt>1 means there were two or
 	 * more matches.  Either way, we have an error.
 	 */
-	if (cnt != 1) {
-		const char *zErr;
-		zErr = cnt == 0 ? "no such column" : "ambiguous column name";
+	if (cnt > 1) {
 		if (zTab) {
-			sqlErrorMsg(pParse, "%s: %s.%s", zErr, zTab, zCol);
+			sqlErrorMsg(pParse, "ambiguous column name: %s.%s",
+				    zTab, zCol);
 		} else {
-			sqlErrorMsg(pParse, "%s: %s", zErr, zCol);
+			sqlErrorMsg(pParse, "ambiguous column name: %s", zCol);
 		}
 		pTopNC->nErr++;
 	}
+	if (cnt == 0) {
+		diag_set(ClientError, ER_NO_SUCH_FIELD_NAME, zCol);
+		sql_parser_error(pParse);
+		pTopNC->nErr++;
+	}
 
 	/* If a column from a table in pSrcList is referenced, then record
 	 * this fact in the pSrcList.a[].colUsed bitmask.  Column 0 causes
@@ -698,9 +702,8 @@ resolveExprStep(Walker * pWalker, Expr * pExpr)
 				   && pParse->explain == 0
 #endif
 			    ) {
-				sqlErrorMsg(pParse,
-						"no such function: %.*s", nId,
-						zId);
+				diag_set(ClientError, ER_NO_SUCH_FUNCTION, zId);
+				sql_parser_error(pParse);
 				pNC->nErr++;
 			} else if (wrong_num_args) {
 				sqlErrorMsg(pParse,
diff --git a/src/box/sql/select.c b/src/box/sql/select.c
index a6e78d0..4283262 100644
--- a/src/box/sql/select.c
+++ b/src/box/sql/select.c
@@ -4426,8 +4426,9 @@ sqlIndexedByLookup(Parse * pParse, struct SrcList_item *pFrom)
 			}
 		}
 		if (idx == NULL) {
-			sqlErrorMsg(pParse, "no such index: %s", zIndexedBy,
-					0);
+			diag_set(ClientError, ER_NO_SUCH_INDEX_NAME,
+				 zIndexedBy, pTab->def->name);
+			sql_parser_error(pParse);
 			return SQL_ERROR;
 		}
 		pFrom->pIBIndex = idx->def;
@@ -5065,9 +5066,10 @@ selectExpander(Walker * pWalker, Select * p)
 				}
 				if (!tableSeen) {
 					if (zTName) {
-						sqlErrorMsg(pParse,
-								"no such table: %s",
-								zTName);
+						diag_set(ClientError,
+							 ER_NO_SUCH_SPACE,
+							 zTName);
+						sql_parser_error(pParse);
 					} else {
 						sqlErrorMsg(pParse,
 								"no tables specified");
diff --git a/src/box/sql/sqlInt.h b/src/box/sql/sqlInt.h
index 7f17fd8..daeb02c 100644
--- a/src/box/sql/sqlInt.h
+++ b/src/box/sql/sqlInt.h
@@ -3270,6 +3270,14 @@ int sqlKeywordCode(const unsigned char *, int);
 int sqlRunParser(Parse *, const char *, char **);
 
 /**
+ * Increment error counter if error suppression isn't set.
+ *
+ * @param parse_context Current parsing context.
+ */
+void
+sql_parser_error(struct Parse *parse_context);
+
+/**
  * This routine is called after a single SQL statement has been
  * parsed and a VDBE program to execute that statement has been
  * prepared.  This routine puts the finishing touches on the
diff --git a/src/box/sql/update.c b/src/box/sql/update.c
index ba24283..d203604 100644
--- a/src/box/sql/update.c
+++ b/src/box/sql/update.c
@@ -191,8 +191,9 @@ sqlUpdate(Parse * pParse,		/* The parser context */
 			}
 		}
 		if (j >= (int)def->field_count) {
-			sqlErrorMsg(pParse, "no such column: %s",
-					pChanges->a[i].zName);
+			diag_set(ClientError, ER_NO_SUCH_FIELD_NAME,
+				 pChanges->a[i].zName);
+			sql_parser_error(pParse);
 			goto update_cleanup;
 		}
 	}
diff --git a/src/box/sql/util.c b/src/box/sql/util.c
index dadae18..ad7bb1e 100644
--- a/src/box/sql/util.c
+++ b/src/box/sql/util.c
@@ -246,6 +246,16 @@ sqlErrorMsg(Parse * pParse, const char *zFormat, ...)
 	}
 }
 
+void
+sql_parser_error(struct Parse *parse_context)
+{
+	if (parse_context->db->suppressErr)
+		return;
+	parse_context->nErr++;
+	parse_context->rc = SQL_TARANTOOL_ERROR;
+}
+
+
 /*
  * Convert an SQL-style quoted string into a normal string by removing
  * the quote characters.  The conversion is done in-place.  If the
diff --git a/test/box/misc.result b/test/box/misc.result
index 97189ec..fce6c67 100644
--- a/test/box/misc.result
+++ b/test/box/misc.result
@@ -365,7 +365,7 @@ t;
   32: box.error.PROC_LUA
   33: box.error.NO_SUCH_PROC
   34: box.error.NO_SUCH_TRIGGER
-  35: box.error.NO_SUCH_INDEX
+  35: box.error.NO_SUCH_INDEX_ID
   36: box.error.NO_SUCH_SPACE
   37: box.error.NO_SUCH_FIELD
   38: box.error.EXACT_FIELD_COUNT
@@ -477,10 +477,12 @@ t;
   145: box.error.NO_SUCH_SEQUENCE
   146: box.error.SEQUENCE_EXISTS
   147: box.error.SEQUENCE_OVERFLOW
+  148: box.error.NO_SUCH_INDEX_NAME
   149: box.error.SPACE_FIELD_IS_DUPLICATE
   150: box.error.CANT_CREATE_COLLATION
   151: box.error.WRONG_COLLATION_OPTIONS
   152: box.error.NULLABLE_PRIMARY
+  153: box.error.NO_SUCH_FIELD_NAME
   154: box.error.TRANSACTION_YIELD
   155: box.error.NO_SUCH_GROUP
   156: box.error.SQL_BIND_VALUE
@@ -502,6 +504,7 @@ t;
   172: box.error.ROWID_OVERFLOW
   173: box.error.DROP_COLLATION
   174: box.error.ILLEGAL_COLLATION_MIX
+  175: box.error.SQL_NO_SUCH_PRAGMA
 ...
 test_run:cmd("setopt delimiter ''");
 ---
diff --git a/test/sql-tap/alter.test.lua b/test/sql-tap/alter.test.lua
index 1aad555..3b2eceb 100755
--- a/test/sql-tap/alter.test.lua
+++ b/test/sql-tap/alter.test.lua
@@ -403,7 +403,7 @@ test:do_catchsql_test(
         SELECT * FROM t1;
     ]], {
         -- <alter-7.6>
-        1, "no such table: T1"
+        1, "Space 'T1' does not exist"
         -- </alter-7.6>
     })
 
diff --git a/test/sql-tap/analyzeF.test.lua b/test/sql-tap/analyzeF.test.lua
index 77d53a6..0df4db4 100755
--- a/test/sql-tap/analyzeF.test.lua
+++ b/test/sql-tap/analyzeF.test.lua
@@ -83,7 +83,7 @@ test:do_catchsql_test(
         SELECT * FROM t1 WHERE x = substr('145', 2, 1) AND y = func(1, 2, 3);
     ]], {
         -- <2.1>
-        1, "no such function: FUNC"
+        1, "Function 'FUNC' does not exist"
         -- </2.1>
     })
 
@@ -93,7 +93,7 @@ test:do_catchsql_test(
         UPDATE t1 SET y=y+1 WHERE x = substr('145', 2, 1) AND y = func(1, 2, 3)
     ]], {
         -- <2.2>
-        1, "no such function: FUNC"
+        1, "Function 'FUNC' does not exist"
         -- </2.2>
     })
 
diff --git a/test/sql-tap/check.test.lua b/test/sql-tap/check.test.lua
index ace35eb..d5c3f2c 100755
--- a/test/sql-tap/check.test.lua
+++ b/test/sql-tap/check.test.lua
@@ -344,7 +344,7 @@ test:do_catchsql_test(
         );
     ]], {
         -- <check-3.3>
-        1, "Failed to create space 'T3': SQL error: no such column: Q"
+        1, "Failed to create space 'T3': Field 'Q' doesn't exist"
         -- </check-3.3>
     })
 
@@ -368,7 +368,7 @@ test:do_catchsql_test(
         );
     ]], {
         -- <check-3.5>
-        1, "Failed to create space 'T3': SQL error: no such column: T2.X"
+        1, "Failed to create space 'T3': Field 'X' doesn't exist"
         -- </check-3.5>
     })
 
diff --git a/test/sql-tap/fkey2.test.lua b/test/sql-tap/fkey2.test.lua
index 03bf025..d347e5a 100755
--- a/test/sql-tap/fkey2.test.lua
+++ b/test/sql-tap/fkey2.test.lua
@@ -309,7 +309,7 @@ test:do_catchsql_test(
         INSERT INTO t9 VALUES(1, 3);
     ]], {
         -- <fkey2-1.29>
-        1, "no such table: T9"
+        1, "Space 'T9' does not exist"
         -- </fkey2-1.29>
     })
 
diff --git a/test/sql-tap/func.test.lua b/test/sql-tap/func.test.lua
index e6b7956..2336fe1 100755
--- a/test/sql-tap/func.test.lua
+++ b/test/sql-tap/func.test.lua
@@ -2550,7 +2550,7 @@ test:do_test(
         ]])
     end, {
         -- <func-28.1>
-        1, "unknown function: NOSUCHFUNC()"
+        1, "Function 'NOSUCHFUNC' does not exist"
         -- </func-28.1>
     })
 
diff --git a/test/sql-tap/gh-2367-pragma.test.lua b/test/sql-tap/gh-2367-pragma.test.lua
index c0792c9..d874bce 100755
--- a/test/sql-tap/gh-2367-pragma.test.lua
+++ b/test/sql-tap/gh-2367-pragma.test.lua
@@ -8,7 +8,7 @@ test:do_catchsql_test(
 	[[
 		PRAGMA kek = 'ON';
 	]], {
-		1, "no such pragma: KEK"
+		1, "Pragma 'KEK' does not exist"
 	})
 
 ---
diff --git a/test/sql-tap/gh-2996-indexed-by.test.lua b/test/sql-tap/gh-2996-indexed-by.test.lua
index 7ee86be..1039ac1 100755
--- a/test/sql-tap/gh-2996-indexed-by.test.lua
+++ b/test/sql-tap/gh-2996-indexed-by.test.lua
@@ -60,7 +60,7 @@ test:do_catchsql_test(
     "indexed-by-1.3",
     "SELECT b FROM t1 INDEXED BY t1ix1 WHERE b <= 5", {
         -- <indexed-by-1.3>
-        1, "no such index: T1IX1"
+        1, "No index 'T1IX1' is defined in space 'T1'"
         -- <indexed-by-1.3>
     })
 
@@ -68,7 +68,7 @@ test:do_catchsql_test(
     "indexed-by-1.4",
     "SELECT b FROM t1 INDEXED BY t1ix2 WHERE b <= 5", {
         -- <indexed-by-1.4>
-        1, "no such index: T1IX2"
+        1, "No index 'T1IX2' is defined in space 'T1'"
         -- <indexed-by-1.4>
     })
 
@@ -103,7 +103,7 @@ test:do_catchsql_test(
     "indexed-by-1.7",
     "DELETE FROM t1 INDEXED BY t1ix1 WHERE b <= 5", {
         -- <indexed-by-1.7>
-        1, "no such index: T1IX1"
+        1, "No index 'T1IX1' is defined in space 'T1'"
         -- <indexed-by-1.7>
     })
 
@@ -111,7 +111,7 @@ test:do_catchsql_test(
     "indexed-by-1.8",
     "DELETE FROM t1 INDEXED BY t1ix2 WHERE b <= 5", {
         -- <indexed-by-1.8>
-        1, "no such index: T1IX2"
+        1, "No index 'T1IX2' is defined in space 'T1'"
         -- <indexed-by-1.8>
     })
 
@@ -145,7 +145,7 @@ test:do_catchsql_test(
     "indexed-by-1.11",
     "UPDATE t1 INDEXED BY t1ix1 SET b = 20 WHERE b = 10", {
         -- <indexed-by-1.11>
-        1, "no such index: T1IX1"
+        1, "No index 'T1IX1' is defined in space 'T1'"
         -- <indexed-by-1.11>
     })
 
@@ -153,7 +153,7 @@ test:do_catchsql_test(
     "indexed-by-1.12",
     "UPDATE t1 INDEXED BY t1ix2 SET b = 20 WHERE b = 10", {
         -- <indexed-by-1.12>
-        1, "no such index: T1IX2"
+        1, "No index 'T1IX2' is defined in space 'T1'"
         -- <indexed-by-1.12>
     })
 
diff --git a/test/sql-tap/gh2130-index-refer-table.test.lua b/test/sql-tap/gh2130-index-refer-table.test.lua
index b3bf519..99a7579 100755
--- a/test/sql-tap/gh2130-index-refer-table.test.lua
+++ b/test/sql-tap/gh2130-index-refer-table.test.lua
@@ -41,7 +41,7 @@ test:do_catchsql_test(
 	]],
 	{
 	-- <index-1.3>
-	1, "index T1.SAME_INDEX_NAME already exists"
+	1, "Index 'SAME_INDEX_NAME' already exists"
 	-- <index-1.3>
 	})
 
@@ -52,7 +52,7 @@ test:do_catchsql_test(
 	]],
 	{
 	-- <index-1.4>
-	1, "index T2.SAME_INDEX_NAME already exists"
+	1, "Index 'SAME_INDEX_NAME' already exists"
 	-- <index-1.4>
 	})
 
diff --git a/test/sql-tap/identifier_case.test.lua b/test/sql-tap/identifier_case.test.lua
index f26399e..923d5e6 100755
--- a/test/sql-tap/identifier_case.test.lua
+++ b/test/sql-tap/identifier_case.test.lua
@@ -75,7 +75,7 @@ data = {
     { 4,  [[ "COLUMNN" ]], {0} },
     { 5,  [[ "columnn" ]], {0} },
     { 6,  [[ "Columnn" ]], {0} },
-    { 7,  [[ "columNN" ]], {1, "/duplicate column name/"} }
+    { 7,  [[ "columNN" ]], {1, "Space field 'columNN' is duplicate"} }
 }
 
 for _, row in ipairs(data) do
diff --git a/test/sql-tap/in1.test.lua b/test/sql-tap/in1.test.lua
index e46ecb7..d32506c 100755
--- a/test/sql-tap/in1.test.lua
+++ b/test/sql-tap/in1.test.lua
@@ -220,7 +220,7 @@ test:do_catchsql_test(
         SELECT a FROM t1 WHERE c IN (10,20)
     ]], {
         -- <in-2.11>
-        1, "no such column: C"
+        1, "Field 'C' doesn't exist"
         -- </in-2.11>
     })
 
diff --git a/test/sql-tap/in3.test.lua b/test/sql-tap/in3.test.lua
index 3f69a77..41f08c8 100755
--- a/test/sql-tap/in3.test.lua
+++ b/test/sql-tap/in3.test.lua
@@ -469,7 +469,7 @@ test:do_catchsql_test(
         (SELECT folderid FROM Folder WHERE path LIKE 'C:\MP3\Albums\' || '%');
     ]], {
         -- <in3-5.2>
-        1, "no such table: FOLDER"
+        1, "Space 'FOLDER' does not exist"
         -- </in3-5.2>
     })
 
diff --git a/test/sql-tap/index-info.test.lua b/test/sql-tap/index-info.test.lua
index 17f7414..d052e8c 100755
--- a/test/sql-tap/index-info.test.lua
+++ b/test/sql-tap/index-info.test.lua
@@ -18,7 +18,7 @@ test:do_catchsql_test(
     "index-info-1.1",
     "PRAGMA index_xinfo (t1.a);",
     {
-        1, "no such pragma: INDEX_XINFO",
+        1, "Pragma 'INDEX_XINFO' does not exist",
     })
 
 -- Case: old index_info syntax is banned.
diff --git a/test/sql-tap/index1.test.lua b/test/sql-tap/index1.test.lua
index 117a4a5..3979fe0 100755
--- a/test/sql-tap/index1.test.lua
+++ b/test/sql-tap/index1.test.lua
@@ -97,7 +97,7 @@ test:do_test(
         return test:catchsql "CREATE INDEX index1 ON test1(f4)"
     end, {
         -- <index-2.1b>
-        1, "no such column: F4"
+        1, "Field 'F4' doesn't exist"
         -- </index-2.1b>
     })
 
@@ -115,7 +115,7 @@ test:do_test(
         return table.insert(v,msg) or v
     end, {
         -- <index-2.2>
-        1, "no such column: F4"
+        1, "Field 'F4' doesn't exist"
         -- </index-2.2>
     })
 
@@ -411,7 +411,7 @@ test:do_catchsql_test(
         DROP INDEX index1 ON test1
     ]], {
         -- <index-8.1>
-        1, "no such index: TEST1.INDEX1"
+        1, "No index 'INDEX1' is defined in space 'TEST1'"
         -- </index-8.1>
     })
 
diff --git a/test/sql-tap/insert1.test.lua b/test/sql-tap/insert1.test.lua
index 86cb141..b1c8957 100755
--- a/test/sql-tap/insert1.test.lua
+++ b/test/sql-tap/insert1.test.lua
@@ -26,7 +26,7 @@ test:do_catchsql_test("insert-1.1", [[
   INSERT INTO test1 VALUES(1,2,3)
 ]], {
   -- <insert-1.1>
-  1, "no such table: TEST1"
+  1, "Space 'TEST1' does not exist"
   -- </insert-1.1>
 })
 
@@ -240,7 +240,7 @@ end, {
     SELECT * FROM t3 ORDER BY a;
   ]], {
     -- <insert-4.3>
-    1, "no such column: T3.A"
+    1, "Field 'A' doesn't exist"
     -- </insert-4.3>
   })
 
@@ -268,7 +268,7 @@ test:do_catchsql_test("insert-4.6", [[
   INSERT INTO t3 VALUES(notafunc(2,3),2,3);
 ]], {
   -- <insert-4.6>
-  1, "no such function: NOTAFUNC"
+  1, "Function 'NOTAFUNC' does not exist"
   -- </insert-4.6>
 })
 
diff --git a/test/sql-tap/insert3.test.lua b/test/sql-tap/insert3.test.lua
index 1bcc71d..46f6399 100755
--- a/test/sql-tap/insert3.test.lua
+++ b/test/sql-tap/insert3.test.lua
@@ -172,7 +172,7 @@ test:do_catchsql_test(
             INSERT INTO t3 (a,b,c)VALUES(1,2,3)
     ]], {
         -- <insert3-3.2>
-        1, "no such column: NOSUCHCOL"
+        1, "Field 'NOSUCHCOL' doesn't exist"
         -- </insert3-3.2>
 })
 
@@ -195,7 +195,7 @@ test:do_catchsql_test(
             INSERT INTO t4 (a,b,c)VALUES(1,2,3)
     ]], {
         -- <insert3-3.4>
-        1, "no such column: NOSUCHCOL"
+        1, "Field 'NOSUCHCOL' doesn't exist"
         -- </insert3-3.4>
 })
 
diff --git a/test/sql-tap/join.test.lua b/test/sql-tap/join.test.lua
index fbcfb0c..b531bbd 100755
--- a/test/sql-tap/join.test.lua
+++ b/test/sql-tap/join.test.lua
@@ -580,7 +580,7 @@ test:do_catchsql_test(
         SELECT * FROM t1 JOIN t2 ON t3.a=t2.b;
     ]], {
         -- <join-3.6>
-        1, "no such column: T3.A"
+        1, "Field 'A' doesn't exist"
         -- </join-3.6>
     })
 
diff --git a/test/sql-tap/limit.test.lua b/test/sql-tap/limit.test.lua
index 788823f..033a345 100755
--- a/test/sql-tap/limit.test.lua
+++ b/test/sql-tap/limit.test.lua
@@ -795,7 +795,7 @@ test:do_catchsql_test(
         SELECT * FROM t1 LIMIT x
     ]], {
         -- <limit-12.3>
-        1, "no such column: X"
+        1, "Field 'X' doesn't exist"
         -- </limit-12.3>
     })
 
@@ -805,7 +805,7 @@ test:do_catchsql_test(
         SELECT * FROM t1 LIMIT 1 OFFSET x
     ]], {
         -- <limit-12.4>
-        1, "no such column: X"
+        1, "Field 'X' doesn't exist"
         -- </limit-12.4>
     })
 
diff --git a/test/sql-tap/lua-tables.test.lua b/test/sql-tap/lua-tables.test.lua
index 409976b..aa10c70 100755
--- a/test/sql-tap/lua-tables.test.lua
+++ b/test/sql-tap/lua-tables.test.lua
@@ -40,7 +40,7 @@ test:do_execsql_test(
 test:do_catchsql_test(
     "lua-tables-4",
     [[SELECT * from t1]],
-    {1, "no such table: T1"}
+    {1, "Space 'T1' does not exist"}
 )
 
 test:do_catchsql_test(
diff --git a/test/sql-tap/lua_sql.test.lua b/test/sql-tap/lua_sql.test.lua
index 0ef0837..1b10b0b 100755
--- a/test/sql-tap/lua_sql.test.lua
+++ b/test/sql-tap/lua_sql.test.lua
@@ -53,7 +53,7 @@ test:do_test(
 test:do_catchsql_test(
     "lua_sql-1.0",
     "select func3(1)",
-    {1, "no such function: FUNC3"})
+    {1, "Function 'FUNC3' does not exist"})
 
 
 -- check for different types
diff --git a/test/sql-tap/misc1.test.lua b/test/sql-tap/misc1.test.lua
index e9b5e1c..4358b58 100755
--- a/test/sql-tap/misc1.test.lua
+++ b/test/sql-tap/misc1.test.lua
@@ -423,7 +423,7 @@ test:do_catchsql_test(
         SELECT t1.*;
     ]], {
         -- <misc1-8.2>
-        1, "no such table: T1"
+        1, "Space 'T1' does not exist"
         -- </misc1-8.2>
     })
 
@@ -887,7 +887,7 @@ test:do_catchsql_test(
         CREATE TABLE test(a integer, primary key(a));
     ]], {
         -- <misc1-16.2>
-        1, "table TEST already exists"
+        1, "Space 'TEST' already exists"
         -- </misc1-16.2>
     })
 
diff --git a/test/sql-tap/select1.test.lua b/test/sql-tap/select1.test.lua
index bacc2b5..9ad0075 100755
--- a/test/sql-tap/select1.test.lua
+++ b/test/sql-tap/select1.test.lua
@@ -13,7 +13,7 @@ test:do_catchsql_test(
         SELECT * FROM test1
     ]], {
         -- <select1-1.1>
-        1, "no such table: TEST1"
+        1, "Space 'TEST1' does not exist"
         -- </select1-1.1>
     })
 
@@ -25,7 +25,7 @@ test:do_catchsql_test(
         SELECT * FROM test1, test2
     ]], {
         -- <select1-1.2>
-        1, "no such table: TEST2"
+        1, "Space 'TEST2' does not exist"
         -- </select1-1.2>
     })
 
@@ -35,7 +35,7 @@ test:do_catchsql_test(
         SELECT * FROM test2, test1
     ]], {
         -- <select1-1.3>
-        1, "no such table: TEST2"
+        1, "Space 'TEST2' does not exist"
         -- </select1-1.3>
     })
 
@@ -519,7 +519,7 @@ test:do_catchsql_test(
         SELECT XYZZY(f1) FROM test1
     ]], {
         -- <select1-2.18>
-        1, "no such function: XYZZY"
+        1, "Function 'XYZZY' does not exist"
         -- </select1-2.18>
     })
 
@@ -1795,7 +1795,7 @@ test:do_catchsql_test(
         SELECT t5.* FROM t3, t4;
     ]], {
         -- <select1-11.10>
-        1, "no such table: T5"
+        1, "Space 'T5' does not exist"
         -- </select1-11.10>
     })
 
@@ -1805,7 +1805,7 @@ test:do_catchsql_test(
         SELECT t3.* FROM t3 AS x, t4;
     ]], {
         -- <select1-11.11>
-        1, "no such table: T3"
+        1, "Space 'T3' does not exist"
         -- </select1-11.11>
     })
 
diff --git a/test/sql-tap/select4.test.lua b/test/sql-tap/select4.test.lua
index dd2d68b..bf600f9 100755
--- a/test/sql-tap/select4.test.lua
+++ b/test/sql-tap/select4.test.lua
@@ -411,7 +411,7 @@ test:do_catchsql_test(
         ORDER BY log;
     ]], {
         -- <select4-5.1>
-        1, "no such table: T2"
+        1, "Space 'T2' does not exist"
         -- </select4-5.1>
     })
 
diff --git a/test/sql-tap/select5.test.lua b/test/sql-tap/select5.test.lua
index 053e4c8..0d132db 100755
--- a/test/sql-tap/select5.test.lua
+++ b/test/sql-tap/select5.test.lua
@@ -88,7 +88,7 @@ test:do_catchsql_test(
         SELECT y, count(*) FROM t1 GROUP BY z ORDER BY y
     ]], {
         -- <select5-2.1.1>
-        1, "no such column: Z"
+        1, "Field 'Z' doesn't exist"
         -- </select5-2.1.1>
     })
 
@@ -98,7 +98,7 @@ test:do_catchsql_test(
         SELECT y, count(*) FROM t1 GROUP BY z(y) ORDER BY y
     ]], {
         -- <select5-2.2>
-        1, "no such function: Z"
+        1, "Function 'Z' does not exist"
         -- </select5-2.2>
     })
 
@@ -118,7 +118,7 @@ test:do_catchsql_test(
         SELECT y, count(*) FROM t1 GROUP BY y HAVING z(y)<3 ORDER BY y
     ]], {
         -- <select5-2.4>
-        1, "no such function: Z"
+        1, "Function 'Z' does not exist"
         -- </select5-2.4>
     })
 
@@ -128,7 +128,7 @@ test:do_catchsql_test(
         SELECT y, count(*) FROM t1 GROUP BY y HAVING count(*)<z ORDER BY y
     ]], {
         -- <select5-2.5>
-        1, "no such column: Z"
+        1, "Field 'Z' doesn't exist"
         -- </select5-2.5>
     })
 
diff --git a/test/sql-tap/table.test.lua b/test/sql-tap/table.test.lua
index 851e574..2bcc5aa 100755
--- a/test/sql-tap/table.test.lua
+++ b/test/sql-tap/table.test.lua
@@ -131,7 +131,7 @@ test:do_test(
         return test:catchsql "CREATE TABLE test2(id primary key, two text default 'hi')"
     end, {
         -- <table-2.1>
-        1, "table TEST2 already exists"
+        1, "Space 'TEST2' already exists"
         -- </table-2.1>
     })
 
@@ -266,7 +266,7 @@ test:do_catchsql_test(
         CREATE TABLE BIG(xyz int primary key)
     ]], {
         -- <table-3.2>
-        1, "table BIG already exists"
+        1, "Space 'BIG' already exists"
         -- </table-3.2>
     })
 
@@ -276,7 +276,7 @@ test:do_catchsql_test(
         CREATE TABLE biG(xyz int primary key)
     ]], {
         -- <table-3.3>
-        1, "table BIG already exists"
+        1, "Space 'BIG' already exists"
         -- </table-3.3>
     })
 
@@ -286,7 +286,7 @@ test:do_catchsql_test(
         CREATE TABLE bIg(xyz int primary key)
     ]], {
         -- <table-3.4>
-        1, "table BIG already exists"
+        1, "Space 'BIG' already exists"
         -- </table-3.4>
     })
 
@@ -377,7 +377,7 @@ test:do_catchsql_test(
         DROP TABLE test009
     ]], {
         -- <table-5.1.1>
-        1, "no such table: TEST009"
+        1, "Space 'TEST009' does not exist"
         -- </table-5.1.1>
     })
 
@@ -650,7 +650,7 @@ test:do_catchsql_test(
         SELECT * FROM t5;
     ]], {
         -- <table-8.7>
-        1, "no such table: T5"
+        1, "Space 'T5' does not exist"
         -- </table-8.7>
     })
 
@@ -697,7 +697,7 @@ test:do_catchsql_test(
         CREATE TABLE t6(a int primary key,b int,a int);
     ]], {
         -- <table-9.1>
-        1, "duplicate column name: A"
+        1, "Space field 'A' is duplicate"
         -- </table-9.1>
     })
 
@@ -707,7 +707,7 @@ test:do_catchsql_test(
         CREATE TABLE t6(a varchar(100) primary key, b blob, a integer);
     ]], {
         -- <table-9.2>
-        1, "duplicate column name: A"
+        1, "Space field 'A' is duplicate"
         -- </table-9.2>
     })
 
diff --git a/test/sql-tap/tkt-4ef7e3cfca.test.lua b/test/sql-tap/tkt-4ef7e3cfca.test.lua
index 29484dd..a30c45c 100755
--- a/test/sql-tap/tkt-4ef7e3cfca.test.lua
+++ b/test/sql-tap/tkt-4ef7e3cfca.test.lua
@@ -31,7 +31,7 @@ test:do_catchsql_test(
         INSERT INTO x VALUES('assert');
     ]], {
         -- <1.1>
-        1, "no such column: ABC.A"
+        1, "Field 'A' doesn't exist"
         -- </1.1>
     })
 
diff --git a/test/sql-tap/tkt3346.test.lua b/test/sql-tap/tkt3346.test.lua
index 5774d29..bcd4d41 100755
--- a/test/sql-tap/tkt3346.test.lua
+++ b/test/sql-tap/tkt3346.test.lua
@@ -94,7 +94,7 @@ test:do_catchsql_test(
         SELECT * FROM (SELECT a,b FROM t1 WHERE 1=x.a) AS x;
     ]], {
         -- <tkt3346-2.1>
-        1, "no such column: X.A"
+        1, "Field 'A' doesn't exist"
         -- </tkt3346-2.1>
     })
 
diff --git a/test/sql-tap/tkt3442.test.lua b/test/sql-tap/tkt3442.test.lua
index 8b03f6d..743045d 100755
--- a/test/sql-tap/tkt3442.test.lua
+++ b/test/sql-tap/tkt3442.test.lua
@@ -75,7 +75,7 @@ test:do_catchsql_test(
         SELECT node FROM listhash WHERE id="5000" LIMIT 1;
     ]], {
         -- <tkt3442-1.5>
-        1, "no such column: 5000"
+        1, "Field '5000' doesn't exist"
         -- </tkt3442-1.5>
     })
 
diff --git a/test/sql-tap/triggerB.test.lua b/test/sql-tap/triggerB.test.lua
index 30207f0..24f75b7 100755
--- a/test/sql-tap/triggerB.test.lua
+++ b/test/sql-tap/triggerB.test.lua
@@ -60,7 +60,7 @@ test:do_catchsql_test(
         INSERT INTO x VALUES(3,1,2);
     ]], {
         -- <triggerB-2.1>
-        1, "no such column: WEN.X"
+        1, "Field 'X' doesn't exist"
         -- </triggerB-2.1>
     })
 
@@ -73,7 +73,7 @@ test:do_catchsql_test(
         UPDATE x SET y=y+1;
     ]], {
         -- <triggerB-2.2>
-        1, "no such column: DLO.X"
+        1, "Field 'X' doesn't exist"
         -- </triggerB-2.2>
     })
 
@@ -111,7 +111,7 @@ test:do_test(
         ]]
     end, {
         -- <triggerB-2.4>
-        1, "no such column: OLD.C"
+        1, "Field 'C' doesn't exist"
         -- </triggerB-2.4>
     })
 
diff --git a/test/sql-tap/update.test.lua b/test/sql-tap/update.test.lua
index 5e242c0..c911969 100755
--- a/test/sql-tap/update.test.lua
+++ b/test/sql-tap/update.test.lua
@@ -25,7 +25,7 @@ test:do_catchsql_test("update-1.1", [[
   UPDATE test1 SET f2=5 WHERE f1<1
 ]], {
   -- <update-1.1>
-  1, "no such table: TEST1"
+  1, "Space 'TEST1' does not exist"
   -- </update-1.1>
 })
 
@@ -58,7 +58,7 @@ test:do_catchsql_test("update-3.2", [[
   UPDATE test1 SET f1=f3*2 WHERE f2==32
 ]], {
   -- <update-3.2>
-  1, "no such column: F3"
+  1, "Field 'F3' doesn't exist"
   -- </update-3.2>
 })
 
@@ -66,7 +66,7 @@ test:do_catchsql_test("update-3.3", [[
   UPDATE test1 SET f1=test2.f1*2 WHERE f2==32
 ]], {
   -- <update-3.3>
-  1, "no such column: TEST2.F1"
+  1, "Field 'F1' doesn't exist"
   -- </update-3.3>
 })
 
@@ -74,7 +74,7 @@ test:do_catchsql_test("update-3.4", [[
   UPDATE test1 SET f3=f1*2 WHERE f2==32
 ]], {
   -- <update-3.4>
-  1, "no such column: F3"
+  1, "Field 'F3' doesn't exist"
   -- </update-3.4>
 })
 
@@ -854,7 +854,7 @@ test:do_catchsql_test("update-9.1", [[
   UPDATE test1 SET x=11 WHERE f1=1025
 ]], {
   -- <update-9.1>
-  1, "no such column: X"
+  1, "Field 'X' doesn't exist"
   -- </update-9.1>
 })
 
@@ -862,7 +862,7 @@ test:do_catchsql_test("update-9.2", [[
   UPDATE test1 SET f1=x(11) WHERE f1=1025
 ]], {
   -- <update-9.2>
-  1, "no such function: X"
+  1, "Function 'X' does not exist"
   -- </update-9.2>
 })
 
@@ -870,7 +870,7 @@ test:do_catchsql_test("update-9.3", [[
   UPDATE test1 SET f1=11 WHERE x=1025
 ]], {
   -- <update-9.3>
-  1, "no such column: X"
+  1, "Field 'X' doesn't exist"
   -- </update-9.3>
 })
 
@@ -878,7 +878,7 @@ test:do_catchsql_test("update-9.4", [[
   UPDATE test1 SET f1=11 WHERE x(f1)=1025
 ]], {
   -- <update-9.4>
-  1, "no such function: X"
+  1, "Function 'X' does not exist"
   -- </update-9.4>
 })
 
diff --git a/test/sql-tap/view.test.lua b/test/sql-tap/view.test.lua
index 81dc9a4..d721361 100755
--- a/test/sql-tap/view.test.lua
+++ b/test/sql-tap/view.test.lua
@@ -69,7 +69,7 @@ if (0 > 0)
             SELECT * FROM v1 ORDER BY a;
         ]], {
             -- <view-1.2>
-            1, "no such table: v1"
+            1, "Space 'V1' does not exist"
             -- </view-1.2>
         })
 
@@ -106,7 +106,7 @@ test:do_catchsql_test(
         SELECT * FROM v1 ORDER BY a;
     ]], {
         -- <view-1.4>
-        1, "no such table: V1"
+        1, "Space 'V1' does not exist"
         -- </view-1.4>
     })
 
@@ -967,7 +967,7 @@ test:do_catchsql_test(
         DROP VIEW nosuchview
     ]], {
         -- <view-17.1>
-        1, "no such view: NOSUCHVIEW"
+        1, "Space 'NOSUCHVIEW' does not exist"
         -- </view-17.1>
     })
 
diff --git a/test/sql-tap/with2.test.lua b/test/sql-tap/with2.test.lua
index d43076c..5b00dfd 100755
--- a/test/sql-tap/with2.test.lua
+++ b/test/sql-tap/with2.test.lua
@@ -537,7 +537,7 @@ test:do_catchsql_test("6.3.2", [[
     INSERT INTO t2 SELECT a, b FROM abc;
 ]], {
     -- <6.3>
-    1, "no such table: ABC"
+    1, "Space 'ABC' does not exist"
     -- </6.3>
 })
 
@@ -600,7 +600,7 @@ test:do_catchsql_test("6.10", [[
     SELECT * FROM x
 ]], {
     -- <6.10>
-    1, "no such column: C"
+    1, "Field 'C' doesn't exist"
     -- </6.10>
 })
 
diff --git a/test/sql/checks.result b/test/sql/checks.result
index 12a3aa1..2eafae8 100644
--- a/test/sql/checks.result
+++ b/test/sql/checks.result
@@ -111,11 +111,11 @@ s = box.space._space:insert(t)
 --
 box.sql.execute("CREATE TABLE w2 (s1 INT PRIMARY KEY, CHECK ((SELECT COUNT(*) FROM w2) = 0));")
 ---
-- error: 'Failed to create space ''W2'': SQL error: no such table: W2'
+- error: 'Failed to create space ''W2'': Space ''W2'' does not exist'
 ...
 box.sql.execute("DROP TABLE w2;")
 ---
-- error: 'no such table: W2'
+- error: Space 'W2' does not exist
 ...
 --
 -- gh-3653: Dissallow bindings for DDL
diff --git a/test/sql/delete.result b/test/sql/delete.result
index 9071434..e024dd6 100644
--- a/test/sql/delete.result
+++ b/test/sql/delete.result
@@ -44,7 +44,7 @@ box.sql.execute("DROP TABLE t1;");
 --
 box.sql.execute("DELETE FROM t1;")
 ---
-- error: 'no such table: T1'
+- error: Space 'T1' does not exist
 ...
 box.sql.execute("CREATE TABLE t2 (s1 INT PRIMARY KEY);")
 ---
@@ -54,7 +54,7 @@ box.sql.execute("CREATE TRIGGER t2 BEFORE INSERT ON t2 BEGIN DELETE FROM t1; END
 ...
 box.sql.execute("INSERT INTO t2 VALUES (0);")
 ---
-- error: 'no such table: T1'
+- error: Space 'T1' does not exist
 ...
 box.sql.execute("DROP TABLE t2;")
 ---
diff --git a/test/sql/drop-table.result b/test/sql/drop-table.result
index 29318a8..0e14d8a 100644
--- a/test/sql/drop-table.result
+++ b/test/sql/drop-table.result
@@ -27,7 +27,7 @@ box.sql.execute("DROP TABLE zzzoobar")
 -- Table does not exist anymore. Should error here.
 box.sql.execute("INSERT INTO zzzoobar VALUES (111, 222, 'c3', 444)")
 ---
-- error: 'no such table: ZZZOOBAR'
+- error: Space 'ZZZOOBAR' does not exist
 ...
 -- gh-3712: if space features sequence, data from _sequence_data
 -- must be deleted before space is dropped.
@@ -92,7 +92,7 @@ box.sql.execute('CREATE TABLE t1 (id INT PRIMARY KEY, a INT)')
 -- Error: no such table.
 box.sql.execute('DROP TABLE t1')
 ---
-- error: 'no such table: T1'
+- error: Space 'T1' does not exist
 ...
 box.session.su('admin')
 ---
diff --git a/test/sql/gh-2929-primary-key.result b/test/sql/gh-2929-primary-key.result
index 5d95d41..aa91813 100644
--- a/test/sql/gh-2929-primary-key.result
+++ b/test/sql/gh-2929-primary-key.result
@@ -40,5 +40,5 @@ box.sql.execute("DROP TABLE t1")
 --
 box.sql.execute("CREATE TABLE tx (a INT, PRIMARY KEY (b));")
 ---
-- error: 'no such column: B'
+- error: Field 'B' doesn't exist
 ...
diff --git a/test/sql/gh-3613-idx-alter-update.result b/test/sql/gh-3613-idx-alter-update.result
index ac62b5f..2815428 100644
--- a/test/sql/gh-3613-idx-alter-update.result
+++ b/test/sql/gh-3613-idx-alter-update.result
@@ -28,7 +28,7 @@ box.snapshot()
 test_run:cmd('restart server default')
 box.sql.execute('DROP INDEX i ON j3')
 ---
-- error: 'no such index: J3.I'
+- error: No index 'I' is defined in space 'J3'
 ...
 box.sql.execute('CREATE INDEX i ON j3 (s1)')
 ---
diff --git a/test/sql/gh-3888-values-blob-assert.result b/test/sql/gh-3888-values-blob-assert.result
index 75152bb..95a81c7 100644
--- a/test/sql/gh-3888-values-blob-assert.result
+++ b/test/sql/gh-3888-values-blob-assert.result
@@ -34,12 +34,12 @@ box.sql.execute('SELECT float')
 -- check 'VALUES' against ID (should fail)
 box.sql.execute('VALUES(TheColumnName)')
 ---
-- error: 'no such column: THECOLUMNNAME'
+- error: Field 'THECOLUMNNAME' doesn't exist
 ...
 -- check 'SELECT' against ID (should fail)
 box.sql.execute('SELECT TheColumnName')
 ---
-- error: 'no such column: THECOLUMNNAME'
+- error: Field 'THECOLUMNNAME' doesn't exist
 ...
 -- check 'VALUES' well-formed expression  (returns value)
 box.sql.execute('VALUES(-0.5e-2)')
diff --git a/test/sql/icu-upper-lower.result b/test/sql/icu-upper-lower.result
index 6ca44b9..0ecfd23 100644
--- a/test/sql/icu-upper-lower.result
+++ b/test/sql/icu-upper-lower.result
@@ -163,7 +163,7 @@ box.sql.execute("select upper('1', 2)")
 ...
 box.sql.execute("select upper(\"1\")")
 ---
-- error: 'no such column: 1'
+- error: Field '1' doesn't exist
 ...
 box.sql.execute("select upper()")
 ---
diff --git a/test/sql/iproto.result b/test/sql/iproto.result
index b0736b0..562e068 100644
--- a/test/sql/iproto.result
+++ b/test/sql/iproto.result
@@ -92,7 +92,7 @@ cn:execute('delete from test where a = 12')
 -- SQL errors.
 cn:execute('insert into not_existing_table values ("kek")')
 ---
-- error: 'Failed to execute SQL statement: no such table: NOT_EXISTING_TABLE'
+- error: 'Failed to execute SQL statement: Space ''NOT_EXISTING_TABLE'' does not exist'
 ...
 cn:execute('insert qwerty gjsdjq  q  qwd qmq;; q;qwd;')
 ---
-- 
2.7.4

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

* [tarantool-patches] Re: [PATCH v1 1/1] sql: rework "no such object" and "object exists" errors
  2019-02-15 10:06 [tarantool-patches] [PATCH v1 1/1] sql: rework "no such object" and "object exists" errors imeevma
@ 2019-02-15 12:44 ` n.pettik
  2019-02-15 12:50   ` Konstantin Osipov
  0 siblings, 1 reply; 4+ messages in thread
From: n.pettik @ 2019-02-15 12:44 UTC (permalink / raw)
  To: tarantool-patches; +Cc: Imeev Mergen, Konstantin Osipov


> diff --git a/src/box/errcode.h b/src/box/errcode.h
> index f7dbb94..e25e05c 100644
> --- a/src/box/errcode.h
> +++ b/src/box/errcode.h
> @@ -87,7 +87,7 @@ struct errcode_record {
> 	/* 32 */_(ER_PROC_LUA,			"%s") \
> 	/* 33 */_(ER_NO_SUCH_PROC,		"Procedure '%.*s' is not defined") \
> 	/* 34 */_(ER_NO_SUCH_TRIGGER,		"Trigger '%s' doesn't exist") \
> -	/* 35 */_(ER_NO_SUCH_INDEX,		"No index #%u is defined in space '%s'") \
> +	/* 35 */_(ER_NO_SUCH_INDEX_ID,		"No index #%u is defined in space '%s'") \
> 	/* 36 */_(ER_NO_SUCH_SPACE,		"Space '%s' does not exist") \
> 	/* 37 */_(ER_NO_SUCH_FIELD,		"Field %d was not found in the tuple") \
> 	/* 38 */_(ER_EXACT_FIELD_COUNT,		"Tuple field count %u does not match space field count %u") \
> @@ -200,12 +200,12 @@ struct errcode_record {
> 	/*145 */_(ER_NO_SUCH_SEQUENCE,		"Sequence '%s' does not exist") \
> 	/*146 */_(ER_SEQUENCE_EXISTS,		"Sequence '%s' already exists") \
> 	/*147 */_(ER_SEQUENCE_OVERFLOW,		"Sequence '%s' has overflowed") \
> -	/*148 */_(ER_UNUSED5,			"") \
> +	/*148 */_(ER_NO_SUCH_INDEX_NAME,	"No index '%s' is defined in space '%s'") \

I’d better say ’No index with name …’.
But it is to be discussed.

> 	/*149 */_(ER_SPACE_FIELD_IS_DUPLICATE,	"Space field '%s' is duplicate") \
> 	/*150 */_(ER_CANT_CREATE_COLLATION,	"Failed to initialize collation: %s.") \
> 	/*151 */_(ER_WRONG_COLLATION_OPTIONS,	"Wrong collation options (field %u): %s") \
> 	/*152 */_(ER_NULLABLE_PRIMARY,		"Primary index of the space '%s' can not contain nullable parts") \
> -	/*153 */_(ER_UNUSED,			"") \
> +	/*153 */_(ER_NO_SUCH_FIELD_NAME,	"Field '%s' doesn't exist") \

Mb it is better to split this error into two:
“Space %s doesn’t feature field with name %s” and
“Unresolved column name %s”

Again, I’m neither SQL expert nor technical writer, so it is not up to me.

> diff --git a/src/box/sql/sqlInt.h b/src/box/sql/sqlInt.h
> index 7f17fd8..daeb02c 100644
> --- a/src/box/sql/sqlInt.h
> +++ b/src/box/sql/sqlInt.h
> @@ -3270,6 +3270,14 @@ int sqlKeywordCode(const unsigned char *, int);
> int sqlRunParser(Parse *, const char *, char **);
> 
> /**
> + * Increment error counter if error suppression isn't set.
> + *
> + * @param parse_context Current parsing context.
> + */
> +void
> +sql_parser_error(struct Parse *parse_context);

I suggest to incapsulate call of diag set inside this
function. To achieve this, lets make function take
variadic params. It would allow us to reduce size
of refactored code, at least.

> +
> +/**
>  * This routine is called after a single SQL statement has been
>  * parsed and a VDBE program to execute that statement has been
>  * prepared.  This routine puts the finishing touches on the
> diff --git a/src/box/sql/update.c b/src/box/sql/update.c
> index ba24283..d203604 100644
> --- a/src/box/sql/update.c
> +++ b/src/box/sql/update.c
> @@ -191,8 +191,9 @@ sqlUpdate(Parse * pParse,		/* The parser context */
> 			}
> 		}
> 		if (j >= (int)def->field_count) {
> -			sqlErrorMsg(pParse, "no such column: %s",
> -					pChanges->a[i].zName);
> +			diag_set(ClientError, ER_NO_SUCH_FIELD_NAME,
> +				 pChanges->a[i].zName);
> +			sql_parser_error(pParse);
> 			goto update_cleanup;
> 		}
> 	}
> diff --git a/src/box/sql/util.c b/src/box/sql/util.c
> index dadae18..ad7bb1e 100644
> --- a/src/box/sql/util.c
> +++ b/src/box/sql/util.c
> @@ -246,6 +246,16 @@ sqlErrorMsg(Parse * pParse, const char *zFormat, ...)
> 	}
> }
> 
> +void
> +sql_parser_error(struct Parse *parse_context)
> +{
> +	if (parse_context->db->suppressErr)
> +		return;

As Konstantin pointed out, seems like we don’t need
taking into consideration suppressErr here.

> +	parse_context->nErr++;
> +	parse_context->rc = SQL_TARANTOOL_ERROR;
> +}
> +
> +

Extra blank line.

> diff --git a/test/sql/checks.result b/test/sql/checks.result
> index 12a3aa1..2eafae8 100644
> --- a/test/sql/checks.result
> +++ b/test/sql/checks.result
> @@ -111,11 +111,11 @@ s = box.space._space:insert(t)
> --
> box.sql.execute("CREATE TABLE w2 (s1 INT PRIMARY KEY, CHECK ((SELECT COUNT(*) FROM w2) = 0));")
> ---
> -- error: 'Failed to create space ''W2'': SQL error: no such table: W2'
> +- error: 'Failed to create space ''W2'': Space ''W2'' does not exist’

Hm, IMHO looks a bit misleading.
Could we improve error reporting in this case?
It would be nice to see smth like “name cannot be resolved” or
“Misuse of space forward declaration”.

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

* [tarantool-patches] Re: [PATCH v1 1/1] sql: rework "no such object" and "object exists" errors
  2019-02-15 12:44 ` [tarantool-patches] " n.pettik
@ 2019-02-15 12:50   ` Konstantin Osipov
  2019-02-15 13:12     ` n.pettik
  0 siblings, 1 reply; 4+ messages in thread
From: Konstantin Osipov @ 2019-02-15 12:50 UTC (permalink / raw)
  To: n.pettik; +Cc: tarantool-patches, Imeev Mergen

* n.pettik <korablev@tarantool.org> [19/02/15 15:46]:
> > +	/*148 */_(ER_NO_SUCH_INDEX_NAME,	"No index '%s' is defined in space '%s'") \
> 
> I’d better say ’No index with name …’.
> But it is to be discussed.

It's a copycat of the INDEX_ID message.

> > +	/*153 */_(ER_NO_SUCH_FIELD_NAME,	"Field '%s' doesn't exist") \
> 
> Mb it is better to split this error into two:
> “Space %s doesn’t feature field with name %s” and
> “Unresolved column name %s”
> 
> Again, I’m neither SQL expert nor technical writer, so it is not up to me.

In a separate patch.

> > /**
> > + * Increment error counter if error suppression isn't set.
> > + *
> > + * @param parse_context Current parsing context.
> > + */
> > +void
> > +sql_parser_error(struct Parse *parse_context);
> 
> I suggest to incapsulate call of diag set inside this
> function. To achieve this, lets make function take
> variadic params. It would allow us to reduce size
> of refactored code, at least.

Nikita, I agree in general but given this entire function is
temporary, I think it's good enough.

> > }
> > 
> > +void
> > +sql_parser_error(struct Parse *parse_context)
> > +{
> > +	if (parse_context->db->suppressErr)
> > +		return;
> 
> As Konstantin pointed out, seems like we don’t need
> taking into consideration suppressErr here.
> 
> > +	parse_context->nErr++;
> > +	parse_context->rc = SQL_TARANTOOL_ERROR;
> > +}
> > +
> > +
> 
> Extra blank line.

Good point, I agree!

> > --
> > box.sql.execute("CREATE TABLE w2 (s1 INT PRIMARY KEY, CHECK ((SELECT COUNT(*) FROM w2) = 0));")
> > ---
> > -- error: 'Failed to create space ''W2'': SQL error: no such table: W2'
> > +- error: 'Failed to create space ''W2'': Space ''W2'' does not exist’
> 
> Hm, IMHO looks a bit misleading.
> Could we improve error reporting in this case?
> It would be nice to see smth like “name cannot be resolved” or
> “Misuse of space forward declaration”.

In a separate patch, please.
> 

-- 
Konstantin Osipov, Moscow, Russia, +7 903 626 22 32
http://tarantool.io - www.twitter.com/kostja_osipov

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

* [tarantool-patches] Re: [PATCH v1 1/1] sql: rework "no such object" and "object exists" errors
  2019-02-15 12:50   ` Konstantin Osipov
@ 2019-02-15 13:12     ` n.pettik
  0 siblings, 0 replies; 4+ messages in thread
From: n.pettik @ 2019-02-15 13:12 UTC (permalink / raw)
  To: tarantool-patches; +Cc: Imeev Mergen, Konstantin Osipov



> On 15 Feb 2019, at 15:50, Konstantin Osipov <kostja@tarantool.org> wrote:
> 
> * n.pettik <korablev@tarantool.org> [19/02/15 15:46]:
>>> +	/*148 */_(ER_NO_SUCH_INDEX_NAME,	"No index '%s' is defined in space '%s'") \
>> 
>> I’d better say ’No index with name …’.
>> But it is to be discussed.
> 
> It's a copycat of the INDEX_ID message.

Yep, I've noticed this, but anyway. Without no difference
between error messages user would wonder why in some
cases name appears, and in other - id. IMHO.

>>> /**
>>> + * Increment error counter if error suppression isn't set.
>>> + *
>>> + * @param parse_context Current parsing context.
>>> + */
>>> +void
>>> +sql_parser_error(struct Parse *parse_context);
>> 
>> I suggest to incapsulate call of diag set inside this
>> function. To achieve this, lets make function take
>> variadic params. It would allow us to reduce size
>> of refactored code, at least.
> 
> Nikita, I agree in general but given this entire function is
> temporary, I think it's good enough.

It is going to exist until we remove parse->nErr and parse->rc -
long enough, I guess.

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

end of thread, other threads:[~2019-02-15 13:12 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-02-15 10:06 [tarantool-patches] [PATCH v1 1/1] sql: rework "no such object" and "object exists" errors imeevma
2019-02-15 12:44 ` [tarantool-patches] " n.pettik
2019-02-15 12:50   ` Konstantin Osipov
2019-02-15 13:12     ` n.pettik

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