From: "n.pettik" <korablev@tarantool.org> To: tarantool-patches@freelists.org Cc: Vladislav Shpilevoy <v.shpilevoy@tarantool.org> Subject: [tarantool-patches] Re: [PATCH 1/6] sql: move constraint name to struct contraint_parse Date: Wed, 16 Jan 2019 23:06:29 +0300 [thread overview] Message-ID: <3C226FE6-A27A-46CD-8C83-AA839AAF08F2@tarantool.org> (raw) In-Reply-To: <834ae33b-dddd-3f51-f6f1-ef5bcc24e240@tarantool.org> >> 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].
next prev parent reply other threads:[~2019-01-16 20:06 UTC|newest] Thread overview: 24+ messages / expand[flat|nested] mbox.gz Atom feed top 2019-01-09 12:13 [tarantool-patches] [PATCH 0/6] Introduce ALTER TABLE ADD CONSTRAINT UNIQUE/PK Nikita Pettik 2019-01-09 12:13 ` [tarantool-patches] [PATCH 1/6] sql: move constraint name to struct contraint_parse Nikita Pettik 2019-01-14 14:04 ` [tarantool-patches] " Vladislav Shpilevoy 2019-01-16 20:06 ` n.pettik [this message] 2019-01-16 20:54 ` Vladislav Shpilevoy 2019-01-17 10:56 ` Konstantin Osipov 2019-01-17 17:14 ` n.pettik 2019-01-09 12:13 ` [tarantool-patches] [PATCH 2/6] sql: rework ALTER TABLE grammar Nikita Pettik 2019-01-14 14:05 ` [tarantool-patches] " Vladislav Shpilevoy 2019-01-16 20:06 ` n.pettik 2019-01-16 20:54 ` Vladislav Shpilevoy 2019-01-17 11:51 ` Konstantin Osipov 2019-01-17 17:14 ` n.pettik 2019-01-18 1:42 ` Konstantin Osipov 2019-01-09 12:13 ` [tarantool-patches] [PATCH 3/6] sql: remove start token from sql_create_index args Nikita Pettik 2019-01-09 12:13 ` [tarantool-patches] [PATCH 4/6] sql: refactor getNewIid() function Nikita Pettik 2019-01-14 14:05 ` [tarantool-patches] " Vladislav Shpilevoy 2019-01-09 12:13 ` [tarantool-patches] [PATCH 5/6] sql: fix error message for improperly created index Nikita Pettik 2019-01-14 14:06 ` [tarantool-patches] " Vladislav Shpilevoy 2019-01-16 20:06 ` n.pettik 2019-01-09 12:13 ` [tarantool-patches] [PATCH 6/6] sql: introduce ALTER TABLE ADD CONSTRAINT UNIQUE/PRIMARY KEY Nikita Pettik 2019-01-14 14:06 ` [tarantool-patches] " Vladislav Shpilevoy 2019-01-16 20:06 ` n.pettik 2019-01-16 20:54 ` Vladislav Shpilevoy
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=3C226FE6-A27A-46CD-8C83-AA839AAF08F2@tarantool.org \ --to=korablev@tarantool.org \ --cc=tarantool-patches@freelists.org \ --cc=v.shpilevoy@tarantool.org \ --subject='[tarantool-patches] Re: [PATCH 1/6] sql: move constraint name to struct contraint_parse' \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: link
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox