[tarantool-patches] [PATCH 1/6] sql: move constraint name to struct contraint_parse

Nikita Pettik korablev at tarantool.org
Wed Jan 9 15:13:15 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/alter.c b/src/box/sql/alter.c
index d0ce9d893..dfd71792b 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_name;
 	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..963b16626 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
@@ -774,9 +774,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,8 +1800,7 @@ 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,
+sql_create_foreign_key(struct Parse *parse_context, struct ExprList *child_cols,
 		       struct Token *parent, struct ExprList *parent_cols,
 		       bool is_deferred, int actions)
 {
@@ -1834,10 +1833,10 @@ sql_create_foreign_key(struct Parse *parse_context, struct SrcList *child,
 	} 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_name->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 +1883,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 +2018,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_name->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);
@@ -2311,10 +2313,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..f4fdf58f2 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);}
@@ -267,7 +267,7 @@ ccons ::= UNIQUE.                {sql_create_index(pParse,0,0,0,0,
                                                    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, NULL, &T, TA, false, R);}
 ccons ::= defer_subclause(D).    {fkey_change_defer_mode(pParse, D);}
 ccons ::= COLLATE id(C).        {sqlite3AddCollateType(pParse, &C);}
 
@@ -308,8 +308,8 @@ 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.
@@ -320,7 +320,7 @@ 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);
+    sql_create_foreign_key(pParse, FA, &T, TA, D, R);
 }
 %type defer_subclause_opt {int}
 defer_subclause_opt(A) ::= .                    {A = 0;}
@@ -1445,17 +1445,21 @@ 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_name = 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_name = X;
+    pParse->constraint->name = Z;
+    sql_create_foreign_key(pParse, FA, &T, TA, D, R);
 }
 
 cmd ::= ALTER TABLE fullname(X) DROP CONSTRAINT nm(Z). {
-    sql_drop_foreign_key(pParse, X, &Z);
+    pParse->constraint->table_name = X;
+    sql_drop_foreign_key(pParse, &Z);
 }
 
 //////////////////////// COMMON TABLE EXPRESSIONS ////////////////////////////
diff --git a/src/box/sql/prepare.c b/src/box/sql/prepare.c
index 824578e45..0a2f59954 100644
--- a/src/box/sql/prepare.c
+++ b/src/box/sql/prepare.c
@@ -58,6 +58,17 @@ 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;
 	assert(ppStmt && *ppStmt == 0);
 	/* assert( !db->mallocFailed ); // not true with SQLITE_USE_ALLOCA */
 
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;
+	/** Name of the constraint currently being parsed. */
+	struct Token name;
+};
+
 /*
  * 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 +2739,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 +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;
 	/**
 	 * Number of FK constraints declared within
 	 * CREATE TABLE statement.
@@ -4136,11 +4150,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.
@@ -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);
 
@@ -4162,12 +4170,10 @@ sql_create_foreign_key(struct Parse *parse_context, struct SrcList *child,
  * <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 +4391,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].
-- 
2.15.1





More information about the Tarantool-patches mailing list