[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