[tarantool-patches] [PATCH v1 3/3] sql: get rid of Column structure
Kirill Shcherbatov
kshcherbatov at tarantool.org
Wed Jul 18 19:52:22 MSK 2018
Get rid of is_primkey in Column structure as it become
redundant. Moved the last member coll with collation pointer
to field_def structure. Finally, dropped Column.
---
src/box/alter.cc | 3 +
src/box/field_def.c | 1 +
src/box/field_def.h | 2 +
src/box/sql/alter.c | 27 ++-------
src/box/sql/build.c | 130 ++++++++++++++++------------------------
src/box/sql/resolve.c | 11 ++--
src/box/sql/select.c | 43 +++++--------
src/box/sql/sqliteInt.h | 11 ----
test/sql-tap/conflict3.test.lua | 10 ++--
9 files changed, 87 insertions(+), 151 deletions(-)
diff --git a/src/box/alter.cc b/src/box/alter.cc
index 7b6bd1a..444bc48 100644
--- a/src/box/alter.cc
+++ b/src/box/alter.cc
@@ -407,6 +407,9 @@ field_def_decode(struct field_def *field, const char **data,
tt_sprintf("collation is reasonable only for "
"string, scalar and any fields"));
}
+ struct coll_id *collation = coll_by_id(field->coll_id);
+ if (collation != NULL)
+ field->coll = collation->coll;
const char *dv = field->default_value;
if (dv != NULL) {
diff --git a/src/box/field_def.c b/src/box/field_def.c
index 8dbead6..12cc3b2 100644
--- a/src/box/field_def.c
+++ b/src/box/field_def.c
@@ -106,6 +106,7 @@ const struct field_def field_def_default = {
.is_nullable = false,
.nullable_action = ON_CONFLICT_ACTION_DEFAULT,
.coll_id = COLL_NONE,
+ .coll = NULL,
.default_value = NULL,
.default_value_expr = NULL
};
diff --git a/src/box/field_def.h b/src/box/field_def.h
index 05f80d4..c8f158c 100644
--- a/src/box/field_def.h
+++ b/src/box/field_def.h
@@ -123,6 +123,8 @@ struct field_def {
enum on_conflict_action nullable_action;
/** Collation ID for string comparison. */
uint32_t coll_id;
+ /** Collating sequence for string comparison. */
+ struct coll *coll;
/** 0-terminated SQL expression for DEFAULT value. */
char *default_value;
/** AST for parsed default value. */
diff --git a/src/box/sql/alter.c b/src/box/sql/alter.c
index fe54e55..38c36e8 100644
--- a/src/box/sql/alter.c
+++ b/src/box/sql/alter.c
@@ -146,7 +146,6 @@ sqlite3AlterFinishAddColumn(Parse * pParse, Token * pColDef)
Table *pNew; /* Copy of pParse->pNewTable */
Table *pTab; /* Table being altered */
const char *zTab; /* Table name */
- Column *pCol; /* The new column */
Expr *pDflt; /* Default value for the new column */
sqlite3 *db; /* The database connection; */
Vdbe *v = pParse->pVdbe; /* The prepared statement under construction */
@@ -161,7 +160,6 @@ sqlite3AlterFinishAddColumn(Parse * pParse, Token * pColDef)
/* Skip the "sqlite_altertab_" prefix on the name. */
zTab = &pNew->def->name[16];
- pCol = &pNew->aCol[pNew->def->field_count - 1];
assert(pNew->def != NULL);
pDflt = space_column_default_expr(SQLITE_PAGENO_TO_SPACEID(pNew->tnum),
pNew->def->field_count - 1);
@@ -181,7 +179,10 @@ sqlite3AlterFinishAddColumn(Parse * pParse, Token * pColDef)
* If there is a NOT NULL constraint, then the default value for the
* column must not be NULL.
*/
- if (pCol->is_primkey) {
+ struct Index *pk = sqlite3PrimaryKeyIndex(pTab);
+ assert(pk != NULL);
+ struct key_def *pk_key_def = pk->def->key_def;
+ if (key_def_find(pk_key_def, pNew->def->field_count - 1) != NULL) {
sqlite3ErrorMsg(pParse, "Cannot add a PRIMARY KEY column");
return;
}
@@ -258,8 +259,6 @@ sqlite3AlterBeginAddColumn(Parse * pParse, SrcList * pSrc)
Table *pNew;
Table *pTab;
Vdbe *v;
- uint32_t i;
- int nAlloc;
sqlite3 *db = pParse->db;
/* Look up the table being altered. */
@@ -296,24 +295,10 @@ sqlite3AlterBeginAddColumn(Parse * pParse, SrcList * pSrc)
}
pParse->pNewTable = pNew;
assert(pNew->def->field_count > 0);
- nAlloc = (((pNew->def->field_count - 1) / 8) * 8) + 8;
- assert((uint32_t)nAlloc >= pNew->def->field_count && nAlloc % 8 == 0 &&
- nAlloc - pNew->def->field_count < 8);
- pNew->aCol =
- (Column *) sqlite3DbMallocZero(db, sizeof(Column) * nAlloc);
/* FIXME: pNew->zName = sqlite3MPrintf(db, "sqlite_altertab_%s", pTab->zName); */
/* FIXME: if (!pNew->aCol || !pNew->zName) { */
- if (!pNew->aCol) {
- assert(db->mallocFailed);
- goto exit_begin_add_column;
- }
- memcpy(pNew->aCol, pTab->aCol, sizeof(Column) * pNew->def->field_count);
- for (i = 0; i < pNew->def->field_count; i++) {
- Column *pCol = &pNew->aCol[i];
- /* FIXME: pNew->def->name = sqlite3DbStrDup(db, pCol->zName); */
- pCol->coll = NULL;
- pNew->def->fields[i].coll_id = COLL_NONE;
- }
+ for (uint32_t i = 0; i < pNew->def->field_count; i++)
+ pNew->def->fields[i] = field_def_default;
pNew->pSchema = db->pSchema;
pNew->addColOffset = pTab->addColOffset;
pNew->nTabRef = 1;
diff --git a/src/box/sql/build.c b/src/box/sql/build.c
index ee97ef9..ed104e4 100644
--- a/src/box/sql/build.c
+++ b/src/box/sql/build.c
@@ -116,38 +116,48 @@ sql_finish_coding(struct Parse *parse_context)
/**
* This is a function which should be called during execution
- * of sqlite3EndTable. It ensures that only PRIMARY KEY
- * constraint may have ON CONFLICT REPLACE clause.
+ * of sqlite3EndTable. It set defaults for columns having no
+ * separate NULL/NOT NULL specifiers and ensures that only
+ * PRIMARY KEY constraint may have ON CONFLICT REPLACE clause.
*
+ * @param parser SQL Parser object.
* @param table Space which should be checked.
- * @retval False, if only primary key constraint has
- * ON CONFLICT REPLACE clause or if there are no indexes
- * with REPLACE as error action. True otherwise.
+ * @retval -1 on error. Parser SQL_TARANTOOL_ERROR is set.
+ * @retval 0 on success.
*/
-static bool
-check_on_conflict_replace_entries(struct Table *table)
-{
- /* Check all NOT NULL constraints. */
- for (int i = 0; i < (int)table->def->field_count; i++) {
- enum on_conflict_action on_error =
- table->def->fields[i].nullable_action;
- if (on_error == ON_CONFLICT_ACTION_REPLACE &&
- table->aCol[i].is_primkey == false) {
- return true;
+static int
+actualize_on_conflict_actions(struct Parse *parser, struct Table *table)
+{
+ const char *err_msg = NULL;
+ struct field_def *field = table->def->fields;
+ struct Index *pk = sqlite3PrimaryKeyIndex(table);
+ for (uint32_t i = 0; i < table->def->field_count; ++i, ++field) {
+ if (field->nullable_action == on_conflict_action_MAX) {
+ /* Set default. */
+ field->nullable_action = ON_CONFLICT_ACTION_NONE;
+ field->is_nullable = true;
}
+ if (field->nullable_action == ON_CONFLICT_ACTION_REPLACE &&
+ (pk == NULL || key_def_find(pk->def->key_def, i) == NULL))
+ goto non_pk_on_conflict_error;
}
- /* Check all UNIQUE constraints. */
+
for (struct Index *idx = table->pIndex; idx; idx = idx->pNext) {
if (idx->onError == ON_CONFLICT_ACTION_REPLACE &&
- !IsPrimaryKeyIndex(idx)) {
- return true;
- }
+ !IsPrimaryKeyIndex(idx))
+ goto non_pk_on_conflict_error;
}
- /*
- * CHECK constraints are not allowed to have REPLACE as
- * error action and therefore can be skipped.
- */
- return false;
+
+ return 0;
+
+non_pk_on_conflict_error:
+ err_msg = tt_sprintf("only PRIMARY KEY constraint can have "
+ "ON CONFLICT REPLACE clause - %s",
+ table->def->name);
+ diag_set(ClientError, ER_SQL, err_msg);
+ parser->rc = SQL_TARANTOOL_ERROR;
+ parser->nErr++;
+ return -1;
}
/*
@@ -340,7 +350,6 @@ deleteTable(sqlite3 * db, Table * pTable)
/* Delete the Table structure itself.
*/
sqlite3HashClear(&pTable->idxHash);
- sqlite3DbFree(db, pTable->aCol);
sqlite3DbFree(db, pTable->zColAff);
assert(pTable->def != NULL);
/* Do not delete pTable->def allocated on region. */
@@ -604,7 +613,6 @@ sqlite3AddColumn(Parse * pParse, Token * pName, Token * pType)
int i;
char *z;
char *zType;
- Column *pCol;
sqlite3 *db = pParse->db;
if ((p = pParse->pNewTable) == 0)
return;
@@ -642,17 +650,6 @@ sqlite3AddColumn(Parse * pParse, Token * pName, Token * pType)
return;
}
}
- if ((p->def->field_count & 0x7) == 0) {
- Column *aNew =
- sqlite3DbRealloc(db, p->aCol,
- (p->def->field_count + 8) *
- sizeof(p->aCol[0]));
- if (aNew == NULL)
- return;
- p->aCol = aNew;
- }
- pCol = &p->aCol[p->def->field_count];
- memset(pCol, 0, sizeof(p->aCol[0]));
struct field_def *column_def = &p->def->fields[p->def->field_count];
memcpy(column_def, &field_def_default, sizeof(field_def_default));
column_def->name = z;
@@ -890,7 +887,6 @@ sqlite3AddPrimaryKey(Parse * pParse, /* Parsing context */
)
{
Table *pTab = pParse->pNewTable;
- Column *pCol = 0;
int iCol = -1, i;
int nTerm;
if (pTab == 0)
@@ -904,8 +900,6 @@ sqlite3AddPrimaryKey(Parse * pParse, /* Parsing context */
pTab->tabFlags |= TF_HasPrimaryKey;
if (pList == 0) {
iCol = pTab->def->field_count - 1;
- pCol = &pTab->aCol[iCol];
- pCol->is_primkey = 1;
nTerm = 1;
} else {
nTerm = pList->nExpr;
@@ -914,25 +908,22 @@ sqlite3AddPrimaryKey(Parse * pParse, /* Parsing context */
sqlite3ExprSkipCollate(pList->a[i].pExpr);
assert(pCExpr != 0);
if (pCExpr->op != TK_ID) {
- sqlite3ErrorMsg(pParse, "expressions prohibited in PRIMARY KEY");
+ sqlite3ErrorMsg(pParse, "expressions prohibited"
+ " in PRIMARY KEY");
goto primary_key_exit;
}
- const char *zCName = pCExpr->u.zToken;
- for (iCol = 0;
- iCol < (int)pTab->def->field_count; iCol++) {
- if (strcmp
- (zCName,
- pTab->def->fields[iCol].name) == 0) {
- pCol = &pTab->aCol[iCol];
- pCol->is_primkey = 1;
+ const char *name = pCExpr->u.zToken;
+ struct space_def *def = pTab->def;
+ for (uint32_t idx = 0; idx < def->field_count; idx++) {
+ if (strcmp(name, def->fields[idx].name) == 0) {
+ iCol = idx;
break;
}
}
}
}
- assert(pCol == NULL || pCol == &pTab->aCol[iCol]);
- if (nTerm == 1 && pCol != NULL &&
- (pTab->def->fields[iCol].type == FIELD_TYPE_INTEGER) &&
+ if (nTerm == 1 && iCol != -1 &&
+ pTab->def->fields[iCol].type == FIELD_TYPE_INTEGER &&
sortOrder != SORT_ORDER_DESC) {
assert(autoInc == 0 || autoInc == 1);
pTab->iPKey = iCol;
@@ -1002,8 +993,8 @@ sqlite3AddCollateType(Parse * pParse, Token * pToken)
if (!zColl)
return;
uint32_t *id = &p->def->fields[i].coll_id;
- p->aCol[i].coll = sql_get_coll_seq(pParse, zColl, id);
- if (p->aCol[i].coll != NULL) {
+ p->def->fields[i].coll = sql_get_coll_seq(pParse, zColl, id);
+ if (p->def->fields[i].coll != NULL) {
/* If the column is declared as "<name> PRIMARY KEY COLLATE <type>",
* then an index may have been created on this column before the
* collation type was added. Correct this if it is the case.
@@ -1163,14 +1154,11 @@ identPut(char *z, int *pIdx, char *zSignedIdent)
static char *
createTableStmt(sqlite3 * db, Table * p)
{
- int i, k, n;
char *zStmt;
char *zSep, *zSep2, *zEnd;
- Column *pCol;
- n = 0;
- for (pCol = p->aCol, i = 0; i < (int)p->def->field_count; i++, pCol++) {
+ int n = 0;
+ for (uint32_t i = 0; i < p->def->field_count; i++)
n += identLength(p->def->fields[i].name) + 5;
- }
n += identLength(p->def->name);
if (n < 50) {
zSep = "";
@@ -1188,10 +1176,10 @@ createTableStmt(sqlite3 * db, Table * p)
return 0;
}
sqlite3_snprintf(n, zStmt, "CREATE TABLE ");
- k = sqlite3Strlen30(zStmt);
+ int k = sqlite3Strlen30(zStmt);
identPut(zStmt, &k, p->def->name);
zStmt[k++] = '(';
- for (pCol = p->aCol, i = 0; i < (int)p->def->field_count; i++, pCol++) {
+ for (uint32_t i = 0; i < p->def->field_count; i++) {
static const char *const azType[] = {
/* AFFINITY_BLOB */ "",
/* AFFINITY_TEXT */ " TEXT",
@@ -1692,22 +1680,9 @@ sqlite3EndTable(Parse * pParse, /* Parse context */
}
}
- /* Set default on_nullable action if required. */
- struct field_def *field = p->def->fields;
- for (uint32_t i = 0; i < p->def->field_count; ++i, ++field) {
- if (field->nullable_action == on_conflict_action_MAX) {
- field->nullable_action = ON_CONFLICT_ACTION_NONE;
- field->is_nullable = true;
- }
- }
-
- if (check_on_conflict_replace_entries(p)) {
- sqlite3ErrorMsg(pParse,
- "only PRIMARY KEY constraint can "
- "have ON CONFLICT REPLACE clause "
- "- %s", p->def->name);
+ if (actualize_on_conflict_actions(pParse, p))
goto cleanup;
- }
+
if (db->init.busy) {
/*
* As rebuild creates a new ExpList tree and
@@ -1882,12 +1857,9 @@ sql_create_view(struct Parse *parse_context, struct Token *begin,
sqlite3SelectAddColumnTypeAndCollation(parse_context, p,
select);
} else {
- assert(p->aCol == NULL);
assert(sel_tab->def->opts.is_temporary);
p->def->fields = sel_tab->def->fields;
p->def->field_count = sel_tab->def->field_count;
- p->aCol = sel_tab->aCol;
- sel_tab->aCol = NULL;
sel_tab->def->fields = NULL;
sel_tab->def->field_count = 0;
}
diff --git a/src/box/sql/resolve.c b/src/box/sql/resolve.c
index a185473..2c49e2c 100644
--- a/src/box/sql/resolve.c
+++ b/src/box/sql/resolve.c
@@ -219,7 +219,6 @@ lookupName(Parse * pParse, /* The parsing context */
NameContext *pTopNC = pNC; /* First namecontext in the list */
int isTrigger = 0; /* True if resolved to a trigger column */
Table *pTab = 0; /* Table hold the row */
- Column *pCol; /* A column of pTab */
assert(pNC); /* the name context cannot be NULL. */
assert(zCol); /* The Z in X.Y.Z cannot be NULL */
@@ -272,9 +271,8 @@ lookupName(Parse * pParse, /* The parsing context */
if (0 == (cntTab++)) {
pMatch = pItem;
}
- for (j = 0, pCol = pTab->aCol;
- j < (int)pTab->def->field_count;
- j++, pCol++) {
+ for (j = 0; j < (int)pTab->def->field_count;
+ j++) {
if (strcmp(pTab->def->fields[j].name,
zCol) == 0) {
/* If there has been exactly one prior match and this match
@@ -331,9 +329,8 @@ lookupName(Parse * pParse, /* The parsing context */
if (pTab) {
int iCol;
cntTab++;
- for (iCol = 0, pCol = pTab->aCol;
- iCol < (int)pTab->def->field_count;
- iCol++, pCol++) {
+ for (iCol = 0; iCol <
+ (int)pTab->def->field_count; iCol++) {
if (strcmp(pTab->def->fields[iCol].name,
zCol) == 0) {
if (iCol == pTab->iPKey) {
diff --git a/src/box/sql/select.c b/src/box/sql/select.c
index 34d5329..d577648 100644
--- a/src/box/sql/select.c
+++ b/src/box/sql/select.c
@@ -1811,25 +1811,15 @@ sqlite3ColumnsFromExprList(Parse * parse, ExprList * expr_list, Table *table)
{
/* Database connection */
sqlite3 *db = parse->db;
- int i, j; /* Loop counters */
u32 cnt; /* Index added to make the name unique */
- Column *aCol, *pCol; /* For looping over result columns */
- int nCol; /* Number of columns in the result set */
Expr *p; /* Expression for a single result column */
char *zName; /* Column name */
int nName; /* Size of name in zName[] */
Hash ht; /* Hash table of column names */
sqlite3HashInit(&ht);
- if (expr_list) {
- nCol = expr_list->nExpr;
- aCol = sqlite3DbMallocZero(db, sizeof(aCol[0]) * nCol);
- testcase(aCol == 0);
- } else {
- nCol = 0;
- aCol = NULL;
- }
- assert(nCol == (i16) nCol);
+ uint32_t column_count =
+ expr_list != NULL ? (uint32_t)expr_list->nExpr : 0;
/*
* This should be a table without resolved columns.
* sqlite3ViewGetColumnNames could use it to resolve
@@ -1838,21 +1828,21 @@ sqlite3ColumnsFromExprList(Parse * parse, ExprList * expr_list, Table *table)
assert(table->def->fields == NULL);
struct region *region = &parse->region;
table->def->fields =
- region_alloc(region, nCol * sizeof(table->def->fields[0]));
+ region_alloc(region,
+ column_count * sizeof(table->def->fields[0]));
if (table->def->fields == NULL) {
sqlite3OomFault(db);
goto cleanup;
}
- for (int i = 0; i < nCol; i++) {
+ for (uint32_t i = 0; i < column_count; i++) {
memcpy(&table->def->fields[i], &field_def_default,
sizeof(field_def_default));
table->def->fields[i].nullable_action = ON_CONFLICT_ACTION_NONE;
table->def->fields[i].is_nullable = true;
}
- table->def->field_count = (uint32_t)nCol;
- table->aCol = aCol;
+ table->def->field_count = column_count;
- for (i = 0, pCol = aCol; i < nCol; i++, pCol++) {
+ for (uint32_t i = 0; i < column_count; i++) {
/* Get an appropriate name for the column
*/
p = sqlite3ExprSkipCollate(expr_list->a[i].pExpr);
@@ -1889,9 +1879,9 @@ sqlite3ColumnsFromExprList(Parse * parse, ExprList * expr_list, Table *table)
while (zName && sqlite3HashFind(&ht, zName) != 0) {
nName = sqlite3Strlen30(zName);
if (nName > 0) {
+ int j;
for (j = nName - 1;
- j > 0 && sqlite3Isdigit(zName[j]); j--) {
- }
+ j > 0 && sqlite3Isdigit(zName[j]); j--);
if (zName[j] == ':')
nName = j;
}
@@ -1901,7 +1891,9 @@ sqlite3ColumnsFromExprList(Parse * parse, ExprList * expr_list, Table *table)
sqlite3_randomness(sizeof(cnt), &cnt);
}
size_t name_len = strlen(zName);
- if (zName != NULL && sqlite3HashInsert(&ht, zName, pCol) == pCol)
+ void *field = &table->def->fields[i];
+ if (zName != NULL &&
+ sqlite3HashInsert(&ht, zName, field) == field)
sqlite3OomFault(db);
table->def->fields[i].name =
region_alloc(region, name_len + 1);
@@ -1921,10 +1913,8 @@ cleanup:
* pTable->def could be not temporal in
* sqlite3ViewGetColumnNames so we need clean-up.
*/
- sqlite3DbFree(db, aCol);
table->def->fields = NULL;
table->def->field_count = 0;
- table->aCol = NULL;
rc = SQLITE_NOMEM_BKPT;
}
return rc;
@@ -1949,8 +1939,6 @@ sqlite3SelectAddColumnTypeAndCollation(Parse * pParse, /* Parsing contexts */
{
sqlite3 *db = pParse->db;
NameContext sNC;
- Column *pCol;
- int i;
Expr *p;
struct ExprList_item *a;
@@ -1963,8 +1951,7 @@ sqlite3SelectAddColumnTypeAndCollation(Parse * pParse, /* Parsing contexts */
memset(&sNC, 0, sizeof(sNC));
sNC.pSrcList = pSelect->pSrc;
a = pSelect->pEList->a;
- for (i = 0, pCol = pTab->aCol;
- i < (int)pTab->def->field_count; i++, pCol++) {
+ for (uint32_t i = 0; i < pTab->def->field_count; i++) {
enum field_type type;
p = a[i].pExpr;
type = columnType(&sNC, p, 0, 0);
@@ -1977,8 +1964,8 @@ sqlite3SelectAddColumnTypeAndCollation(Parse * pParse, /* Parsing contexts */
bool unused;
uint32_t id;
struct coll *coll = sql_expr_coll(pParse, p, &unused, &id);
- if (coll != NULL && pCol->coll == NULL) {
- pCol->coll = coll;
+ if (coll != NULL && pTab->def->fields[i].coll == NULL) {
+ pTab->def->fields[i].coll = coll;
pTab->def->fields[i].coll_id = id;
}
}
diff --git a/src/box/sql/sqliteInt.h b/src/box/sql/sqliteInt.h
index 9f6e97e..984bec9 100644
--- a/src/box/sql/sqliteInt.h
+++ b/src/box/sql/sqliteInt.h
@@ -1872,16 +1872,6 @@ struct Savepoint {
#define SAVEPOINT_RELEASE 1
#define SAVEPOINT_ROLLBACK 2
-/*
- * information about each column of an SQL table is held in an instance
- * of this structure.
- */
-struct Column {
- /** Collating sequence. */
- struct coll *coll;
- u8 is_primkey; /* Boolean propertie for being PK */
-};
-
#define sqlite3IsNumericAffinity(X) ((X)>=AFFINITY_NUMERIC)
/*
@@ -1910,7 +1900,6 @@ struct Column {
* by an instance of the following structure.
*/
struct Table {
- Column *aCol; /* Information about each column */
Index *pIndex; /* List of SQL indexes on this table. */
FKey *pFKey; /* Linked list of all foreign keys in this table */
char *zColAff; /* String defining the affinity of each column */
diff --git a/test/sql-tap/conflict3.test.lua b/test/sql-tap/conflict3.test.lua
index 345537e..9b55550 100755
--- a/test/sql-tap/conflict3.test.lua
+++ b/test/sql-tap/conflict3.test.lua
@@ -359,7 +359,7 @@ test:do_catchsql_test(
CREATE TABLE t3(a PRIMARY KEY ON CONFLICT REPLACE,
b UNIQUE ON CONFLICT REPLACE);
]], {
- 1, "only PRIMARY KEY constraint can have ON CONFLICT REPLACE clause - T3"
+ 1, "SQL error: only PRIMARY KEY constraint can have ON CONFLICT REPLACE clause - T3"
})
test:do_catchsql_test(
@@ -368,7 +368,7 @@ test:do_catchsql_test(
CREATE TABLE t3(a PRIMARY KEY,
b UNIQUE ON CONFLICT REPLACE);
]], {
- 1, "only PRIMARY KEY constraint can have ON CONFLICT REPLACE clause - T3"
+ 1, "SQL error: only PRIMARY KEY constraint can have ON CONFLICT REPLACE clause - T3"
})
test:do_catchsql_test(
@@ -378,7 +378,7 @@ test:do_catchsql_test(
b UNIQUE ON CONFLICT REPLACE,
c UNIQUE ON CONFLICT REPLACE);
]], {
- 1, "only PRIMARY KEY constraint can have ON CONFLICT REPLACE clause - T3"
+ 1, "SQL error: only PRIMARY KEY constraint can have ON CONFLICT REPLACE clause - T3"
})
test:do_catchsql_test(
@@ -387,7 +387,7 @@ test:do_catchsql_test(
CREATE TABLE t3(a PRIMARY KEY,
b NOT NULL ON CONFLICT REPLACE DEFAULT 1488);
]], {
- 1, "only PRIMARY KEY constraint can have ON CONFLICT REPLACE clause - T3"
+ 1, "SQL error: only PRIMARY KEY constraint can have ON CONFLICT REPLACE clause - T3"
})
test:do_catchsql_test(
@@ -396,7 +396,7 @@ test:do_catchsql_test(
CREATE TABLE t3(a PRIMARY KEY ON CONFLICT REPLACE,
b NOT NULL ON CONFLICT REPLACE DEFAULT 1488);
]], {
- 1, "only PRIMARY KEY constraint can have ON CONFLICT REPLACE clause - T3"
+ 1, "SQL error: only PRIMARY KEY constraint can have ON CONFLICT REPLACE clause - T3"
})
test:finish_test()
--
2.7.4
More information about the Tarantool-patches
mailing list