Tarantool development patches archive
 help / color / mirror / Atom feed
From: Nikita Pettik <korablev@tarantool.org>
To: tarantool-patches@freelists.org
Cc: v.shpilevoy@tarantool.org, Nikita Pettik <korablev@tarantool.org>
Subject: [tarantool-patches] [PATCH 1/6] sql: move constraint name to struct contraint_parse
Date: Wed,  9 Jan 2019 14:13:15 +0200	[thread overview]
Message-ID: <499ebc6e21ade22cde794f8470bf5900131d42f5.1547035183.git.korablev@tarantool.org> (raw)
In-Reply-To: <cover.1547035183.git.korablev@tarantool.org>
In-Reply-To: <cover.1547035183.git.korablev@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/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

  reply	other threads:[~2019-01-09 12:13 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 ` Nikita Pettik [this message]
2019-01-14 14:04   ` [tarantool-patches] Re: [PATCH 1/6] sql: move constraint name to struct contraint_parse Vladislav Shpilevoy
2019-01-16 20:06     ` n.pettik
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=499ebc6e21ade22cde794f8470bf5900131d42f5.1547035183.git.korablev@tarantool.org \
    --to=korablev@tarantool.org \
    --cc=tarantool-patches@freelists.org \
    --cc=v.shpilevoy@tarantool.org \
    --subject='Re: [tarantool-patches] [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