[tarantool-patches] [PATCH] sql: remove struct Table
i.koptelov
ivan.koptelov at tarantool.org
Wed Feb 6 20:17:34 MSK 2019
>> On 1 Feb 2019, at 14:05, Ivan Koptelov<ivan.koptelov at tarantool.org> wrote:
>>
>> Thank you for the review! Sorry for all these code style errors.
>> I consider review changes minor, so I put diff b/w first and
>> second version of patch at the end of the letter.
>> (second commit on the branch 'review fixes' would be squashed)
> Don’t do it next time, pls. Instead, inline fixes as an answers to comments,
> especially when it comes for huge diff ( 209 insertions(+), 259 deletions(-))
> Otherwise, it takes a while to track fixed chunks of code in a whole diff.
Sorry for this. All review fixes below is inlined.
>>>> Completely removes struct Table. Also the
>>>> patch simplifies memory management as in
>>>> many cases struct space (which replaces
>>>> struct Table) is allocated on region
>>>> and shouldn't be explicitly freed.
>>> Feel free to use up to 72 chars in commit message body.
>>>
>>> sql: remove struct Table
>>>
>>> Completely removes struct Table. Also the patch simplifies memory
>>> management as in many cases struct space (which replaces struct Table)
>>> is allocated on region and shouldn't be explicitly freed.
>>>
>>> Note that after commit subject's prefix we use lower-case.
>>>
>> Fixed.
>>> Also, for some reason content of this letter looks very strange:
>>> at least it contains unusual fonts… I am not complaining but
>>> are you sure that you set up git-email correctly?
>>>
> It still looks weird. Please, verify that text you send is plain.
>
>>>> +
>>>> #if SQLITE_MAX_COLUMN
>>>> - if ((int)p->def->field_count + 1 > db->aLimit[SQLITE_LIMIT_COLUMN]) {
>>>> + if ((int)space->def->field_count + 1 > db->aLimit[SQLITE_LIMIT_COLUMN]) {
>>>> sqlite3ErrorMsg(pParse, "too many columns on %s",
>>>> - p->def->name);
>>>> + space->def->name);
>>>> return;
>>>> }
>>>> #endif
>>>> - /*
>>>> + /**
> One more nit: we start comments from single star if they appear inside functions.
Fixed:
@@ -471,7 +445,7 @@ sqlite3AddColumn(Parse * pParse, Token * pName, struct type_def *type_def)
return;
}
#endif
- /**
+ /*
* As sql_field_retrieve will allocate memory on region
* ensure that p->space->def is also temporal and would be
* dropped.
>>>> @@ -435,7 +428,7 @@ sql_table_delete_from(struct Parse *parse, struct SrcList *tab_list,
>>>> }
>>>> void
>>>> -sql_generate_row_delete(struct Parse *parse, struct Table *table,
>>>> +sql_generate_row_delete(struct Parse *parse, struct space *space,
>>>> struct sql_trigger *trigger_list, int cursor,
>>>> int reg_pk, short npk, bool need_update_count,
>>>> enum on_conflict_action onconf, u8 mode,
>>>> @@ -464,31 +457,31 @@ sql_generate_row_delete(struct Parse *parse, struct Table *table,
>>>> /* If there are any triggers to fire, allocate a range of registers to
>>>> * use for the old.* references in the triggers.
>>>> */
>>>> - if (table != NULL &&
>>>> - (fkey_is_required(table->def->id, NULL) || trigger_list != NULL)) {
>>>> + if (space != NULL &&
>>>> + (fkey_is_required(space->def->id, NULL) ||
>>>> + trigger_list != NULL)) {
>>>>
>>> Broken indentation.
>> Fixed now.
> diff --git a/src/box/sql/delete.c b/src/box/sql/delete.c
> index e8354f7e4..1dbf244cc 100644
> --- a/src/box/sql/delete.c
> +++ b/src/box/sql/delete.c
> @@ -458,8 +458,7 @@ sql_generate_row_delete(struct Parse *parse, struct space *space,
> * use for the old.* references in the triggers.
> */
> if (space != NULL &&
> - (fkey_is_required(space->def->id, NULL) ||
> - trigger_list != NULL)) {
> + (fkey_is_required(space->def->id, NULL) || trigger_list != NULL)) {
> /* Mask of OLD.* columns in use */
> /* TODO: Could use temporary registers here. */
> uint32_t mask =
Sorry.
diff --git a/src/box/sql/delete.c b/src/box/sql/delete.c
index e8354f7e4..143803f9d 100644
--- a/src/box/sql/delete.c
+++ b/src/box/sql/delete.c
@@ -458,8 +458,7 @@ sql_generate_row_delete(struct Parse *parse, struct space *space,
* use for the old.* references in the triggers.
*/
if (space != NULL &&
- (fkey_is_required(space->def->id, NULL) ||
- trigger_list != NULL)) {
+ (fkey_is_required(space, NULL) || trigger_list != NULL)) {
>>>> +/**
>>>> * Add type and collation information to a column list based on
>>>> * a SELECT statement.
>>>> *
>>>> - * The column list presumably came from selectColumnNamesFromExprList().
>>>> - * The column list has only names, not types or collations. This
>>>> - * routine goes through and adds the types and collations.
>>>> + * The column list presumably came from
>>>> + * selectColumnNamesFromExprList(). The column list has only
>>>> + * names, not types or collations. This routine goes through
>>>> + * and adds the types and collations.
>>>>
>>> Why did you change this comment?
>> Because the length of it's lines exceeded 65 chars.
> But this fix is not related to patch: it doesn’t even contain words like ’table’.
Ok, let's keep things to the point. Reverted changes.
>>>> @@ -2000,23 +2006,20 @@ sqlite3ResultSetOfSelect(Parse * pParse, Select * pSelect)
>>>> while (pSelect->pPrior)
>>>> pSelect = pSelect->pPrior;
>>>> user_session->sql_flags = savedFlags;
>>>> - Table *table = sql_ephemeral_table_new(pParse, NULL);
>>>> - if (table == NULL)
>>>> + struct space *space = sql_ephemeral_space_new(pParse, NULL);
>>>> +
>>>> + if (space == NULL)
>>>> return 0;
>>>> - /* The sqlite3ResultSetOfSelect() is only used n contexts where lookaside
>>>> + /* The sqlite3ResultSetOfSelect() is only used in contexts where lookaside
>>>> * is disabled
>>>>
>>> Extra diff.
>> Empty line is removed.
> I mean not (only) empty line, but fix of the comment. Nevermind.
>
>>>> */
>>>> assert(db->lookaside.bDisable);
>>>> - table->nTabRef = 1;
>>>> - table->tuple_log_count = DEFAULT_TUPLE_LOG_COUNT;
>>>> - assert(sqlite3LogEst(DEFAULT_TUPLE_COUNT) == DEFAULT_TUPLE_LOG_COUNT);
>>>> - sqlite3ColumnsFromExprList(pParse, pSelect->pEList, table);
>>>> - sqlite3SelectAddColumnTypeAndCollation(pParse, table, pSelect);
>>>> + sqlite3ColumnsFromExprList(pParse, pSelect->pEList, space->def);
>>>> + sqlite3SelectAddColumnTypeAndCollation(pParse, space, pSelect);
>>>> if (db->mallocFailed) {
>>>> - sqlite3DeleteTable(db, table);
>>>> return 0;
> return NULL;
diff --git a/src/box/sql/select.c b/src/box/sql/select.c
index 79b8eafca..b30aa6200 100644
@@ -1998,13 +1993,13 @@ sqlite3ResultSetOfSelect(Parse * pParse, Select * pSelect)
user_session->sql_flags &= SQLITE_ShortColNames;
sqlite3SelectPrep(pParse, pSelect, 0);
if (pParse->nErr)
- return 0;
+ return NULL;
while (pSelect->pPrior)
pSelect = pSelect->pPrior;
user_session->sql_flags = savedFlags;
struct space *space = sql_ephemeral_space_new(pParse, NULL);
if (space == NULL)
- return 0;
+ return NULL;
/* The sqlite3ResultSetOfSelect() is only used in contexts where lookaside
* is disabled
*/
@@ -2012,7 +2007,7 @@ sqlite3ResultSetOfSelect(Parse * pParse, Select * pSelect)
sqlite3ColumnsFromExprList(pParse, pSelect->pEList, space->def);
sqlite3SelectAddColumnTypeAndCollation(pParse, space->def, pSelect);
if (db->mallocFailed)
- return 0;
+ return NULL;
return space;
}
>
>>>> /**
>>>> * Generate code for a DELETE FROM statement.
>>>> @@ -3603,10 +3581,11 @@ int sqlite3WhereOkOnePass(WhereInfo *, int *);
>>>> /**
>>>> * Generate code that will extract the iColumn-th column from
>>>> - * table pTab and store the column value in a register.
>>>> + * table defined by space_def and store the column value in a
>>>> + * register.
>>>> *
>>>> * An effort is made to store the column value in register iReg.
>>>> - * This is not garanteeed for GetColumn() - the result can be
>>>> + * This is not guaranteed for GetColumn() - the result can be
>>>>
>>> Extra diff.
>> This diff fixes typo 'garanteeed' -> ‘guaranteed'
> It is not related to patch. Instead, it enlarges diff to be reviewed.
Ok, changes reverted.
> As for space_by_id() clean-up: you can make key_is_required() accept
> struct space instead of space_id. You can remove space_checks_expr_list()
> function.
Ok, done.
diff --git a/src/box/sql.h b/src/box/sql.h
index d0b654e9c..e7b3933b9 100644
--- a/src/box/sql.h
+++ b/src/box/sql.h
@@ -172,14 +172,6 @@ sql_expr_extract_select(struct Parse *parser, struct Select *select);
struct Expr*
space_column_default_expr(uint32_t space_id, uint32_t fieldno);
-/**
- * Get server checks list by space_id.
- * @param space_id Space ID.
- * @retval Checks list.
- */
-struct ExprList *
-space_checks_expr_list(uint32_t space_id);
-
/**
* Return the number of bytes required to create a duplicate of the
* expression passed as the first argument. The second argument is a
diff --git a/src/box/sql/build.c b/src/box/sql/build.c
index 599ece6d5..4b055529c 100644
--- a/src/box/sql/build.c
+++ b/src/box/sql/build.c
@@ -789,16 +763,6 @@ sql_column_collation(struct space_def *def, uint32_t column, uint32_t *coll_id)
return field->coll;
}
-struct ExprList *
-space_checks_expr_list(uint32_t space_id)
-{
- struct space *space;
- space = space_by_id(space_id);
- assert(space != NULL);
- assert(space->def != NULL);
- return space->def->opts.checks;
-}
-
int
vdbe_emit_open_cursor(struct Parse *parse_context, int cursor, int index_id,
struct space *space)
diff --git a/src/box/sql/delete.c b/src/box/sql/delete.c
index e8354f7e4..143803f9d 100644
--- a/src/box/sql/delete.c
+++ b/src/box/sql/delete.c
@@ -149,7 +149,7 @@ sql_table_delete_from(struct Parse *parse, struct SrcList *tab_list,
assert(space != NULL);
trigger_list = sql_triggers_exist(space->def, TK_DELETE, NULL, NULL);
bool is_complex = trigger_list != NULL ||
- fkey_is_required(space->def->id, NULL);
+ fkey_is_required(space, NULL);
bool is_view = space->def->opts.is_view;
/* If table is really a view, make sure it has been
@@ -458,8 +458,7 @@ sql_generate_row_delete(struct Parse *parse, struct space *space,
* use for the old.* references in the triggers.
*/
if (space != NULL &&
- (fkey_is_required(space->def->id, NULL) ||
- trigger_list != NULL)) {
+ (fkey_is_required(space, NULL) || trigger_list != NULL)) {
/* Mask of OLD.* columns in use */
/* TODO: Could use temporary registers here. */
uint32_t mask =
diff --git a/src/box/sql/fkey.c b/src/box/sql/fkey.c
index 61cfb6fd7..28b53e7fd 100644
--- a/src/box/sql/fkey.c
+++ b/src/box/sql/fkey.c
@@ -421,7 +421,7 @@ fkey_scan_children(struct Parse *parser, struct SrcList *src,
VdbeCoverage(v);
}
- struct space *child_space = space_by_id(fkey->child_id);
+ struct space *child_space = src->a[0].space;
assert(child_space != NULL);
/*
* Create an Expr object representing an SQL expression
@@ -672,9 +672,8 @@ fkey_emit_check(struct Parse *parser, struct space *space, int reg_old,
}
bool
-fkey_is_required(uint32_t space_id, const int *changes)
+fkey_is_required(struct space *space, const int *changes)
{
- struct space *space = space_by_id(space_id);
if (changes == NULL) {
/*
* A DELETE operation. FK processing is required
diff --git a/src/box/sql/insert.c b/src/box/sql/insert.c
index f28567dd1..6bd716767 100644
--- a/src/box/sql/insert.c
+++ b/src/box/sql/insert.c
@@ -929,7 +929,7 @@ vdbe_emit_constraint_checks(struct Parse *parse_context, struct space *space,
if (on_conflict == ON_CONFLICT_ACTION_DEFAULT)
on_conflict = ON_CONFLICT_ACTION_ABORT;
/* Test all CHECK constraints. */
- struct ExprList *checks = space_checks_expr_list(def->id);
+ struct ExprList *checks = def->opts.checks;
enum on_conflict_action on_conflict_check = on_conflict;
if (on_conflict == ON_CONFLICT_ACTION_REPLACE)
on_conflict_check = ON_CONFLICT_ACTION_ABORT;
@@ -1244,8 +1244,8 @@ xferOptimization(Parse * pParse, /* Parser context */
return 0;
}
/* Get server checks. */
- ExprList *pCheck_src = space_checks_expr_list(src->def->id);
- ExprList *pCheck_dest = space_checks_expr_list(dest->def->id);
+ ExprList *pCheck_src = src->def->opts.checks;
+ ExprList *pCheck_dest = dest->def->opts.checks;
if (pCheck_dest != NULL &&
sqlite3ExprListCompare(pCheck_src, pCheck_dest, -1) != 0) {
/* Tables have different CHECK constraints. Ticket #2252 */
diff --git a/src/box/sql/sqliteInt.h b/src/box/sql/sqliteInt.h
index c9ec9b1ca..c4fdccec0 100644
--- a/src/box/sql/sqliteInt.h
+++ b/src/box/sql/sqliteInt.h
@@ -4750,12 +4743,12 @@ fkey_emit_actions(struct Parse *parser, struct space *space, int reg_old,
* changes[] array is set to -1. If the column is modified,
* the value is 0 or greater.
*
- * @param space_id Id of space to be modified.
+ * @param space Space to be modified.
* @param changes Array of modified fields for UPDATE.
* @retval True, if any foreign key processing will be required.
*/
bool
-fkey_is_required(uint32_t space_id, const int *changes);
+fkey_is_required(struct space *space, const int *changes);
diff --git a/src/box/sql/update.c b/src/box/sql/update.c
index f7b7dc10d..a7affa954 100644
--- a/src/box/sql/update.c
+++ b/src/box/sql/update.c
@@ -201,7 +201,7 @@ sqlite3Update(Parse * pParse, /* The parser context */
*/
pTabList->a[0].colUsed = 0;
- hasFK = fkey_is_required(space->def->id, aXRef);
+ hasFK = fkey_is_required(space, aXRef);
/* Begin generating code. */
v = sqlite3GetVdbe(pParse);
> Also this fix removes one space_by_id usage:
>
> diff --git a/src/box/sql/fkey.c b/src/box/sql/fkey.c
> index 61cfb6fd7..238ab7891 100644
> --- a/src/box/sql/fkey.c
> +++ b/src/box/sql/fkey.c
> @@ -421,7 +421,7 @@ fkey_scan_children(struct Parse *parser, struct SrcList *src,
> VdbeCoverage(v);
> }
> - struct space *child_space = space_by_id(fkey->child_id);
> + struct space *child_space = src->a[0].space;
Done.
>> diff --git a/src/box/
>> schema.cc b/src/box/schema.cc
>>
>> index 8625d92ea..2d12f01d0 100644
>> --- a/src/box/
>> schema.cc
>>
>> +++ b/src/box/
>> schema.cc
>>
>> @@ -193,8 +193,8 @@ space_cache_replace(struct space *old_space, struct space *new_space)
>> mh_strnptr_del(spaces_by_name, k, NULL);
>> }
>> /*
>> - * Insert @new_space into @spaces cache, replacing
>> - * @old_space if it's not NULL.
>> + * Insert @updated_space into @spaces cache,
>> + * replacing @old_space if it's not NULL.
>> */
>> const struct mh_i32ptr_node_t node_p = { space_id(new_space),
>> new_space };
>> @@ -209,7 +209,7 @@ space_cache_replace(struct space *old_space, struct space *new_space)
>> assert(old_space_by_id == old_space);
>> (void)old_space_by_id;
>> /*
>> - * Insert @new_space into @spaces_by_name cache.
>> + * Insert @updated_space into @spaces_by_name cache.
>> */
> Why these changes are here?
Sorry, they should not be there (auto-refactor error)
diff --git a/src/box/schema.cc b/src/box/schema.cc
index 2d12f01d0..8625d92ea 100644
--- a/src/box/schema.cc
+++ b/src/box/schema.cc
@@ -193,8 +193,8 @@ space_cache_replace(struct space *old_space, struct space *new_space)
mh_strnptr_del(spaces_by_name, k, NULL);
}
/*
- * Insert @updated_space into @spaces cache,
- * replacing @old_space if it's not NULL.
+ * Insert @new_space into @spaces cache, replacing
+ * @old_space if it's not NULL.
*/
const struct mh_i32ptr_node_t node_p = { space_id(new_space),
new_space };
@@ -209,7 +209,7 @@ space_cache_replace(struct space *old_space, struct space *new_space)
assert(old_space_by_id == old_space);
(void)old_space_by_id;
/*
- * Insert @updated_space into @spaces_by_name cache.
+ * Insert @new_space into @spaces_by_name cache.
*/
const char *name = space_name(new_space);
uint32_t name_len = strlen(name);
>> /**
>> diff --git a/src/box/sql/build.c b/src/box/sql/build.c
>> index cae0b3f6e..599ece6d5 100644
>> --- a/src/box/sql/build.c
>> +++ b/src/box/sql/build.c
>> @@ -247,7 +247,7 @@ sql_space_column_is_in_pk(struct space *space, uint32_t column)
>> void
>> sql_space_delete(struct sqlite3 *db, struct space *space)
>> {
>> - if (!space || !db || db->pnBytesFreed == 0)
>> + if (space != NULL || db != NULL|| db->pnBytesFreed == 0)
>> return;
>> if (space->def->opts.is_temporary) {
>> @@ -310,35 +310,13 @@ sqlite3CheckIdentifierName(Parse *pParse, char *zName)
>> }
>> struct index *
>> -sql_table_primary_key(const struct space *space)
>> +sql_space_primary_key(const struct space *space)
> It is used only in build.c, you can make this function static.
Done
@@ -309,7 +280,10 @@ sqlite3CheckIdentifierName(Parse *pParse, char *zName)
return SQLITE_OK;
}
-struct index *
+/**
+ * Return the PRIMARY KEY index of a table.
+ */
+static struct index *
sql_space_primary_key(const struct space *space)
{
if (space->index_count == 0 || space->index[0]->def->iid != 0)
@@ -3331,12 +3331,6 @@ void
sqlite3SelectAddColumnTypeAndCollation(Parse *, struct space_def *, Select *);
struct space *sqlite3ResultSetOfSelect(Parse *, Select *);
-/**
- * Return the PRIMARY KEY index of a table.
- */
-struct index *
-sql_space_primary_key(const struct space *space);
-
void sqlite3StartTable(Parse *, Token *, int);
void sqlite3AddColumn(Parse *, Token *, struct type_def *);
> The same is for sql_ephemeral_space_def_new() - lets make it static
> or even inline it (since it used only once). If the latter, then you can
> alloc space at once for space and def.
Done.
@@ -234,16 +226,6 @@ sql_expr_delete(struct sqlite3 *db, struct Expr *expr, bool extern_alloc);
struct space *
sql_ephemeral_space_new(struct Parse *parser, const char *name);
-/**
- * Create and initialize a new ephemeral space_def object.
- * @param parser SQL Parser object.
- * @param name Name of space to be created.
- * @retval NULL on memory allocation error, Parser state changed.
- * @retval not NULL on success.
- */
-struct space_def *
-sql_ephemeral_space_def_new(struct Parse *parser, const char *name);
-
/**
* Duplicate Expr list.
* The flags parameter contains a combination of the EXPRDUP_XXX
@@ -1233,7 +1233,14 @@ space_column_default_expr(uint32_t space_id, uint32_t fieldno)
return space->def->fields[fieldno].default_value_expr;
}
-struct space_def *
+/**
+ * Create and initialize a new ephemeral space_def object.
+ * @param parser SQL Parser object.
+ * @param name Name of space to be created.
+ * @retval NULL on memory allocation error, Parser state changed.
+ * @retval not NULL on success.
+ */
+static struct space_def *
sql_ephemeral_space_def_new(struct Parse *parser, const char *name)
{
struct space_def *def = NULL;
> void
> -sqlite3DeleteTable(sqlite3 * db, Table * pTable)
> +sql_space_delete(struct sqlite3 *db, struct space *space, bool is_list_del)
> {
> - /* Do not delete the table until the reference count reaches zero. */
> - if (!pTable)
> - return;
> - if (((!db || db->pnBytesFreed == 0) && (--pTable->nTabRef) > 0))
> + if (space != NULL || db != NULL || db->pnBytesFreed == 0)
> return;
>
> You refactored this if-clause in a wrong way.
>
> if (!db) <=> if (db == NULL)
> if (!space) <=> if (space == NULL)
>
> Fix it since it leads to numerous leaks.
Sorry, fixed.
> What is more, you don’t need to call this function in sqlite3SrcListDelete().
> We must free index defs only during table creation. In this case, they are
> stored in updated_space. Check out diff:
>
> diff --git a/src/box/sql/build.c b/src/box/sql/build.c
> index 599ece6d5..e6da4be97 100644
> --- a/src/box/sql/build.c
> +++ b/src/box/sql/build.c
> @@ -232,35 +232,6 @@ sql_space_column_is_in_pk(struct space *space, uint32_t column)
> return false;
> }
> -/**
> - * Remove the memory data structures associated with the given
> - * space. The only case when some parts of space must be
> - * deleted explicitly is when it comes from building
> - * routine (i.e. it was born during CREATE TABLE
> - * processing). In this case only index defs and check
> - * expressions are allocated using malloc; the rest - on region.
> - * This case is identified by 'is_temporary' flag == TRUE.
> - *
> - * @param db Database handler.
> - * @param space Space to be deleted.
> - */
> -void
> -sql_space_delete(struct sqlite3 *db, struct space *space)
> -{
> - if (space != NULL || db != NULL|| db->pnBytesFreed == 0)
> - return;
> -
> - if (space->def->opts.is_temporary) {
> - for (uint32_t i = 0; i < space->index_count; ++i)
> - index_def_delete(space->index[i]->def);
> - /**
> - * Do not delete space and space->def allocated
> - * on region.
> - */
> - sql_expr_list_delete(db, space->def->opts.checks);
> - }
> -}
> -
> /*
> * Given a token, return a string that consists of the text of that
> * token. Space to hold the returned string
> @@ -2813,7 +2784,17 @@ sqlite3SrcListDelete(sqlite3 * db, SrcList * pList)
> sqlite3DbFree(db, pItem->u1.zIndexedBy);
> if (pItem->fg.isTabFunc)
> sql_expr_list_delete(db, pItem->u1.pFuncArg);
> - sql_space_delete(db, pItem->space);
> + /*
> + * Space is either not temporary which means that
> + * it came from space cache; or space is temporary
> + * but has no indexes and check constraints.
> + * The latter proves that it is not the space
> + * which might come from CREATE TABLE routines.
> + */
> + assert(pItem->space == NULL ||
> + !pItem->space->def->opts.is_temporary ||
> + (pItem->space->index == NULL &&
> + pItem->space->def->opts.checks == NULL));
> sql_select_delete(db, pItem->pSelect);
> sql_expr_delete(db, pItem->pOn, false);
> sqlite3IdListDelete(db, pItem->pUsing);
> diff --git a/src/box/sql/sqliteInt.h b/src/box/sql/sqliteInt.h
> index c9ec9b1ca..83b78507a 100644
> --- a/src/box/sql/sqliteInt.h
> +++ b/src/box/sql/sqliteInt.h
> @@ -3453,7 +3453,6 @@ sql_store_select(struct Parse *parse_context, struct Select *select);
> void
> sql_drop_table(struct Parse *, struct SrcList *, bool, bool);
> -void sql_space_delete(sqlite3 *, struct space *);
> void sqlite3Insert(Parse *, SrcList *, Select *, IdList *,
> enum on_conflict_action);
> void *sqlite3ArrayAllocate(sqlite3 *, void *, int, int *, int *);
> diff --git a/src/box/sql/tokenize.c b/src/box/sql/tokenize.c
> index 3102c75bd..99f87f81c 100644
> --- a/src/box/sql/tokenize.c
> +++ b/src/box/sql/tokenize.c
> @@ -416,6 +416,27 @@ sql_token(const char *z, int *type, bool *is_reserved)
> return i;
> }
> +/**
> + * This function is called to release parsing artifacts
> + * during table creation. The only objects allocated using
> + * malloc are index defs and check constraints.
> + * Note that this functions can't be called on ordinary
> + * space object. It is purpose to clean-up parser->updated_space.
> + *
> + * @param db Database handler.
> + * @param space Space to be deleted.
> + */
> +static void
> +parser_space_delete(struct sqlite3 *db, struct space *space)
> +{
> + if (space == NULL || db == NULL || db->pnBytesFreed == 0)
> + return;x
> + assert(space->def->opts.is_temporary);
> + for (uint32_t i = 0; i < space->index_count; ++i)
> + index_def_delete(space->index[i]->def);
> + sql_expr_list_delete(db, space->def->opts.checks);
> +}
> +
> /*
> * Run the parser on the given SQL string. The parser structure is
> * passed in. An SQLITE_ status code is returned. If an error occurs
> @@ -529,7 +550,7 @@ sqlite3RunParser(Parse * pParse, const char *zSql, char **pzErrMsg)
> sqlite3VdbeDelete(pParse->pVdbe);
> pParse->pVdbe = 0;
> }
> - sql_space_delete(db, pParse->updated_space);
> + parser_space_delete(db, pParse->updated_space);
>
> You can even try to move index defs and checks allocations
> to the region. In this case, we won’t have to free anything at all.
>
>
>
Done. The diff is identical to yours.
More information about the Tarantool-patches
mailing list