[tarantool-patches] Re: [PATCH v4 6/8] sql: refactor AST trigger object name

n.pettik korablev at tarantool.org
Wed Jun 27 18:57:12 MSK 2018


I see that in this patch you provide changes which are related not
only to renaming, but to refactoring of some functions, to removing
#ifdef SQLITE_OMIT_TRIGGER macros etc.

Lets mention these facts in commit message.

Moreover, if you placed this patch before ’sql: move Triggers to server ‘,
you would avoid additional diffs in alter.cc and trigger.c

> @@ -457,9 +456,10 @@ sql_generate_row_delete(struct Parse *parse, struct Table *table,
> 		/* Mask of OLD.* columns in use */
> 		/* TODO: Could use temporary registers here. */
> 		uint32_t mask =
> -		    sqlite3TriggerColmask(parse, trigger_list, 0, 0,
> -					  TRIGGER_BEFORE | TRIGGER_AFTER, table,
> -					  onconf);
> +			sql_trigger_colmask(parse, trigger_list, 0, 0,
> +					    TRIGGER_BEFORE | TRIGGER_AFTER,
> +					    table,
> +					    onconf);

You can fit ’table’ and ‘onconf’ args in one line.

> @@ -3018,21 +3019,23 @@ struct Parse {
> 					 */
> 
> /*
> - * Each trigger present in the database schema is stored as an instance of
> - * struct Trigger.
> + * Each trigger present in the database schema is stored as an
> + * instance of struct sql_trigger.
>  *
>  * Pointers to instances of struct Trigger are stored in two ways.
> - * 1. In the "trigHash" hash table (part of the sqlite3* that represents the
> - *    database). This allows Trigger structures to be retrieved by name.
> - * 2. All triggers associated with a single table form a linked list, using the
> - *    pNext member of struct Trigger. A pointer to the first element of the
> - *    linked list is stored as the "pTrigger" member of the associated
> - *    struct Table.
> - *
> - * The "step_list" member points to the first element of a linked list
> - * containing the SQL statements specified as the trigger program.
> - */
> -struct Trigger {
> + * 1. In the "trigHash" hash table (part of the sqlite3* that
> + *    represents the database). This allows Trigger structures to
> + *    be retrieved by name.
> + * 2. All triggers associated with a single table form a linked
> + *    list, using the next member of struct sql_trigger. A pointer
> + *    to the first element of the linked list is stored as the
> + *    "pTrigger" member of the associated struct Table.
> + *
> + * The "step_list" member points to the first element of a linked
> + * list containing the SQL statements specified as the trigger
> + * program.
> + */
> +struct sql_trigger {
> 	char *zName;		/* The name of the trigger                        */
> 	/** The ID of space the trigger refers to. */
> 	uint32_t space_id;
> @@ -3042,7 +3045,8 @@ struct Trigger {
> 	IdList *pColumns;	/* If this is an UPDATE OF <column-list> trigger,
> 				   the <column-list> is stored here */
> 	TriggerStep *step_list;	/* Link list of trigger program steps             */
> -	Trigger *pNext;		/* Next trigger associated with the table */
> +	/** Next trigger associated with the table. */
> +	struct sql_trigger *next;
> };

I would also fix comments inside struct definition.

> @@ -4064,17 +4069,143 @@
> +void
> +sql_trigger_begin(struct Parse *parse, struct Token *name, int tr_tm,
> +		  int op, struct IdList *columns, struct SrcList *table,
> +		  struct Expr *when, int no_err);
> +
> +/**
> + * This routine is called after all of the trigger actions have
> + * been parsed in order to complete the process of building the
> + * trigger.
> + *
> + * @param parse Parser context.
> + * @param step_list The triggered program.
> + * @param token Token that describes the complete CREATE TRIGGER.
> + */
> +void sql_trigger_finish(Parse *, TriggerStep *, Token *);

Place type of return value at separate line. Also add names of args to prototype.

> -/*
> - * This routine is called after all of the trigger actions have been parsed
> - * in order to complete the process of building the trigger.
> - */
> void
> -sqlite3FinishTrigger(Parse * pParse,	/* Parser context */
> -		     TriggerStep * pStepList,	/* The triggered program */
> -		     Token * pAll	/* Token that describes the complete CREATE TRIGGER */
> -    )
> +sql_trigger_finish(struct Parse *parse, struct TriggerStep *step_list,
> +		   struct Token *token)
> {
> 	/* Trigger being finished. */
> -	Trigger *pTrig = pParse->parsed_ast.trigger;
> -	char *zName;		/* Name of trigger */
> -	char *zSql = 0;		/* SQL text */
> -	char *zOpts = 0;	/* MsgPack containing SQL options */
> -	sqlite3 *db = pParse->db;	/* The database */
> -	DbFixer sFix;		/* Fixer object */
> -	Token nameToken;	/* Trigger name for error reporting */
> -
> -	pParse->parsed_ast.trigger = NULL;
> -	if (NEVER(pParse->nErr) || !pTrig)
> +	struct sql_trigger *trigger = parse->parsed_ast.trigger;
> +	/* Name of trigger. */
> +	char *trigger_name;

You don’t need to declare all variables beforehand: its obsolete style
used in SQLite.

> +	/* SQL text. */
> +	char *sql_str = NULL;
> +	/* MsgPack containing SQL options. */
> +	char *opts_buff = NULL;
> +	/* The database. */
> +	struct sqlite3 *db = parse->db;
> +
> +	parse->parsed_ast.trigger = NULL;
> +	if (NEVER(parse->nErr) || trigger == NULL)
> 		goto triggerfinish_cleanup;
> -	zName = pTrig->zName;
> -	pTrig->step_list = pStepList;
> -	while (pStepList) {
> -		pStepList->pTrig = pTrig;
> -		pStepList = pStepList->pNext;
> +	trigger_name = trigger->zName;
> +	trigger->step_list = step_list;
> +	while (step_list != NULL) {
> +		step_list->trigger = trigger;
> +		step_list = step_list->pNext;
> 	}
> -	sqlite3TokenInit(&nameToken, pTrig->zName);
> -	sqlite3FixInit(&sFix, pParse, "trigger", &nameToken);
> -	if (sqlite3FixTriggerStep(&sFix, pTrig->step_list)
> -	    || sqlite3FixExpr(&sFix, pTrig->pWhen)
> -	    ) {
> +
> +	/* Trigger name for error reporting. */
> +	struct Token trigger_name_token;
> +	/* Fixer object. */
> +	struct DbFixer fixdb;
> +	sqlite3TokenInit(&trigger_name_token, trigger->zName);
> +	sqlite3FixInit(&fixdb, parse, "trigger", &trigger_name_token);
> +	if (sqlite3FixTriggerStep(&fixdb, trigger->step_list)
> +	    || sqlite3FixExpr(&fixdb, trigger->pWhen))

Put ‘or’ operator at previous line:

	if (sqlite3FixTriggerStep(&fixdb, trigger->step_list) ||
	    sqlite3FixExpr(&fixdb, trigger->pWhen))

> -/*
> +/**
>  * Create and populate a new TriggerPrg object with a sub-program
>  * implementing trigger pTrigger with ON CONFLICT policy orconf.
> + *
> + * @param parser Current parse context.
> + * @param trigger sql_trigger to code.
> + * @param table trigger is attached to.
> + * @param orconf ON CONFLICT policy to code trigger program with.
> + *
> + * @retval not NULL on success.
> + * @retval NULL on error.
>  */
> static TriggerPrg *
> -codeRowTrigger(Parse * pParse,	/* Current parse context */
> -	       Trigger * pTrigger,	/* Trigger to code */
> -	       Table * pTab,	/* The table pTrigger is attached to */
> -	       int orconf	/* ON CONFLICT policy to code trigger program with */
> -    )
> +sql_row_trigger_program(struct Parse *parser, struct sql_trigger *trigger,
> +			struct Table *table, int orconf)

Lets call it vdbe_code_row_trigger() or smth like that.

> @@ -880,34 +868,37 @@ codeRowTrigger(Parse * pParse,	/* Current parse context */
> 	sql_parser_create(pSubParse, db);
> 	memset(&sNC, 0, sizeof(sNC));
> 	sNC.pParse = pSubParse;
> -	pSubParse->pTriggerTab = pTab;
> +	pSubParse->pTriggerTab = table;
> 	pSubParse->pToplevel = pTop;
> -	pSubParse->eTriggerOp = pTrigger->op;
> -	pSubParse->nQueryLoop = pParse->nQueryLoop;
> +	pSubParse->eTriggerOp = trigger->op;
> +	pSubParse->nQueryLoop = parser->nQueryLoop;
> 
> -	v = sqlite3GetVdbe(pSubParse);
> -	if (v) {
> +	/* Temporary VM. */

Why VM is temporary?

> +vdbe_code_row_trigger_direct(struct Parse *parser, struct sql_trigger *trigger,
> +			     struct Table *table, int reg, int orconf,
> +			     int ignore_jump)
> {
> -	Vdbe *v = sqlite3GetVdbe(pParse);	/* Main VM */
> -	TriggerPrg *pPrg;
> -	struct session *user_session = current_session();
> +	/* Main VM. */
> +	struct Vdbe *v = sqlite3GetVdbe(parser);
> 
> -	pPrg = getRowTrigger(pParse, p, pTab, orconf);
> -	assert(pPrg || pParse->nErr || pParse->db->mallocFailed);
> +	TriggerPrg *pPrg = sql_row_trigger(parser, trigger, table, orconf);
> +	assert(pPrg != NULL || parser->nErr != 0 ||
> +	       parser->db->mallocFailed != 0);
> 
> -	/* Code the OP_Program opcode in the parent VDBE. P4 of the OP_Program
> -	 * is a pointer to the sub-vdbe containing the trigger program.
> +	/*
> +	 * Code the OP_Program opcode in the parent VDBE. P4 of
> +	 * the OP_Program is a pointer to the sub-vdbe containing
> +	 * the trigger program.
> 	 */
> -	if (pPrg) {
> -		int bRecursive = (p->zName &&
> -				  0 ==
> -				  (user_session->
> -				   sql_flags & SQLITE_RecTriggers));
> -
> -		sqlite3VdbeAddOp4(v, OP_Program, reg, ignoreJump,
> -				  ++pParse->nMem, (const char *)pPrg->pProgram,
> -				  P4_SUBPROGRAM);
> -		VdbeComment((v, "Call: %s.%s", (p->zName ? p->zName : "fkey"),
> -			     onErrorText(orconf)));
> +	if (pPrg == NULL)
> +		return;
> 
> -		/* Set the P5 operand of the OP_Program instruction to non-zero if
> -		 * recursive invocation of this trigger program is disallowed. Recursive
> -		 * invocation is disallowed if (a) the sub-program is really a trigger,
> -		 * not a foreign key action, and (b) the flag to enable recursive triggers
> -		 * is clear.
> -		 */
> -		sqlite3VdbeChangeP5(v, (u8) bRecursive);
> -	}
> +	struct session *user_session = current_session();
> +	bool recursive = (trigger->zName && !(user_session->sql_flags &
> +					      SQLITE_RecTriggers));

We call bool variables with ‘is_’ or ‘if_’  prefix, as a rule.

> u32
> -sqlite3TriggerColmask(Parse * pParse,	/* Parse context */
> -		      Trigger * pTrigger,	/* List of triggers on table pTab */
> -		      ExprList * pChanges,	/* Changes list for any UPDATE OF triggers */
> -		      int isNew,	/* 1 for new.* ref mask, 0 for old.* ref mask */
> -		      int tr_tm,	/* Mask of TRIGGER_BEFORE|TRIGGER_AFTER */
> -		      Table * pTab,	/* The table to code triggers from */
> -		      int orconf	/* Default ON CONFLICT policy for trigger steps */
> -    )
> +sql_trigger_colmask(Parse *parser, struct sql_trigger *trigger,
> +		    ExprList *changes_list, int new, int tr_tm,
> +		    Table *table, int orconf)
> {
> -	const int op = pChanges ? TK_UPDATE : TK_DELETE;
> +	const int op = changes_list != NULL ? TK_UPDATE : TK_DELETE;
> 	u32 mask = 0;
> -	Trigger *p;
> 
> -	assert(isNew == 1 || isNew == 0);
> -	for (p = pTrigger; p; p = p->pNext) {
> +	assert(new == 1 || new == 0);

We call bool variables with ‘is_’ or ‘if_’ prefixes, as a rule.

> 
> 





More information about the Tarantool-patches mailing list