Tarantool development patches archive
 help / color / mirror / Atom feed
From: Kirill Shcherbatov <kshcherbatov@tarantool.org>
To: tarantool-patches@freelists.org,
	tarantool-patches@dev.tarantool.org, kostja.osipov@gmail.com,
	korablev@tarantool.org
Subject: [Tarantool-patches] [PATCH v1 7/9] sql: wrap all ASTs in sql_trigger_expr structure
Date: Mon, 14 Oct 2019 19:03:22 +0300	[thread overview]
Message-ID: <b0d56a21e83ec1f81506d9048bddd7b8ff6467d0.1571068485.git.kshcherbatov@tarantool.org> (raw)
In-Reply-To: <cover.1571068485.git.kshcherbatov@tarantool.org>

Introduced a new sql_trigger_expr to aggregate all
sql_triger-related ASTs. This allows to rework
sql_trigger_compile function in further patches to return
sql_trigger_expr object instead of the complete trigger
object.

It is an important step of refactoring, because we are going
to construct trigger and trigger_def objects universally by
information that will be defined in the _trigger space.

Needed for #4343
---
 src/box/sql.h               | 37 +++++++++++++++-----
 src/box/sql/fk_constraint.c | 15 +++++---
 src/box/sql/trigger.c       | 69 +++++++++++++++++++++++++++++--------
 3 files changed, 92 insertions(+), 29 deletions(-)

diff --git a/src/box/sql.h b/src/box/sql.h
index 09d2b7d7c..d0c18b6ff 100644
--- a/src/box/sql.h
+++ b/src/box/sql.h
@@ -99,6 +99,32 @@ sql_expr_compile(struct sql *db, const char *expr, int expr_len);
 struct Select *
 sql_view_compile(struct sql *db, const char *view_stmt);
 
+/** The SQL Trigger AST runtime representation. */
+struct sql_trigger_expr {
+	/** The WHEN clause of the expression (may be NULL). */
+	struct Expr *when;
+	/**
+	 * If this is an UPDATE OF <column-list> trigger,
+	 * the <column-list> is stored here
+	 */
+	struct IdList *cols;
+	/** Link list of trigger program steps. */
+	struct TriggerStep *step_list;
+};
+
+/**
+ * Allocate a new SQL Trigger AST runtime object.
+ * In case of successfull construction, the constructed object
+ * start manipulate given arguments lifecycle.
+ */
+struct sql_trigger_expr *
+sql_trigger_expr_new(struct sql *db, struct IdList *cols, struct Expr *when,
+		     struct TriggerStep *step_list);
+
+/** Free SQL Trigger AST object. */
+void
+sql_trigger_expr_delete(struct sql *db, struct sql_trigger_expr *trigger_expr);
+
 /**
  * Perform parsing of provided SQL request and construct trigger AST.
  * @param db SQL context handle.
@@ -452,15 +478,8 @@ struct sql_trigger {
 	 * triggering event. The value is `BEFORE` or `AFTER`.
 	 */
 	enum trigger_action_timing action_timing;
-	/** The WHEN clause of the expression (may be NULL). */
-	struct Expr *pWhen;
-	/**
-	 * If this is an UPDATE OF <column-list> trigger,
-	 * the <column-list> is stored here
-	 */
-	struct IdList *pColumns;
-	/** Link list of trigger program steps. */
-	struct TriggerStep *step_list;
+	/** The SQL trigger AST. */
+	struct sql_trigger_expr *expr;
 	/**
 	 * Organize sql_trigger structs into linked list
 	 * with space::trigger_list.
diff --git a/src/box/sql/fk_constraint.c b/src/box/sql/fk_constraint.c
index 539a16560..454ed311f 100644
--- a/src/box/sql/fk_constraint.c
+++ b/src/box/sql/fk_constraint.c
@@ -856,22 +856,27 @@ fk_constraint_action_trigger(struct Parse *pParse, struct space_def *def,
 							     sizeof(*trigger));
 	if (trigger != NULL) {
 		size_t step_size = sizeof(TriggerStep) + name_len + 1;
-		trigger->step_list = sqlDbMallocZero(db, step_size);
+		step = sqlDbMallocZero(db, step_size);
 		rlist_create(&trigger->link);
-		step = trigger->step_list;
+		if (step == NULL)
+			goto end;
 		step->zTarget = (char *) &step[1];
 		memcpy((char *) step->zTarget, space_name, name_len);
-
 		step->pWhere = sqlExprDup(db, where, EXPRDUP_REDUCE);
 		step->pExprList = sql_expr_list_dup(db, list, EXPRDUP_REDUCE);
 		step->pSelect = sqlSelectDup(db, select, EXPRDUP_REDUCE);
 		if (when != NULL) {
 			when = sqlPExpr(pParse, TK_NOT, when, 0);
-			trigger->pWhen =
-				sqlExprDup(db, when, EXPRDUP_REDUCE);
+			if (when == NULL)
+				goto end;
 		}
+		trigger->expr = sql_trigger_expr_new(db, NULL, when, step);
+		if (trigger->expr == NULL)
+			goto end;
+		when = NULL;
 	}
 
+end:
 	sql_expr_delete(db, where, false);
 	sql_expr_delete(db, when, false);
 	sql_expr_list_delete(db, list);
diff --git a/src/box/sql/trigger.c b/src/box/sql/trigger.c
index 3a0ee6b7d..71a78d7ed 100644
--- a/src/box/sql/trigger.c
+++ b/src/box/sql/trigger.c
@@ -106,14 +106,15 @@ sql_store_trigger(struct Parse *parse)
 	trigger_name = NULL;
 	trigger->event_manipulation = trigger_def->event_manipulation;
 	trigger->action_timing = trigger_def->action_timing;
-	trigger->pWhen = sqlExprDup(db, trigger_def->when, EXPRDUP_REDUCE);
-	trigger->pColumns = sqlIdListDup(db, trigger_def->cols);
 	rlist_create(&trigger->link);
-	if ((trigger_def->when != NULL && trigger->pWhen == NULL) ||
-	    (trigger_def->cols != NULL && trigger->pColumns == NULL))
+	trigger->expr = sql_trigger_expr_new(db, trigger_def->cols,
+					     trigger_def->when,
+					     trigger_def->step_list);
+	if (trigger->expr == NULL)
 		goto trigger_cleanup;
-	trigger->step_list = parse->create_trigger_def.step_list;
-	parse->create_trigger_def.step_list = NULL;
+	trigger_def->cols = NULL;
+	trigger_def->when = NULL;
+	trigger_def->step_list = NULL;
 
 	assert(parse->parsed_ast.trigger == NULL);
 	parse->parsed_ast.trigger = trigger;
@@ -247,15 +248,53 @@ sql_trigger_delete_step(struct sql *db, struct Token *table_name,
 	return trigger_step;
 }
 
+struct sql_trigger_expr *
+sql_trigger_expr_new(struct sql *db, struct IdList *cols, struct Expr *when,
+		     struct TriggerStep *step_list)
+{
+	struct sql_trigger_expr *trigger_expr =
+		(struct sql_trigger_expr *)malloc(sizeof(*trigger_expr));
+	if (trigger_expr == NULL) {
+		diag_set(OutOfMemory, sizeof(*trigger_expr),
+			 "malloc", "trigger_expr");
+		return NULL;
+	}
+	if (when != NULL) {
+		trigger_expr->when = sqlExprDup(db, when, EXPRDUP_REDUCE);
+		if (trigger_expr->when == NULL) {
+			diag_set(OutOfMemory,
+				 sql_expr_sizeof(when, EXPRDUP_REDUCE),
+				 "sqlExprDup", "trigger_expr->when");
+			free(trigger_expr);
+			return NULL;
+		}
+	} else {
+		trigger_expr->when = NULL;
+	}
+	/* Object refers to reduced copy of when expression. */
+	sql_expr_delete(db, when, false);
+	trigger_expr->cols = cols;
+	trigger_expr->step_list = step_list;
+	return trigger_expr;
+}
+
+void
+sql_trigger_expr_delete(struct sql *db, struct sql_trigger_expr *trigger_expr)
+{
+	sqlDeleteTriggerStep(db, trigger_expr->step_list);
+	sql_expr_delete(db, trigger_expr->when, false);
+	sqlIdListDelete(db, trigger_expr->cols);
+	free(trigger_expr);
+}
+
 void
 sql_trigger_delete(struct sql *db, struct sql_trigger *trigger)
 {
 	if (trigger == NULL)
 		return;
-	sqlDeleteTriggerStep(db, trigger->step_list);
+	if (trigger->expr != NULL)
+		sql_trigger_expr_delete(db, trigger->expr);
 	sqlDbFree(db, trigger->zName);
-	sql_expr_delete(db, trigger->pWhen, false);
-	sqlIdListDelete(db, trigger->pColumns);
 	sqlDbFree(db, trigger);
 }
 
@@ -427,7 +466,7 @@ sql_triggers_exist(struct space *space,
 	struct sql_trigger *p;
 	rlist_foreach_entry(p, trigger_list, link) {
 		if (p->event_manipulation == event_manipulation &&
-		    checkColumnOverlap(p->pColumns, changes_list) != 0)
+		    checkColumnOverlap(p->expr->cols, changes_list) != 0)
 			mask |= (1 << p->action_timing);
 	}
 	if (mask_ptr != NULL)
@@ -665,8 +704,8 @@ sql_row_trigger_program(struct Parse *parser, struct sql_trigger *trigger,
 		 * immediately halted by jumping to the OP_Halt
 		 * inserted at the end of the program.
 		 */
-		if (trigger->pWhen != NULL) {
-			pWhen = sqlExprDup(db, trigger->pWhen, 0);
+		if (trigger->expr->when != NULL) {
+			pWhen = sqlExprDup(db, trigger->expr->when, 0);
 			if (0 == sqlResolveExprNames(&sNC, pWhen)
 			    && db->mallocFailed == 0) {
 				iEndTrigger = sqlVdbeMakeLabel(v);
@@ -678,7 +717,7 @@ sql_row_trigger_program(struct Parse *parser, struct sql_trigger *trigger,
 		}
 
 		/* Code the trigger program into the sub-vdbe. */
-		codeTriggerProgram(pSubParse, trigger->step_list, orconf);
+		codeTriggerProgram(pSubParse, trigger->expr->step_list, orconf);
 
 		/* Insert an OP_Halt at the end of the sub-program. */
 		if (iEndTrigger)
@@ -814,7 +853,7 @@ vdbe_code_row_trigger(struct Parse *parser, struct rlist *trigger_list,
 		/* Determine whether we should code trigger. */
 		if (p->event_manipulation == event_manipulation &&
 		    p->action_timing == action_timing &&
-		    checkColumnOverlap(p->pColumns, changes_list)) {
+		    checkColumnOverlap(p->expr->cols, changes_list)) {
 			vdbe_code_row_trigger_direct(parser, p, space, reg,
 						     orconf, ignore_jump);
 		}
@@ -838,7 +877,7 @@ sql_trigger_colmask(Parse *parser, struct rlist *trigger_list,
 	rlist_foreach_entry(p, trigger_list, link) {
 		if (p->event_manipulation == event_manipulation &&
 		    ((action_timing_mask & (1 << p->action_timing)) != 0) &&
-		    checkColumnOverlap(p->pColumns, changes_list)) {
+		    checkColumnOverlap(p->expr->cols, changes_list)) {
 			TriggerPrg *prg =
 				sql_row_trigger(parser, p, space, orconf);
 			if (prg != NULL)
-- 
2.23.0

  parent reply	other threads:[~2019-10-14 16:03 UTC|newest]

Thread overview: 31+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-10-14 16:03 [Tarantool-patches] [PATCH v1 0/9] schema: rework _trigger space Kirill Shcherbatov
2019-10-14 16:03 ` [Tarantool-patches] [PATCH v1 1/9] sql: remove redundant pointer in TriggerStep Kirill Shcherbatov
2019-10-15 15:35   ` [Tarantool-patches] [tarantool-patches] " Nikita Pettik
2019-10-14 16:03 ` [Tarantool-patches] [PATCH v1 2/9] box: rename struct trigger to lua_trigger Kirill Shcherbatov
2019-10-17  7:33   ` Konstantin Osipov
2019-10-14 16:03 ` [Tarantool-patches] [PATCH v1 3/9] box: introduce trigger_event_manipulation enum Kirill Shcherbatov
2019-10-17  7:35   ` Konstantin Osipov
2019-10-14 16:03 ` [Tarantool-patches] [PATCH v1 4/9] box: introduce trigger_action_timing enum Kirill Shcherbatov
2019-10-14 16:03 ` [Tarantool-patches] [PATCH v1 5/9] sql: use rlist to organize triggers in a list Kirill Shcherbatov
2019-10-17  7:36   ` Konstantin Osipov
2019-10-14 16:03 ` [Tarantool-patches] [PATCH v1 6/9] sql: rework CREATE TABLE rule in parser Kirill Shcherbatov
2019-10-14 16:03 ` Kirill Shcherbatov [this message]
2019-10-14 16:03 ` [Tarantool-patches] [PATCH v1 8/9] sql: inherit sql_trigger from a new trigger class Kirill Shcherbatov
2019-10-17  7:38   ` Konstantin Osipov
2019-10-14 16:03 ` [Tarantool-patches] [PATCH v1 9/9] schema: rework _trigger system space Kirill Shcherbatov
2019-10-17  7:44   ` Konstantin Osipov
2019-10-15 21:34 ` [Tarantool-patches] [tarantool-patches] [PATCH v1 0/9] schema: rework _trigger space Nikita Pettik
2019-10-16  5:57   ` Konstantin Osipov
2019-10-16  5:58     ` Konstantin Osipov
2019-10-16 11:07     ` Nikita Pettik
2019-10-16 11:11       ` Konstantin Osipov
2019-10-16 12:18         ` Nikita Pettik
2019-10-16 12:32           ` Konstantin Osipov
2019-10-16 12:47             ` Nikita Pettik
2019-10-16 12:53               ` Konstantin Osipov
2019-10-16 13:13                 ` Nikita Pettik
2019-10-16 14:18                   ` Konstantin Osipov
2019-10-16 12:53           ` [Tarantool-patches] [tarantool-patches] " Kirill Shcherbatov
2019-10-16 13:31             ` Nikita Pettik
2019-10-16 13:47               ` Kirill Shcherbatov
2019-10-16 20:27                 ` 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=b0d56a21e83ec1f81506d9048bddd7b8ff6467d0.1571068485.git.kshcherbatov@tarantool.org \
    --to=kshcherbatov@tarantool.org \
    --cc=korablev@tarantool.org \
    --cc=kostja.osipov@gmail.com \
    --cc=tarantool-patches@dev.tarantool.org \
    --cc=tarantool-patches@freelists.org \
    --subject='Re: [Tarantool-patches] [PATCH v1 7/9] sql: wrap all ASTs in sql_trigger_expr structure' \
    /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