[tarantool-patches] Re: [PATCH v1 1/1] sql: remove struct Enc
Vladislav Shpilevoy
v.shpilevoy at tarantool.org
Fri Aug 24 19:33:35 MSK 2018
Thanks for the patch!
> diff --git a/src/box/sql.c b/src/box/sql.c
> index ae12cae..28ad9d3 100644
> --- a/src/box/sql.c
> +++ b/src/box/sql.c
> @@ -1315,10 +1261,10 @@ int tarantoolSqlite3MakeTableFormat(Table *pTable, void *buf)
> base_len += 1;
> if (default_str != NULL)
> base_len += 1;
> - p = enc->encode_map(p, base_len);
> - p = enc->encode_str(p, "name", 4);
> - p = enc->encode_str(p, field->name, strlen(field->name));
> - p = enc->encode_str(p, "type", 4);
> + mpstream_encode_map(&stream, base_len);
> + mpstream_encode_str(&stream, "name", strlen("name"));
> + mpstream_encode_str(&stream, field->name, strlen(field->name));
> + mpstream_encode_str(&stream, "type", strlen("type"));
1. This construction 'encode_str(stream, str, strlen(str))' is
extremely frequent in the overall project. Please, in the previous
commit split mpstream_encode_str into 2 functions:
mpstream_encode_str(stream, str)
mpstream_encode_strn(stream, str, len)
The first one calls mpstream_encode_strn(stream, str, strlen(str))
and is static inline in the header. With those SQL encoders we can
use mpstream_encode_str(stream, str).
> if (i == pk_forced_int) {
> t = "integer";
> } else {
> @@ -1329,108 +1275,149 @@ int tarantoolSqlite3MakeTableFormat(Table *pTable, void *buf)
> }
>
> assert(def->fields[i].is_nullable ==
> - action_is_nullable(def->fields[i].nullable_action));
> - p = enc->encode_str(p, t, strlen(t));
> - p = enc->encode_str(p, "affinity", 8);
> - p = enc->encode_uint(p, def->fields[i].affinity);
> - p = enc->encode_str(p, "is_nullable", 11);
> - p = enc->encode_bool(p, def->fields[i].is_nullable);
> - p = enc->encode_str(p, "nullable_action", 15);
> + action_is_nullable(def->fields[i].
> + nullable_action));
> + mpstream_encode_str(&stream, t, strlen(t));
> + mpstream_encode_str(&stream, "affinity", strlen("affinity"));
> + mpstream_encode_uint(&stream,
> + def->fields[i].affinity);
> + mpstream_encode_str(&stream, "is_nullable",
> + strlen("is_nullable"));
> + mpstream_encode_bool(&stream,
> + def->fields[i].is_nullable);
> + mpstream_encode_str(&stream, "nullable_action",
> + strlen("nullable_action"));
> assert(def->fields[i].nullable_action < on_conflict_action_MAX);
> const char *action =
> on_conflict_action_strs[def->fields[i].nullable_action];
> - p = enc->encode_str(p, action, strlen(action));
> + mpstream_encode_str(&stream, action, strlen(action));
> if (cid != COLL_NONE) {
> - p = enc->encode_str(p, "collation", strlen("collation"));
> - p = enc->encode_uint(p, cid);
> + mpstream_encode_str(&stream, "collation",
> + strlen("collation"));
> + mpstream_encode_uint(&stream, cid);
> }
> if (default_str != NULL) {
> - p = enc->encode_str(p, "default", strlen("default"));
> - p = enc->encode_str(p, default_str, strlen(default_str));
> + mpstream_encode_str(&stream, "default",
> + strlen("default"));
> + mpstream_encode_str(&stream, default_str,
> + strlen(default_str));
> }
> }
> - return (int)(p - base);
> + mpstream_flush(&stream);
> + if (is_error)
> + return NULL;
2. Neither region_alloc_cb nor reserve_cb set diagnostics, so
here you return NULL, but have an empty diag.
> + size_t sz = region_used(region) - used;
> + char *raw = region_join(region, sz);
> + if (raw == NULL)
> + diag_set(OutOfMemory, sz, "region_join", "raw");
> + else
> + *size = sz;
> + return raw;
> }
>
> diff --git a/src/box/sql/build.c b/src/box/sql/build.c
> index dddeb12..462b6e6 100644
> --- a/src/box/sql/build.c
> +++ b/src/box/sql/build.c
> @@ -1603,33 +1614,53 @@ vdbe_emit_fkey_create(struct Parse *parse_context, const struct fkey_def *fk)
> fkey_action_strs[fk->on_delete], P4_STATIC);
> sqlite3VdbeAddOp4(vdbe, OP_String8, 0, constr_tuple_reg + 6, 0,
> fkey_action_strs[fk->on_update], P4_STATIC);
> - size_t parent_size = fkey_encode_links(fk, FIELD_LINK_PARENT, NULL);
> - size_t child_size = fkey_encode_links(fk, FIELD_LINK_CHILD, NULL);
> + struct region *region = &parse_context->region;
> + uint32_t parent_links_size = 0;
> + char *parent_links =
> + fkey_encode_links(region, fk, FIELD_LINK_PARENT,
> + &parent_links_size);
> + if (parent_links == NULL)
> + goto error;
> + uint32_t child_links_size = 0;
> + char *child_links =
> + fkey_encode_links(region, fk, FIELD_LINK_CHILD,
> + &child_links_size);
> + if (child_links == NULL)
> + goto error;
> /*
> * We are allocating memory for both parent and child
> * arrays in the same chunk. Thus, first OP_Blob opcode
> * interprets it as static memory, and the second one -
> * as dynamic and releases memory.
> */
> - char *parent_links = sqlite3DbMallocRaw(parse_context->db,
> - parent_size + child_size);
> - if (parent_links == NULL) {
> - sqlite3DbFree(parse_context->db, (void *) name_copy);
> + char *raw = sqlite3DbMallocRaw(parse_context->db,
> + parent_links_size + child_links_size);
> + if (raw == NULL) {
> + sqlite3DbFree(parse_context->db, name_copy);
3. You shall not free name copy here. It is added to Vdbe in the
first lines of the function as P4_DYNAMIC and will be freed on
Vdbe destruction.
> return;
> }
4. I have pushed my fixes on the branch. Please, look,
squash, and fix other things.
My diff is below:
===============================================================
commit 19fb0e03bf99a74e41349af4553299899f32deeb
Author: Vladislav Shpilevoy <v.shpilevoy at tarantool.org>
Date: Fri Aug 24 16:59:22 2018 +0300
Review fixes
diff --git a/src/box/sql.c b/src/box/sql.c
index 28ad9d37f..790c0529a 100644
--- a/src/box/sql.c
+++ b/src/box/sql.c
@@ -1220,11 +1220,11 @@ static const char *convertSqliteAffinity(int affinity, bool allow_nulls)
}
}
+/** Callback to forward and error from mpstream methods. */
static void
set_encode_error(void *error_ctx)
{
- bool *is_error = error_ctx;
- *is_error = true;
+ *(bool *)error_ctx = true;
}
char *
@@ -1273,18 +1273,14 @@ sql_encode_table(struct region *region, struct Table *table, uint32_t *size)
convertSqliteAffinity(affinity,
def->fields[i].is_nullable);
}
-
assert(def->fields[i].is_nullable ==
- action_is_nullable(def->fields[i].
- nullable_action));
+ action_is_nullable(def->fields[i].nullable_action));
mpstream_encode_str(&stream, t, strlen(t));
mpstream_encode_str(&stream, "affinity", strlen("affinity"));
- mpstream_encode_uint(&stream,
- def->fields[i].affinity);
+ mpstream_encode_uint(&stream, def->fields[i].affinity);
mpstream_encode_str(&stream, "is_nullable",
strlen("is_nullable"));
- mpstream_encode_bool(&stream,
- def->fields[i].is_nullable);
+ mpstream_encode_bool(&stream, def->fields[i].is_nullable);
mpstream_encode_str(&stream, "nullable_action",
strlen("nullable_action"));
assert(def->fields[i].nullable_action < on_conflict_action_MAX);
@@ -1306,12 +1302,10 @@ sql_encode_table(struct region *region, struct Table *table, uint32_t *size)
mpstream_flush(&stream);
if (is_error)
return NULL;
- size_t sz = region_used(region) - used;
- char *raw = region_join(region, sz);
+ *size = region_used(region) - used;
+ char *raw = region_join(region, *size);
if (raw == NULL)
- diag_set(OutOfMemory, sz, "region_join", "raw");
- else
- *size = sz;
+ diag_set(OutOfMemory, *size, "region_join", "raw");
return raw;
}
@@ -1326,12 +1320,16 @@ sql_encode_table_opts(struct region *region, struct Table *table,
mpstream_init(&stream, region, region_reserve_cb, region_alloc_cb,
set_encode_error, &is_error);
bool is_view = false;
- bool has_checks = false;
+ int checks_cnt = 0;
+ struct ExprList_item *a;
if (table != NULL) {
is_view = table->def->opts.is_view;
- has_checks = table->def->opts.checks != NULL;
+ struct ExprList *checks = table->def->opts.checks;
+ if (checks != NULL) {
+ checks_cnt = checks->nExpr;
+ a = checks->a;
+ }
}
- uint32_t checks_cnt = has_checks ? table->def->opts.checks->nExpr : 0;
mpstream_encode_map(&stream, 1 + is_view + (checks_cnt > 0));
mpstream_encode_str(&stream, "sql", strlen("sql"));
@@ -1340,39 +1338,32 @@ sql_encode_table_opts(struct region *region, struct Table *table,
mpstream_encode_str(&stream, "view", strlen("view"));
mpstream_encode_bool(&stream, true);
}
- if (checks_cnt == 0)
- goto finish;
-
- /* Encode checks. */
- struct ExprList_item *a = table->def->opts.checks->a;
- mpstream_encode_str(&stream, "checks", strlen("checks"));
- mpstream_encode_array(&stream, checks_cnt);
- for (uint32_t i = 0; i < checks_cnt && !is_error; ++i) {
- int items = (a[i].pExpr != NULL) + (a[i].zName != NULL);
+ if (checks_cnt > 0) {
+ mpstream_encode_str(&stream, "checks", strlen("checks"));
+ mpstream_encode_array(&stream, checks_cnt);
+ }
+ for (int i = 0; i < checks_cnt && !is_error; ++i, ++a) {
+ int items = (a->pExpr != NULL) + (a->zName != NULL);
mpstream_encode_map(&stream, items);
- assert(a[i].pExpr != NULL);
- struct Expr *pExpr = a[i].pExpr;
+ assert(a->pExpr != NULL);
+ struct Expr *pExpr = a->pExpr;
assert(pExpr->u.zToken != NULL);
mpstream_encode_str(&stream, "expr", strlen("expr"));
mpstream_encode_str(&stream, pExpr->u.zToken,
strlen(pExpr->u.zToken));
- if (a[i].zName != NULL) {
+ if (a->zName != NULL) {
mpstream_encode_str(&stream, "name", strlen("name"));
- mpstream_encode_str(&stream, a[i].zName,
- strlen(a[i].zName));
+ mpstream_encode_str(&stream, a->zName,
+ strlen(a->zName));
}
}
-
-finish:
mpstream_flush(&stream);
if (is_error)
return NULL;
- size_t sz = region_used(region) - used;
- char *raw = region_join(region, sz);
+ *size = region_used(region) - used;
+ char *raw = region_join(region, *size);
if (raw == NULL)
- diag_set(OutOfMemory, sz, "region_join", "raw");
- else
- *size = sz;
+ diag_set(OutOfMemory, *size, "region_join", "raw");
return raw;
}
@@ -1392,18 +1383,16 @@ fkey_encode_links(struct region *region, const struct fkey_def *def, int type,
mpstream_flush(&stream);
if (is_error)
return NULL;
- size_t sz = region_used(region) - used;
- char *raw = region_join(region, sz);
+ *size = region_used(region) - used;
+ char *raw = region_join(region, *size);
if (raw == NULL)
- diag_set(OutOfMemory, sz, "region_join", "raw");
- else
- *size = sz;
+ diag_set(OutOfMemory, *size, "region_join", "raw");
return raw;
}
char *
sql_encode_index_parts(struct region *region, struct SqliteIndex *index,
- uint32_t *size)
+ uint32_t *size)
{
size_t used = region_used(region);
struct mpstream stream;
@@ -1415,13 +1404,12 @@ sql_encode_index_parts(struct region *region, struct SqliteIndex *index,
* treat it as strict type, not affinity.
*/
uint32_t pk_forced_int = UINT32_MAX;
- struct SqliteIndex *primary_index =
- sqlite3PrimaryKeyIndex(index->pTable);
+ struct SqliteIndex *pk = sqlite3PrimaryKeyIndex(index->pTable);
struct field_def *fields = index->pTable->def->fields;
- if (primary_index->def->key_def->part_count == 1) {
- int pk = primary_index->def->key_def->parts[0].fieldno;
- if (fields[pk].type == FIELD_TYPE_INTEGER)
- pk_forced_int = pk;
+ if (pk->def->key_def->part_count == 1) {
+ int fieldno = pk->def->key_def->parts[0].fieldno;
+ if (fields[fieldno].type == FIELD_TYPE_INTEGER)
+ pk_forced_int = fieldno;
}
/* gh-2187
@@ -1431,10 +1419,9 @@ sql_encode_index_parts(struct region *region, struct SqliteIndex *index,
* data layout.
*/
struct key_def *key_def = index->def->key_def;
- uint32_t part_count = key_def->part_count;
struct key_part *part = key_def->parts;
- mpstream_encode_array(&stream, part_count);
- for (uint32_t i = 0; i < part_count; ++i, ++part) {
+ mpstream_encode_array(&stream, key_def->part_count);
+ for (uint32_t i = 0; i < key_def->part_count; ++i, ++part) {
uint32_t col = part->fieldno;
assert(fields[col].is_nullable ==
action_is_nullable(fields[col].nullable_action));
@@ -1459,8 +1446,7 @@ sql_encode_index_parts(struct region *region, struct SqliteIndex *index,
}
mpstream_encode_str(&stream, "is_nullable",
strlen("is_nullable"));
- mpstream_encode_bool(&stream,
- fields[col].is_nullable);
+ mpstream_encode_bool(&stream, fields[col].is_nullable);
mpstream_encode_str(&stream, "nullable_action",
strlen("nullable_action"));
const char *action_str =
@@ -1478,12 +1464,10 @@ sql_encode_index_parts(struct region *region, struct SqliteIndex *index,
mpstream_flush(&stream);
if (is_error)
return NULL;
- size_t sz = region_used(region) - used;
- char *raw = region_join(region, sz);
+ *size = region_used(region) - used;
+ char *raw = region_join(region, *size);
if (raw == NULL)
- diag_set(OutOfMemory, sz, "region_join", "raw");
- else
- *size = sz;
+ diag_set(OutOfMemory, *size, "region_join", "raw");
return raw;
}
@@ -1514,12 +1498,10 @@ sql_encode_index_opts(struct region *region, struct SqliteIndex *index,
mpstream_flush(&stream);
if (is_error)
return NULL;
- size_t sz = region_used(region) - used;
- char *raw = region_join(region, sz);
+ *size = region_used(region) - used;
+ char *raw = region_join(region, *size);
if (raw == NULL)
- diag_set(OutOfMemory, sz, "region_join", "raw");
- else
- *size = sz;
+ diag_set(OutOfMemory, *size, "region_join", "raw");
return raw;
}
diff --git a/src/box/sql/build.c b/src/box/sql/build.c
index 462b6e67b..ab1438db4 100644
--- a/src/box/sql/build.c
+++ b/src/box/sql/build.c
@@ -1371,9 +1371,8 @@ createSpace(Parse * pParse, int iSpaceId, char *zStmt)
int iRecord = (pParse->nMem += 7);
struct region *region = &pParse->region;
uint32_t table_opts_stmt_sz = 0;
- char *table_opts_stmt =
- sql_encode_table_opts(region, table, zStmt,
- &table_opts_stmt_sz);
+ char *table_opts_stmt = sql_encode_table_opts(region, table, zStmt,
+ &table_opts_stmt_sz);
if (table_opts_stmt == NULL)
goto error;
uint32_t table_stmt_sz = 0;
@@ -1602,10 +1601,8 @@ vdbe_emit_fkey_create(struct Parse *parse_context, const struct fkey_def *fk)
BOX_FK_CONSTRAINT_ID, 0,
constr_tuple_reg, 2,
ER_CONSTRAINT_EXISTS, error_msg,
- false, OP_NoConflict) != 0) {
- sqlite3DbFree(parse_context->db, name_copy);
+ false, OP_NoConflict) != 0)
return;
- }
sqlite3VdbeAddOp2(vdbe, OP_Bool, 0, constr_tuple_reg + 3);
sqlite3VdbeChangeP4(vdbe, -1, (char*)&fk->is_deferred, P4_BOOL);
sqlite3VdbeAddOp4(vdbe, OP_String8, 0, constr_tuple_reg + 4, 0,
@@ -1616,15 +1613,13 @@ vdbe_emit_fkey_create(struct Parse *parse_context, const struct fkey_def *fk)
fkey_action_strs[fk->on_update], P4_STATIC);
struct region *region = &parse_context->region;
uint32_t parent_links_size = 0;
- char *parent_links =
- fkey_encode_links(region, fk, FIELD_LINK_PARENT,
- &parent_links_size);
+ char *parent_links = fkey_encode_links(region, fk, FIELD_LINK_PARENT,
+ &parent_links_size);
if (parent_links == NULL)
goto error;
uint32_t child_links_size = 0;
- char *child_links =
- fkey_encode_links(region, fk, FIELD_LINK_CHILD,
- &child_links_size);
+ char *child_links = fkey_encode_links(region, fk, FIELD_LINK_CHILD,
+ &child_links_size);
if (child_links == NULL)
goto error;
/*
@@ -1635,10 +1630,8 @@ vdbe_emit_fkey_create(struct Parse *parse_context, const struct fkey_def *fk)
*/
char *raw = sqlite3DbMallocRaw(parse_context->db,
parent_links_size + child_links_size);
- if (raw == NULL) {
- sqlite3DbFree(parse_context->db, name_copy);
+ if (raw == NULL)
return;
- }
memcpy(raw, parent_links, parent_links_size);
parent_links = raw;
raw += parent_links_size;
@@ -1660,7 +1653,6 @@ vdbe_emit_fkey_create(struct Parse *parse_context, const struct fkey_def *fk)
error:
parse_context->nErr++;
parse_context->rc = SQL_TARANTOOL_ERROR;
- sqlite3DbFree(parse_context->db, name_copy);
}
/**
diff --git a/src/box/sql/tarantoolInt.h b/src/box/sql/tarantoolInt.h
index 6a42ed3c6..78790a2bb 100644
--- a/src/box/sql/tarantoolInt.h
+++ b/src/box/sql/tarantoolInt.h
@@ -139,25 +139,25 @@ tarantoolSqlite3IncrementMaxid(uint64_t *space_max_id);
/**
* Encode format as entry to be inserted to _space on @region.
+ * @param region Region to use.
+ * @param table Table to encode.
+ * @param[out] size Size of result allocation.
*
- * @param region region to use.
- * @param table table to encode.
- * @param[out] size size of result allocation.
- * @retval NULL on error.
- * @retval not NULL pointer to msgpack on success.
+ * @retval NULL Error.
+ * @retval not NULL Pointer to msgpack on success.
*/
char *
sql_encode_table(struct region *region, struct Table *table, uint32_t *size);
/**
* Encode "opts" dictionary for _space entry on @region.
+ * @param region Region to use.
+ * @param table Table containing opts to encode.
+ * @param sql Source request to encode.
+ * @param[out] size Size of result allocation.
*
- * @param region region to use.
- * @param table table containing opts to encode.
- * @param sql source request to encode.
- * @param[out] size size of result allocation.
- * @retval NULL on error.
- * @retval not NULL pointer to msgpack on success
+ * @retval NULL Error.
+ * @retval not NULL Pointer to msgpack on success.
*/
char *
sql_encode_table_opts(struct region *region, struct Table *table,
@@ -166,13 +166,13 @@ sql_encode_table_opts(struct region *region, struct Table *table,
/**
* Encode links of given foreign key constraint into MsgPack on
* @region.
- *
- * @param region region to use.
+ * @param region Wegion to use.
* @param def FK def to encode links of.
* @param type Links type to encode.
- * @param[out] size size of result allocation.
- * @retval NULL on error.
- * @retval not NULL pointer to msgpack on success
+ * @param[out] Size size of result allocation.
+ *
+ * @retval NULL Error.
+ * @retval not NULL Pointer to msgpack on success.
*/
char *
fkey_encode_links(struct region *region, const struct fkey_def *def, int type,
@@ -181,12 +181,12 @@ fkey_encode_links(struct region *region, const struct fkey_def *def, int type,
/**
* Encode index parts of given foreign key constraint into
* MsgPack on @region.
+ * @param region Region to use.
+ * @param index Index to encode.
+ * @param[out] size Size of result allocation.
*
- * @param region region to use.
- * @param index index to encode.
- * @param[out] size size of result allocation.
- * @retval NULL on error.
- * @retval not NULL pointer to msgpack on success
+ * @retval NULL Error.
+ * @retval not NULL Pointer to msgpack on success
*/
char *
sql_encode_index_parts(struct region *region, struct Index *index,
diff --git a/src/box/sql/trigger.c b/src/box/sql/trigger.c
index 6a0708107..f400c2551 100644
--- a/src/box/sql/trigger.c
+++ b/src/box/sql/trigger.c
@@ -173,16 +173,12 @@ sql_trigger_finish(struct Parse *parse, struct TriggerStep *step_list,
{
/* Trigger being finished. */
struct sql_trigger *trigger = parse->parsed_ast.trigger;
- /* 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;
+ goto cleanup;
char *trigger_name = trigger->zName;
trigger->step_list = step_list;
while (step_list != NULL) {
@@ -202,17 +198,18 @@ sql_trigger_finish(struct Parse *parse, struct TriggerStep *step_list,
/* Make an entry in the _trigger space. */
struct Vdbe *v = sqlite3GetVdbe(parse);
if (v == 0)
- goto triggerfinish_cleanup;
+ goto cleanup;
struct Table *sys_trigger =
- sqlite3HashFind(&parse->db->pSchema->tblHash,
+ sqlite3HashFind(&db->pSchema->tblHash,
TARANTOOL_SYS_TRIGGER_NAME);
if (NEVER(sys_trigger == NULL))
- goto triggerfinish_cleanup;
+ goto cleanup;
- sql_str = sqlite3MPrintf(db, "CREATE TRIGGER %s", token->z);
- if (db->mallocFailed)
- goto triggerfinish_cleanup;
+ char *sql_str =
+ sqlite3MPrintf(db, "CREATE TRIGGER %s", token->z);
+ if (sql_str == NULL)
+ goto cleanup;
int cursor = parse->nTab++;
sqlite3OpenTable(parse, cursor, sys_trigger, OP_OpenWrite);
@@ -228,23 +225,24 @@ sql_trigger_finish(struct Parse *parse, struct TriggerStep *step_list,
uint32_t opts_buff_sz = 0;
char *data = sql_encode_table_opts(&fiber()->gc, NULL, sql_str,
&opts_buff_sz);
- if (data != NULL) {
- opts_buff = sqlite3DbMallocRaw(parse->db, opts_buff_sz);
- if (opts_buff != NULL)
- memcpy(opts_buff, data, opts_buff_sz);
- } else {
+ sqlite3DbFree(db, sql_str);
+ if (data == NULL) {
parse->nErr++;
parse->rc = SQL_TARANTOOL_ERROR;
+ goto cleanup;
}
+ char *opts_buff = sqlite3DbMallocRaw(db, opts_buff_sz);
if (opts_buff == NULL)
- goto triggerfinish_cleanup;
+ goto cleanup;
+ memcpy(opts_buff, data, opts_buff_sz);
- trigger_name = sqlite3DbStrDup(parse->db, trigger_name);
- if (trigger_name == NULL)
- goto triggerfinish_cleanup;
+ trigger_name = sqlite3DbStrDup(db, trigger_name);
+ if (trigger_name == NULL) {
+ sqlite3DbFree(db, opts_buff);
+ goto cleanup;
+ }
- sqlite3VdbeAddOp4(v,
- OP_String8, 0, first_col, 0,
+ sqlite3VdbeAddOp4(v, OP_String8, 0, first_col, 0,
trigger_name, P4_DYNAMIC);
sqlite3VdbeAddOp2(v, OP_Integer, trigger->space_id,
first_col + 1);
@@ -263,11 +261,7 @@ sql_trigger_finish(struct Parse *parse, struct TriggerStep *step_list,
trigger = NULL;
}
- triggerfinish_cleanup:
- if (db->mallocFailed) {
- sqlite3DbFree(db, sql_str);
- sqlite3DbFree(db, opts_buff);
- }
+cleanup:
sql_trigger_delete(db, trigger);
assert(parse->parsed_ast.trigger == NULL || parse->parse_only);
sqlite3DeleteTriggerStep(db, step_list);
More information about the Tarantool-patches
mailing list