From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from localhost (localhost [127.0.0.1]) by turing.freelists.org (Avenir Technologies Mail Multiplex) with ESMTP id 011E025DC2 for ; Wed, 16 Jan 2019 15:06:34 -0500 (EST) Received: from turing.freelists.org ([127.0.0.1]) by localhost (turing.freelists.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id qH3uL-ZzozNX for ; Wed, 16 Jan 2019 15:06:33 -0500 (EST) Received: from smtpng3.m.smailru.net (smtpng3.m.smailru.net [94.100.177.149]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by turing.freelists.org (Avenir Technologies Mail Multiplex) with ESMTPS id E1B3B24AD6 for ; Wed, 16 Jan 2019 15:06:32 -0500 (EST) Content-Type: text/plain; charset=us-ascii Mime-Version: 1.0 (Mac OS X Mail 12.0 \(3445.100.39\)) Subject: [tarantool-patches] Re: [PATCH 1/6] sql: move constraint name to struct contraint_parse From: "n.pettik" In-Reply-To: <834ae33b-dddd-3f51-f6f1-ef5bcc24e240@tarantool.org> Date: Wed, 16 Jan 2019 23:06:29 +0300 Content-Transfer-Encoding: quoted-printable Message-Id: <3C226FE6-A27A-46CD-8C83-AA839AAF08F2@tarantool.org> References: <499ebc6e21ade22cde794f8470bf5900131d42f5.1547035183.git.korablev@tarantool.org> <834ae33b-dddd-3f51-f6f1-ef5bcc24e240@tarantool.org> Sender: tarantool-patches-bounce@freelists.org Errors-to: tarantool-patches-bounce@freelists.org Reply-To: tarantool-patches@freelists.org List-help: List-unsubscribe: List-software: Ecartis version 1.0.0 List-Id: tarantool-patches List-subscribe: List-owner: List-post: List-archive: To: tarantool-patches@freelists.org Cc: Vladislav Shpilevoy >> 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; >=20 > 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 =3D parse->constraint->table_name; + struct SrcList *src_tab =3D parse->constraint->table; assert(src_tab->nSrc =3D=3D 1); struct sqlite3 *db =3D parse->db; char *new_name =3D 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 =3D NULL; if (is_alter) { const char *child_name =3D - = parse_context->constraint->table_name->a[0].zName; + parse_context->constraint->table->a[0].zName; child_space =3D space_by_name(child_name); if (child_space =3D=3D 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 =3D - parse_context->constraint->table_name->a[0].zName; + parse_context->constraint->table->a[0].zName; assert(table_name !=3D NULL); struct space *child =3D space_by_name(table_name); if (child =3D=3D 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 ::=3D ANALYZE nm(X). = {sqlite3Analyze(pParse, &X);} =20 //////////////////////// ALTER TABLE table ... = //////////////////////////////// cmd ::=3D ALTER TABLE fullname(X) RENAME TO nm(Z). { - pParse->constraint->table_name =3D X; + pParse->constraint->table =3D X; sql_alter_table_rename(pParse, &Z); } =20 cmd ::=3D 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 =3D X; + pParse->constraint->table =3D X; pParse->constraint->name =3D Z; sql_create_foreign_key(pParse, FA, &T, TA, D, R); } =20 cmd ::=3D ALTER TABLE fullname(X) DROP CONSTRAINT nm(Z). { - pParse->constraint->table_name =3D X; + pParse->constraint->table =3D X; sql_drop_foreign_key(pParse, &Z); } =20 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; }; >=20 >> + /** Name of the constraint currently being parsed. */ >> + struct Token name; >> +}; >=20 > 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 =3D=3D NULL) goto primary_key_exit; - sql_create_index(pParse, 0, 0, list, 0, SORT_ORDER_ASC, + pParse->constraint.cols =3D list; + sql_create_index(pParse, 0, 0, 0, SORT_ORDER_ASC, false, SQL_INDEX_TYPE_CONSTRAINT_PK); + pParse->constraint.cols =3D 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 =3D pList; + sql_create_index(pParse, 0, 0, 0, sortOrder, false, SQL_INDEX_TYPE_CONSTRAINT_PK); + pParse->constraint.cols =3D NULL; pList =3D 0; if (pParse->nErr > 0) goto primary_key_exit; @@ -1800,9 +1803,9 @@ columnno_by_name(struct Parse *parse_context, = const struct space *space, } =20 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 =3D 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 =3D new_tab =3D=3D NULL; uint32_t child_cols_count; + struct ExprList *child_cols =3D parse_context->constraint.cols; @@ -2226,7 +2231,7 @@ constraint_is_named(const char *name) =20 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 =3D NULL; struct sqlite3 *db =3D parse->db; assert(!db->init.busy); + struct ExprList *col_list =3D 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 ::=3D NULL onconf(R). { ccons ::=3D NOT NULL onconf(R). = {sql_column_add_nullable_action(pParse, R);} ccons ::=3D PRIMARY KEY sortorder(Z) autoinc(I). {sqlite3AddPrimaryKey(pParse,0,I,Z);} -ccons ::=3D UNIQUE. {sql_create_index(pParse,0,0,0,0, +ccons ::=3D UNIQUE. {sql_create_index(pParse,0,0,0, SORT_ORDER_ASC, = false, = SQL_INDEX_TYPE_CONSTRAINT_UNIQUE);} ccons ::=3D CHECK LP expr(X) RP. = {sql_add_check_constraint(pParse,&X);} ccons ::=3D 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 ::=3D defer_subclause(D). {fkey_change_defer_mode(pParse, D);} ccons ::=3D COLLATE id(C). {sqlite3AddCollateType(pParse, &C);} -tcons ::=3D UNIQUE LP sortlist(X) RP. - {sql_create_index(pParse,0,0,X,0, - = SORT_ORDER_ASC,false, - = SQL_INDEX_TYPE_CONSTRAINT_UNIQUE);} +tcons ::=3D UNIQUE LP sortlist(X) RP. { + pParse->constraint.cols =3D X; + sql_create_index(pParse,0,0,0, SORT_ORDER_ASC,false, + SQL_INDEX_TYPE_CONSTRAINT_UNIQUE); +} tcons ::=3D CHECK LP expr(E) RP onconf. {sql_add_check_constraint(pParse,&E);} tcons ::=3D 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 =3D FA; + sql_create_foreign_key(pParse, &T, TA, D, R); } @@ -1211,7 +1213,8 @@ paren_exprlist(A) ::=3D LP exprlist(X) RP. {A =3D = X;} // cmd ::=3D 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 =3D Z; + sql_create_index(pParse, &X, sqlite3SrcListAppend(pParse->db,0,&Y), = &S, SORT_ORDER_ASC, NE, U); } =20 cmd ::=3D 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 =3D X; - pParse->constraint->name =3D Z; - sql_create_foreign_key(pParse, FA, &T, TA, D, R); + pParse->constraint.table =3D X; + pParse->constraint.name =3D Z; + pParse->constraint.cols =3D 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=3D=3DNULL. * @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); =20 @@ -4150,9 +4154,6 @@ fkey_change_defer_mode(struct Parse = *parse_context, bool is_deferred); * OR to handle * * @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; >=20 > 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 =3D pReprepare; - sParse.constraint =3D region_alloc(&sParse.region, - sizeof(*sParse.constraint)); - if (sParse.constraint =3D=3D NULL) { - diag_set(OutOfMemory, sizeof(*sParse.constraint), = "region", - "constraint"); - sql_parser_destroy(&sParse); - rc =3D SQLITE_NOMEM; - return rc; - } - sParse.constraint->name.z =3D NULL; - sParse.constraint->name.n =3D 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. >=20 >> /** >> * 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); >=20 > 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" =20 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 =3D parse->constraint.table; assert(src_tab->nSrc =3D=3D 1); struct sqlite3 *db =3D parse->db; char *new_name =3D 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 =3D type_def->type; column_def->type =3D = sql_affinity_to_field_type(column_def->affinity); p->def->field_count++; - pParse->constraintName.n =3D 0; + pParse->constraint.name.n =3D 0; } =20 void @@ -727,8 +727,10 @@ sqlite3AddPrimaryKey(Parse * pParse, /* = Parsing context */ &token, = 0)); if (list =3D=3D NULL) goto primary_key_exit; - sql_create_index(pParse, 0, 0, list, 0, SORT_ORDER_ASC, + pParse->constraint.cols =3D list; + sql_create_index(pParse, 0, 0, 0, SORT_ORDER_ASC, false, SQL_INDEX_TYPE_CONSTRAINT_PK); + pParse->constraint.cols =3D 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 =3D pList; + sql_create_index(pParse, 0, 0, 0, sortOrder, false, SQL_INDEX_TYPE_CONSTRAINT_PK); + pParse->constraint.cols =3D NULL; pList =3D 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, } =20 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 =3D 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 =3D new_tab =3D=3D NULL; uint32_t child_cols_count; + struct ExprList *child_cols =3D parse_context->constraint.cols; if (child_cols =3D=3D NULL) { assert(!is_alter); child_cols_count =3D 1; } else { child_cols_count =3D child_cols->nExpr; } - assert(!is_alter || (child !=3D NULL && child->nSrc =3D=3D 1)); struct space *child_space =3D NULL; if (is_alter) { - const char *child_name =3D child->a[0].zName; + const char *child_name =3D + parse_context->constraint.table->a[0].zName; child_space =3D space_by_name(child_name); if (child_space =3D=3D 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 =3D=3D NULL && !is_alter) { - if (parse_context->constraintName.n =3D=3D 0) { + if (!is_alter) { + if (parse_context->constraint.name.n =3D=3D 0) { constraint_name =3D sqlite3MPrintf(db, = "FK_CONSTRAINT_%d_%s", = ++parse_context->fkey_count, new_tab->def->name); } else { - struct Token *cnstr_nm =3D = &parse_context->constraintName; + struct Token *cnstr_nm =3D + &parse_context->constraint.name; constraint_name =3D sqlite3NameFromToken(db, = cnstr_nm); } } else { - constraint_name =3D sqlite3NameFromToken(db, = constraint); + constraint_name =3D + sqlite3NameFromToken(db, + = &parse_context->constraint.name); } if (constraint_name =3D=3D NULL) goto exit_create_fk; @@ -2016,11 +2023,11 @@ fkey_change_defer_mode(struct Parse = *parse_context, bool is_deferred) } =20 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 !=3D NULL && table->nSrc =3D=3D 1); - const char *table_name =3D table->a[0].zName; + const char *table_name =3D + parse_context->constraint.table->a[0].zName; + assert(table_name !=3D NULL); struct space *child =3D space_by_name(table_name); if (child =3D=3D NULL) { diag_set(ClientError, ER_NO_SUCH_SPACE, table_name); @@ -2224,7 +2231,7 @@ constraint_is_named(const char *name) =20 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 =3D NULL; struct sqlite3 *db =3D parse->db; assert(!db->init.busy); + struct ExprList *col_list =3D parse->constraint.cols; =20 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 =3D NULL; - if (parse->constraintName.z !=3D NULL) + if (parse->constraint.name.z !=3D NULL) constraint_name =3D sqlite3NameFromToken(db, - = &parse->constraintName); + = &parse->constraint.name); =20 /* * 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) ::=3D id(A). { carglist ::=3D carglist cconsdef. carglist ::=3D . cconsdef ::=3D cconsname ccons. -cconsname ::=3D CONSTRAINT nm(X). {pParse->constraintName =3D = X;} -cconsname ::=3D . {pParse->constraintName.n =3D= 0;} +cconsname ::=3D CONSTRAINT nm(X). {pParse->constraint.name =3D = X;} +cconsname ::=3D . {pParse->constraint.name.n = =3D 0;} ccons ::=3D DEFAULT term(X). = {sqlite3AddDefaultValue(pParse,&X);} ccons ::=3D DEFAULT LP expr(X) RP. = {sqlite3AddDefaultValue(pParse,&X);} ccons ::=3D DEFAULT PLUS term(X). = {sqlite3AddDefaultValue(pParse,&X);} @@ -262,12 +262,12 @@ ccons ::=3D NULL onconf(R). { ccons ::=3D NOT NULL onconf(R). = {sql_column_add_nullable_action(pParse, R);} ccons ::=3D PRIMARY KEY sortorder(Z) autoinc(I). {sqlite3AddPrimaryKey(pParse,0,I,Z);} -ccons ::=3D UNIQUE. {sql_create_index(pParse,0,0,0,0, +ccons ::=3D UNIQUE. {sql_create_index(pParse,0,0,0, SORT_ORDER_ASC, = false, = SQL_INDEX_TYPE_CONSTRAINT_UNIQUE);} ccons ::=3D CHECK LP expr(X) RP. = {sql_add_check_constraint(pParse,&X);} ccons ::=3D 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 ::=3D defer_subclause(D). {fkey_change_defer_mode(pParse, D);} ccons ::=3D COLLATE id(C). {sqlite3AddCollateType(pParse, &C);} =20 @@ -308,19 +308,21 @@ init_deferred_pred_opt(A) ::=3D INITIALLY = DEFERRED. {A =3D 1;} init_deferred_pred_opt(A) ::=3D INITIALLY IMMEDIATE. {A =3D 0;} =20 tconsdef ::=3D tconsname tcons. -tconsname ::=3D CONSTRAINT nm(X). {pParse->constraintName =3D X;} -tconsname ::=3D . {pParse->constraintName.n =3D = 0;} +tconsname ::=3D CONSTRAINT nm(X). {pParse->constraint.name =3D X;} +tconsname ::=3D . {pParse->constraint.name.n =3D = 0;} tcons ::=3D PRIMARY KEY LP sortlist(X) autoinc(I) RP. {sqlite3AddPrimaryKey(pParse,X,I,0);} -tcons ::=3D UNIQUE LP sortlist(X) RP. - {sql_create_index(pParse,0,0,X,0, - = SORT_ORDER_ASC,false, - = SQL_INDEX_TYPE_CONSTRAINT_UNIQUE);} +tcons ::=3D UNIQUE LP sortlist(X) RP. { + pParse->constraint.cols =3D X; + sql_create_index(pParse,0,0,0, SORT_ORDER_ASC,false, + SQL_INDEX_TYPE_CONSTRAINT_UNIQUE); +} tcons ::=3D CHECK LP expr(E) RP onconf. {sql_add_check_constraint(pParse,&E);} tcons ::=3D 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 =3D FA; + sql_create_foreign_key(pParse, &T, TA, D, R); } %type defer_subclause_opt {int} defer_subclause_opt(A) ::=3D . {A =3D 0;} @@ -1211,7 +1213,8 @@ paren_exprlist(A) ::=3D LP exprlist(X) RP. {A =3D = X;} // cmd ::=3D 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 =3D Z; + sql_create_index(pParse, &X, sqlite3SrcListAppend(pParse->db,0,&Y), = &S, SORT_ORDER_ASC, NE, U); } =20 @@ -1445,17 +1448,22 @@ cmd ::=3D ANALYZE nm(X). = {sqlite3Analyze(pParse, &X);} =20 //////////////////////// ALTER TABLE table ... = //////////////////////////////// cmd ::=3D ALTER TABLE fullname(X) RENAME TO nm(Z). { - sql_alter_table_rename(pParse,X,&Z); + pParse->constraint.table =3D X; + sql_alter_table_rename(pParse, &Z); } =20 cmd ::=3D 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 =3D X; + pParse->constraint.name =3D Z; + pParse->constraint.cols =3D FA; + sql_create_foreign_key(pParse, &T, TA, D, R); } =20 cmd ::=3D ALTER TABLE fullname(X) DROP CONSTRAINT nm(Z). { - sql_drop_foreign_key(pParse, X, &Z); + pParse->constraint.table =3D X; + sql_drop_foreign_key(pParse, &Z); } =20 //////////////////////// 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; }; =20 +/** + * 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=3D=3DNULL. * @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); =20 @@ -4136,14 +4154,6 @@ fkey_change_defer_mode(struct Parse = *parse_context, bool is_deferred); * OR to handle * * @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); =20 /** * Function called from parser to handle * 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); =20 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); =20 /** * Return the length (in bytes) of the token that begins at z[0].