[tarantool-patches] Re: [PATCH 1/6] sql: move constraint name to struct contraint_parse
n.pettik
korablev at tarantool.org
Wed Jan 16 23:06:29 MSK 2019
>> Before this patch name of constraint being parsed was held as a separate
>> struct Token within parser context. Meanwhile, we also need to store
>> name of table which constraint is related to (in order to implement
>> ALTER TABLE ADD CONSTRAINT with several options: foreign key, unique,
>> primary key, etc). Hence, lets move constraint name to a separate
>> structure and save it alongside with the name of table.
>> Needed for #3097
>> ---
>> src/box/sql/alter.c | 4 ++--
>> src/box/sql/build.c | 36 +++++++++++++++++++-----------------
>> src/box/sql/parse.y | 22 +++++++++++++---------
>> src/box/sql/prepare.c | 11 +++++++++++
>> src/box/sql/sqliteInt.h | 32 ++++++++++++++++++--------------
>> 5 files changed, 63 insertions(+), 42 deletions(-)
>> diff --git a/src/box/sql/sqliteInt.h b/src/box/sql/sqliteInt.h
>> index 4110a5991..51a5d01b5 100644
>> --- a/src/box/sql/sqliteInt.h
>> +++ b/src/box/sql/sqliteInt.h
>> @@ -2691,6 +2691,17 @@ struct fkey_parse {
>> struct rlist link;
>> };
>> +/**
>> + * Used to hold intermediate meta-information during
>> + * constraint creation or alteration.
>> + */
>> +struct constraint_parse {
>> + /** Name of table which constraint belongs to. */
>> + struct SrcList *table_name;
>
> 1. I guess, it is not a 'table_name', but a 'table' since it
> is struct SrcList, not const char * nor Token.
Ok:
diff --git a/src/box/sql/alter.c b/src/box/sql/alter.c
index dfd71792b..32e8b9ae0 100644
--- a/src/box/sql/alter.c
+++ b/src/box/sql/alter.c
@@ -40,7 +40,7 @@
void
sql_alter_table_rename(struct Parse *parse, struct Token *new_name_tk)
{
- struct SrcList *src_tab = parse->constraint->table_name;
+ struct SrcList *src_tab = parse->constraint->table;
assert(src_tab->nSrc == 1);
struct sqlite3 *db = parse->db;
char *new_name = sqlite3NameFromToken(db, new_name_tk);
diff --git a/src/box/sql/build.c b/src/box/sql/build.c
index 963b16626..4367149d0 100644
--- a/src/box/sql/build.c
+++ b/src/box/sql/build.c
@@ -1836,7 +1836,7 @@ sql_create_foreign_key(struct Parse *parse_context, struct ExprList *child_cols,
struct space *child_space = NULL;
if (is_alter) {
const char *child_name =
- parse_context->constraint->table_name->a[0].zName;
+ parse_context->constraint->table->a[0].zName;
child_space = space_by_name(child_name);
if (child_space == NULL) {
diag_set(ClientError, ER_NO_SUCH_SPACE, child_name);
@@ -2021,7 +2021,7 @@ void
sql_drop_foreign_key(struct Parse *parse_context, struct Token *constraint)
{
const char *table_name =
- parse_context->constraint->table_name->a[0].zName;
+ parse_context->constraint->table->a[0].zName;
assert(table_name != NULL);
struct space *child = space_by_name(table_name);
if (child == NULL) {
diff --git a/src/box/sql/parse.y b/src/box/sql/parse.y
index f4fdf58f2..c3677765e 100644
--- a/src/box/sql/parse.y
+++ b/src/box/sql/parse.y
@@ -1445,20 +1445,20 @@ cmd ::= ANALYZE nm(X). {sqlite3Analyze(pParse, &X);}
//////////////////////// ALTER TABLE table ... ////////////////////////////////
cmd ::= ALTER TABLE fullname(X) RENAME TO nm(Z). {
- pParse->constraint->table_name = X;
+ pParse->constraint->table = X;
sql_alter_table_rename(pParse, &Z);
}
cmd ::= ALTER TABLE fullname(X) ADD CONSTRAINT nm(Z) FOREIGN KEY
LP eidlist(FA) RP REFERENCES nm(T) eidlist_opt(TA) refargs(R)
defer_subclause_opt(D). {
- pParse->constraint->table_name = X;
+ pParse->constraint->table = X;
pParse->constraint->name = Z;
sql_create_foreign_key(pParse, FA, &T, TA, D, R);
}
cmd ::= ALTER TABLE fullname(X) DROP CONSTRAINT nm(Z). {
- pParse->constraint->table_name = X;
+ pParse->constraint->table = X;
sql_drop_foreign_key(pParse, &Z);
}
diff --git a/src/box/sql/sqliteInt.h b/src/box/sql/sqliteInt.h
index 51a5d01b5..981e3c660 100644
--- a/src/box/sql/sqliteInt.h
+++ b/src/box/sql/sqliteInt.h
@@ -2697,7 +2697,7 @@ struct fkey_parse {
*/
struct constraint_parse {
/** Name of table which constraint belongs to. */
- struct SrcList *table_name;
+ struct SrcList *table;
/** Name of the constraint currently being parsed. */
struct Token name;
};
>
>> + /** Name of the constraint currently being parsed. */
>> + struct Token name;
>> +};
>
> 2.1. Also, I see that struct constraint_parse is not able to
> describe a foreign key - it has no parent table, referenced
> columns - you pass them separately from struct constraint_parse
> which looks contr-intuitive. Can you please, elaborate so it,
> for example, has struct fkey_parse as a member? Or at least,
> have both parent and child table name and cols as Token and
> ExprList pointers?
According to ANSI only three constraints can be added:
UNIQUE/PK, FK and CHECK. Only name of table and name
of constraint are shared among features of these constraints:
CHECK also has ExprSpan and UNIQUE - columns (child).
I guess it is fair to move child cols to this structure,
but other members seems to be redundant.
Hence, I will add parent name and parent colls
only if you insist.
diff --git a/src/box/sql/build.c b/src/box/sql/build.c
index 963b16626..af961592a 100644
--- a/src/box/sql/build.c
+++ b/src/box/sql/build.c
@@ -727,8 +726,10 @@ sqlite3AddPrimaryKey(Parse * pParse, /* Parsing context */
&token, 0));
if (list == NULL)
goto primary_key_exit;
- sql_create_index(pParse, 0, 0, list, 0, SORT_ORDER_ASC,
+ pParse->constraint.cols = list;
+ sql_create_index(pParse, 0, 0, 0, SORT_ORDER_ASC,
false, SQL_INDEX_TYPE_CONSTRAINT_PK);
+ pParse->constraint.cols = NULL;
if (db->mallocFailed)
goto primary_key_exit;
} else if (autoInc) {
@@ -736,8 +737,10 @@ sqlite3AddPrimaryKey(Parse * pParse, /* Parsing context */
"INTEGER PRIMARY KEY or INT PRIMARY KEY");
goto primary_key_exit;
} else {
- sql_create_index(pParse, 0, 0, pList, 0, sortOrder, false,
+ pParse->constraint.cols = pList;
+ sql_create_index(pParse, 0, 0, 0, sortOrder, false,
SQL_INDEX_TYPE_CONSTRAINT_PK);
+ pParse->constraint.cols = NULL;
pList = 0;
if (pParse->nErr > 0)
goto primary_key_exit;
@@ -1800,9 +1803,9 @@ columnno_by_name(struct Parse *parse_context, const struct space *space,
}
void
-sql_create_foreign_key(struct Parse *parse_context, struct ExprList *child_cols,
- struct Token *parent, struct ExprList *parent_cols,
- bool is_deferred, int actions)
+sql_create_foreign_key(struct Parse *parse_context, struct Token *parent,
+ struct ExprList *parent_cols, bool is_deferred,
+ int actions)
{
struct sqlite3 *db = parse_context->db;
/*
@@ -1827,6 +1830,7 @@ sql_create_foreign_key(struct Parse *parse_context, struct ExprList *child_cols,
/* Whether we are processing ALTER TABLE or CREATE TABLE. */
bool is_alter = new_tab == NULL;
uint32_t child_cols_count;
+ struct ExprList *child_cols = parse_context->constraint.cols;
@@ -2226,7 +2231,7 @@ constraint_is_named(const char *name)
void
sql_create_index(struct Parse *parse, struct Token *token,
- struct SrcList *tbl_name, struct ExprList *col_list,
+ struct SrcList *tbl_name,
MAYBE_UNUSED struct Token *start, enum sort_order sort_order,
bool if_not_exist, enum sql_index_type idx_type) {
/* The index to be created. */
@@ -2235,6 +2240,7 @@ sql_create_index(struct Parse *parse, struct Token *token,
char *name = NULL;
struct sqlite3 *db = parse->db;
assert(!db->init.busy);
+ struct ExprList *col_list = parse->constraint.cols;
diff --git a/src/box/sql/parse.y b/src/box/sql/parse.y
index f4fdf58f2..d0d436884 100644
--- a/src/box/sql/parse.y
+++ b/src/box/sql/parse.y
@@ -262,12 +262,12 @@ ccons ::= NULL onconf(R). {
ccons ::= NOT NULL onconf(R). {sql_column_add_nullable_action(pParse, R);}
ccons ::= PRIMARY KEY sortorder(Z) autoinc(I).
{sqlite3AddPrimaryKey(pParse,0,I,Z);}
-ccons ::= UNIQUE. {sql_create_index(pParse,0,0,0,0,
+ccons ::= UNIQUE. {sql_create_index(pParse,0,0,0,
SORT_ORDER_ASC, false,
SQL_INDEX_TYPE_CONSTRAINT_UNIQUE);}
ccons ::= CHECK LP expr(X) RP. {sql_add_check_constraint(pParse,&X);}
ccons ::= REFERENCES nm(T) eidlist_opt(TA) refargs(R).
- {sql_create_foreign_key(pParse, NULL, &T, TA, false, R);}
+ {sql_create_foreign_key(pParse, &T, TA, false, R);}
ccons ::= defer_subclause(D). {fkey_change_defer_mode(pParse, D);}
ccons ::= COLLATE id(C). {sqlite3AddCollateType(pParse, &C);}
-tcons ::= UNIQUE LP sortlist(X) RP.
- {sql_create_index(pParse,0,0,X,0,
- SORT_ORDER_ASC,false,
- SQL_INDEX_TYPE_CONSTRAINT_UNIQUE);}
+tcons ::= UNIQUE LP sortlist(X) RP. {
+ pParse->constraint.cols = X;
+ sql_create_index(pParse,0,0,0, SORT_ORDER_ASC,false,
+ SQL_INDEX_TYPE_CONSTRAINT_UNIQUE);
+}
tcons ::= CHECK LP expr(E) RP onconf.
{sql_add_check_constraint(pParse,&E);}
tcons ::= FOREIGN KEY LP eidlist(FA) RP
REFERENCES nm(T) eidlist_opt(TA) refargs(R) defer_subclause_opt(D). {
- sql_create_foreign_key(pParse, FA, &T, TA, D, R);
+ pParse->constraint.cols = FA;
+ sql_create_foreign_key(pParse, &T, TA, D, R);
}
@@ -1211,7 +1213,8 @@ paren_exprlist(A) ::= LP exprlist(X) RP. {A = X;}
//
cmd ::= createkw(S) uniqueflag(U) INDEX ifnotexists(NE) nm(X)
ON nm(Y) LP sortlist(Z) RP. {
- sql_create_index(pParse, &X, sqlite3SrcListAppend(pParse->db,0,&Y), Z, &S,
+ pParse->constraint.cols = Z;
+ sql_create_index(pParse, &X, sqlite3SrcListAppend(pParse->db,0,&Y), &S,
SORT_ORDER_ASC, NE, U);
}
cmd ::= ALTER TABLE fullname(X) ADD CONSTRAINT nm(Z) FOREIGN KEY
LP eidlist(FA) RP REFERENCES nm(T) eidlist_opt(TA) refargs(R)
defer_subclause_opt(D). {
- pParse->constraint->table_name = X;
- pParse->constraint->name = Z;
- sql_create_foreign_key(pParse, FA, &T, TA, D, R);
+ pParse->constraint.table = X;
+ pParse->constraint.name = Z;
+ pParse->constraint.cols = FA;
+ sql_create_foreign_key(pParse, &T, TA, D, R);
}
diff --git a/src/box/sql/sqliteInt.h b/src/box/sql/sqliteInt.h
index 51a5d01b5..7b98a960a 100644
--- a/src/box/sql/sqliteInt.h
+++ b/src/box/sql/sqliteInt.h
@@ -2697,9 +2697,14 @@ struct fkey_parse {
*/
struct constraint_parse {
/** Name of table which constraint belongs to. */
- struct SrcList *table_name;
+ struct SrcList *table;
/** Name of the constraint currently being parsed. */
struct Token name;
+ /**
+ * List of columns involved in constraint definition:
+ * indexed or referencing columns.
+ */
+ struct ExprList *cols;
@@ -3509,7 +3514,6 @@ void sqlite3IdListDelete(sqlite3 *, IdList *);
* @param parse All information about this parse.
* @param token Index name. May be NULL.
* @param tbl_name Table to index. Use pParse->pNewTable ifNULL.
- * @param col_list A list of columns to be indexed.
* @param start The CREATE token that begins this statement.
* @param sort_order Sort order of primary key when pList==NULL.
* @param if_not_exist Omit error if index already exists.
@@ -3517,7 +3521,7 @@ void sqlite3IdListDelete(sqlite3 *, IdList *);
*/
void
sql_create_index(struct Parse *parse, struct Token *token,
- struct SrcList *tbl_name, struct ExprList *col_list,
+ struct SrcList *tbl_name,
struct Token *start, enum sort_order sort_order,
bool if_not_exist, enum sql_index_type idx_type);
@@ -4150,9 +4154,6 @@ fkey_change_defer_mode(struct Parse *parse_context, bool is_deferred);
* OR to handle <CREATE TABLE ...>
*
* @param parse_context Parsing context.
- * @param child_cols Columns of child table involved in FK.
- * May be NULL on CREATE TABLE statement processing.
- * If so, the last column added is used.
* @param parent Name of referenced table.
* @param parent_cols List of referenced columns. If NULL, columns
* which make up PK of referenced table are used.
@@ -4161,9 +4162,9 @@ fkey_change_defer_mode(struct Parse *parse_context, bool is_deferred);
* algorithms (e.g. CASCADE, RESTRICT etc).
*/
void
-sql_create_foreign_key(struct Parse *parse_context, struct ExprList *child_cols,
- struct Token *parent, struct ExprList *parent_cols,
- bool is_deferred, int actions);
+sql_create_foreign_key(struct Parse *parse_context, struct Token *parent,
+ struct ExprList *parent_cols, bool is_deferred,
+ int actions);
>> +
>> /*
>> * An SQL parser context. A copy of this structure is passed through
>> * the parser and down into all the parser action routine in order to
>> @@ -2781,6 +2791,10 @@ struct Parse {
>> TriggerPrg *pTriggerPrg; /* Linked list of coded triggers */
>> With *pWith; /* Current WITH clause, or NULL */
>> With *pWithToFree; /* Free this WITH object at the end of the parse */
>> + /**
>> + * Constraint currently being parsed.
>> + */
>> + struct constraint_parse *constraint;
>
> 3. Make it an object, not a pointer, please. Anyway you allocate it on
> each prepare.
Ok:
diff --git a/src/box/sql/prepare.c b/src/box/sql/prepare.c
index 0a2f59954..824578e45 100644
--- a/src/box/sql/prepare.c
+++ b/src/box/sql/prepare.c
@@ -58,17 +58,6 @@ sqlite3Prepare(sqlite3 * db, /* Database handle. */
Parse sParse; /* Parsing context */
sql_parser_create(&sParse, db);
sParse.pReprepare = pReprepare;
- sParse.constraint = region_alloc(&sParse.region,
- sizeof(*sParse.constraint));
- if (sParse.constraint == NULL) {
- diag_set(OutOfMemory, sizeof(*sParse.constraint), "region",
- "constraint");
- sql_parser_destroy(&sParse);
- rc = SQLITE_NOMEM;
- return rc;
- }
- sParse.constraint->name.z = NULL;
- sParse.constraint->name.n = 0;
diff --git a/src/box/sql/sqliteInt.h b/src/box/sql/sqliteInt.h
index 51a5d01b5..03ce7a4d9 100644
--- a/src/box/sql/sqliteInt.h
+++ b/src/box/sql/sqliteInt.h
@@ -2794,7 +2794,7 @@ struct Parse {
/**
* Constraint currently being parsed.
*/
- struct constraint_parse *constraint;
+ struct constraint_parse constraint;
See other monotonic changes at the end of letter.
>
>> /**
>> * Number of FK constraints declared within
>> * CREATE TABLE statement.
>> @@ -4152,8 +4161,7 @@ fkey_change_defer_mode(struct Parse *parse_context, bool is_deferred);
>> * algorithms (e.g. CASCADE, RESTRICT etc).
>> */
>> void
>> -sql_create_foreign_key(struct Parse *parse_context, struct SrcList *child,
>> - struct Token *constraint, struct ExprList *child_cols,
>> +sql_create_foreign_key(struct Parse *parse_context, struct ExprList *child_cols,
>> struct Token *parent, struct ExprList *parent_cols,
>> bool is_deferred, int actions);
>
> 2.2 This is what I've described in point 2 - child part is partially moved into
> struct contraint_parse, whilst parent still is separate.
Whole patch:
diff --git a/src/box/sql/alter.c b/src/box/sql/alter.c
index d0ce9d893..aa14bab06 100644
--- a/src/box/sql/alter.c
+++ b/src/box/sql/alter.c
@@ -38,9 +38,9 @@
#include "box/schema.h"
void
-sql_alter_table_rename(struct Parse *parse, struct SrcList *src_tab,
- struct Token *new_name_tk)
+sql_alter_table_rename(struct Parse *parse, struct Token *new_name_tk)
{
+ struct SrcList *src_tab = parse->constraint.table;
assert(src_tab->nSrc == 1);
struct sqlite3 *db = parse->db;
char *new_name = sqlite3NameFromToken(db, new_name_tk);
diff --git a/src/box/sql/build.c b/src/box/sql/build.c
index 49b90b5d0..1861659d6 100644
--- a/src/box/sql/build.c
+++ b/src/box/sql/build.c
@@ -566,7 +566,7 @@ sqlite3AddColumn(Parse * pParse, Token * pName, struct type_def *type_def)
column_def->affinity = type_def->type;
column_def->type = sql_affinity_to_field_type(column_def->affinity);
p->def->field_count++;
- pParse->constraintName.n = 0;
+ pParse->constraint.name.n = 0;
}
void
@@ -727,8 +727,10 @@ sqlite3AddPrimaryKey(Parse * pParse, /* Parsing context */
&token, 0));
if (list == NULL)
goto primary_key_exit;
- sql_create_index(pParse, 0, 0, list, 0, SORT_ORDER_ASC,
+ pParse->constraint.cols = list;
+ sql_create_index(pParse, 0, 0, 0, SORT_ORDER_ASC,
false, SQL_INDEX_TYPE_CONSTRAINT_PK);
+ pParse->constraint.cols = NULL;
if (db->mallocFailed)
goto primary_key_exit;
} else if (autoInc) {
@@ -736,8 +738,10 @@ sqlite3AddPrimaryKey(Parse * pParse, /* Parsing context */
"INTEGER PRIMARY KEY or INT PRIMARY KEY");
goto primary_key_exit;
} else {
- sql_create_index(pParse, 0, 0, pList, 0, sortOrder, false,
+ pParse->constraint.cols = pList;
+ sql_create_index(pParse, 0, 0, 0, sortOrder, false,
SQL_INDEX_TYPE_CONSTRAINT_PK);
+ pParse->constraint.cols = NULL;
pList = 0;
if (pParse->nErr > 0)
goto primary_key_exit;
@@ -774,9 +778,9 @@ sql_add_check_constraint(struct Parse *parser, struct ExprSpan *span)
sqlite3DbFree(parser->db, expr->u.zToken);
goto release_expr;
}
- if (parser->constraintName.n) {
+ if (parser->constraint.name.n) {
sqlite3ExprListSetName(parser, table->def->opts.checks,
- &parser->constraintName, 1);
+ &parser->constraint.name, 1);
}
} else {
release_expr:
@@ -1800,10 +1804,9 @@ columnno_by_name(struct Parse *parse_context, const struct space *space,
}
void
-sql_create_foreign_key(struct Parse *parse_context, struct SrcList *child,
- struct Token *constraint, struct ExprList *child_cols,
- struct Token *parent, struct ExprList *parent_cols,
- bool is_deferred, int actions)
+sql_create_foreign_key(struct Parse *parse_context, struct Token *parent,
+ struct ExprList *parent_cols, bool is_deferred,
+ int actions)
{
struct sqlite3 *db = parse_context->db;
/*
@@ -1828,16 +1831,17 @@ sql_create_foreign_key(struct Parse *parse_context, struct SrcList *child,
/* Whether we are processing ALTER TABLE or CREATE TABLE. */
bool is_alter = new_tab == NULL;
uint32_t child_cols_count;
+ struct ExprList *child_cols = parse_context->constraint.cols;
if (child_cols == NULL) {
assert(!is_alter);
child_cols_count = 1;
} else {
child_cols_count = child_cols->nExpr;
}
- assert(!is_alter || (child != NULL && child->nSrc == 1));
struct space *child_space = NULL;
if (is_alter) {
- const char *child_name = child->a[0].zName;
+ const char *child_name =
+ parse_context->constraint.table->a[0].zName;
child_space = space_by_name(child_name);
if (child_space == NULL) {
diag_set(ClientError, ER_NO_SUCH_SPACE, child_name);
@@ -1884,18 +1888,21 @@ sql_create_foreign_key(struct Parse *parse_context, struct SrcList *child,
goto exit_create_fk;
}
}
- if (constraint == NULL && !is_alter) {
- if (parse_context->constraintName.n == 0) {
+ if (!is_alter) {
+ if (parse_context->constraint.name.n == 0) {
constraint_name =
sqlite3MPrintf(db, "FK_CONSTRAINT_%d_%s",
++parse_context->fkey_count,
new_tab->def->name);
} else {
- struct Token *cnstr_nm = &parse_context->constraintName;
+ struct Token *cnstr_nm =
+ &parse_context->constraint.name;
constraint_name = sqlite3NameFromToken(db, cnstr_nm);
}
} else {
- constraint_name = sqlite3NameFromToken(db, constraint);
+ constraint_name =
+ sqlite3NameFromToken(db,
+ &parse_context->constraint.name);
}
if (constraint_name == NULL)
goto exit_create_fk;
@@ -2016,11 +2023,11 @@ fkey_change_defer_mode(struct Parse *parse_context, bool is_deferred)
}
void
-sql_drop_foreign_key(struct Parse *parse_context, struct SrcList *table,
- struct Token *constraint)
+sql_drop_foreign_key(struct Parse *parse_context, struct Token *constraint)
{
- assert(table != NULL && table->nSrc == 1);
- const char *table_name = table->a[0].zName;
+ const char *table_name =
+ parse_context->constraint.table->a[0].zName;
+ assert(table_name != NULL);
struct space *child = space_by_name(table_name);
if (child == NULL) {
diag_set(ClientError, ER_NO_SUCH_SPACE, table_name);
@@ -2224,7 +2231,7 @@ constraint_is_named(const char *name)
void
sql_create_index(struct Parse *parse, struct Token *token,
- struct SrcList *tbl_name, struct ExprList *col_list,
+ struct SrcList *tbl_name,
MAYBE_UNUSED struct Token *start, enum sort_order sort_order,
bool if_not_exist, enum sql_index_type idx_type) {
/* The index to be created. */
@@ -2233,6 +2240,7 @@ sql_create_index(struct Parse *parse, struct Token *token,
char *name = NULL;
struct sqlite3 *db = parse->db;
assert(!db->init.busy);
+ struct ExprList *col_list = parse->constraint.cols;
if (db->mallocFailed || parse->nErr > 0)
goto exit_create_index;
@@ -2311,10 +2319,10 @@ sql_create_index(struct Parse *parse, struct Token *token,
}
} else {
char *constraint_name = NULL;
- if (parse->constraintName.z != NULL)
+ if (parse->constraint.name.z != NULL)
constraint_name =
sqlite3NameFromToken(db,
- &parse->constraintName);
+ &parse->constraint.name);
/*
* This naming is temporary. Now it's not
diff --git a/src/box/sql/parse.y b/src/box/sql/parse.y
index 50bb2ba01..d0d436884 100644
--- a/src/box/sql/parse.y
+++ b/src/box/sql/parse.y
@@ -237,8 +237,8 @@ nm(A) ::= id(A). {
carglist ::= carglist cconsdef.
carglist ::= .
cconsdef ::= cconsname ccons.
-cconsname ::= CONSTRAINT nm(X). {pParse->constraintName = X;}
-cconsname ::= . {pParse->constraintName.n = 0;}
+cconsname ::= CONSTRAINT nm(X). {pParse->constraint.name = X;}
+cconsname ::= . {pParse->constraint.name.n = 0;}
ccons ::= DEFAULT term(X). {sqlite3AddDefaultValue(pParse,&X);}
ccons ::= DEFAULT LP expr(X) RP. {sqlite3AddDefaultValue(pParse,&X);}
ccons ::= DEFAULT PLUS term(X). {sqlite3AddDefaultValue(pParse,&X);}
@@ -262,12 +262,12 @@ ccons ::= NULL onconf(R). {
ccons ::= NOT NULL onconf(R). {sql_column_add_nullable_action(pParse, R);}
ccons ::= PRIMARY KEY sortorder(Z) autoinc(I).
{sqlite3AddPrimaryKey(pParse,0,I,Z);}
-ccons ::= UNIQUE. {sql_create_index(pParse,0,0,0,0,
+ccons ::= UNIQUE. {sql_create_index(pParse,0,0,0,
SORT_ORDER_ASC, false,
SQL_INDEX_TYPE_CONSTRAINT_UNIQUE);}
ccons ::= CHECK LP expr(X) RP. {sql_add_check_constraint(pParse,&X);}
ccons ::= REFERENCES nm(T) eidlist_opt(TA) refargs(R).
- {sql_create_foreign_key(pParse, NULL, NULL, NULL, &T, TA, false, R);}
+ {sql_create_foreign_key(pParse, &T, TA, false, R);}
ccons ::= defer_subclause(D). {fkey_change_defer_mode(pParse, D);}
ccons ::= COLLATE id(C). {sqlite3AddCollateType(pParse, &C);}
@@ -308,19 +308,21 @@ init_deferred_pred_opt(A) ::= INITIALLY DEFERRED. {A = 1;}
init_deferred_pred_opt(A) ::= INITIALLY IMMEDIATE. {A = 0;}
tconsdef ::= tconsname tcons.
-tconsname ::= CONSTRAINT nm(X). {pParse->constraintName = X;}
-tconsname ::= . {pParse->constraintName.n = 0;}
+tconsname ::= CONSTRAINT nm(X). {pParse->constraint.name = X;}
+tconsname ::= . {pParse->constraint.name.n = 0;}
tcons ::= PRIMARY KEY LP sortlist(X) autoinc(I) RP.
{sqlite3AddPrimaryKey(pParse,X,I,0);}
-tcons ::= UNIQUE LP sortlist(X) RP.
- {sql_create_index(pParse,0,0,X,0,
- SORT_ORDER_ASC,false,
- SQL_INDEX_TYPE_CONSTRAINT_UNIQUE);}
+tcons ::= UNIQUE LP sortlist(X) RP. {
+ pParse->constraint.cols = X;
+ sql_create_index(pParse,0,0,0, SORT_ORDER_ASC,false,
+ SQL_INDEX_TYPE_CONSTRAINT_UNIQUE);
+}
tcons ::= CHECK LP expr(E) RP onconf.
{sql_add_check_constraint(pParse,&E);}
tcons ::= FOREIGN KEY LP eidlist(FA) RP
REFERENCES nm(T) eidlist_opt(TA) refargs(R) defer_subclause_opt(D). {
- sql_create_foreign_key(pParse, NULL, NULL, FA, &T, TA, D, R);
+ pParse->constraint.cols = FA;
+ sql_create_foreign_key(pParse, &T, TA, D, R);
}
%type defer_subclause_opt {int}
defer_subclause_opt(A) ::= . {A = 0;}
@@ -1211,7 +1213,8 @@ paren_exprlist(A) ::= LP exprlist(X) RP. {A = X;}
//
cmd ::= createkw(S) uniqueflag(U) INDEX ifnotexists(NE) nm(X)
ON nm(Y) LP sortlist(Z) RP. {
- sql_create_index(pParse, &X, sqlite3SrcListAppend(pParse->db,0,&Y), Z, &S,
+ pParse->constraint.cols = Z;
+ sql_create_index(pParse, &X, sqlite3SrcListAppend(pParse->db,0,&Y), &S,
SORT_ORDER_ASC, NE, U);
}
@@ -1445,17 +1448,22 @@ cmd ::= ANALYZE nm(X). {sqlite3Analyze(pParse, &X);}
//////////////////////// ALTER TABLE table ... ////////////////////////////////
cmd ::= ALTER TABLE fullname(X) RENAME TO nm(Z). {
- sql_alter_table_rename(pParse,X,&Z);
+ pParse->constraint.table = X;
+ sql_alter_table_rename(pParse, &Z);
}
cmd ::= ALTER TABLE fullname(X) ADD CONSTRAINT nm(Z) FOREIGN KEY
LP eidlist(FA) RP REFERENCES nm(T) eidlist_opt(TA) refargs(R)
defer_subclause_opt(D). {
- sql_create_foreign_key(pParse, X, &Z, FA, &T, TA, D, R);
+ pParse->constraint.table = X;
+ pParse->constraint.name = Z;
+ pParse->constraint.cols = FA;
+ sql_create_foreign_key(pParse, &T, TA, D, R);
}
cmd ::= ALTER TABLE fullname(X) DROP CONSTRAINT nm(Z). {
- sql_drop_foreign_key(pParse, X, &Z);
+ pParse->constraint.table = X;
+ sql_drop_foreign_key(pParse, &Z);
}
//////////////////////// COMMON TABLE EXPRESSIONS ////////////////////////////
diff --git a/src/box/sql/sqliteInt.h b/src/box/sql/sqliteInt.h
index 4110a5991..e38e0da08 100644
--- a/src/box/sql/sqliteInt.h
+++ b/src/box/sql/sqliteInt.h
@@ -2691,6 +2691,22 @@ struct fkey_parse {
struct rlist link;
};
+/**
+ * Used to hold intermediate meta-information during
+ * constraint creation or alteration.
+ */
+struct constraint_parse {
+ /** Name of table which constraint belongs to. */
+ struct SrcList *table;
+ /** Name of the constraint currently being parsed. */
+ struct Token name;
+ /**
+ * List of columns involved in constraint definition:
+ * indexed or referencing columns.
+ */
+ struct ExprList *cols;
+};
+
/*
* An SQL parser context. A copy of this structure is passed through
* the parser and down into all the parser action routine in order to
@@ -2728,7 +2744,6 @@ struct Parse {
int nLabel; /* Number of labels used */
int *aLabel; /* Space to hold the labels */
ExprList *pConstExpr; /* Constant expressions */
- Token constraintName; /* Name of the constraint currently being parsed */
int nMaxArg; /* Max args passed to user function by sub-program */
int nSelect; /* Number of SELECT statements seen */
int nSelectIndent; /* How far to indent SELECTTRACE() output */
@@ -2781,6 +2796,10 @@ struct Parse {
TriggerPrg *pTriggerPrg; /* Linked list of coded triggers */
With *pWith; /* Current WITH clause, or NULL */
With *pWithToFree; /* Free this WITH object at the end of the parse */
+ /**
+ * Constraint currently being parsed.
+ */
+ struct constraint_parse constraint;
/**
* Number of FK constraints declared within
* CREATE TABLE statement.
@@ -3495,7 +3514,6 @@ void sqlite3IdListDelete(sqlite3 *, IdList *);
* @param parse All information about this parse.
* @param token Index name. May be NULL.
* @param tbl_name Table to index. Use pParse->pNewTable ifNULL.
- * @param col_list A list of columns to be indexed.
* @param start The CREATE token that begins this statement.
* @param sort_order Sort order of primary key when pList==NULL.
* @param if_not_exist Omit error if index already exists.
@@ -3503,7 +3521,7 @@ void sqlite3IdListDelete(sqlite3 *, IdList *);
*/
void
sql_create_index(struct Parse *parse, struct Token *token,
- struct SrcList *tbl_name, struct ExprList *col_list,
+ struct SrcList *tbl_name,
struct Token *start, enum sort_order sort_order,
bool if_not_exist, enum sql_index_type idx_type);
@@ -4136,14 +4154,6 @@ fkey_change_defer_mode(struct Parse *parse_context, bool is_deferred);
* OR to handle <CREATE TABLE ...>
*
* @param parse_context Parsing context.
- * @param child Name of table to be altered. NULL on CREATE TABLE
- * statement processing.
- * @param constraint Name of the constraint to be created. May be
- * NULL on CREATE TABLE statement processing.
- * Then, auto-generated name is used.
- * @param child_cols Columns of child table involved in FK.
- * May be NULL on CREATE TABLE statement processing.
- * If so, the last column added is used.
* @param parent Name of referenced table.
* @param parent_cols List of referenced columns. If NULL, columns
* which make up PK of referenced table are used.
@@ -4152,22 +4162,19 @@ fkey_change_defer_mode(struct Parse *parse_context, bool is_deferred);
* algorithms (e.g. CASCADE, RESTRICT etc).
*/
void
-sql_create_foreign_key(struct Parse *parse_context, struct SrcList *child,
- struct Token *constraint, struct ExprList *child_cols,
- struct Token *parent, struct ExprList *parent_cols,
- bool is_deferred, int actions);
+sql_create_foreign_key(struct Parse *parse_context, struct Token *parent,
+ struct ExprList *parent_cols, bool is_deferred,
+ int actions);
/**
* Function called from parser to handle
* <ALTER TABLE table DROP CONSTRAINT constraint> SQL statement.
*
* @param parse_context Parsing context.
- * @param table Table to be altered.
* @param constraint Name of constraint to be dropped.
*/
void
-sql_drop_foreign_key(struct Parse *parse_context, struct SrcList *table,
- struct Token *constraint);
+sql_drop_foreign_key(struct Parse *parse_context, struct Token *constraint);
void sqlite3Detach(Parse *, Expr *);
int sqlite3AtoF(const char *z, double *, int);
@@ -4385,12 +4392,10 @@ extern int sqlite3PendingByte;
* command.
*
* @param parse Current parsing context.
- * @param src_tab The table to rename.
* @param new_name_tk Token containing new name of the table.
*/
void
-sql_alter_table_rename(struct Parse *parse, struct SrcList *src_tab,
- struct Token *new_name_tk);
+sql_alter_table_rename(struct Parse *parse, struct Token *new_name_tk);
/**
* Return the length (in bytes) of the token that begins at z[0].
More information about the Tarantool-patches
mailing list