Tarantool development patches archive
 help / color / mirror / Atom feed
From: "n.pettik" <korablev@tarantool.org>
To: tarantool-patches@freelists.org
Cc: Konstantin Osipov <kostja@tarantool.org>,
	Vladislav Shpilevoy <v.shpilevoy@tarantool.org>
Subject: [tarantool-patches] Re: [PATCH 2/6] sql: rework ALTER TABLE grammar
Date: Thu, 17 Jan 2019 20:14:50 +0300	[thread overview]
Message-ID: <C8EB016B-A539-4598-94B4-5863A6D6A3B1@tarantool.org> (raw)
In-Reply-To: <20190117115100.GM28204@chai>



> On 17 Jan 2019, at 14:51, Konstantin Osipov <kostja@tarantool.org> wrote:
> 
> * Nikita Pettik <korablev@tarantool.org> [19/01/09 15:17]:
>> +alter_table_start ::= ALTER TABLE fullname(Z) . {
>> +  pParse->constraint->table_name = Z;
>> +  pParse->constraint->name.n = 0;
>> +}
> 
> It's bikeshed at this point, but in future you will have other
> ALTER TABLE clauses: add/drop column, add/drop index,

Indexes out of scope: they are part of constraint routines.

> add/drop
> constraint. It's unclear why you initialize a specific parsing
> context (constraint definition) right in alter_table_start rule.
> OK for now.

We must save name of table before any other processing.
So, at the moment of parsing table’s name we don’t have
any notion about next actions yet.

We can use the way you suggested in previous letter:
introduce some hierarchical structures.
For instance ALTER can be implemented in the next way:

diff --git a/src/box/sql/sqliteInt.h b/src/box/sql/sqliteInt.h
index e38e0da08..f1a5e1974 100644
--- a/src/box/sql/sqliteInt.h
+++ b/src/box/sql/sqliteInt.h
@@ -2707,6 +2707,105 @@ struct constraint_parse {
        struct ExprList *cols;
 };
 
+enum entity_type {
+       ENTITY_TYPE_TABLE = 0,
+       ENTITY_TYPE_INDEX,
+       ENTITY_TYPE_TRIGGER,
+       ENTITY_TYPE_CONSTRAINT,
+       ENTITY_TYPE_COLUMN
+};
+
+/***
+ * Hierarchy is following:
+ *
+ * Base structure is ALTER.
+ * ALTER is omitted only for CREATE TABLE.
+ *
+ * DROP is general for all existing objects and includes
+ * name of object itself, name of parent object (table),
+ * IF EXISTS clause and may contain on-drop behaviour.
+ * Hence, it terms of grammar - it is terminal symbol.
+ *
+ * RENAME can be applied only to table, so it is also
+ * terminal symbol.
+ *
+ * CREATE in turn can be expanded to nonterminal symbol
+ * CREATE CONSTRAINT or to terminal CREATE TABLE/INDEX/TRIGGER.
+ * CREATE CONSTRAINT unfolds to FOREIGN KEY or UNIQUE/PRIMARY KEY.
+ *
+ * For instance, ALTER TABLE t ADD CONSTRAINT c FOREIGN KEY
+ *                  REFERENCES t2(id);
+ * ALTER *TABLE* -> CREATE ENTITY -> CREATE CONSTRAINT -> CREATE FK
+ *
+ * CREATE TRIGGER tr1 ...
+ * ALTER *TABLE* -> CREATE ENTITY -> CREATE TRIGGER
+ */
+struct alter_entity_def {
+       enum entity_type entity_type;
+       struct SrcList *entity_name;
+};
+
+struct rename_entity_def {
+       struct alter_entity_def *base;
+       struct Token new_name;
+};
+
+struct create_entity_def {
+       struct alter_entity_def *base;
+       /** Statement comes with IF NOT EXISTS clause. */
+       bool if_not_exist;
+       struct Token *name;
+};
+
+struct drop_entity_def {
+       struct alter_entity_def *base;
+       /** Statement comes with IF EXISTS clause. */
+       bool if_exist;
+       struct Token entity_name;
+       /** One of CASCADE, RESTRICT */
+       int drop_behaviour;
+};
+
+struct create_trigger_def {
+       struct create_entity_def *base;
+       /** One of TK_BEFORE, TK_AFTER, TK_INSTEAD. */
+       int tr_tm;
+       /** One of TK_INSERT, TK_UPDATE, TK_DELETE. */
+       int op;
+       /** Column list if this is an UPDATE OF trigger. */
+       struct IdList *columns;
+       /** When clause. */
+       struct Expr *when;
+       bool if_not_exist;
+
+};
+struct create_table_def {
+       struct create_entity_def *base;
+       struct space_def *table_def;
+       struct Select *select;
+};
+
+struct create_index_def {
+       struct create_entity_def *base;
+       enum sort_order sort_order;
+       enum sql_index_type idx_type;
+       struct ExprList *col_list;
+};
+
+struct create_constraint_def {
+       struct create_entity_def *base;
+       /** One of DEFERRED, IMMEDIATE. */
+       int check_time;
+};
+
+struct create_fk_def {
+       struct create_constraint_def *base;
+       struct ExprList *child_cols;
+       struct ExprList *parent_cols;
+       struct Token *parent_name;
+       enum fkey_action action;
+};
+
diff --git a/src/box/sql/parse.y b/src/box/sql/parse.y
index de5429498..84597bb91 100644
--- a/src/box/sql/parse.y
+++ b/src/box/sql/parse.y
@@ -1452,8 +1452,11 @@ cmd ::= alter_table_start alter_table_action .
  * the separate rule.
  */
 alter_table_start ::= ALTER TABLE fullname(Z) . {
-  pParse->constraint.table = Z;
-  pParse->constraint.name.n = 0;
+  pParse->alter_entity_def =
+    region_alloc(pParse->region, sizeof(struct alter_entity_def));
+  pParse->alter_entity_def->entity_type = ENTITY_TYPE_TABLE;
+  pParse->alter_entity_def->parent_name = Z;
+  pParse->alter_entity_def->entity_name.n = 0;
 }
 
 alter_table_action ::= add_constraint_def.
@@ -1461,25 +1464,44 @@ alter_table_action ::= drop_constraint_def.
 alter_table_action ::= rename.
 
 rename ::= RENAME TO nm(Z). {
-  sql_alter_table_rename(pParse, &Z);
+  struct alter_entity_rename *entity_rename =
+    region_alloc(pParse->region, sizeof(struct rename_entity_def));
+  entity_rename->base = pParse->alter_entity_def;
+  entity_rename->new_name = Z;
+  pParse->alter_entity_def = (struct alter_entity_def *) entity_rename;
+  sql_alter_table_rename(pParse);
 }
 
 add_constraint_def ::= add_constraint_start constraint_def.
 
 add_constraint_start ::= ADD CONSTRAINT nm(Z). {
-  pParse->constraint.name = Z;
+  struct create_entity_def *entity_create =
+    region_alloc(pParse->region, sizeof(struct create_entity_def));
+  entity_create->base = pParse->alter_entity_def;
+  entity_create->name = Z;
+  entity_create->if_not_exist = false;
+  pParse->alter_entity_def = (struct alter_entity_def *)entity_create;
 }
 
 constraint_def ::= foreign_key_def.
 
 foreign_key_def ::= FOREIGN KEY LP eidlist(FA) RP REFERENCES nm(T)
                     eidlist_opt(TA) refargs(R) defer_subclause_opt(D). {
-  pParse->constraint.cols = FA;
-  sql_create_foreign_key(pParse, &T, TA, D, R);
+  struct create_fk_def *fk_def =
+    region_alloc(pParse->region, sizeof(struct create_fk_def));
+  fk_def->child_cols = FA;
+  fk_def->parent_cols = TA;
+  fk_def->action = R;
+  fk_def->parent_name = T;
+  sql_create_foreign_key(pParse);
 }
 
 drop_constraint_def ::= DROP CONSTRAINT nm(Z). {
-  sql_drop_foreign_key(pParse, &Z);
+    struct drop_entity_rename *entity_drop =
+      region_alloc(pParse->region, sizeof(struct drop_entity_def));
+    entity_drop->base = pParse->alter_entity_def;
+    entity_drop->new_name = Z;
+  sql_drop_foreign_key(pParse);
 }

It is easy to fix other create/drop statements to use
these structures. If it is OK to you and Vlad, I can
rework whole patch.

>> +
>> +alter_table_action ::= add_constraint_def.
>> +alter_table_action ::= drop_constraint_def.
> 
> Why use the same data structure for create and drop?

For the sake of simplicity.

> When I drop a
> constraint I specify its name and (perhaps) table name, none of
> other properties.

Not quite: drop constraint clause also may include drop behaviour:
one of CASCADE or RESTRICT.
In our implementation it is always RESTRICT.

> To capture drop context one could use:
> 
> struct drop_object_def {
>    enum object_type object_type;
>    const char *object_name;
>    const char *parent_object_name;
> };
> 
> rename of an object could be captured in a similar data structure.

Rename and drop are the easiest cases.

  reply	other threads:[~2019-01-17 17:14 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
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 [this message]
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=C8EB016B-A539-4598-94B4-5863A6D6A3B1@tarantool.org \
    --to=korablev@tarantool.org \
    --cc=kostja@tarantool.org \
    --cc=tarantool-patches@freelists.org \
    --cc=v.shpilevoy@tarantool.org \
    --subject='[tarantool-patches] Re: [PATCH 2/6] sql: rework ALTER TABLE grammar' \
    /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