From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from localhost (localhost [127.0.0.1]) by turing.freelists.org (Avenir Technologies Mail Multiplex) with ESMTP id C79B829870 for ; Tue, 28 Aug 2018 20:58:20 -0400 (EDT) Received: from turing.freelists.org ([127.0.0.1]) by localhost (turing.freelists.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id pBeTsysZ1Ce8 for ; Tue, 28 Aug 2018 20:58:20 -0400 (EDT) Received: from smtp33.i.mail.ru (smtp33.i.mail.ru [94.100.177.93]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by turing.freelists.org (Avenir Technologies Mail Multiplex) with ESMTPS id 3D8852943D for ; Tue, 28 Aug 2018 20:58:20 -0400 (EDT) Subject: [tarantool-patches] Re: [PATCH 5/7] sql: remove lookups in Table hash References: <9de5ab38d451d8a024df8912e8d3ae086d5f6ab4.1535064700.git.korablev@tarantool.org> From: Vladislav Shpilevoy Message-ID: <1281b39a-fe5e-293f-6d26-16df4d3952e0@tarantool.org> Date: Tue, 28 Aug 2018 21:58:14 -0300 MIME-Version: 1.0 In-Reply-To: <9de5ab38d451d8a024df8912e8d3ae086d5f6ab4.1535064700.git.korablev@tarantool.org> Content-Type: text/plain; charset=utf-8; format=flowed Content-Language: en-US Content-Transfer-Encoding: 7bit Sender: tarantool-patches-bounce@freelists.org Errors-to: tarantool-patches-bounce@freelists.org Reply-To: tarantool-patches@freelists.org List-help: List-unsubscribe: List-software: Ecartis version 1.0.0 List-Id: tarantool-patches List-subscribe: List-owner: List-post: List-archive: To: tarantool-patches@freelists.org, Nikita Pettik Thanks for the patch! See 11 comments below and a commit on the branch. On 23/08/2018 19:55, Nikita Pettik wrote: > Instead of looking at Table hash lets extract space from Tarantool > internals and create Table wrapper around it. The major question - why do we still need struct Table? Just because of Table.nTabRef? This looks like an insignificant stopper since anyway we need refs for struct space and multiversion transactional DDL. We could create surrogate struct spaces for some temporary things instead of surrogate Tables. And do not create anything for ordinal spaces. > > Part of #3561 > --- > src/box/sql/build.c | 16 +--- > src/box/sql/delete.c | 84 ++++++++------------ > src/box/sql/expr.c | 2 +- > src/box/sql/fkey.c | 15 +++- > src/box/sql/insert.c | 48 ++++++----- > src/box/sql/pragma.c | 176 ++++++++++++++++++++++------------------- > src/box/sql/select.c | 41 +--------- > src/box/sql/sqliteInt.h | 35 +++++--- > src/box/sql/trigger.c | 10 +-- > src/box/sql/update.c | 10 +-- > test/sql-tap/analyze9.test.lua | 2 +- > test/sql-tap/join.test.lua | 6 +- > test/sql/delete.result | 4 +- > 13 files changed, 204 insertions(+), 245 deletions(-) > > diff --git a/src/box/sql/build.c b/src/box/sql/build.c > index 79dc46592..840604aa3 100644 > --- a/src/box/sql/build.c > +++ b/src/box/sql/build.c > @@ -217,22 +217,10 @@ sqlite3CommitInternalChanges() > current_session()->sql_flags &= ~SQLITE_InternChanges; > } > > -/* > - * Return true if given column is part of primary key. > - * If field number is less than 63, corresponding bit > - * in column mask is tested. Otherwise, check whether 64-th bit > - * in mask is set or not. If it is set, then iterate through > - * key parts of primary index and check field number. > - * In case it isn't set, there are no key columns among > - * the rest of fields. > - */ > bool > -table_column_is_in_pk(Table *table, uint32_t column) > +sql_space_column_is_in_pk(struct space *space, uint32_t column) > { > - struct space *space = space_by_id(table->def->id); > - assert(space != NULL); > - > - struct index *primary_idx = index_find(space, 0 /* PK */); > + struct index *primary_idx = space->index[0]; 1. space_index(space, 0). Also I see below check for idx == NULL. But if a space has no indexes, its space->index is NULL as well AFAIK. How does it work? The previous version was checking if a space has an index. > /* Views don't have any indexes. */ > if (primary_idx == NULL) > return false; > diff --git a/src/box/sql/delete.c b/src/box/sql/delete.c > index 0f285cc8b..a457a71d1 100644 > --- a/src/box/sql/delete.c > +++ b/src/box/sql/delete.c > @@ -36,16 +36,31 @@ > #include "tarantoolInt.h" > > struct Table * > -sql_list_lookup_table(struct Parse *parse, SrcList *src_list) > +sql_lookup_table(struct Parse *parse, struct SrcList_item *tbl_name) > { > - struct SrcList_item *item = src_list->a; > - assert(item != NULL && src_list->nSrc == 1); > - struct Table *table = sqlite3LocateTable(parse, 0, item->zName); > - sqlite3DeleteTable(parse->db, item->pTab); > - item->pTab = table; > - if (table != NULL) > - item->pTab->nTabRef++; > - if (sqlite3IndexedByLookup(parse, item) != 0) > + assert(tbl_name != NULL); > + uint32_t space_id = box_space_id_by_name(tbl_name->zName, > + strlen(tbl_name->zName)); > + sqlite3DeleteTable(parse->db, tbl_name->pTab); 2. What is happening here? If tbl_name->pTab != NULL, why do you recreate it? > + struct space *space = space_by_id(space_id); > + if (space_id == BOX_ID_NIL || space == NULL) { 3. If 'space_id' == BOX_ID_NIL then space == NULL as well, always. You should not even try to lookup a space when box_space_id_by_name returned BOX_ID_NIL. > + sqlite3ErrorMsg(parse, "no such table: %s", tbl_name->zName); 4. ER_NO_SUCH_SPACE. > + return NULL; > + } > + assert(space != NULL); > + if (space->def->field_count == 0) { > + sqlite3ErrorMsg(parse, "no format for space: %s", > + tbl_name->zName); 5. ER_UNSUPPORTED or a new error code. > + return NULL; > + } > + struct Table *table = sqlite3DbMallocZero(parse->db, sizeof(*table)); > + if (table == NULL) > + return NULL; > + table->def = space_def_dup(space->def); > + table->space = space; > + table->nTabRef = 1; > + tbl_name->pTab = table; > + if (sqlite3IndexedByLookup(parse, tbl_name) != 0) > table = NULL; 6. And here table leaks. > return table; > } > diff --git a/src/box/sql/expr.c b/src/box/sql/expr.c > index cb4f89e35..7b6300c75 100644 > --- a/src/box/sql/expr.c > +++ b/src/box/sql/expr.c > @@ -278,7 +278,7 @@ comparisonAffinity(Expr * pExpr) > aff = > sqlite3CompareAffinity(pExpr->x.pSelect->pEList->a[0].pExpr, > aff); > - } else if (NEVER(aff == 0)) { > + } else { > aff = AFFINITY_BLOB; > } > return aff; 7. Why? How is affinity linked with the patch? > diff --git a/src/box/sql/insert.c b/src/box/sql/insert.c > index 9220d34e1..d3950254e 100644 > --- a/src/box/sql/insert.c > +++ b/src/box/sql/insert.c > @@ -1234,40 +1233,40 @@ xferOptimization(Parse * pParse, /* Parser context */ > * we have to check the semantics. > */ > pItem = pSelect->pSrc->a; > - pSrc = sqlite3LocateTable(pParse, 0, pItem->zName); > + uint32_t src_id = box_space_id_by_name(pItem->zName, > + strlen(pItem->zName)); > /* FROM clause does not contain a real table. */ > - if (pSrc == NULL) > + if (src_id == BOX_ID_NIL) > return 0; > + struct space *src = space_by_id(src_id); > + assert(src != NULL); 8. In this function you do not need pDest as Table. It is enough to pass a space here. Only sqlite3OpenTable still uses struct Table in this function, but anyway in the first lines it does space lookup. I fixed this remark partially and dirty. Please, finish my fixes (refactor or remove sqlite3OpenTable etc). > diff --git a/src/box/sql/pragma.c b/src/box/sql/pragma.c > index 6173462ff..063836989 100644 > --- a/src/box/sql/pragma.c > +++ b/src/box/sql/pragma.c > @@ -245,6 +245,95 @@ sql_default_engine_set(const char *engine_name) > return 0; > } > > +/** > + * This function handles PRAGMA TABLE_INFO(). > + * > + * Return a single row for each column of the named table. > + * The columns of the returned data set are: > + * > + * - cid: Column id (numbered from left to right, starting at 0); > + * - name: Column name; > + * - type: Column declaration type; > + * - notnull: True if 'NOT NULL' is part of column declaration; > + * - dflt_value: The default value for the column, if any. > + * > + * @param parse Current parsing context. > + * @param tbl_name Name of table to be examined. > + */ > +static void > +sql_pragma_table_info(struct Parse *parse, const char *tbl_name) > +{ > + if (tbl_name == NULL) > + return; > + uint32_t space_id = box_space_id_by_name(tbl_name, strlen(tbl_name)); > + if (space_id == BOX_ID_NIL) > + return; > + struct space *space = space_by_id(space_id); > + assert(space != NULL); > + struct space_def *def = space->def; > + struct index *pk = space->index[0]; 9. space_index(). What is strange, you use space_index sometimes. > + parse->nMem = 6; > + if (def->opts.is_view) { > + const char *sql = def->opts.sql; > + sql_view_assign_cursors(parse, sql); > + } > + struct Vdbe *v = sqlite3GetVdbe(parse); > + for (uint32_t i = 0, k; i < def->field_count; ++i) { > + if (!sql_space_column_is_in_pk(space, i)) { > + k = 0; > + } else if (pk == NULL) { > + k = 1; > + } else { > + struct key_def *kdef = pk->def->key_def; > + k = key_def_find(kdef, i) - kdef->parts + 1; > + } > + bool is_nullable = def->fields[i].is_nullable; > + char *expr_str = def->fields[i].default_value; > + const char *name = def->fields[i].name; > + enum field_type type = def->fields[i].type; > + sqlite3VdbeMultiLoad(v, 1, "issisi", i, name, > + field_type_strs[type], !is_nullable, > + expr_str, k); > + sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 6); > + } > +} > diff --git a/src/box/sql/sqliteInt.h b/src/box/sql/sqliteInt.h > index 3ae8db1bc..08893c473 100644 > --- a/src/box/sql/sqliteInt.h > +++ b/src/box/sql/sqliteInt.h > @@ -3333,6 +3333,11 @@ void sqlite3ExprListSetSpan(Parse *, ExprList *, ExprSpan *); > u32 sqlite3ExprListFlags(const ExprList *); > int sqlite3Init(sqlite3 *); > > +void sqlite3Pragma(Parse *, Token *, Token *, Token *, int); > +void sqlite3ResetAllSchemasOfConnection(sqlite3 *); > +void sqlite3CommitInternalChanges(); > +void sqlite3DeleteColumnNames(sqlite3 *, Table *); 10. Why do you need these movements? > + > /** > * This is the callback routine for the code that initializes the > * database. See sqlite3Init() below for additional information. > diff --git a/test/sql-tap/analyze9.test.lua b/test/sql-tap/analyze9.test.lua > index 2b37e3ad5..05ed50192 100755 > --- a/test/sql-tap/analyze9.test.lua > +++ b/test/sql-tap/analyze9.test.lua > @@ -1021,7 +1021,7 @@ test:do_execsql_test( > INSERT INTO x1 VALUES(3, 4); > INSERT INTO x1 VALUES(5, 6); > ANALYZE; > - INSERT INTO "_sql_stat4" VALUES('x1', 'abc', 0, 0, 0, ''); > + INSERT INTO "_sql_stat4" VALUES('x1', 'abc', '', '', '', ''); 11. Why are tests changed? As I understand, you just did refactoring. > ]]) > > test:do_execsql_test( > diff --git a/test/sql-tap/join.test.lua b/test/sql-tap/join.test.lua > index 04b7674ed..ac05a98b2 100755 > --- a/test/sql-tap/join.test.lua > +++ b/test/sql-tap/join.test.lua > @@ -1080,9 +1080,9 @@ jointest("join-12.9", 1000, {1, 'at most 64 tables in a join'}) > -- if X(703, "X!cmd", [=[["expr","[lsearch [db eval {PRAGMA compile_options}] MEMDEBUG]<0"]]=]) > -- then > jointest("join-12.10", 65534, {1, 'at most 64 tables in a join'}) > -jointest("join-12.11", 65535, {1, 'too many references to "T14": max 65535'}) > -jointest("join-12.12", 65536, {1, 'too many references to "T14": max 65535'}) > -jointest("join-12.13", 65537, {1, 'too many references to "T14": max 65535'}) > +jointest("join-12.11", 65535, {1, 'at most 64 tables in a join'}) > +jointest("join-12.12", 65536, {1, 'at most 64 tables in a join'}) > +jointest("join-12.13", 65537, {1, 'at most 64 tables in a join'}) > -- end > --end > > diff --git a/test/sql/delete.result b/test/sql/delete.result > index 52f9969c1..993e9e04d 100644 > --- a/test/sql/delete.result > +++ b/test/sql/delete.result > @@ -44,7 +44,7 @@ box.sql.execute("DROP TABLE t1;"); > -- > box.sql.execute("DELETE FROM t1;") > --- > -- error: Space 'T1' does not exist > +- error: 'no such table: T1' > ... > box.sql.execute("CREATE TABLE t2 (s1 INT PRIMARY KEY);") > --- > @@ -54,7 +54,7 @@ box.sql.execute("CREATE TRIGGER t2 BEFORE INSERT ON t2 BEGIN DELETE FROM t1; END > ... > box.sql.execute("INSERT INTO t2 VALUES (0);") > --- > -- error: Space 'T1' does not exist > +- error: 'no such table: T1' > ... > box.sql.execute("DROP TABLE t2;") > --- > My diff is on the branch and below: commit df9555fabbed80c080858f5662e0bbd351056cc2 Author: Vladislav Shpilevoy Date: Tue Aug 28 21:21:35 2018 -0300 Review fixes diff --git a/src/box/sql/build.c b/src/box/sql/build.c index ff8594fba..6ac3463f5 100644 --- a/src/box/sql/build.c +++ b/src/box/sql/build.c @@ -224,17 +224,12 @@ sql_space_column_is_in_pk(struct space *space, uint32_t column) /* Views don't have any indexes. */ if (primary_idx == NULL) return false; - struct index_def *idx_def = primary_idx->def; - uint64_t pk_mask = idx_def->key_def->column_mask; - if (column < 63) { - return pk_mask & (((uint64_t) 1) << column); - } else if ((pk_mask & (((uint64_t) 1) << 63)) != 0) { - for (uint32_t i = 0; i < idx_def->key_def->part_count; ++i) { - struct key_part *part = &idx_def->key_def->parts[i]; - if (part->fieldno == column) - return true; - } - } + struct key_def *key_def = primary_idx->def->key_def; + uint64_t pk_mask = key_def->column_mask; + if (column < 63) + return (pk_mask & (((uint64_t) 1) << column)) != 0; + else if ((pk_mask & (((uint64_t) 1) << 63)) != 0) + return key_def_find(key_def, column) != NULL; return false; } diff --git a/src/box/sql/fkey.c b/src/box/sql/fkey.c index 215ad2867..b2d2a19e7 100644 --- a/src/box/sql/fkey.c +++ b/src/box/sql/fkey.c @@ -620,10 +620,10 @@ fkey_emit_check(struct Parse *parser, struct Table *tab, int reg_old, memset(&fake_tab, 0, sizeof(fake_tab)); fake_tab.def = child->def; fake_tab.space = child; + /* Prevent from deallocationg fake_tab. */ + fake_tab.nTabRef = 2; item->pTab = &fake_tab; item->zName = sqlite3DbStrDup(db, child->def->name); - /* Prevent from deallocationg fake_tab. */ - item->pTab->nTabRef = 2; item->iCursor = parser->nTab++; if (reg_new != 0) { diff --git a/src/box/sql/insert.c b/src/box/sql/insert.c index a2f323f04..49bac58f0 100644 --- a/src/box/sql/insert.c +++ b/src/box/sql/insert.c @@ -46,17 +46,15 @@ void sqlite3OpenTable(Parse * pParse, /* Generate code into this VDBE */ int iCur, /* The cursor number of the table */ - Table * pTab, /* The table to be opened */ + struct space *space, /* The table to be opened */ int opcode) /* OP_OpenRead or OP_OpenWrite */ { Vdbe *v; v = sqlite3GetVdbe(pParse); assert(opcode == OP_OpenWrite || opcode == OP_OpenRead); - - struct space *space = space_by_id(pTab->def->id); assert(space->index_count > 0); vdbe_emit_open_cursor(pParse, iCur, 0, space); - VdbeComment((v, "%s", pTab->def->name)); + VdbeComment((v, "%s", space->def->name)); } char * @@ -1159,6 +1157,8 @@ xferOptimization(Parse * pParse, /* Parser context */ int destHasUniqueIdx = 0; /* True if pDest has a UNIQUE index */ int regData, regTupleid; /* Registers holding data and tupleid */ struct session *user_session = current_session(); + struct space *dest = space_by_id(pDest->def->id); + assert(dest != NULL); if (pSelect == NULL) return 0; /* Must be of the form INSERT INTO ... SELECT ... */ @@ -1170,7 +1170,7 @@ xferOptimization(Parse * pParse, /* Parser context */ return 0; } /* The pDest must not have triggers. */ - if (space_trigger_list(pDest->def->id) != NULL) + if (dest->sql_triggers != NULL) return 0; if (onError == ON_CONFLICT_ACTION_DEFAULT) { if (onError == ON_CONFLICT_ACTION_DEFAULT) @@ -1221,41 +1221,41 @@ xferOptimization(Parse * pParse, /* Parser context */ */ pItem = pSelect->pSrc->a; uint32_t src_id = box_space_id_by_name(pItem->zName, - strlen(pItem->zName)); + strlen(pItem->zName)); /* FROM clause does not contain a real table. */ if (src_id == BOX_ID_NIL) return 0; struct space *src = space_by_id(src_id); assert(src != NULL); /* Src and dest may not be the same table. */ - if (src->def->id == pDest->space->def->id) + if (src->def->id == dest->def->id) return 0; /* Src may not be a view. */ if (src->def->opts.is_view) return 0; /* Number of columns must be the same in src and dst. */ - if (pDest->def->field_count != src->def->field_count) + if (dest->def->field_count != src->def->field_count) return 0; - for (i = 0; i < (int)pDest->def->field_count; i++) { + for (i = 0; i < (int)dest->def->field_count; i++) { enum affinity_type dest_affinity = - pDest->def->fields[i].affinity; + dest->def->fields[i].affinity; enum affinity_type src_affinity = src->def->fields[i].affinity; /* Affinity must be the same on all columns. */ if (dest_affinity != src_affinity) return 0; uint32_t id; - if (sql_column_collation(pDest->def, i, &id) != + if (sql_column_collation(dest->def, i, &id) != sql_column_collation(src->def, i, &id)) return 0; - if (!pDest->def->fields[i].is_nullable && + if (!dest->def->fields[i].is_nullable && src->def->fields[i].is_nullable) return 0; /* Default values for second and subsequent columns need to match. */ if (i > 0) { char *src_expr_str = src->def->fields[i].default_value; char *dest_expr_str = - pDest->def->fields[i].default_value; + dest->def->fields[i].default_value; if ((dest_expr_str == NULL) != (src_expr_str == NULL) || (dest_expr_str && strcmp(src_expr_str, dest_expr_str) != 0) @@ -1264,8 +1264,8 @@ xferOptimization(Parse * pParse, /* Parser context */ } } } - for (uint32_t i = 0; i < pDest->space->index_count; ++i) { - pDestIdx = pDest->space->index[i]; + for (uint32_t i = 0; i < dest->index_count; ++i) { + pDestIdx = dest->index[i]; if (pDestIdx->def->opts.is_unique) destHasUniqueIdx = 1; for (uint32_t j = 0; j < src->index_count; ++j) { @@ -1280,7 +1280,7 @@ xferOptimization(Parse * pParse, /* Parser context */ } /* Get server checks. */ ExprList *pCheck_src = space_checks_expr_list(src->def->id); - ExprList *pCheck_dest = space_checks_expr_list(pDest->def->id); + ExprList *pCheck_dest = space_checks_expr_list(dest->def->id); if (pCheck_dest != NULL && sqlite3ExprListCompare(pCheck_src, pCheck_dest, -1) != 0) { /* Tables have different CHECK constraints. Ticket #2252 */ @@ -1291,8 +1291,6 @@ xferOptimization(Parse * pParse, /* Parser context */ * So the extra complication to make this rule less restrictive is probably * not worth the effort. Ticket [6284df89debdfa61db8073e062908af0c9b6118e] */ - struct space *dest = space_by_id(pDest->def->id); - assert(dest != NULL); if ((user_session->sql_flags & SQLITE_ForeignKeys) != 0 && !rlist_empty(&dest->child_fkey)) return 0; @@ -1312,7 +1310,7 @@ xferOptimization(Parse * pParse, /* Parser context */ iDest = pParse->nTab++; regData = sqlite3GetTempReg(pParse); regTupleid = sqlite3GetTempReg(pParse); - sqlite3OpenTable(pParse, iDest, pDest, OP_OpenWrite); + sqlite3OpenTable(pParse, iDest, dest, OP_OpenWrite); assert(destHasUniqueIdx); if (destHasUniqueIdx /* (2) */ || (onError != ON_CONFLICT_ACTION_ABORT @@ -1342,10 +1340,7 @@ xferOptimization(Parse * pParse, /* Parser context */ vdbe_emit_open_cursor(pParse, iSrc, pSrcIdx->def->iid, src); VdbeComment((v, "%s", pSrcIdx->def->name)); - struct space *dest_space = space_by_id(pDest->def->id); - vdbe_emit_open_cursor(pParse, iDest, - pDestIdx->def->iid, - dest_space); + vdbe_emit_open_cursor(pParse, iDest, pDestIdx->def->iid, dest); VdbeComment((v, "%s", pDestIdx->def->name)); addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0); VdbeCoverage(v); diff --git a/src/box/sql/pragma.c b/src/box/sql/pragma.c index 063836989..3451d7c79 100644 --- a/src/box/sql/pragma.c +++ b/src/box/sql/pragma.c @@ -270,15 +270,13 @@ sql_pragma_table_info(struct Parse *parse, const char *tbl_name) return; struct space *space = space_by_id(space_id); assert(space != NULL); - struct space_def *def = space->def; struct index *pk = space->index[0]; parse->nMem = 6; - if (def->opts.is_view) { - const char *sql = def->opts.sql; - sql_view_assign_cursors(parse, sql); - } + if (space->def->opts.is_view) + sql_view_assign_cursors(parse, space->def->opts.sql); struct Vdbe *v = sqlite3GetVdbe(parse); - for (uint32_t i = 0, k; i < def->field_count; ++i) { + struct field_def *field = space->def->fields; + for (uint32_t i = 0, k; i < space->def->field_count; ++i, ++field) { if (!sql_space_column_is_in_pk(space, i)) { k = 0; } else if (pk == NULL) { @@ -287,13 +285,10 @@ sql_pragma_table_info(struct Parse *parse, const char *tbl_name) struct key_def *kdef = pk->def->key_def; k = key_def_find(kdef, i) - kdef->parts + 1; } - bool is_nullable = def->fields[i].is_nullable; - char *expr_str = def->fields[i].default_value; - const char *name = def->fields[i].name; - enum field_type type = def->fields[i].type; - sqlite3VdbeMultiLoad(v, 1, "issisi", i, name, - field_type_strs[type], !is_nullable, - expr_str, k); + sqlite3VdbeMultiLoad(v, 1, "issisi", i, field->name, + field_type_strs[field->type], + !field->is_nullable, field->default_value, + k); sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 6); } } @@ -316,7 +311,7 @@ sql_pragma_table_stats(struct space *space, void *data) if (pk == NULL) return 0; struct Vdbe *v = sqlite3GetVdbe(parse); - LogEst tuple_count_est = sqlite3LogEst(pk->vtab->size(pk)); + LogEst tuple_count_est = sqlite3LogEst(index_size(pk)); size_t avg_tuple_size_pk = sql_index_tuple_size(space, pk); parse->nMem = 4; sqlite3VdbeMultiLoad(v, 1, "ssii", space->def->name, 0, diff --git a/src/box/sql/sqliteInt.h b/src/box/sql/sqliteInt.h index 596e38fdc..0c9801e1c 100644 --- a/src/box/sql/sqliteInt.h +++ b/src/box/sql/sqliteInt.h @@ -3585,7 +3585,7 @@ Select *sqlite3SelectNew(Parse *, ExprList *, SrcList *, Expr *, ExprList *, struct Table * sql_lookup_table(struct Parse *parse, struct SrcList_item *tbl_name); -void sqlite3OpenTable(Parse *, int iCur, Table *, int); +void sqlite3OpenTable(Parse *, int iCur, struct space *, int); /** * Generate code for a DELETE FROM statement. * diff --git a/src/box/sql/where.c b/src/box/sql/where.c index 1b9ba436c..ce93b0940 100644 --- a/src/box/sql/where.c +++ b/src/box/sql/where.c @@ -4582,6 +4582,7 @@ sqlite3WhereBegin(Parse * pParse, /* The parser context */ struct SrcList_item *pTabItem = &pTabList->a[pLevel->iFrom]; Table *pTab = pTabItem->pTab; pLoop = pLevel->pWLoop; + struct space *space = space_cache_find(pTabItem->pTab->def->id); if (pTab->def->id == 0 || pTab->def->opts.is_view) { /* Do nothing */ } else if ((pLoop->wsFlags & WHERE_IDX_ONLY) == 0 && @@ -4591,7 +4592,7 @@ sqlite3WhereBegin(Parse * pParse, /* The parser context */ op = OP_OpenWrite; pWInfo->aiCurOnePass[0] = pTabItem->iCursor; }; - sqlite3OpenTable(pParse, pTabItem->iCursor, pTab, op); + sqlite3OpenTable(pParse, pTabItem->iCursor, space, op); assert(pTabItem->iCursor == pLevel->iTabCur); testcase(pWInfo->eOnePass == ONEPASS_OFF && pTab->nCol == BMS - 1); @@ -4607,7 +4608,6 @@ sqlite3WhereBegin(Parse * pParse, /* The parser context */ } if (pLoop->wsFlags & WHERE_INDEXED) { struct index_def *idx_def = pLoop->index_def; - struct space *space = space_cache_find(pTabItem->pTab->def->id); int iIndexCur; int op = OP_OpenRead; /* Check if index is primary. Either of