[tarantool-patches] [PATCH v7 7/7] sql: remove Checks to server
Kirill Shcherbatov
kshcherbatov at tarantool.org
Wed May 23 17:05:34 MSK 2018
New server checks stored in space_opts. For ExprList transfering
to server data is packed in msgpack as array of maps:
[{"expr_str": "x < y", "name" : "FIRST"}, ..]
Introduced checks_array_decode aimed to unpack this
complex package.
Introduced sql_checks_update_space_def_reference to update space
references as space_def pointer changes over the time,
i.e. resolved checks refer released memory.
Resolves #3272.
---
src/box/alter.cc | 5 +++
src/box/opt_def.h | 5 ++-
src/box/space_def.c | 96 +++++++++++++++++++++++++++++++++++++++
src/box/space_def.h | 12 ++---
src/box/sql.c | 107 +++++++++++++++++++++++++++++++++++++++++++-
src/box/sql.h | 43 ++++++++++++++++++
src/box/sql/build.c | 65 +++++++++++++++++++--------
src/box/sql/insert.c | 33 ++++++++------
src/box/sql/pragma.h | 2 -
src/box/sql/resolve.c | 2 -
src/box/sql/sqliteInt.h | 1 -
test/sql-tap/check.test.lua | 10 ++---
12 files changed, 329 insertions(+), 52 deletions(-)
diff --git a/src/box/alter.cc b/src/box/alter.cc
index e4780da..b379da2 100644
--- a/src/box/alter.cc
+++ b/src/box/alter.cc
@@ -523,6 +523,11 @@ space_def_new_from_tuple(struct tuple *tuple, uint32_t errcode,
space_def_new_xc(id, uid, exact_field_count, name, name_len,
engine_name, engine_name_len, &opts, fields,
field_count);
+ if (def->opts.checks != NULL &&
+ sql_checks_resolve_space_def_reference(def->opts.checks, def) != 0){
+ tnt_raise(ClientError, errcode, def->name,
+ box_error_message(box_error_last()));
+ }
auto def_guard = make_scoped_guard([=] { space_def_delete(def); });
struct engine *engine = engine_find_xc(def->engine_name);
engine_check_space_def_xc(engine, def);
diff --git a/src/box/opt_def.h b/src/box/opt_def.h
index 71fef3a..91e4f0b 100644
--- a/src/box/opt_def.h
+++ b/src/box/opt_def.h
@@ -79,11 +79,12 @@ struct opt_def {
#define OPT_DEF_ENUM(key, enum_name, opts, field, to_enum) \
{ key, OPT_ENUM, offsetof(opts, field), sizeof(int), #enum_name, \
- sizeof(enum enum_name), enum_name##_strs, enum_name##_MAX, {to_enum} }
+ sizeof(enum enum_name), enum_name##_strs, enum_name##_MAX, \
+ { to_enum } }
#define OPT_DEF_ARRAY(key, opts, field, to_array) \
{ key, OPT_ARRAY, offsetof(opts, field), sizeof(((opts *)0)->field), \
- NULL, 0, NULL, 0, {to_array} }
+ NULL, 0, NULL, 0, { (void *)to_array} }
#define OPT_END {NULL, opt_type_MAX, 0, 0, NULL, 0, NULL, 0, {NULL}}
diff --git a/src/box/space_def.c b/src/box/space_def.c
index 9e0e7e3..7bff86f 100644
--- a/src/box/space_def.c
+++ b/src/box/space_def.c
@@ -33,17 +33,33 @@
#include "diag.h"
#include "error.h"
#include "sql.h"
+#include "msgpuck.h"
+
+/**
+ * Make checks from msgpack.
+ * @param str pointer to array of maps
+ * e.g. [{"expr_str": "x < y", "name": "ONE"}, ..].
+ * @param len array items count.
+ * @param opt pointer to store parsing result.
+ * @retval not NULL Checks pointer on success.
+ * @retval NULL on error.
+ */
+static int
+checks_array_decode(const char **str, uint32_t len, char *opt);
const struct space_opts space_opts_default = {
/* .temporary = */ false,
/* .view = */ false,
/* .sql = */ NULL,
+ /* .checks = */ NULL,
};
const struct opt_def space_opts_reg[] = {
OPT_DEF("temporary", OPT_BOOL, struct space_opts, temporary),
OPT_DEF("view", OPT_BOOL, struct space_opts, is_view),
OPT_DEF("sql", OPT_STRPTR, struct space_opts, sql),
+ OPT_DEF_ARRAY("checks", struct space_opts, checks,
+ checks_array_decode),
OPT_END,
};
@@ -122,6 +138,19 @@ space_def_dup(const struct space_def *src)
}
}
}
+ if (src->opts.checks != NULL) {
+ ret->opts.checks =
+ sql_expr_list_dup(sql_get(), src->opts.checks, 0);
+ if (ret->opts.checks == NULL) {
+ diag_set(OutOfMemory, 0, "sql_expr_list_dup",
+ "ret->opts.checks");
+ space_def_destroy_fields(ret->fields, ret->field_count);
+ free(ret->opts.sql);
+ free(ret);
+ return NULL;
+ }
+ sql_checks_update_space_def_reference(ret->opts.checks, ret);
+ }
tuple_dictionary_ref(ret->dict);
return ret;
}
@@ -207,6 +236,18 @@ space_def_new(uint32_t id, uint32_t uid, uint32_t exact_field_count,
}
}
}
+ if (opts->checks != NULL) {
+ def->opts.checks = sql_expr_list_dup(sql_get(), opts->checks, 0);
+ if (def->opts.checks == NULL) {
+ diag_set(OutOfMemory, 0, "sql_expr_list_dup",
+ "def->opts.checks");
+ space_def_destroy_fields(def->fields, def->field_count);
+ free(def->opts.sql);
+ free(def);
+ return NULL;
+ }
+ sql_checks_update_space_def_reference(def->opts.checks, def);
+ }
return def;
}
@@ -231,3 +272,58 @@ space_def_delete(struct space_def *def)
TRASH(def);
free(def);
}
+
+void
+space_opts_destroy(struct space_opts *opts)
+{
+ free(opts->sql);
+ sql_expr_list_delete(sql_get(), opts->checks);
+ TRASH(opts);
+}
+
+static int
+checks_array_decode(const char **str, uint32_t len, char *opt)
+{
+ struct ExprList *checks = NULL;
+ const char **map = str;
+ struct sqlite3 *db = sql_get();
+ for (unsigned i = 0; i < len; i++) {
+ checks = sql_expr_list_append(db, checks, NULL);
+ if (checks == NULL) {
+ diag_set(OutOfMemory, 0, "sql_expr_list_append",
+ "pChecks");
+ goto error;
+ }
+ const char *expr_name = NULL;
+ const char *expr_str = NULL;
+ uint32_t expr_name_len = 0;
+ uint32_t expr_str_len = 0;
+ uint32_t map_size = mp_decode_map(map);
+ for (unsigned j = 0; j < map_size; j++) {
+ if (mp_typeof(**map) != MP_STR) {
+ diag_set(ClientError, ER_WRONG_INDEX_OPTIONS, 0,
+ "key must be a string");
+ goto error;
+ }
+ uint32_t key_len;
+ const char *key = mp_decode_str(map, &key_len);
+ if (strncmp(key, "expr_str", key_len) == 0) {
+ expr_str = mp_decode_str(map, &expr_str_len);
+ } else if (strncmp(key, "name", key_len) == 0) {
+ expr_name = mp_decode_str(map, &expr_name_len);
+ } else {
+ diag_set(ClientError, ER_WRONG_INDEX_OPTIONS, 0,
+ "invalid MsgPack");
+ goto error;
+ }
+ }
+ sql_check_list_item_init(checks, i, expr_name,
+ expr_name_len, expr_str,
+ expr_str_len);
+ }
+ *(void **)opt = checks;
+ return 0;
+error:
+ sql_expr_list_delete(db, checks);
+ return -1;
+}
diff --git a/src/box/space_def.h b/src/box/space_def.h
index 5328203..e9bd283 100644
--- a/src/box/space_def.h
+++ b/src/box/space_def.h
@@ -61,6 +61,10 @@ struct space_opts {
* SQL statement that produced this space.
*/
char *sql;
+ /**
+ * SQL Checks expressions list.
+ */
+ struct ExprList *checks;
};
extern const struct space_opts space_opts_default;
@@ -79,12 +83,8 @@ space_opts_create(struct space_opts *opts)
/**
* Destroy space options
*/
-static inline void
-space_opts_destroy(struct space_opts *opts)
-{
- free(opts->sql);
- TRASH(opts);
-}
+void
+space_opts_destroy(struct space_opts *opts);
/** Space metadata. */
struct space_def {
diff --git a/src/box/sql.c b/src/box/sql.c
index 0845e65..d62e14c 100644
--- a/src/box/sql.c
+++ b/src/box/sql.c
@@ -1508,13 +1508,49 @@ int tarantoolSqlite3MakeTableOpts(Table *pTable, const char *zSql, void *buf)
bool is_view = false;
if (pTable != NULL)
is_view = pTable->def->opts.is_view;
- p = enc->encode_map(base, is_view ? 2 : 1);
+
+ bool has_checks = (pTable != NULL && pTable->def->opts.checks != NULL);
+ int checks_cnt = has_checks ? pTable->def->opts.checks->nExpr : 0;
+
+ int map_fields = 1;
+ map_fields += is_view == true;
+ map_fields += (checks_cnt > 0);
+ p = enc->encode_map(base, map_fields);
+
p = enc->encode_str(p, "sql", 3);
p = enc->encode_str(p, zSql, strlen(zSql));
if (is_view) {
p = enc->encode_str(p, "view", 4);
p = enc->encode_bool(p, true);
}
+ if (checks_cnt == 0)
+ return (int)(p - base);
+ /* Encode checks. */
+ struct ExprList_item *a = pTable->def->opts.checks->a;
+ p = enc->encode_str(p, "checks", 6);
+ p = enc->encode_array(p, checks_cnt);
+ for (int i = 0; i < checks_cnt; ++i) {
+ int items = 0;
+ items += a[i].pExpr != NULL;
+ items += a[i].zName != NULL;
+ p = enc->encode_map(p, items);
+ /*
+ * a[i].pExpr could be NULL for VIEW column names
+ * represented as checks.
+ */
+ if (a[i].pExpr != NULL) {
+ Expr *pExpr = a[i].pExpr;
+ assert(pExpr->u.zToken != NULL);
+ p = enc->encode_str(p, "expr_str", 8);
+ p = enc->encode_str(p, pExpr->u.zToken,
+ strlen(pExpr->u.zToken));
+ }
+ if (a[i].zName != NULL) {
+ p = enc->encode_str(p, "name", 10);
+ p = enc->encode_str(p, a[i].zName,
+ strlen(a[i].zName));
+ }
+ }
return (int)(p - base);
}
@@ -1761,3 +1797,72 @@ sql_table_def_rebuild(struct sqlite3 *db, struct Table *pTable)
pTable->def->opts.temporary = false;
return 0;
}
+
+int
+sql_check_list_item_init(struct ExprList *expr_list, int idx,
+ const char *expr_name, uint32_t expr_name_len,
+ const char *expr_str, uint32_t expr_str_len)
+{
+ assert(idx < expr_list->nExpr);
+ struct ExprList_item *item = &expr_list->a[idx];
+ memset(item, 0, sizeof(struct ExprList_item));
+ if (expr_name != NULL) {
+ item->zName = sqlite3DbStrNDup(db, expr_name, expr_name_len);
+ if (item->zName == NULL)
+ return -1;
+ }
+ struct Expr *check = NULL;
+ if (expr_str != NULL &&
+ sql_expr_compile(db, expr_str, expr_str_len,
+ &check) != 0) {
+ sqlite3DbFree(db, item->zName);
+ return -1;
+ }
+ item->pExpr = check;
+ return 0;
+}
+
+static int
+update_space_def_callback(Walker *pWalker, Expr *pExpr)
+{
+ if (pExpr->op == TK_COLUMN && ExprHasProperty(pExpr, EP_Resolved))
+ pExpr->space_def = (struct space_def *) pWalker->pParse;
+ return WRC_Continue;
+}
+
+void
+sql_checks_update_space_def_reference(ExprList *expr_list,
+ struct space_def *def)
+{
+ assert(expr_list != NULL);
+ Walker w;
+ memset(&w, 0, sizeof(w));
+ w.xExprCallback = update_space_def_callback;
+ w.pParse = (void *)def;
+
+ for (int i = 0; i < expr_list->nExpr; i++)
+ sqlite3WalkExpr(&w, expr_list->a[i].pExpr);
+}
+
+int
+sql_checks_resolve_space_def_reference(ExprList *expr_list,
+ struct space_def *def)
+{
+ Parse parser;
+ sql_parser_create(&parser, sql_get());
+ parser.parse_only = true;
+
+ Table dummy_table;
+ memset(&dummy_table, 0, sizeof(dummy_table));
+ dummy_table.def = def;
+
+ sql_resolve_self_reference(&parser, &dummy_table, NC_IsCheck, NULL,
+ expr_list);
+ int rc = parser.rc;
+ if (rc != SQLITE_OK)
+ diag_set(IllegalParams, parser.zErrMsg);
+
+ sql_parser_destroy(&parser);
+
+ return rc == SQLITE_OK ? 0 : -1;
+}
diff --git a/src/box/sql.h b/src/box/sql.h
index d031d9b..e626f76 100644
--- a/src/box/sql.h
+++ b/src/box/sql.h
@@ -103,6 +103,15 @@ struct Expr*
space_column_default_expr(uint32_t space_id, uint32_t fieldno);
/**
+ * Get server checks list by space_id.
+ * @param space_id Space ID.
+ * @retval NULL on error.
+ * @param not NULL on success.
+ */
+struct ExprList *
+space_checks_expr_list(uint32_t space_id);
+
+/**
* Return the number of bytes required to create a duplicate of the
* expression passed as the first argument. The second argument is a
* mask containing EXPRDUP_XXX flags.
@@ -235,6 +244,40 @@ sql_resolve_self_reference(struct Parse *parser, struct Table *table, int type,
struct Expr *expr, struct ExprList *expr_list);
/**
+ * Initialize check_list_item.
+ * @param expr_list ExprList with item.
+ * @param idx item index.
+ * @param expr_name expression name (optional).
+ * @param expr_name_len expresson name length (optional).
+ * @param expr_str expression to build string.
+ * @param expr_str_len expression to build string length.
+ * @retval 0 on success.
+ * @retval -1 on error.
+ */
+int
+sql_check_list_item_init(struct ExprList *expr_list, int idx,
+ const char *expr_name, uint32_t expr_name_len,
+ const char *expr_str, uint32_t expr_str_len);
+
+/**
+ * Resolve space_def references checks for expr_list.
+ * @param expr_list to modify.
+ * @param def to refer to.
+ */
+int
+sql_checks_resolve_space_def_reference(struct ExprList *expr_list,
+ struct space_def *def);
+
+/**
+ * Update space_def references for expr_list.
+ * @param expr_list to modify.
+ * @param def to refer to.
+ */
+void
+sql_checks_update_space_def_reference(struct ExprList *expr_list,
+ struct space_def *def);
+
+/**
* Initialize a new parser object.
* A number of service allocations are performed on the region, which is also
* cleared in the destroy function.
diff --git a/src/box/sql/build.c b/src/box/sql/build.c
index d00bb1d..f5bb54d 100644
--- a/src/box/sql/build.c
+++ b/src/box/sql/build.c
@@ -406,7 +406,6 @@ deleteTable(sqlite3 * db, Table * pTable)
sqlite3DbFree(db, pTable->aCol);
sqlite3DbFree(db, pTable->zColAff);
sqlite3SelectDelete(db, pTable->pSelect);
- sql_expr_list_delete(db, pTable->pCheck);
assert(pTable->def != NULL);
/* Do not delete pTable->def allocated on region. */
if (!pTable->def->opts.temporary)
@@ -1022,19 +1021,29 @@ sqlite3AddPrimaryKey(Parse * pParse, /* Parsing context */
void
sql_add_check_constraint(Parse *parser, ExprSpan *span)
{
-#ifndef SQLITE_OMIT_CHECK
struct Expr *expr = span->pExpr;
Table *table = parser->pNewTable;
if (table != NULL) {
- table->pCheck =
- sql_expr_list_append(parser->db, table->pCheck, expr);
+ expr->u.zToken =
+ sqlite3DbStrNDup(parser->db, (char *)span->zStart,
+ (int)(span->zEnd - span->zStart));
+ if (expr->u.zToken == NULL)
+ goto release_expr;
+ table->def->opts.checks =
+ sql_expr_list_append(parser->db,
+ table->def->opts.checks, expr);
+ if (table->def->opts.checks == NULL) {
+ sqlite3DbFree(parser->db, expr->u.zToken);
+ goto release_expr;
+ }
if (parser->constraintName.n) {
- sqlite3ExprListSetName(parser, table->pCheck,
+ sqlite3ExprListSetName(parser, table->def->opts.checks,
&parser->constraintName, 1);
}
- } else
-#endif
+ } else {
+release_expr:
sql_expr_delete(parser->db, expr, false);
+ }
}
/*
@@ -1177,6 +1186,16 @@ space_is_view(Table *table) {
return space->def->opts.is_view;
}
+struct ExprList *
+space_checks_expr_list(uint32_t space_id)
+{
+ struct space *space;
+ space = space_by_id(space_id);
+ assert(space != NULL);
+ assert(space->def != NULL);
+ return space->def->opts.checks;
+}
+
/**
* Create cursor which will be positioned to the space/index.
* It makes space lookup and loads pointer to it into register,
@@ -1848,17 +1867,14 @@ sqlite3EndTable(Parse * pParse, /* Parse context */
return;
}
+ /*
+ * As rebuild creates a new ExpList tree and old_def
+ * is allocated on region release old tree manually.
+ */
+ struct ExprList *old_checks = p->def->opts.checks;
if (sql_table_def_rebuild(db, p) != 0)
return;
-
-#ifndef SQLITE_OMIT_CHECK
- /* Resolve names in all CHECK constraint expressions.
- */
- if (p->pCheck) {
- sql_resolve_self_reference(pParse, p, NC_IsCheck, NULL,
- p->pCheck);
- }
-#endif /* !defined(SQLITE_OMIT_CHECK) */
+ sql_expr_list_delete(db, old_checks);
/* If not initializing, then create new Tarantool space.
*
@@ -1979,6 +1995,15 @@ sqlite3EndTable(Parse * pParse, /* Parse context */
}
#endif
}
+
+ /*
+ * Checks are useless for now as all operations process with
+ * the server checks instance. Remove to do not consume extra memory,
+ * don't require make a copy on space_def_dup and to improve
+ * debuggability.
+ */
+ sql_expr_list_delete(db, p->def->opts.checks);
+ p->def->opts.checks = NULL;
}
#ifndef SQLITE_OMIT_VIEW
@@ -2020,7 +2045,7 @@ sqlite3CreateView(Parse * pParse, /* The parsing context */
*/
p->pSelect = sqlite3SelectDup(db, pSelect, EXPRDUP_REDUCE);
p->def->opts.is_view = true;
- p->pCheck = sql_expr_list_dup(db, pCNames, EXPRDUP_REDUCE);
+ p->def->opts.checks = sql_expr_list_dup(db, pCNames, EXPRDUP_REDUCE);
if (db->mallocFailed)
goto create_view_fail;
@@ -2106,7 +2131,9 @@ sql_view_column_names(struct Parse *parse, struct Table *table)
struct Table *sel_tab = sqlite3ResultSetOfSelect(parse, select);
parse->nTab = n;
int rc = 0;
- if (table->pCheck != NULL) {
+ /* Get server checks. */
+ ExprList *checks = space_checks_expr_list(table->def->id);
+ if (checks != NULL) {
/* CREATE VIEW name(arglist) AS ...
* The names of the columns in the table are taken
* from arglist which is stored in table->pCheck.
@@ -2115,7 +2142,7 @@ sql_view_column_names(struct Parse *parse, struct Table *table)
* VIEW it holds the list of column names.
*/
struct space_def *old_def = table->def;
- sqlite3ColumnsFromExprList(parse, table->pCheck, table);
+ sqlite3ColumnsFromExprList(parse, checks, table);
if (sql_table_def_rebuild(db, table) != 0) {
rc = -1;
} else {
diff --git a/src/box/sql/insert.c b/src/box/sql/insert.c
index 6e7144c..f78f679 100644
--- a/src/box/sql/insert.c
+++ b/src/box/sql/insert.c
@@ -1164,21 +1164,23 @@ sqlite3GenerateConstraintChecks(Parse * pParse, /* The parser context */
}
}
- /* Test all CHECK constraints
+ /*
+ * Get server checks.
+ * Test all CHECK constraints.
*/
-#ifndef SQLITE_OMIT_CHECK
- if (pTab->pCheck && (user_session->sql_flags &
- SQLITE_IgnoreChecks) == 0) {
- ExprList *pCheck = pTab->pCheck;
+ uint32_t space_id = SQLITE_PAGENO_TO_SPACEID(pTab->tnum);
+ ExprList *checks = space_checks_expr_list(space_id);
+ if (checks != NULL && (user_session->sql_flags &
+ SQLITE_IgnoreChecks) == 0) {
pParse->ckBase = regNewData + 1;
if (override_error != ON_CONFLICT_ACTION_DEFAULT)
on_error = override_error;
else
on_error = ON_CONFLICT_ACTION_ABORT;
- for (i = 0; i < pCheck->nExpr; i++) {
+ for (i = 0; i < checks->nExpr; i++) {
int allOk;
- Expr *pExpr = pCheck->a[i].pExpr;
+ Expr *pExpr = checks->a[i].pExpr;
if (aiChng
&& checkConstraintUnchanged(pExpr, aiChng))
continue;
@@ -1188,7 +1190,7 @@ sqlite3GenerateConstraintChecks(Parse * pParse, /* The parser context */
if (on_error == ON_CONFLICT_ACTION_IGNORE) {
sqlite3VdbeGoto(v, ignoreDest);
} else {
- char *zName = pCheck->a[i].zName;
+ char *zName = checks->a[i].zName;
if (zName == 0)
zName = pTab->def->name;
if (on_error == ON_CONFLICT_ACTION_REPLACE)
@@ -1202,7 +1204,6 @@ sqlite3GenerateConstraintChecks(Parse * pParse, /* The parser context */
sqlite3VdbeResolveLabel(v, allOk);
}
}
-#endif /* !defined(SQLITE_OMIT_CHECK) */
/* Test all UNIQUE constraints by creating entries for each UNIQUE
* index and making sure that duplicate entries do not already exist.
@@ -1886,12 +1887,16 @@ xferOptimization(Parse * pParse, /* Parser context */
return 0; /* pDestIdx has no corresponding index in pSrc */
}
}
-#ifndef SQLITE_OMIT_CHECK
- if (pDest->pCheck
- && sqlite3ExprListCompare(pSrc->pCheck, pDest->pCheck, -1)) {
- return 0; /* Tables have different CHECK constraints. Ticket #2252 */
+ /* Get server checks. */
+ ExprList *pCheck_src = space_checks_expr_list(
+ SQLITE_PAGENO_TO_SPACEID(pSrc->tnum));
+ ExprList *pCheck_dest = space_checks_expr_list(
+ SQLITE_PAGENO_TO_SPACEID(pDest->tnum));
+ if (pCheck_dest
+ && sqlite3ExprListCompare(pCheck_src, pCheck_dest, -1)) {
+ /* Tables have different CHECK constraints. Ticket #2252 */
+ return 0;
}
-#endif
#ifndef SQLITE_OMIT_FOREIGN_KEY
/* Disallow the transfer optimization if the destination table constains
* any foreign key constraints. This is more restrictive than necessary.
diff --git a/src/box/sql/pragma.h b/src/box/sql/pragma.h
index eb7c93b..f966018 100644
--- a/src/box/sql/pragma.h
+++ b/src/box/sql/pragma.h
@@ -166,14 +166,12 @@ static const PragmaName aPragmaName[] = {
/* iArg: */ SQLITE_FullColNames},
#endif
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
-#if !defined(SQLITE_OMIT_CHECK)
{ /* zName: */ "ignore_check_constraints",
/* ePragTyp: */ PragTyp_FLAG,
/* ePragFlg: */ PragFlg_Result0 | PragFlg_NoColumns1,
/* ColNames: */ 0, 0,
/* iArg: */ SQLITE_IgnoreChecks},
#endif
-#endif
#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
{ /* zName: */ "index_info",
/* ePragTyp: */ PragTyp_INDEX_INFO,
diff --git a/src/box/sql/resolve.c b/src/box/sql/resolve.c
index fd82119..0523b4e 100644
--- a/src/box/sql/resolve.c
+++ b/src/box/sql/resolve.c
@@ -530,10 +530,8 @@ notValid(Parse * pParse, /* Leave error message here */
const char *zIn = "partial index WHERE clauses";
if (pNC->ncFlags & NC_IdxExpr)
zIn = "index expressions";
-#ifndef SQLITE_OMIT_CHECK
else if (pNC->ncFlags & NC_IsCheck)
zIn = "CHECK constraints";
-#endif
sqlite3ErrorMsg(pParse, "%s prohibited in %s", zMsg, zIn);
}
}
diff --git a/src/box/sql/sqliteInt.h b/src/box/sql/sqliteInt.h
index 5746cb4..7611b4c 100644
--- a/src/box/sql/sqliteInt.h
+++ b/src/box/sql/sqliteInt.h
@@ -1924,7 +1924,6 @@ struct Table {
Select *pSelect; /* NULL for tables. Points to definition if a view. */
FKey *pFKey; /* Linked list of all foreign keys in this table */
char *zColAff; /* String defining the affinity of each column */
- ExprList *pCheck; /* All CHECK constraints */
/* ... also used as column name list in a VIEW */
Hash idxHash; /* All (named) indices indexed by name */
int tnum; /* Root BTree page for this table */
diff --git a/test/sql-tap/check.test.lua b/test/sql-tap/check.test.lua
index 9e21c55..82d0fb7 100755
--- a/test/sql-tap/check.test.lua
+++ b/test/sql-tap/check.test.lua
@@ -345,7 +345,7 @@ test:do_catchsql_test(
);
]], {
-- <check-3.1>
- 1, "subqueries prohibited in CHECK constraints"
+ 1, "Failed to create space 'T3': subqueries prohibited in CHECK constraints"
-- </check-3.1>
})
@@ -370,7 +370,7 @@ test:do_catchsql_test(
);
]], {
-- <check-3.3>
- 1, "no such column: Q"
+ 1, "Failed to create space 'T3': no such column: Q"
-- </check-3.3>
})
@@ -394,7 +394,7 @@ test:do_catchsql_test(
);
]], {
-- <check-3.5>
- 1, "no such column: T2.X"
+ 1, "Failed to create space 'T3': no such column: T2.X"
-- </check-3.5>
})
@@ -555,7 +555,7 @@ test:do_catchsql_test(
);
]], {
-- <check-5.1>
- 1, "parameters prohibited in CHECK constraints"
+ 1, "Failed to create space 'T5': parameters prohibited in CHECK constraints"
-- </check-5.1>
})
@@ -567,7 +567,7 @@ test:do_catchsql_test(
);
]], {
-- <check-5.2>
- 1, "parameters prohibited in CHECK constraints"
+ 1, "Failed to create space 'T5': parameters prohibited in CHECK constraints"
-- </check-5.2>
})
--
2.7.4
More information about the Tarantool-patches
mailing list