* [tarantool-patches] [PATCH] sql: get rid off tnum field of struct Table @ 2018-07-20 11:37 Kirill Yukhin 2018-07-20 14:07 ` [tarantool-patches] " n.pettik 2018-07-20 16:53 ` Kirill Yukhin 0 siblings, 2 replies; 5+ messages in thread From: Kirill Yukhin @ 2018-07-20 11:37 UTC (permalink / raw) To: korablev; +Cc: tarantool-patches, Kirill Yukhin Basic structures (struct Table/Index) of legacy SQL's data dictionary used to so-called tnum to refer to engine's btree structures. Tarantool used this field to store composition of space_id and index_id. Recently both structures incorporated native space_def/index_def descriptors. This patch finally removes tnum field. It also refactors init_callback machinery, removing varargs from declarations. Closes #3482 --- Issue: https://github.com/tarantool/tarantool/issues/3482 Branch: https://github.com/tarantool/tarantool/commits/kyukhin/gh-3482-remove-tnum src/box/sql.c | 108 ++++++++++++++------------------------------- src/box/sql/alter.c | 5 ++- src/box/sql/analyze.c | 16 +++---- src/box/sql/build.c | 43 +++++++----------- src/box/sql/delete.c | 2 +- src/box/sql/expr.c | 6 +-- src/box/sql/fkey.c | 12 +++-- src/box/sql/insert.c | 43 +++++++----------- src/box/sql/main.c | 27 ------------ src/box/sql/pragma.c | 14 ++---- src/box/sql/prepare.c | 91 +++++++++++++++----------------------- src/box/sql/select.c | 3 +- src/box/sql/sqliteInt.h | 53 ++++++++++++++-------- src/box/sql/tarantoolInt.h | 22 +++++++-- src/box/sql/vdbe.c | 56 +++++++++-------------- src/box/sql/vdbe.h | 1 - src/box/sql/vdbeaux.c | 9 +--- src/box/sql/where.c | 69 ++++++++++++----------------- 18 files changed, 227 insertions(+), 353 deletions(-) diff --git a/src/box/sql.c b/src/box/sql.c index d2cc0a9..d48c3cf 100644 --- a/src/box/sql.c +++ b/src/box/sql.c @@ -726,28 +726,13 @@ rename_fail: return SQL_TARANTOOL_ERROR; } -/* - * Rename the table in _space. Update tuple with corresponding id with - * new name and statement fields and insert back. If sql_stmt is NULL, - * then return from function after getting length of new statement: - * it is the way how to dynamically allocate memory for new statement in VDBE. - * So basically this function should be called twice: firstly to get length of - * CREATE TABLE statement, and secondly to make routine of replacing tuple and - * filling out param sql_stmt with new CREATE TABLE statement. - * - * @param iTab pageno of table to be renamed - * @param new_name new name of table - * @param[out] sql_stmt CREATE TABLE statement for new name table, can be NULL. - * - * @retval SQLITE_OK on success, SQLITE_TARANTOOL_ERROR otherwise. - */ -int tarantoolSqlite3RenameTable(int iTab, const char *new_name, char **sql_stmt) +int +sql_rename_table(uint32_t space_id, const char *new_name, char **sql_stmt) { - assert(iTab > 0); - assert(new_name); - assert(sql_stmt); + assert(space_id != 0); + assert(new_name != NULL); + assert(sql_stmt != NULL); - int space_id = SQLITE_PAGENO_TO_SPACEID(iTab); box_tuple_t *tuple; uint32_t key_len = mp_sizeof_uint(space_id) + mp_sizeof_array(1); char *key_begin = (char*) region_alloc(&fiber()->gc, key_len); @@ -858,14 +843,13 @@ rename_fail: * Acts almost as tarantoolSqlite3RenameTable, but doesn't change * name of table, only statement. */ -int tarantoolSqlite3RenameParentTable(int iTab, const char *old_parent_name, +int tarantoolSqlite3RenameParentTable(int space_id, const char *old_parent_name, const char *new_parent_name) { - assert(iTab > 0); - assert(old_parent_name); - assert(new_parent_name); + assert(space_id != 0); + assert(old_parent_name != NULL); + assert(new_parent_name != NULL); - int space_id = SQLITE_PAGENO_TO_SPACEID(iTab); box_tuple_t *tuple; uint32_t key_len = mp_sizeof_uint(space_id) + mp_sizeof_array(1); @@ -1181,63 +1165,34 @@ cursor_advance(BtCursor *pCur, int *pRes) * Schema support. */ -/* - * Manully add objects to SQLite in-memory schema. - * This is loosely based on sqlite_master row format. - * @Params - * name - object name - * id - SQLITE_PAGENO_FROM_SPACEID_INDEXID(...) - * for tables and indices - * sql - SQL statement that created this object - */ -static void -sql_schema_put(InitData *init, - const char *name, - uint32_t spaceid, uint32_t indexid, - const char *sql) -{ - int pageno = SQLITE_PAGENO_FROM_SPACEID_AND_INDEXID(spaceid, indexid); - - char *argv[] = { - (char *)name, - (char *)&pageno, - (char *)sql, - NULL - }; - - if (init->rc != SQLITE_OK) return; - - sqlite3InitCallback(init, 3, argv, NULL); -} - static int space_foreach_put_cb(struct space *space, void *udata) { if (space->def->opts.sql == NULL) return 0; /* Not SQL space. */ - sql_schema_put((InitData *) udata, space->def->name, space->def->id, 0, - space->def->opts.sql); + sql_init_callback((struct init_data *) udata, space->def->name, + space->def->id, 0, space->def->opts.sql); for (uint32_t i = 0; i < space->index_count; ++i) { struct index_def *def = space_index_def(space, i); if (def->opts.sql != NULL) { - sql_schema_put((InitData *) udata, def->name, - def->space_id, def->iid, def->opts.sql); + sql_init_callback((struct init_data *) udata, def->name, + def->space_id, def->iid, def->opts.sql); } } return 0; } /* Load database schema from Tarantool. */ -void tarantoolSqlite3LoadSchema(InitData *init) +void tarantoolSqlite3LoadSchema(struct init_data *init) { - sql_schema_put( + sql_init_callback( init, TARANTOOL_SYS_SCHEMA_NAME, BOX_SCHEMA_ID, 0, "CREATE TABLE \""TARANTOOL_SYS_SCHEMA_NAME "\" (\"key\" TEXT PRIMARY KEY, \"value\")" ); - sql_schema_put( + sql_init_callback( init, TARANTOOL_SYS_SPACE_NAME, BOX_SPACE_ID, 0, "CREATE TABLE \""TARANTOOL_SYS_SPACE_NAME @@ -1245,7 +1200,7 @@ void tarantoolSqlite3LoadSchema(InitData *init) "\"engine\" TEXT, \"field_count\" INT, \"opts\", \"format\")" ); - sql_schema_put( + sql_init_callback( init, TARANTOOL_SYS_INDEX_NAME, BOX_INDEX_ID, 0, "CREATE TABLE \""TARANTOOL_SYS_INDEX_NAME"\" " @@ -1253,38 +1208,41 @@ void tarantoolSqlite3LoadSchema(InitData *init) "\"opts\", \"parts\", PRIMARY KEY (\"id\", \"iid\"))" ); - sql_schema_put( + sql_init_callback( init, TARANTOOL_SYS_TRIGGER_NAME, BOX_TRIGGER_ID, 0, "CREATE TABLE \""TARANTOOL_SYS_TRIGGER_NAME"\" (" "\"name\" TEXT PRIMARY KEY, \"space_id\" INT, \"opts\")" ); - sql_schema_put( + sql_init_callback( init, TARANTOOL_SYS_TRUNCATE_NAME, BOX_TRUNCATE_ID, 0, "CREATE TABLE \""TARANTOOL_SYS_TRUNCATE_NAME "\" (\"id\" INT PRIMARY KEY, \"count\" INT NOT NULL)" ); - sql_schema_put(init, TARANTOOL_SYS_SEQUENCE_NAME, BOX_SEQUENCE_ID, 0, - "CREATE TABLE \""TARANTOOL_SYS_SEQUENCE_NAME - "\" (\"id\" INT PRIMARY KEY, \"uid\" INT, \"name\" TEXT, \"step\" INT, " - "\"max\" INT, \"min\" INT, \"start\" INT, \"cache\" INT, \"cycle\" INT)"); + sql_init_callback(init, TARANTOOL_SYS_SEQUENCE_NAME, BOX_SEQUENCE_ID, 0, + "CREATE TABLE \""TARANTOOL_SYS_SEQUENCE_NAME + "\" (\"id\" INT PRIMARY KEY, \"uid\" INT, \"name\" TEXT, \"step\" INT, " + "\"max\" INT, \"min\" INT, \"start\" INT, \"cache\" INT, \"cycle\" INT)"); - sql_schema_put(init, TARANTOOL_SYS_SPACE_SEQUENCE_NAME, BOX_SPACE_SEQUENCE_ID, 0, - "CREATE TABLE \""TARANTOOL_SYS_SPACE_SEQUENCE_NAME - "\" (\"space_id\" INT PRIMARY KEY, \"sequence_id\" INT, \"flag\" INT)"); + sql_init_callback(init, TARANTOOL_SYS_SPACE_SEQUENCE_NAME, + BOX_SPACE_SEQUENCE_ID, 0, + "CREATE TABLE \""TARANTOOL_SYS_SPACE_SEQUENCE_NAME + "\" (\"space_id\" INT PRIMARY KEY, \"sequence_id\" INT, \"flag\" INT)"); - sql_schema_put(init, TARANTOOL_SYS_SQL_STAT1_NAME, BOX_SQL_STAT1_ID, 0, - "CREATE TABLE \""TARANTOOL_SYS_SQL_STAT1_NAME + sql_init_callback(init, TARANTOOL_SYS_SQL_STAT1_NAME, + BOX_SQL_STAT1_ID, 0, + "CREATE TABLE \""TARANTOOL_SYS_SQL_STAT1_NAME "\"(\"tbl\" text," "\"idx\" text," "\"stat\" not null," "PRIMARY KEY(\"tbl\", \"idx\"))"); - sql_schema_put(init, TARANTOOL_SYS_SQL_STAT4_NAME, BOX_SQL_STAT4_ID, 0, - "CREATE TABLE \""TARANTOOL_SYS_SQL_STAT4_NAME + sql_init_callback(init, TARANTOOL_SYS_SQL_STAT4_NAME, + BOX_SQL_STAT4_ID, 0, + "CREATE TABLE \""TARANTOOL_SYS_SQL_STAT4_NAME "\"(\"tbl\" text," "\"idx\" text," "\"neq\" text," diff --git a/src/box/sql/alter.c b/src/box/sql/alter.c index fe54e55..8c1c36b 100644 --- a/src/box/sql/alter.c +++ b/src/box/sql/alter.c @@ -60,7 +60,8 @@ reloadTableSchema(Parse * pParse, Table * pTab, const char *zName) return; char *zNewName = sqlite3MPrintf(pParse->db, "%s", zName); - sqlite3VdbeAddRenameTableOp(v, pTab->tnum, zNewName); + sqlite3VdbeAddOp4(v, OP_RenameTable, pTab->def->id, 0, 0, zNewName, + P4_DYNAMIC); } /* @@ -163,7 +164,7 @@ sqlite3AlterFinishAddColumn(Parse * pParse, Token * pColDef) zTab = &pNew->def->name[16]; pCol = &pNew->aCol[pNew->def->field_count - 1]; assert(pNew->def != NULL); - pDflt = space_column_default_expr(SQLITE_PAGENO_TO_SPACEID(pNew->tnum), + pDflt = space_column_default_expr(pNew->def->id, pNew->def->field_count - 1); pTab = sqlite3HashFind(&db->pSchema->tblHash, zTab);; assert(pTab); diff --git a/src/box/sql/analyze.c b/src/box/sql/analyze.c index 36648b3..00d96d2 100644 --- a/src/box/sql/analyze.c +++ b/src/box/sql/analyze.c @@ -803,7 +803,7 @@ analyzeOneTable(Parse * pParse, /* Parser context */ if (v == 0 || NEVER(pTab == 0)) { return; } - assert(pTab->tnum != 0); + assert(pTab->def->id != 0); if (sqlite3_strlike("\\_%", pTab->def->name, '\\') == 0) { /* Do not gather statistics on system tables */ return; @@ -882,9 +882,8 @@ analyzeOneTable(Parse * pParse, /* Parser context */ pParse->nMem = MAX(pParse->nMem, regPrev + part_count); /* Open a read-only cursor on the index being analyzed. */ - struct space *space = - space_by_id(SQLITE_PAGENO_TO_SPACEID(pIdx->tnum)); - int idx_id = SQLITE_PAGENO_TO_INDEXID(pIdx->tnum); + struct space *space = space_by_id(pIdx->def->space_id); + int idx_id = pIdx->def->iid; assert(space != NULL); sqlite3VdbeAddOp4(v, OP_OpenRead, iIdxCur, idx_id, 0, (void *) space, P4_SPACEPTR); @@ -1624,7 +1623,7 @@ const log_est_t default_tuple_est[] = {DEFAULT_TUPLE_LOG_COUNT, LogEst sql_space_tuple_log_count(struct Table *tab) { - struct space *space = space_by_id(SQLITE_PAGENO_TO_SPACEID(tab->tnum)); + struct space *space = space_by_id(tab->def->id); if (space == NULL) return tab->tuple_log_count; struct index *pk = space_index(space, 0); @@ -1638,11 +1637,10 @@ sql_space_tuple_log_count(struct Table *tab) log_est_t index_field_tuple_est(struct Index *idx, uint32_t field) { - struct space *space = space_by_id(SQLITE_PAGENO_TO_SPACEID(idx->tnum)); - if (space == NULL) + struct space *space = space_by_id(idx->pTable->def->id); + if (space == NULL || strcmp(idx->def->opts.sql, "fake_autoindex") == 0) return idx->def->opts.stat->tuple_log_est[field]; - struct index *tnt_idx = - space_index(space, SQLITE_PAGENO_TO_INDEXID(idx->tnum)); + struct index *tnt_idx = space_index(space, idx->def->iid); assert(tnt_idx != NULL); assert(field <= tnt_idx->def->key_def->part_count); if (tnt_idx->def->opts.stat == NULL) { diff --git a/src/box/sql/build.c b/src/box/sql/build.c index fc6681a..2f29c52 100644 --- a/src/box/sql/build.c +++ b/src/box/sql/build.c @@ -278,8 +278,7 @@ sqlite3CommitInternalChanges() bool table_column_is_in_pk(Table *table, uint32_t column) { - uint32_t space_id = SQLITE_PAGENO_TO_SPACEID(table->tnum); - struct space *space = space_by_id(space_id); + struct space *space = space_by_id(table->def->id); assert(space != NULL); struct index *primary_idx = index_find(space, 0 /* PK */); @@ -1604,8 +1603,10 @@ sqlite3EndTable(Parse * pParse, /* Parse context */ * schema. */ if (db->init.busy) { - p->tnum = db->init.newTnum; - p->def->id = SQLITE_PAGENO_TO_SPACEID(p->tnum); + p->def->id = db->init.space_id; + for(struct Index *idx = p->pIndex; idx != NULL; + idx = idx->pNext) + idx->def->space_id = p->def->id; } if (!p->def->opts.is_view) { @@ -2263,15 +2264,9 @@ sqlite3DeferForeignKey(Parse * pParse, int isDeferred) * Generate code that will erase and refill index *pIdx. This is * used to initialize a newly created index or to recompute the * content of an index in response to a REINDEX command. - * - * if memRootPage is not negative, it means that the index is newly - * created. The register specified by memRootPage contains the - * root page number of the index. If memRootPage is negative, then - * the index already exists and must be cleared before being refilled and - * the root page number of the index is taken from pIndex->tnum. */ static void -sqlite3RefillIndex(Parse * pParse, Index * pIndex, int memRootPage) +sqlite3RefillIndex(Parse * pParse, Index * pIndex) { Table *pTab = pIndex->pTable; /* The table that is indexed */ int iTab = pParse->nTab++; /* Btree cursor used for pTab */ @@ -2279,7 +2274,6 @@ sqlite3RefillIndex(Parse * pParse, Index * pIndex, int memRootPage) int iSorter; /* Cursor opened by OpenSorter (if in use) */ int addr1; /* Address of top of loop */ int addr2; /* Address to jump to for next iteration */ - int tnum; /* Root page of index */ int iPartIdxLabel; /* Jump to this label to skip a row */ Vdbe *v; /* Generate code into this virtual machine */ int regRecord; /* Register holding assembled index record */ @@ -2287,11 +2281,6 @@ sqlite3RefillIndex(Parse * pParse, Index * pIndex, int memRootPage) v = sqlite3GetVdbe(pParse); if (v == 0) return; - if (memRootPage >= 0) { - tnum = memRootPage; - } else { - tnum = pIndex->tnum; - } struct key_def *def = key_def_dup(pIndex->def->key_def); if (def == NULL) { sqlite3OomFault(db); @@ -2318,13 +2307,11 @@ sqlite3RefillIndex(Parse * pParse, Index * pIndex, int memRootPage) sqlite3VdbeAddOp2(v, OP_Next, iTab, addr1 + 1); VdbeCoverage(v); sqlite3VdbeJumpHere(v, addr1); - if (memRootPage < 0) - sqlite3VdbeAddOp2(v, OP_Clear, SQLITE_PAGENO_TO_SPACEID(tnum), - 0); - struct space *space = space_by_id(SQLITE_PAGENO_TO_SPACEID(tnum)); - vdbe_emit_open_cursor(pParse, iIdx, SQLITE_PAGENO_TO_INDEXID(tnum), + sqlite3VdbeAddOp2(v, OP_Clear, pIndex->pTable->def->id, 0); + struct space *space = space_by_id(pIndex->pTable->def->id); + vdbe_emit_open_cursor(pParse, iIdx, pIndex->def->iid, space); - sqlite3VdbeChangeP5(v, memRootPage >= 0 ? OPFLAG_P2ISREG : 0); + sqlite3VdbeChangeP5(v, 0); addr1 = sqlite3VdbeAddOp2(v, OP_SorterSort, iSorter, 0); VdbeCoverage(v); @@ -2722,7 +2709,7 @@ sql_create_index(struct Parse *parse, struct Token *token, */ uint32_t iid = idx_type != SQL_INDEX_TYPE_CONSTRAINT_PK; if (db->init.busy) - iid = SQLITE_PAGENO_TO_INDEXID(db->init.newTnum); + iid = db->init.index_id; if (index_fill_def(parse, index, table, iid, name, strlen(name), col_list, idx_type, sql_stmt) != 0) @@ -2852,7 +2839,7 @@ sql_create_index(struct Parse *parse, struct Token *token, goto exit_create_index; } user_session->sql_flags |= SQLITE_InternChanges; - index->tnum = db->init.newTnum; + index->def->iid = db->init.index_id; } /* @@ -2885,7 +2872,7 @@ sql_create_index(struct Parse *parse, struct Token *token, sqlite3VdbeChangeP5(vdbe, OPFLAG_SEEKEQ); assert(start != NULL); - space_id = SQLITE_PAGENO_TO_SPACEID(table->tnum); + space_id = table->def->id; index_id = getNewIid(parse, space_id, cursor); sqlite3VdbeAddOp1(vdbe, OP_Close, cursor); createIndex(parse, index, space_id, index_id, sql_stmt); @@ -3583,7 +3570,7 @@ reindexTable(Parse * pParse, Table * pTab, struct coll *coll) for (pIndex = pTab->pIndex; pIndex; pIndex = pIndex->pNext) { if (coll == 0 || collationMatch(coll, pIndex)) { sql_set_multi_write(pParse, false); - sqlite3RefillIndex(pParse, pIndex, -1); + sqlite3RefillIndex(pParse, pIndex); } } } @@ -3677,7 +3664,7 @@ sqlite3Reindex(Parse * pParse, Token * pName1, Token * pName2) pIndex = sqlite3HashFind(&pTab->idxHash, z); if (pIndex != NULL) { sql_set_multi_write(pParse, false); - sqlite3RefillIndex(pParse, pIndex, -1); + sqlite3RefillIndex(pParse, pIndex); return; } diff --git a/src/box/sql/delete.c b/src/box/sql/delete.c index f9d3498..0681177 100644 --- a/src/box/sql/delete.c +++ b/src/box/sql/delete.c @@ -125,7 +125,7 @@ sql_table_delete_from(struct Parse *parse, struct SrcList *tab_list, table = sql_list_lookup_table(parse, tab_list); if (table == NULL) goto delete_from_cleanup; - space_id = SQLITE_PAGENO_TO_SPACEID(table->tnum); + space_id = table->def->id; space = space_by_id(space_id); assert(space != NULL); trigger_list = sql_triggers_exist(table, TK_DELETE, NULL, NULL); diff --git a/src/box/sql/expr.c b/src/box/sql/expr.c index 360558a..d408adb 100644 --- a/src/box/sql/expr.c +++ b/src/box/sql/expr.c @@ -2474,10 +2474,8 @@ sqlite3FindInIndex(Parse * pParse, /* Parsing context */ pIdx->def->name), P4_DYNAMIC); struct space *space = - space_by_id(SQLITE_PAGENO_TO_SPACEID(pIdx->tnum)); - uint32_t idx_id = - SQLITE_PAGENO_TO_INDEXID(pIdx-> - tnum); + space_by_id(pIdx->pTable->def->id); + uint32_t idx_id = pIdx->def->iid; vdbe_emit_open_cursor(pParse, iTab, idx_id, space); VdbeComment((v, "%s", pIdx->def->name)); diff --git a/src/box/sql/fkey.c b/src/box/sql/fkey.c index 8cacfe7..6dd9130 100644 --- a/src/box/sql/fkey.c +++ b/src/box/sql/fkey.c @@ -426,9 +426,9 @@ fkLookupParent(Parse * pParse, /* Parse context */ int regTemp = sqlite3GetTempRange(pParse, nCol); int regRec = sqlite3GetTempReg(pParse); struct space *space = - space_by_id(SQLITE_PAGENO_TO_SPACEID(pIdx->tnum)); - uint32_t idx_id = SQLITE_PAGENO_TO_INDEXID(pIdx->tnum); - vdbe_emit_open_cursor(pParse, iCur, idx_id, space); + space_by_id(pIdx->pTable->def->id); + vdbe_emit_open_cursor(pParse, iCur, pIdx->def->iid, + space); for (i = 0; i < nCol; i++) { sqlite3VdbeAddOp2(v, OP_Copy, aiCol[i] + 1 + regData, @@ -1304,12 +1304,10 @@ fkActionTrigger(struct Parse *pParse, struct Table *pTab, struct FKey *pFKey, &tToCol, 0)); } else if (action == OE_SetDflt) { - uint32_t space_id = - SQLITE_PAGENO_TO_SPACEID( - pFKey->pFrom->tnum); Expr *pDflt = space_column_default_expr( - space_id, (uint32_t)iFromCol); + pFKey->pFrom->def->id, + (uint32_t)iFromCol); if (pDflt) { pNew = sqlite3ExprDup(db, pDflt, diff --git a/src/box/sql/insert.c b/src/box/sql/insert.c index 3af9f9a..504701d 100644 --- a/src/box/sql/insert.c +++ b/src/box/sql/insert.c @@ -384,7 +384,7 @@ sqlite3Insert(Parse * pParse, /* Parser context */ if (pTab == NULL) goto insert_cleanup; - space_id = SQLITE_PAGENO_TO_SPACEID(pTab->tnum); + space_id = pTab->def->id; /* Figure out if we have any triggers and if the table being * inserted into is a view @@ -742,7 +742,7 @@ sqlite3Insert(Parse * pParse, /* Parser context */ if (i == pTab->iAutoIncPKey) { sqlite3VdbeAddOp2(v, OP_NextAutoincValue, - pTab->tnum, + SQLITE_PAGENO_FROM_SPACEID_AND_INDEXID(pTab->def->id, 0), iRegStore); continue; } @@ -1075,9 +1075,7 @@ sqlite3GenerateConstraintChecks(Parse * pParse, /* The parser context */ on_error = ON_CONFLICT_ACTION_ABORT; struct Expr *dflt = NULL; - dflt = space_column_default_expr( - SQLITE_PAGENO_TO_SPACEID(pTab->tnum), - i); + dflt = space_column_default_expr(pTab->def->id, i); if (on_error == ON_CONFLICT_ACTION_REPLACE && dflt == 0) on_error = ON_CONFLICT_ACTION_ABORT; @@ -1124,8 +1122,7 @@ sqlite3GenerateConstraintChecks(Parse * pParse, /* The parser context */ * Get server checks. * Test all CHECK constraints. */ - uint32_t space_id = SQLITE_PAGENO_TO_SPACEID(pTab->tnum); - ExprList *checks = space_checks_expr_list(space_id); + ExprList *checks = space_checks_expr_list(pTab->def->id); if (checks != NULL && (user_session->sql_flags & SQLITE_IgnoreChecks) == 0) { pParse->ckBase = regNewData + 1; @@ -1389,7 +1386,7 @@ sqlite3GenerateConstraintChecks(Parse * pParse, /* The parser context */ ++i, ++part) { char *p4 = (char *) part->coll; x = part->fieldno; - if (pPk->tnum==0) + if (pTab->def->id == 0) x = -1; if (i == (pk_part_count - 1)) { addrJump = addrUniqueOk; @@ -1531,7 +1528,7 @@ sqlite3OpenTableAndIndices(Parse * pParse, /* Parsing context */ *piDataCur = iDataCur; if (piIdxCur) *piIdxCur = iBase; - struct space *space = space_by_id(SQLITE_PAGENO_TO_SPACEID(pTab->tnum)); + struct space *space = space_by_id(pTab->def->id); assert(space != NULL); /* One iteration of this cycle adds OpenRead/OpenWrite which * opens cursor for current index. @@ -1579,10 +1576,9 @@ sqlite3OpenTableAndIndices(Parse * pParse, /* Parsing context */ p5 = 0; } if (aToOpen == 0 || aToOpen[i + 1]) { - int idx_id = - SQLITE_PAGENO_TO_INDEXID(pIdx->tnum); - sqlite3VdbeAddOp4(v, op, iIdxCur, idx_id, 0, - (void *) space, P4_SPACEPTR); + sqlite3VdbeAddOp4(v, op, iIdxCur, pIdx->def->iid, + 0, (void *) space, + P4_SPACEPTR); sqlite3VdbeChangeP5(v, p5); VdbeComment((v, "%s", pIdx->def->name)); } @@ -1781,12 +1777,10 @@ xferOptimization(Parse * pParse, /* Parser context */ } /* Default values for second and subsequent columns need to match. */ if (i > 0) { - uint32_t src_space_id = - SQLITE_PAGENO_TO_SPACEID(pSrc->tnum); + uint32_t src_space_id = pSrc->def->id; struct space *src_space = space_cache_find(src_space_id); - uint32_t dest_space_id = - SQLITE_PAGENO_TO_SPACEID(pDest->tnum); + uint32_t dest_space_id = pDest->def->id; struct space *dest_space = space_cache_find(dest_space_id); assert(src_space != NULL && dest_space != NULL); @@ -1814,10 +1808,8 @@ xferOptimization(Parse * pParse, /* Parser context */ return 0; } /* Get server checks. */ - ExprList *pCheck_src = space_checks_expr_list( - SQLITE_PAGENO_TO_SPACEID(pSrc->tnum)); - ExprList *pCheck_dest = space_checks_expr_list( - SQLITE_PAGENO_TO_SPACEID(pDest->tnum)); + ExprList *pCheck_src = space_checks_expr_list(pSrc->def->id); + ExprList *pCheck_dest = space_checks_expr_list(pDest->def->id); if (pCheck_dest != NULL && sqlite3ExprListCompare(pCheck_src, pCheck_dest, -1) != 0) { /* Tables have different CHECK constraints. Ticket #2252 */ @@ -1885,15 +1877,14 @@ xferOptimization(Parse * pParse, /* Parser context */ } assert(pSrcIdx); struct space *src_space = - space_by_id(SQLITE_PAGENO_TO_SPACEID(pSrcIdx->tnum)); + space_by_id(pSrc->def->id); vdbe_emit_open_cursor(pParse, iSrc, - SQLITE_PAGENO_TO_INDEXID(pSrcIdx->tnum), + pSrcIdx->def->iid, src_space); VdbeComment((v, "%s", pSrcIdx->def->name)); - struct space *dest_space = - space_by_id(SQLITE_PAGENO_TO_SPACEID(pDestIdx->tnum)); + struct space *dest_space = space_by_id(pDest->def->id); vdbe_emit_open_cursor(pParse, iDest, - SQLITE_PAGENO_TO_INDEXID(pDestIdx->tnum), + pDestIdx->def->iid, dest_space); VdbeComment((v, "%s", pDestIdx->def->name)); addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0); diff --git a/src/box/sql/main.c b/src/box/sql/main.c index 85bc7e9..ded3b5b 100644 --- a/src/box/sql/main.c +++ b/src/box/sql/main.c @@ -2388,33 +2388,6 @@ sqlite3_test_control(int op, ...) rc = SQLITE_ERROR; break; } - - /* sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, db, dbName, onOff, tnum); - * - * This test control is used to create imposter tables. "db" is a pointer - * to the database connection. dbName is the database name (ex: "main" or - * "temp") which will receive the imposter. "onOff" turns imposter mode on - * or off. "tnum" is the root page of the b-tree to which the imposter - * table should connect. - * - * Enable imposter mode only when the schema has already been parsed. Then - * run a single CREATE TABLE statement to construct the imposter table in - * the parsed schema. Then turn imposter mode back off again. - * - * If onOff==0 and tnum>0 then reset the schema for all databases, causing - * the schema to be reparsed the next time it is needed. This has the - * effect of erasing all imposter tables. - */ - case SQLITE_TESTCTRL_IMPOSTER:{ - sqlite3 *db = va_arg(ap, sqlite3 *); - db->init.busy = db->init.imposterTable = - va_arg(ap, int); - db->init.newTnum = va_arg(ap, int); - if (db->init.busy == 0 && db->init.newTnum > 0) { - sqlite3ResetAllSchemasOfConnection(db); - } - break; - } } va_end(ap); #endif /* SQLITE_UNTESTABLE */ diff --git a/src/box/sql/pragma.c b/src/box/sql/pragma.c index cabe22b..0c838fa 100644 --- a/src/box/sql/pragma.c +++ b/src/box/sql/pragma.c @@ -432,9 +432,8 @@ sqlite3Pragma(Parse * pParse, Token * pId, /* First part of [schema.]id field */ for (i = sqliteHashFirst(&db->pSchema->tblHash); i; i = sqliteHashNext(i)) { Table *pTab = sqliteHashData(i); - uint32_t space_id = - SQLITE_PAGENO_TO_SPACEID(pTab->tnum); - struct space *space = space_by_id(space_id); + struct space *space; + space = space_by_id(pTab->def->id); assert(space != NULL); struct index *pk = space_index(space, 0); size_t avg_tuple_size_pk = @@ -447,10 +446,8 @@ sqlite3Pragma(Parse * pParse, Token * pId, /* First part of [schema.]id field */ sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 4); for (pIdx = pTab->pIndex; pIdx; pIdx = pIdx->pNext) { - uint32_t iid = - SQLITE_PAGENO_TO_INDEXID(pIdx->tnum); struct index *idx = - space_index(space, iid); + space_index(space, pIdx->def->iid); assert(idx != NULL); size_t avg_tuple_size_idx = sql_index_tuple_size(space, idx); @@ -689,12 +686,9 @@ sqlite3Pragma(Parse * pParse, Token * pId, /* First part of [schema.]id field */ struct space *space = space_cache_find(pIdx->pTable-> def->id); - int idx_id = - SQLITE_PAGENO_TO_INDEXID(pIdx-> - tnum); assert(space != NULL); sqlite3VdbeAddOp4(v, OP_OpenRead, i, - idx_id, 0, + pIdx->def->iid, 0, (void *) space, P4_SPACEPTR); diff --git a/src/box/sql/prepare.c b/src/box/sql/prepare.c index 629f68e..14239c4 100644 --- a/src/box/sql/prepare.c +++ b/src/box/sql/prepare.c @@ -44,12 +44,12 @@ * that the database is corrupt. */ static void -corruptSchema(InitData * pData, /* Initialization context */ +corruptSchema(struct init_data *data, /* Initialization context */ const char *zObj, /* Object being parsed at the point of error */ const char *zExtra /* Error information */ ) { - sqlite3 *db = pData->db; + sqlite3 *db = data->db; if (!db->mallocFailed) { char *z; if (zObj == 0) @@ -57,46 +57,30 @@ corruptSchema(InitData * pData, /* Initialization context */ z = sqlite3MPrintf(db, "malformed database schema (%s)", zObj); if (zExtra) z = sqlite3MPrintf(db, "%z - %s", z, zExtra); - sqlite3DbFree(db, *pData->pzErrMsg); - *pData->pzErrMsg = z; + sqlite3DbFree(db, *data->pzErrMsg); + *data->pzErrMsg = z; } - pData->rc = db->mallocFailed ? SQLITE_NOMEM_BKPT : SQLITE_CORRUPT_BKPT; + data->rc = db->mallocFailed ? SQLITE_NOMEM_BKPT : SQLITE_CORRUPT_BKPT; } /* Necessary for appropriate value return in InitCallback. * Otherwise it will return uint32_t instead of 64 bit pointer. */ struct space *space_by_id(uint32_t id); -/* - * This is the callback routine for the code that initializes the - * database. See sqlite3Init() below for additional information. - * This routine is also called from the OP_ParseSchema opcode of the VDBE. - * - * Each callback contains the following information: - * - * argv[0] = name of thing being created - * argv[1] = root page number address. - * argv[2] = SQL text for the CREATE statement. - * - */ + int -sqlite3InitCallback(void *pInit, int argc, char **argv, char **NotUsed) +sql_init_callback(struct init_data *init, const char *name, + uint32_t space_id, uint32_t index_id, const char *sql) { - InitData *pData = (InitData *) pInit; - sqlite3 *db = pData->db; - assert(argc == 3); - UNUSED_PARAMETER2(NotUsed, argc); + sqlite3 *db = init->db; if (db->mallocFailed) { - corruptSchema(pData, argv[0], 0); + corruptSchema(init, name, 0); return 1; } - if (argv == 0) - return 0; /* Might happen if EMPTY_RESULT_CALLBACKS are on */ - if (argv[1] == 0) { - corruptSchema(pData, argv[0], 0); - } else if ((strlen(argv[2]) > 7) && - sqlite3_strnicmp(argv[2], "create ", 7) == 0) { + assert(space_id > 0); + if ((strlen(sql) > 7) && + sqlite3_strnicmp(sql, "create ", 7) == 0) { /* Call the parser to process a CREATE TABLE, INDEX or VIEW. * But because db->init.busy is set to 1, no VDBE code is generated * or executed. All the parser does is build the internal data @@ -107,25 +91,24 @@ sqlite3InitCallback(void *pInit, int argc, char **argv, char **NotUsed) TESTONLY(int rcp); /* Return code from sqlite3_prepare() */ assert(db->init.busy); - db->init.newTnum = *((int *)argv[1]); + db->init.space_id = space_id; + db->init.index_id = index_id; db->init.orphanTrigger = 0; - TESTONLY(rcp =) sqlite3_prepare(db, argv[2], - strlen(argv[2]) + 1, &pStmt, 0); + TESTONLY(rcp =) sqlite3_prepare(db, sql, + strlen(sql) + 1, &pStmt, 0); rc = db->errCode; assert((rc & 0xFF) == (rcp & 0xFF)); if (SQLITE_OK != rc) { - pData->rc = rc; - if (rc == SQLITE_NOMEM) { + init->rc = rc; + if (rc == SQLITE_NOMEM) sqlite3OomFault(db); - } else if (rc != SQLITE_INTERRUPT - && (rc & 0xFF) != SQLITE_LOCKED) { - corruptSchema(pData, argv[0], - sqlite3_errmsg(db)); - } + else if (rc != SQLITE_INTERRUPT && + (rc & 0xFF) != SQLITE_LOCKED) + corruptSchema(init, name, sqlite3_errmsg(db)); } sqlite3_finalize(pStmt); - } else if (argv[0] == 0 || (argv[2] != 0 && argv[2][0] != 0)) { - corruptSchema(pData, argv[0], 0); + } else if (name == NULL || (sql != NULL && sql[0] != 0)) { + corruptSchema(init, name, 0); } else { /* If the SQL column is blank it means this is an index that * was created to be the PRIMARY KEY or to fulfill a UNIQUE @@ -134,12 +117,10 @@ sqlite3InitCallback(void *pInit, int argc, char **argv, char **NotUsed) * to do here is record the root page number for that index. */ Index *pIndex; - long pageNo = *((long *)argv[1]); - int iSpace = (int)SQLITE_PAGENO_TO_SPACEID(pageNo); - struct space *pSpace = space_by_id(iSpace); - const char *zSpace = space_name(pSpace); - pIndex = sqlite3LocateIndex(db, argv[0], zSpace); - if (pIndex == 0) { + struct space *space = space_by_id(space_id); + const char *zSpace = space_name(space); + pIndex = sqlite3LocateIndex(db, name, zSpace); + if (pIndex == NULL) { /* This can occur if there exists an index on a TEMP table which * has the same name as another index on a permanent index. Since * the permanent table is hidden by the TEMP table, we can also @@ -147,7 +128,7 @@ sqlite3InitCallback(void *pInit, int argc, char **argv, char **NotUsed) */ /* Do Nothing */ ; } - pIndex->tnum = pageNo; + pIndex->def->iid = index_id; } return 0; } @@ -161,18 +142,18 @@ extern int sqlite3InitDatabase(sqlite3 * db) { int rc; - InitData initData; + struct init_data init; assert(db->pSchema != NULL); - memset(&initData, 0, sizeof(InitData)); - initData.db = db; + memset(&init, 0, sizeof(init)); + init.db = db; /* Load schema from Tarantool - into the primary db only. */ - tarantoolSqlite3LoadSchema(&initData); + tarantoolSqlite3LoadSchema(&init); - if (initData.rc) { - rc = initData.rc; + if (init.rc) { + rc = init.rc; goto error_out; } @@ -185,7 +166,7 @@ sqlite3InitDatabase(sqlite3 * db) */ assert(db->init.busy); { - rc = initData.rc; + rc = init.rc; if (rc == SQLITE_OK) sql_analysis_load(db); } diff --git a/src/box/sql/select.c b/src/box/sql/select.c index e548021..cf25326 100644 --- a/src/box/sql/select.c +++ b/src/box/sql/select.c @@ -4364,8 +4364,7 @@ is_simple_count(struct Select *select, struct AggInfo *agg_info) select->pSrc->nSrc != 1 || select->pSrc->a[0].pSelect != NULL) { return NULL; } - uint32_t space_id = - SQLITE_PAGENO_TO_SPACEID(select->pSrc->a[0].pTab->tnum); + uint32_t space_id = select->pSrc->a[0].pTab->def->id; struct space *space = space_by_id(space_id); assert(space != NULL && !space->def->opts.is_view); struct Expr *expr = select->pEList->a[0].pExpr; diff --git a/src/box/sql/sqliteInt.h b/src/box/sql/sqliteInt.h index f122b3f..b989331 100644 --- a/src/box/sql/sqliteInt.h +++ b/src/box/sql/sqliteInt.h @@ -844,8 +844,7 @@ sqlite3_vfs_find(const char *zVfsName); #define SQLITE_TESTCTRL_BYTEORDER 22 #define SQLITE_TESTCTRL_ISINIT 23 #define SQLITE_TESTCTRL_SORTER_MMAP 24 -#define SQLITE_TESTCTRL_IMPOSTER 25 -#define SQLITE_TESTCTRL_LAST 25 +#define SQLITE_TESTCTRL_LAST 24 int sqlite3_status64(int op, sqlite3_int64 * pCurrent, @@ -1608,7 +1607,8 @@ struct sqlite3 { int aLimit[SQLITE_N_LIMIT]; /* Limits */ int nMaxSorterMmap; /* Maximum size of regions mapped by sorter */ struct sqlite3InitInfo { /* Information used during initialization */ - int newTnum; /* Rootpage of table being initialized */ + uint32_t space_id; + uint32_t index_id; u8 busy; /* TRUE if currently initializing */ u8 orphanTrigger; /* Last statement is orphaned TEMP trigger */ u8 imposterTable; /* Building an imposter table */ @@ -1916,7 +1916,6 @@ struct Table { char *zColAff; /* String defining the affinity of each column */ /* ... also used as column name list in a VIEW */ Hash idxHash; /* All (named) indices indexed by name */ - int tnum; /* Root BTree page for this table */ u32 nTabRef; /* Number of pointers to this Table */ i16 iAutoIncPKey; /* If PK is marked INTEGER PRIMARY KEY AUTOINCREMENT, store column number here, -1 otherwise Tarantool specifics */ @@ -2092,10 +2091,7 @@ enum sql_index_type { * While parsing a CREATE TABLE or CREATE INDEX statement in order to * generate VDBE code (as opposed to reading from Tarantool's _space * space as part of parsing an existing database schema), transient instances - * of this structure may be created. In this case the Index.tnum variable is - * used to store the address of a VDBE instruction, not a database page - * number (it cannot - the database page is not allocated until the VDBE - * program is executed). See convertToWithoutRowidTable() for details. + * of this structure may be created. */ struct Index { /** The SQL table being indexed. */ @@ -2108,8 +2104,6 @@ struct Index { Schema *pSchema; /** WHERE clause for partial indices. */ Expr *pPartIdxWhere; - /** DB Page containing root of this index. */ - int tnum; /** * Conflict resolution algorithm to employ whenever an * attempt is made to insert a non-unique element in @@ -3131,15 +3125,18 @@ struct StrAccum { #define isMalloced(X) (((X)->printfFlags & SQLITE_PRINTF_MALLOCED)!=0) -/* +/** * A pointer to this structure is used to communicate information - * from sqlite3Init and OP_ParseSchema into the sqlite3InitCallback. - */ -typedef struct { - sqlite3 *db; /* The database being initialized */ - char **pzErrMsg; /* Error message stored here */ - int rc; /* Result code stored here */ -} InitData; + * from sqlite3Init and OP_ParseSchema into the sql_init_callback. + */ +struct init_data { + /* The database being initialized */ + sqlite3 *db; + /* Error message stored here */ + char **pzErrMsg; + /* Result code stored here */ + int rc; +}; /* * Structure containing global configuration data for the SQLite library. @@ -3478,7 +3475,25 @@ void sqlite3ExprListSetName(Parse *, ExprList *, Token *, int); void sqlite3ExprListSetSpan(Parse *, ExprList *, ExprSpan *); u32 sqlite3ExprListFlags(const ExprList *); int sqlite3Init(sqlite3 *); -int sqlite3InitCallback(void *, int, char **, char **); + +/** + * This is the callback routine for the code that initializes the + * database. See sqlite3Init() below for additional information. + * This routine is also called from the OP_ParseSchema2 opcode of + * the VDBE. + * + * @param init Initialization context. + * @param name Name of thing being created. + * @param space_id Space identifier. + * @param index_id Index identifier. + * @param sql Text of SQL query. + * + * @retval 0 on success, 1 otherwise. + */ +int +sql_init_callback(struct init_data *init, const char *name, + uint32_t space_id, uint32_t index_id, const char *sql); + void sqlite3Pragma(Parse *, Token *, Token *, Token *, int); void sqlite3ResetAllSchemasOfConnection(sqlite3 *); void sqlite3CommitInternalChanges(); diff --git a/src/box/sql/tarantoolInt.h b/src/box/sql/tarantoolInt.h index f043a60..b34e671 100644 --- a/src/box/sql/tarantoolInt.h +++ b/src/box/sql/tarantoolInt.h @@ -44,7 +44,7 @@ ((pgno) & 1023) /* Load database schema from Tarantool. */ -void tarantoolSqlite3LoadSchema(InitData * init); +void tarantoolSqlite3LoadSchema(struct init_data * init); /* Misc */ const char *tarantoolErrorMessage(); @@ -82,10 +82,24 @@ int sql_delete_by_key(struct space *space, char *key, uint32_t key_size); int tarantoolSqlite3ClearTable(struct space *space); -/* Rename table pTab with zNewName by inserting new tuple to _space. - * SQL statement, which creates table with new name is saved in pzSqlStmt. +/** + * Rename the table in _space. Update tuple with corresponding id + * with new name and statement fields and insert back. If sql_stmt + * is NULL, then return from function after getting length of new + * statement: it is the way how to dynamically allocate memory for + * new statement in VDBE. So basically this function should be + * called twice: firstly to get length of CREATE TABLE statement, + * and secondly to make routine of replacing tuple and filling out + * param sql_stmt with new CREATE TABLE statement. + * + * @param space_id Table's space identifier. + * @param new_name new name of table + * @param[out] sql_stmt CREATE TABLE statement for new name table, can be NULL. + * + * @retval SQLITE_OK on success, SQLITE_TARANTOOL_ERROR otherwise. */ -int tarantoolSqlite3RenameTable(int iTab, const char *zNewName, char **zSqlStmt); +int +sql_rename_table(uint32_t space_id, const char *new_name, char **sql_stmt); /* Alter trigger statement after rename table. */ int tarantoolSqlite3RenameTrigger(const char *zTriggerName, diff --git a/src/box/sql/vdbe.c b/src/box/sql/vdbe.c index 195638e..d07bb00 100644 --- a/src/box/sql/vdbe.c +++ b/src/box/sql/vdbe.c @@ -4615,19 +4615,16 @@ case OP_ResetSorter: { * <name, pageno (which is hash(spaceId, indexId)), sql> */ case OP_ParseSchema2: { - InitData initData; + struct init_data init; Mem *pRec, *pRecEnd; - char *argv[4] = {NULL, NULL, NULL, NULL}; - - assert(db->pSchema != NULL); - initData.db = db; - initData.pzErrMsg = &p->zErrMsg; + init.db = db; + init.pzErrMsg = &p->zErrMsg; assert(db->init.busy==0); db->init.busy = 1; - initData.rc = SQLITE_OK; + init.rc = SQLITE_OK; assert(!db->mallocFailed); pRec = &aMem[pOp->p1]; @@ -4641,16 +4638,12 @@ case OP_ParseSchema2: { * * Uppdate the schema. */ - for( ; pRecEnd-pRec>=4 && initData.rc==SQLITE_OK; pRec+=4) { - argv[0] = pRec[0].z; - int pageNo = SQLITE_PAGENO_FROM_SPACEID_AND_INDEXID(pRec[1].u.i, - pRec[2].u.i); - argv[1] = (char *)&pageNo; - argv[2] = pRec[3].z; - sqlite3InitCallback(&initData, 3, argv, NULL); + for(; pRecEnd - pRec >= 4 && init.rc == SQLITE_OK; pRec += 4) { + sql_init_callback(&init, pRec[0].z, pRec[1].u.i, pRec[2].u.i, + pRec[3].z); } - rc = initData.rc; + rc = init.rc; db->init.busy = 0; if (rc) { @@ -4664,7 +4657,7 @@ case OP_ParseSchema2: { } /* Opcode: RenameTable P1 * * P4 * - * Synopsis: P1 = root, P4 = name + * Synopsis: P1 = space_id, P4 = name * * Rename table P1 with name from P4. * Invoke tarantoolSqlite3RenameTable, which updates tuple with @@ -4676,18 +4669,16 @@ case OP_ParseSchema2: { * */ case OP_RenameTable: { - unsigned space_id; + uint32_t space_id; struct space *space; const char *zOldTableName; const char *zNewTableName; Table *pTab; FKey *pFKey; - int iRootPage; - InitData initData; - char *argv[4] = {NULL, NULL, NULL, NULL}; + struct init_data init; char *zSqlStmt; - space_id = SQLITE_PAGENO_TO_SPACEID(pOp->p1); + space_id = pOp->p1; space = space_by_id(space_id); assert(space); /* Rename space op doesn't change triggers. */ @@ -4696,19 +4687,17 @@ case OP_RenameTable: { assert(zOldTableName); pTab = sqlite3HashFind(&db->pSchema->tblHash, zOldTableName); assert(pTab); - iRootPage = pTab->tnum; zNewTableName = pOp->p4.z; zOldTableName = sqlite3DbStrNDup(db, zOldTableName, sqlite3Strlen30(zOldTableName)); - rc = tarantoolSqlite3RenameTable(pTab->tnum, zNewTableName, - &zSqlStmt); + rc = sql_rename_table(space_id, zNewTableName, &zSqlStmt); if (rc) goto abort_due_to_error; /* If it is parent table, all children statements should be updated. */ for (pFKey = sqlite3FkReferences(pTab); pFKey; pFKey = pFKey->pNextTo) { - assert(pFKey->zTo); - assert(pFKey->pFrom); - rc = tarantoolSqlite3RenameParentTable(pFKey->pFrom->tnum, + assert(pFKey->zTo != NULL); + assert(pFKey->pFrom != NULL); + rc = tarantoolSqlite3RenameParentTable(pFKey->pFrom->def->id, pFKey->zTo, zNewTableName); if (rc) goto abort_due_to_error; @@ -4720,17 +4709,14 @@ case OP_RenameTable: { sqlite3UnlinkAndDeleteTable(db, pTab->def->name); - initData.db = db; - initData.pzErrMsg = &p->zErrMsg; + init.db = db; + init.pzErrMsg = &p->zErrMsg; assert(db->init.busy == 0); db->init.busy = 1; - initData.rc = SQLITE_OK; - argv[0] = (char*) zNewTableName; - argv[1] = (char*) &iRootPage; - argv[2] = zSqlStmt; - sqlite3InitCallback(&initData, 3, argv, NULL); + init.rc = SQLITE_OK; + sql_init_callback(&init, zNewTableName, space_id, 0, zSqlStmt); db->init.busy = 0; - rc = initData.rc; + rc = init.rc; if (rc) { sqlite3CommitInternalChanges(); goto abort_due_to_error; diff --git a/src/box/sql/vdbe.h b/src/box/sql/vdbe.h index 03ae44e..cfcc262 100644 --- a/src/box/sql/vdbe.h +++ b/src/box/sql/vdbe.h @@ -234,7 +234,6 @@ void sqlite3VdbeVerifyNoResultRow(Vdbe * p); VdbeOp *sqlite3VdbeAddOpList(Vdbe *, int nOp, VdbeOpList const *aOp, int iLineno); void sqlite3VdbeAddParseSchema2Op(Vdbe * p, int, int); -void sqlite3VdbeAddRenameTableOp(Vdbe * p, int, char *); void sqlite3VdbeChangeOpcode(Vdbe *, u32 addr, u8); void sqlite3VdbeChangeP1(Vdbe *, u32 addr, int P1); void sqlite3VdbeChangeP2(Vdbe *, u32 addr, int P2); diff --git a/src/box/sql/vdbeaux.c b/src/box/sql/vdbeaux.c index c96157a..c71e0fe 100644 --- a/src/box/sql/vdbeaux.c +++ b/src/box/sql/vdbeaux.c @@ -410,12 +410,6 @@ sqlite3VdbeAddParseSchema2Op(Vdbe * p, int iRec, int n) sqlite3VdbeAddOp3(p, OP_ParseSchema2, iRec, n, 0); } -void -sqlite3VdbeAddRenameTableOp(Vdbe * p, int iTab, char* zNewName) -{ - sqlite3VdbeAddOp4(p, OP_RenameTable, iTab, 0, 0, zNewName, P4_DYNAMIC); -} - /* * Add an opcode that includes the p4 value as an integer. */ @@ -4001,8 +3995,7 @@ sqlite3VdbeRecordUnpackMsgpack(struct key_def *key_def, /* Information about the enum on_conflict_action table_column_nullable_action(struct Table *tab, uint32_t column) { - uint32_t space_id = SQLITE_PAGENO_TO_SPACEID(tab->tnum); - struct space *space = space_cache_find(space_id); + struct space *space = space_cache_find(tab->def->id); assert(space != NULL); diff --git a/src/box/sql/where.c b/src/box/sql/where.c index c115c4a..5d59837 100644 --- a/src/box/sql/where.c +++ b/src/box/sql/where.c @@ -373,11 +373,10 @@ whereScanInit(WhereScan * pScan, /* The WhereScan object being initialized */ if (pIdx != NULL) { int j = iColumn; /* - * pIdx->def->opts.sql == "fake_autoindex" means that + * pIdx->def->iid == UINT32_MAX means that * pIdx is a fake integer primary key index. */ - if (pIdx->def->opts.sql != NULL && - strcmp(pIdx->def->opts.sql, "fake_autoindex") != 0) { + if (pIdx->def->iid != UINT32_MAX) { iColumn = pIdx->def->key_def->parts[iColumn].fieldno; pScan->idxaff = pIdx->pTable->def->fields[iColumn].affinity; @@ -938,10 +937,9 @@ whereKeyStats(Parse * pParse, /* Database connection */ int roundUp, /* Round up if true. Round down if false */ tRowcnt * aStat) /* OUT: stats written here */ { - uint32_t space_id = SQLITE_PAGENO_TO_SPACEID(pIdx->tnum); - struct space *space = space_by_id(space_id); + struct space *space = space_by_id(pIdx->pTable->def->id); assert(space != NULL); - uint32_t iid = SQLITE_PAGENO_TO_INDEXID(pIdx->tnum); + uint32_t iid = pIdx->def->iid; struct index *idx = space_index(space, iid); assert(idx != NULL && idx->def->opts.stat != NULL); struct index_sample *samples = idx->def->opts.stat->samples; @@ -1217,10 +1215,9 @@ whereRangeSkipScanEst(Parse * pParse, /* Parsing & code generating context */ int *pbDone) /* Set to true if at least one expr. value extracted */ { Index *p = pLoop->pIndex; - struct space *space = space_by_id(SQLITE_PAGENO_TO_SPACEID(p->tnum)); + struct space *space = space_by_id(p->pTable->def->id); assert(space != NULL); - struct index *index = space_index(space, - SQLITE_PAGENO_TO_INDEXID(p->tnum)); + struct index *index = space_index(space, p->def->iid); assert(index != NULL && index->def->opts.stat != NULL); int nEq = pLoop->nEq; sqlite3 *db = pParse->db; @@ -1348,11 +1345,10 @@ whereRangeScanEst(Parse * pParse, /* Parsing & code generating context */ Index *p = pLoop->pIndex; int nEq = pLoop->nEq; - uint32_t space_id = SQLITE_PAGENO_TO_SPACEID(p->tnum); + uint32_t space_id = p->pTable->def->id; struct space *space = space_by_id(space_id); assert(space != NULL); - uint32_t iid = SQLITE_PAGENO_TO_INDEXID(p->tnum); - struct index *idx = space_index(space, iid); + struct index *idx = space_index(space, p->def->iid); assert(idx != NULL); struct index_stat *stat = idx->def->opts.stat; /* @@ -1406,14 +1402,11 @@ whereRangeScanEst(Parse * pParse, /* Parsing & code generating context */ * are in range. */ iLower = 0; - uint32_t space_id = - SQLITE_PAGENO_TO_SPACEID(p->tnum); + uint32_t space_id = p->def->space_id; struct space *space = space_by_id(space_id); assert(space != NULL); - uint32_t iid = - SQLITE_PAGENO_TO_INDEXID(p->tnum); struct index *idx = - space_index(space, iid); + space_index(space, p->def->iid); assert(idx != NULL); iUpper = index_size(idx); } else { @@ -2178,8 +2171,8 @@ whereLoopInsert(WhereLoopBuilder * pBuilder, WhereLoop * pTemplate) } rc = whereLoopXfer(db, p, pTemplate); Index *pIndex = p->pIndex; - if (pIndex && pIndex->tnum == 0) - p->pIndex = 0; + if (pIndex != NULL && pIndex->pTable->def->opts.is_view) + p->pIndex = NULL; return rc; } @@ -2347,8 +2340,8 @@ whereRangeVectorLen(Parse * pParse, /* Parsing context */ * terms only. If it is modified, this value is restored before this * function returns. * - * If pProbe->tnum==0, that means pIndex is a fake index used for the - * INTEGER PRIMARY KEY. + * If pProbe->def->space_id==0, that means pIndex is a fake index + * used for the INTEGER PRIMARY KEY. */ static int whereLoopAddBtreeIndex(WhereLoopBuilder * pBuilder, /* The WhereLoop factory */ @@ -2391,12 +2384,11 @@ whereLoopAddBtreeIndex(WhereLoopBuilder * pBuilder, /* The WhereLoop factory */ opMask = WO_EQ | WO_IN | WO_GT | WO_GE | WO_LT | WO_LE | WO_ISNULL; } - struct space *space = - space_by_id(SQLITE_PAGENO_TO_SPACEID(pProbe->tnum)); + struct space *space = space_by_id(pProbe->def->space_id); struct index *idx = NULL; struct index_stat *stat = NULL; - if (space != NULL) { - idx = space_index(space, SQLITE_PAGENO_TO_INDEXID(pProbe->tnum)); + if (space != NULL && pProbe->def->iid != UINT32_MAX) { + idx = space_index(space, pProbe->def->iid); assert(idx != NULL); stat = idx->def->opts.stat; } @@ -2514,7 +2506,7 @@ whereLoopAddBtreeIndex(WhereLoopBuilder * pBuilder, /* The WhereLoop factory */ bool index_is_unique_not_null = pProbe->def->key_def->is_nullable && pProbe->def->opts.is_unique; - if (pProbe->tnum != 0 && + if (pProbe->def->space_id != 0 && !index_is_unique_not_null) { pNew->wsFlags |= WHERE_UNQ_WANTED; } else { @@ -2577,7 +2569,7 @@ whereLoopAddBtreeIndex(WhereLoopBuilder * pBuilder, /* The WhereLoop factory */ assert(eOp & (WO_ISNULL | WO_EQ | WO_IN)); assert(pNew->nOut == saved_nOut); - if (pTerm->truthProb <= 0 && pProbe->tnum != 0 ) { + if (pTerm->truthProb <= 0 && !pProbe->pTable->def->opts.is_view) { assert((eOp & WO_IN) || nIn == 0); testcase(eOp & WO_IN); pNew->nOut += pTerm->truthProb; @@ -2639,11 +2631,10 @@ whereLoopAddBtreeIndex(WhereLoopBuilder * pBuilder, /* The WhereLoop factory */ * visiting the rows in the main table. */ struct space *space = - space_by_id(SQLITE_PAGENO_TO_SPACEID(pProbe->tnum)); + space_by_id(pProbe->pTable->def->id); assert(space != NULL); struct index *idx = - space_index(space, - SQLITE_PAGENO_TO_INDEXID(pProbe->tnum)); + space_index(space, pProbe->def->iid); assert(idx != NULL); /* * FIXME: currently, the procedure below makes no @@ -2750,11 +2741,10 @@ static bool index_is_unordered(struct Index *idx) { assert(idx != NULL); - struct space *space = space_by_id(SQLITE_PAGENO_TO_SPACEID(idx->tnum)); + struct space *space = space_by_id(idx->pTable->def->id); if (space == NULL) return false; - uint32_t iid = SQLITE_PAGENO_TO_INDEXID(idx->tnum); - struct index *tnt_idx = space_index(space, iid); + struct index *tnt_idx = space_index(space, idx->def->iid); if (tnt_idx == NULL) return false; if (tnt_idx->def->opts.stat != NULL) @@ -2920,6 +2910,8 @@ whereLoopAddBtree(WhereLoopBuilder * pBuilder, /* WHERE clause information */ sizeof("fake_autoindex") - 1, TREE, &opts, key_def, NULL); key_def_delete(key_def); + /* Special marker for non-existent index. */ + fake_index.def->iid = UINT32_MAX; if (fake_index.def == NULL) { pWInfo->pParse->nErr++; @@ -3026,7 +3018,7 @@ whereLoopAddBtree(WhereLoopBuilder * pBuilder, /* WHERE clause information */ /* The ONEPASS_DESIRED flags never occurs together with ORDER BY */ assert((pWInfo->wctrlFlags & WHERE_ONEPASS_DESIRED) == 0 || b == 0); - if (pProbe->tnum <= 0) { + if (pProbe->def->iid == UINT32_MAX) { /* Integer primary key index */ pNew->wsFlags = WHERE_IPK; @@ -4778,15 +4770,12 @@ sqlite3WhereBegin(Parse * pParse, /* The parser context */ if (op) { if (pIx != NULL) { uint32_t space_id = - SQLITE_PAGENO_TO_SPACEID(pIx-> - tnum); + pIx->pTable->def->id; struct space *space = space_by_id(space_id); - uint32_t idx_id = - SQLITE_PAGENO_TO_INDEXID(pIx-> - tnum); vdbe_emit_open_cursor(pParse, iIndexCur, - idx_id, space); + pIx->def->iid, + space); } else { vdbe_emit_open_cursor(pParse, iIndexCur, idx_def->iid, -- 2.16.2 ^ permalink raw reply [flat|nested] 5+ messages in thread
* [tarantool-patches] Re: [PATCH] sql: get rid off tnum field of struct Table 2018-07-20 11:37 [tarantool-patches] [PATCH] sql: get rid off tnum field of struct Table Kirill Yukhin @ 2018-07-20 14:07 ` n.pettik 2018-07-20 14:32 ` Kirill Yukhin 2018-07-20 16:53 ` Kirill Yukhin 1 sibling, 1 reply; 5+ messages in thread From: n.pettik @ 2018-07-20 14:07 UTC (permalink / raw) To: tarantool-patches; +Cc: Kirill Yukhin > diff --git a/src/box/sql/insert.c b/src/box/sql/insert.c > index 3af9f9a..504701d 100644 > --- a/src/box/sql/insert.c > +++ b/src/box/sql/insert.c > @@ -384,7 +384,7 @@ sqlite3Insert(Parse * pParse, /* Parser context */ > if (pTab == NULL) > goto insert_cleanup; > > - space_id = SQLITE_PAGENO_TO_SPACEID(pTab->tnum); > + space_id = pTab->def->id; > > /* Figure out if we have any triggers and if the table being > * inserted into is a view > @@ -742,7 +742,7 @@ sqlite3Insert(Parse * pParse, /* Parser context */ > if (i == pTab->iAutoIncPKey) { > sqlite3VdbeAddOp2(v, > OP_NextAutoincValue, > - pTab->tnum, > + SQLITE_PAGENO_FROM_SPACEID_AND_INDEXID(pTab->def->id, 0), It looks disgusting.. Lets also refactor OP_NextAutoincValue so that it accepts raw space_id. After that, remove these SQLITE_PAGENO macroses at all. > diff --git a/src/box/sql/pragma.c b/src/box/sql/pragma.c > index cabe22b..0c838fa 100644 > --- a/src/box/sql/pragma.c > +++ b/src/box/sql/pragma.c > @@ -432,9 +432,8 @@ sqlite3Pragma(Parse * pParse, Token * pId, /* First part of [schema.]id field */ > for (i = sqliteHashFirst(&db->pSchema->tblHash); i; > i = sqliteHashNext(i)) { > Table *pTab = sqliteHashData(i); > - uint32_t space_id = > - SQLITE_PAGENO_TO_SPACEID(pTab->tnum); > - struct space *space = space_by_id(space_id); > + struct space *space; > + space = space_by_id(pTab->def->id); Squash two lines into one: struct space *space = space_by_id(pTab->def->id); > @@ -161,18 +142,18 @@ extern int > sqlite3InitDatabase(sqlite3 * db) > { > int rc; > - InitData initData; > + struct init_data init; > > assert(db->pSchema != NULL); > > - memset(&initData, 0, sizeof(InitData)); > - initData.db = db; > + memset(&init, 0, sizeof(init)); > + init.db = db; > > /* Load schema from Tarantool - into the primary db only. */ > - tarantoolSqlite3LoadSchema(&initData); > + tarantoolSqlite3LoadSchema(&init); > > - if (initData.rc) { > - rc = initData.rc; > + if (init.rc) { > + rc = init.rc; > goto error_out; > } > > -/* > +/** > * A pointer to this structure is used to communicate information > - * from sqlite3Init and OP_ParseSchema into the sqlite3InitCallback. > - */ > -typedef struct { > - sqlite3 *db; /* The database being initialized */ > - char **pzErrMsg; /* Error message stored here */ > - int rc; /* Result code stored here */ > -} InitData; > + * from sqlite3Init and OP_ParseSchema into the sql_init_callback. > + */ > +struct init_data { > + /* The database being initialized */ > + sqlite3 *db; > + /* Error message stored here */ > + char **pzErrMsg; > + /* Result code stored here */ Comments inside struct definition should look like: /** … */ And put dot at the end of sentences. > > diff --git a/src/box/sql/tarantoolInt.h b/src/box/sql/tarantoolInt.h > index f043a60..b34e671 100644 > --- a/src/box/sql/tarantoolInt.h > +++ b/src/box/sql/tarantoolInt.h > @@ -44,7 +44,7 @@ > ((pgno) & 1023) > > /* Load database schema from Tarantool. */ > -void tarantoolSqlite3LoadSchema(InitData * init); > +void tarantoolSqlite3LoadSchema(struct init_data * init); struct init_data *init — remove extra space. > @@ -2178,8 +2171,8 @@ whereLoopInsert(WhereLoopBuilder * pBuilder, WhereLoop * pTemplate) > } > rc = whereLoopXfer(db, p, pTemplate); > Index *pIndex = p->pIndex; > - if (pIndex && pIndex->tnum == 0) > - p->pIndex = 0; > + if (pIndex != NULL && pIndex->pTable->def->opts.is_view) > + p->pIndex = NULL; > return rc; > } These conditions don’t seem to be equivalent: view features ordinary space_id AFAIK. > > @@ -2347,8 +2340,8 @@ whereRangeVectorLen(Parse * pParse, /* Parsing context */ > * terms only. If it is modified, this value is restored before this > * function returns. > * > - * If pProbe->tnum==0, that means pIndex is a fake index used for the > - * INTEGER PRIMARY KEY. > + * If pProbe->def->space_id==0, that means pIndex is a fake index > + * used for the INTEGER PRIMARY KEY. But in fact you use another sign of fake index: iid == UINT32_MAX > */ > static int > whereLoopAddBtreeIndex(WhereLoopBuilder * pBuilder, /* The WhereLoop factory */ > @@ -2391,12 +2384,11 @@ whereLoopAddBtreeIndex(WhereLoopBuilder * pBuilder, /* The WhereLoop factory */ > opMask = > WO_EQ | WO_IN | WO_GT | WO_GE | WO_LT | WO_LE | WO_ISNULL; > } > - struct space *space = > - space_by_id(SQLITE_PAGENO_TO_SPACEID(pProbe->tnum)); > + struct space *space = space_by_id(pProbe->def->space_id); > struct index *idx = NULL; > struct index_stat *stat = NULL; > - if (space != NULL) { > - idx = space_index(space, SQLITE_PAGENO_TO_INDEXID(pProbe->tnum)); > + if (space != NULL && pProbe->def->iid != UINT32_MAX) { > + idx = space_index(space, pProbe->def->iid); > assert(idx != NULL); > stat = idx->def->opts.stat; > } > > @@ -2577,7 +2569,7 @@ whereLoopAddBtreeIndex(WhereLoopBuilder * pBuilder, /* The WhereLoop factory */ > assert(eOp & (WO_ISNULL | WO_EQ | WO_IN)); > > assert(pNew->nOut == saved_nOut); > - if (pTerm->truthProb <= 0 && pProbe->tnum != 0 ) { > + if (pTerm->truthProb <= 0 && !pProbe->pTable->def->opts.is_view) { The same as previous remark: these conditions don’t seem to be equivalent ^ permalink raw reply [flat|nested] 5+ messages in thread
* [tarantool-patches] Re: [PATCH] sql: get rid off tnum field of struct Table 2018-07-20 14:07 ` [tarantool-patches] " n.pettik @ 2018-07-20 14:32 ` Kirill Yukhin 2018-07-20 16:12 ` n.pettik 0 siblings, 1 reply; 5+ messages in thread From: Kirill Yukhin @ 2018-07-20 14:32 UTC (permalink / raw) To: n.pettik; +Cc: tarantool-patches Hello Nikita, Thanks for review. Answers inlined. Updated patch in the bottom. On 20 июл 17:07, n.pettik wrote: > > > diff --git a/src/box/sql/insert.c b/src/box/sql/insert.c > > index 3af9f9a..504701d 100644 > > --- a/src/box/sql/insert.c > > +++ b/src/box/sql/insert.c > > @@ -384,7 +384,7 @@ sqlite3Insert(Parse * pParse, /* Parser context */ > > if (pTab == NULL) > > goto insert_cleanup; > > > > - space_id = SQLITE_PAGENO_TO_SPACEID(pTab->tnum); > > + space_id = pTab->def->id; > > > > /* Figure out if we have any triggers and if the table being > > * inserted into is a view > > @@ -742,7 +742,7 @@ sqlite3Insert(Parse * pParse, /* Parser context */ > > if (i == pTab->iAutoIncPKey) { > > sqlite3VdbeAddOp2(v, > > OP_NextAutoincValue, > > - pTab->tnum, > > + SQLITE_PAGENO_FROM_SPACEID_AND_INDEXID(pTab->def->id, 0), > > It looks disgusting.. Lets also refactor OP_NextAutoincValue so that > it accepts raw space_id. After that, remove these SQLITE_PAGENO > macroses at all. All macros removed. > > diff --git a/src/box/sql/pragma.c b/src/box/sql/pragma.c > > index cabe22b..0c838fa 100644 > > --- a/src/box/sql/pragma.c > > +++ b/src/box/sql/pragma.c > > @@ -432,9 +432,8 @@ sqlite3Pragma(Parse * pParse, Token * pId, /* First part of [schema.]id field */ > > for (i = sqliteHashFirst(&db->pSchema->tblHash); i; > > i = sqliteHashNext(i)) { > > Table *pTab = sqliteHashData(i); > > - uint32_t space_id = > > - SQLITE_PAGENO_TO_SPACEID(pTab->tnum); > > - struct space *space = space_by_id(space_id); > > + struct space *space; > > + space = space_by_id(pTab->def->id); > Squash two lines into one: > struct space *space = space_by_id(pTab->def->id); Done. > > @@ -161,18 +142,18 @@ extern int > > sqlite3InitDatabase(sqlite3 * db) > > { > > int rc; > > - InitData initData; > > + struct init_data init; > > > > assert(db->pSchema != NULL); > > > > - memset(&initData, 0, sizeof(InitData)); > > - initData.db = db; > > + memset(&init, 0, sizeof(init)); > > + init.db = db; > > > > /* Load schema from Tarantool - into the primary db only. */ > > - tarantoolSqlite3LoadSchema(&initData); > > + tarantoolSqlite3LoadSchema(&init); > > > > - if (initData.rc) { > > - rc = initData.rc; > > + if (init.rc) { > > + rc = init.rc; > > goto error_out; > > } > > > > -/* > > +/** > > * A pointer to this structure is used to communicate information > > - * from sqlite3Init and OP_ParseSchema into the sqlite3InitCallback. > > - */ > > -typedef struct { > > - sqlite3 *db; /* The database being initialized */ > > - char **pzErrMsg; /* Error message stored here */ > > - int rc; /* Result code stored here */ > > -} InitData; > > + * from sqlite3Init and OP_ParseSchema into the sql_init_callback. > > + */ > > +struct init_data { > > + /* The database being initialized */ > > + sqlite3 *db; > > + /* Error message stored here */ > > + char **pzErrMsg; > > + /* Result code stored here */ > > Comments inside struct definition should look like: > /** … */ > And put dot at the end of sentences. Done. > > diff --git a/src/box/sql/tarantoolInt.h b/src/box/sql/tarantoolInt.h > > index f043a60..b34e671 100644 > > --- a/src/box/sql/tarantoolInt.h > > +++ b/src/box/sql/tarantoolInt.h > > @@ -44,7 +44,7 @@ > > ((pgno) & 1023) > > > > /* Load database schema from Tarantool. */ > > -void tarantoolSqlite3LoadSchema(InitData * init); > > +void tarantoolSqlite3LoadSchema(struct init_data * init); > struct init_data *init — remove extra space. Done. > > @@ -2178,8 +2171,8 @@ whereLoopInsert(WhereLoopBuilder * pBuilder, WhereLoop * pTemplate) > > } > > rc = whereLoopXfer(db, p, pTemplate); > > Index *pIndex = p->pIndex; > > - if (pIndex && pIndex->tnum == 0) > > - p->pIndex = 0; > > + if (pIndex != NULL && pIndex->pTable->def->opts.is_view) > > + p->pIndex = NULL; > > return rc; > > } > These conditions don’t seem to be equivalent: view features ordinary space_id AFAIK. Fixed. > > @@ -2347,8 +2340,8 @@ whereRangeVectorLen(Parse * pParse, /* Parsing context */ > > * terms only. If it is modified, this value is restored before this > > * function returns. > > * > > - * If pProbe->tnum==0, that means pIndex is a fake index used for the > > - * INTEGER PRIMARY KEY. > > + * If pProbe->def->space_id==0, that means pIndex is a fake index > > + * used for the INTEGER PRIMARY KEY. > But in fact you use another sign of fake index: > iid == UINT32_MAX Updated comment. > > */ > > static int > > whereLoopAddBtreeIndex(WhereLoopBuilder * pBuilder, /* The WhereLoop factory */ > > @@ -2391,12 +2384,11 @@ whereLoopAddBtreeIndex(WhereLoopBuilder * pBuilder, /* The WhereLoop factory */ > > opMask = > > WO_EQ | WO_IN | WO_GT | WO_GE | WO_LT | WO_LE | WO_ISNULL; > > } > > - struct space *space = > > - space_by_id(SQLITE_PAGENO_TO_SPACEID(pProbe->tnum)); > > + struct space *space = space_by_id(pProbe->def->space_id); > > struct index *idx = NULL; > > struct index_stat *stat = NULL; > > - if (space != NULL) { > > - idx = space_index(space, SQLITE_PAGENO_TO_INDEXID(pProbe->tnum)); > > + if (space != NULL && pProbe->def->iid != UINT32_MAX) { > > + idx = space_index(space, pProbe->def->iid); > > assert(idx != NULL); > > stat = idx->def->opts.stat; > > } > > > > @@ -2577,7 +2569,7 @@ whereLoopAddBtreeIndex(WhereLoopBuilder * pBuilder, /* The WhereLoop factory */ > > assert(eOp & (WO_ISNULL | WO_EQ | WO_IN)); > > > > assert(pNew->nOut == saved_nOut); > > - if (pTerm->truthProb <= 0 && pProbe->tnum != 0 ) { > > + if (pTerm->truthProb <= 0 && !pProbe->pTable->def->opts.is_view) { > > The same as previous remark: these conditions don’t seem to be equivalent Fixed. -- Regards, Kirill Yukhin commit 3856d92e699ca9e3320f64ec4c1e3d695e5d1a18 Author: Kirill Yukhin <kyukhin@tarantool.org> Date: Tue Jul 17 15:37:46 2018 +0300 sql: get rid off tnum field of struct Table Basic structures (struct Table/Index) of legacy SQL's data dictionary used to so-called tnum to refer to engine's btree structures. Tarantool used this field to store composition of space_id and index_id. Recently both structures incorporated native space_def/index_def descriptors. This patch finally removes tnum field. It also refactors init_callback machinery, removing varargs from declarations. Closes #3482 diff --git a/src/box/sql.c b/src/box/sql.c index d2cc0a9..d48c3cf 100644 --- a/src/box/sql.c +++ b/src/box/sql.c @@ -726,28 +726,13 @@ rename_fail: return SQL_TARANTOOL_ERROR; } -/* - * Rename the table in _space. Update tuple with corresponding id with - * new name and statement fields and insert back. If sql_stmt is NULL, - * then return from function after getting length of new statement: - * it is the way how to dynamically allocate memory for new statement in VDBE. - * So basically this function should be called twice: firstly to get length of - * CREATE TABLE statement, and secondly to make routine of replacing tuple and - * filling out param sql_stmt with new CREATE TABLE statement. - * - * @param iTab pageno of table to be renamed - * @param new_name new name of table - * @param[out] sql_stmt CREATE TABLE statement for new name table, can be NULL. - * - * @retval SQLITE_OK on success, SQLITE_TARANTOOL_ERROR otherwise. - */ -int tarantoolSqlite3RenameTable(int iTab, const char *new_name, char **sql_stmt) +int +sql_rename_table(uint32_t space_id, const char *new_name, char **sql_stmt) { - assert(iTab > 0); - assert(new_name); - assert(sql_stmt); + assert(space_id != 0); + assert(new_name != NULL); + assert(sql_stmt != NULL); - int space_id = SQLITE_PAGENO_TO_SPACEID(iTab); box_tuple_t *tuple; uint32_t key_len = mp_sizeof_uint(space_id) + mp_sizeof_array(1); char *key_begin = (char*) region_alloc(&fiber()->gc, key_len); @@ -858,14 +843,13 @@ rename_fail: * Acts almost as tarantoolSqlite3RenameTable, but doesn't change * name of table, only statement. */ -int tarantoolSqlite3RenameParentTable(int iTab, const char *old_parent_name, +int tarantoolSqlite3RenameParentTable(int space_id, const char *old_parent_name, const char *new_parent_name) { - assert(iTab > 0); - assert(old_parent_name); - assert(new_parent_name); + assert(space_id != 0); + assert(old_parent_name != NULL); + assert(new_parent_name != NULL); - int space_id = SQLITE_PAGENO_TO_SPACEID(iTab); box_tuple_t *tuple; uint32_t key_len = mp_sizeof_uint(space_id) + mp_sizeof_array(1); @@ -1181,63 +1165,34 @@ cursor_advance(BtCursor *pCur, int *pRes) * Schema support. */ -/* - * Manully add objects to SQLite in-memory schema. - * This is loosely based on sqlite_master row format. - * @Params - * name - object name - * id - SQLITE_PAGENO_FROM_SPACEID_INDEXID(...) - * for tables and indices - * sql - SQL statement that created this object - */ -static void -sql_schema_put(InitData *init, - const char *name, - uint32_t spaceid, uint32_t indexid, - const char *sql) -{ - int pageno = SQLITE_PAGENO_FROM_SPACEID_AND_INDEXID(spaceid, indexid); - - char *argv[] = { - (char *)name, - (char *)&pageno, - (char *)sql, - NULL - }; - - if (init->rc != SQLITE_OK) return; - - sqlite3InitCallback(init, 3, argv, NULL); -} - static int space_foreach_put_cb(struct space *space, void *udata) { if (space->def->opts.sql == NULL) return 0; /* Not SQL space. */ - sql_schema_put((InitData *) udata, space->def->name, space->def->id, 0, - space->def->opts.sql); + sql_init_callback((struct init_data *) udata, space->def->name, + space->def->id, 0, space->def->opts.sql); for (uint32_t i = 0; i < space->index_count; ++i) { struct index_def *def = space_index_def(space, i); if (def->opts.sql != NULL) { - sql_schema_put((InitData *) udata, def->name, - def->space_id, def->iid, def->opts.sql); + sql_init_callback((struct init_data *) udata, def->name, + def->space_id, def->iid, def->opts.sql); } } return 0; } /* Load database schema from Tarantool. */ -void tarantoolSqlite3LoadSchema(InitData *init) +void tarantoolSqlite3LoadSchema(struct init_data *init) { - sql_schema_put( + sql_init_callback( init, TARANTOOL_SYS_SCHEMA_NAME, BOX_SCHEMA_ID, 0, "CREATE TABLE \""TARANTOOL_SYS_SCHEMA_NAME "\" (\"key\" TEXT PRIMARY KEY, \"value\")" ); - sql_schema_put( + sql_init_callback( init, TARANTOOL_SYS_SPACE_NAME, BOX_SPACE_ID, 0, "CREATE TABLE \""TARANTOOL_SYS_SPACE_NAME @@ -1245,7 +1200,7 @@ void tarantoolSqlite3LoadSchema(InitData *init) "\"engine\" TEXT, \"field_count\" INT, \"opts\", \"format\")" ); - sql_schema_put( + sql_init_callback( init, TARANTOOL_SYS_INDEX_NAME, BOX_INDEX_ID, 0, "CREATE TABLE \""TARANTOOL_SYS_INDEX_NAME"\" " @@ -1253,38 +1208,41 @@ void tarantoolSqlite3LoadSchema(InitData *init) "\"opts\", \"parts\", PRIMARY KEY (\"id\", \"iid\"))" ); - sql_schema_put( + sql_init_callback( init, TARANTOOL_SYS_TRIGGER_NAME, BOX_TRIGGER_ID, 0, "CREATE TABLE \""TARANTOOL_SYS_TRIGGER_NAME"\" (" "\"name\" TEXT PRIMARY KEY, \"space_id\" INT, \"opts\")" ); - sql_schema_put( + sql_init_callback( init, TARANTOOL_SYS_TRUNCATE_NAME, BOX_TRUNCATE_ID, 0, "CREATE TABLE \""TARANTOOL_SYS_TRUNCATE_NAME "\" (\"id\" INT PRIMARY KEY, \"count\" INT NOT NULL)" ); - sql_schema_put(init, TARANTOOL_SYS_SEQUENCE_NAME, BOX_SEQUENCE_ID, 0, - "CREATE TABLE \""TARANTOOL_SYS_SEQUENCE_NAME - "\" (\"id\" INT PRIMARY KEY, \"uid\" INT, \"name\" TEXT, \"step\" INT, " - "\"max\" INT, \"min\" INT, \"start\" INT, \"cache\" INT, \"cycle\" INT)"); + sql_init_callback(init, TARANTOOL_SYS_SEQUENCE_NAME, BOX_SEQUENCE_ID, 0, + "CREATE TABLE \""TARANTOOL_SYS_SEQUENCE_NAME + "\" (\"id\" INT PRIMARY KEY, \"uid\" INT, \"name\" TEXT, \"step\" INT, " + "\"max\" INT, \"min\" INT, \"start\" INT, \"cache\" INT, \"cycle\" INT)"); - sql_schema_put(init, TARANTOOL_SYS_SPACE_SEQUENCE_NAME, BOX_SPACE_SEQUENCE_ID, 0, - "CREATE TABLE \""TARANTOOL_SYS_SPACE_SEQUENCE_NAME - "\" (\"space_id\" INT PRIMARY KEY, \"sequence_id\" INT, \"flag\" INT)"); + sql_init_callback(init, TARANTOOL_SYS_SPACE_SEQUENCE_NAME, + BOX_SPACE_SEQUENCE_ID, 0, + "CREATE TABLE \""TARANTOOL_SYS_SPACE_SEQUENCE_NAME + "\" (\"space_id\" INT PRIMARY KEY, \"sequence_id\" INT, \"flag\" INT)"); - sql_schema_put(init, TARANTOOL_SYS_SQL_STAT1_NAME, BOX_SQL_STAT1_ID, 0, - "CREATE TABLE \""TARANTOOL_SYS_SQL_STAT1_NAME + sql_init_callback(init, TARANTOOL_SYS_SQL_STAT1_NAME, + BOX_SQL_STAT1_ID, 0, + "CREATE TABLE \""TARANTOOL_SYS_SQL_STAT1_NAME "\"(\"tbl\" text," "\"idx\" text," "\"stat\" not null," "PRIMARY KEY(\"tbl\", \"idx\"))"); - sql_schema_put(init, TARANTOOL_SYS_SQL_STAT4_NAME, BOX_SQL_STAT4_ID, 0, - "CREATE TABLE \""TARANTOOL_SYS_SQL_STAT4_NAME + sql_init_callback(init, TARANTOOL_SYS_SQL_STAT4_NAME, + BOX_SQL_STAT4_ID, 0, + "CREATE TABLE \""TARANTOOL_SYS_SQL_STAT4_NAME "\"(\"tbl\" text," "\"idx\" text," "\"neq\" text," diff --git a/src/box/sql/alter.c b/src/box/sql/alter.c index fe54e55..8c1c36b 100644 --- a/src/box/sql/alter.c +++ b/src/box/sql/alter.c @@ -60,7 +60,8 @@ reloadTableSchema(Parse * pParse, Table * pTab, const char *zName) return; char *zNewName = sqlite3MPrintf(pParse->db, "%s", zName); - sqlite3VdbeAddRenameTableOp(v, pTab->tnum, zNewName); + sqlite3VdbeAddOp4(v, OP_RenameTable, pTab->def->id, 0, 0, zNewName, + P4_DYNAMIC); } /* @@ -163,7 +164,7 @@ sqlite3AlterFinishAddColumn(Parse * pParse, Token * pColDef) zTab = &pNew->def->name[16]; pCol = &pNew->aCol[pNew->def->field_count - 1]; assert(pNew->def != NULL); - pDflt = space_column_default_expr(SQLITE_PAGENO_TO_SPACEID(pNew->tnum), + pDflt = space_column_default_expr(pNew->def->id, pNew->def->field_count - 1); pTab = sqlite3HashFind(&db->pSchema->tblHash, zTab);; assert(pTab); diff --git a/src/box/sql/analyze.c b/src/box/sql/analyze.c index 36648b3..00d96d2 100644 --- a/src/box/sql/analyze.c +++ b/src/box/sql/analyze.c @@ -803,7 +803,7 @@ analyzeOneTable(Parse * pParse, /* Parser context */ if (v == 0 || NEVER(pTab == 0)) { return; } - assert(pTab->tnum != 0); + assert(pTab->def->id != 0); if (sqlite3_strlike("\\_%", pTab->def->name, '\\') == 0) { /* Do not gather statistics on system tables */ return; @@ -882,9 +882,8 @@ analyzeOneTable(Parse * pParse, /* Parser context */ pParse->nMem = MAX(pParse->nMem, regPrev + part_count); /* Open a read-only cursor on the index being analyzed. */ - struct space *space = - space_by_id(SQLITE_PAGENO_TO_SPACEID(pIdx->tnum)); - int idx_id = SQLITE_PAGENO_TO_INDEXID(pIdx->tnum); + struct space *space = space_by_id(pIdx->def->space_id); + int idx_id = pIdx->def->iid; assert(space != NULL); sqlite3VdbeAddOp4(v, OP_OpenRead, iIdxCur, idx_id, 0, (void *) space, P4_SPACEPTR); @@ -1624,7 +1623,7 @@ const log_est_t default_tuple_est[] = {DEFAULT_TUPLE_LOG_COUNT, LogEst sql_space_tuple_log_count(struct Table *tab) { - struct space *space = space_by_id(SQLITE_PAGENO_TO_SPACEID(tab->tnum)); + struct space *space = space_by_id(tab->def->id); if (space == NULL) return tab->tuple_log_count; struct index *pk = space_index(space, 0); @@ -1638,11 +1637,10 @@ sql_space_tuple_log_count(struct Table *tab) log_est_t index_field_tuple_est(struct Index *idx, uint32_t field) { - struct space *space = space_by_id(SQLITE_PAGENO_TO_SPACEID(idx->tnum)); - if (space == NULL) + struct space *space = space_by_id(idx->pTable->def->id); + if (space == NULL || strcmp(idx->def->opts.sql, "fake_autoindex") == 0) return idx->def->opts.stat->tuple_log_est[field]; - struct index *tnt_idx = - space_index(space, SQLITE_PAGENO_TO_INDEXID(idx->tnum)); + struct index *tnt_idx = space_index(space, idx->def->iid); assert(tnt_idx != NULL); assert(field <= tnt_idx->def->key_def->part_count); if (tnt_idx->def->opts.stat == NULL) { diff --git a/src/box/sql/build.c b/src/box/sql/build.c index cb7f1e4..755208b 100644 --- a/src/box/sql/build.c +++ b/src/box/sql/build.c @@ -278,8 +278,7 @@ sqlite3CommitInternalChanges() bool table_column_is_in_pk(Table *table, uint32_t column) { - uint32_t space_id = SQLITE_PAGENO_TO_SPACEID(table->tnum); - struct space *space = space_by_id(space_id); + struct space *space = space_by_id(table->def->id); assert(space != NULL); struct index *primary_idx = index_find(space, 0 /* PK */); @@ -1598,8 +1597,10 @@ sqlite3EndTable(Parse * pParse, /* Parse context */ * schema. */ if (db->init.busy) { - p->tnum = db->init.newTnum; - p->def->id = SQLITE_PAGENO_TO_SPACEID(p->tnum); + p->def->id = db->init.space_id; + for(struct Index *idx = p->pIndex; idx != NULL; + idx = idx->pNext) + idx->def->space_id = p->def->id; } if (!p->def->opts.is_view) { @@ -2257,15 +2258,9 @@ sqlite3DeferForeignKey(Parse * pParse, int isDeferred) * Generate code that will erase and refill index *pIdx. This is * used to initialize a newly created index or to recompute the * content of an index in response to a REINDEX command. - * - * if memRootPage is not negative, it means that the index is newly - * created. The register specified by memRootPage contains the - * root page number of the index. If memRootPage is negative, then - * the index already exists and must be cleared before being refilled and - * the root page number of the index is taken from pIndex->tnum. */ static void -sqlite3RefillIndex(Parse * pParse, Index * pIndex, int memRootPage) +sqlite3RefillIndex(Parse * pParse, Index * pIndex) { Table *pTab = pIndex->pTable; /* The table that is indexed */ int iTab = pParse->nTab++; /* Btree cursor used for pTab */ @@ -2273,7 +2268,6 @@ sqlite3RefillIndex(Parse * pParse, Index * pIndex, int memRootPage) int iSorter; /* Cursor opened by OpenSorter (if in use) */ int addr1; /* Address of top of loop */ int addr2; /* Address to jump to for next iteration */ - int tnum; /* Root page of index */ int iPartIdxLabel; /* Jump to this label to skip a row */ Vdbe *v; /* Generate code into this virtual machine */ int regRecord; /* Register holding assembled index record */ @@ -2281,11 +2275,6 @@ sqlite3RefillIndex(Parse * pParse, Index * pIndex, int memRootPage) v = sqlite3GetVdbe(pParse); if (v == 0) return; - if (memRootPage >= 0) { - tnum = memRootPage; - } else { - tnum = pIndex->tnum; - } struct key_def *def = key_def_dup(pIndex->def->key_def); if (def == NULL) { sqlite3OomFault(db); @@ -2312,13 +2301,11 @@ sqlite3RefillIndex(Parse * pParse, Index * pIndex, int memRootPage) sqlite3VdbeAddOp2(v, OP_Next, iTab, addr1 + 1); VdbeCoverage(v); sqlite3VdbeJumpHere(v, addr1); - if (memRootPage < 0) - sqlite3VdbeAddOp2(v, OP_Clear, SQLITE_PAGENO_TO_SPACEID(tnum), - 0); - struct space *space = space_by_id(SQLITE_PAGENO_TO_SPACEID(tnum)); - vdbe_emit_open_cursor(pParse, iIdx, SQLITE_PAGENO_TO_INDEXID(tnum), + sqlite3VdbeAddOp2(v, OP_Clear, pIndex->pTable->def->id, 0); + struct space *space = space_by_id(pIndex->pTable->def->id); + vdbe_emit_open_cursor(pParse, iIdx, pIndex->def->iid, space); - sqlite3VdbeChangeP5(v, memRootPage >= 0 ? OPFLAG_P2ISREG : 0); + sqlite3VdbeChangeP5(v, 0); addr1 = sqlite3VdbeAddOp2(v, OP_SorterSort, iSorter, 0); VdbeCoverage(v); @@ -2717,7 +2704,7 @@ sql_create_index(struct Parse *parse, struct Token *token, */ uint32_t iid = idx_type != SQL_INDEX_TYPE_CONSTRAINT_PK; if (db->init.busy) - iid = SQLITE_PAGENO_TO_INDEXID(db->init.newTnum); + iid = db->init.index_id; if (index_fill_def(parse, index, table, iid, name, strlen(name), col_list, idx_type, sql_stmt) != 0) @@ -2847,7 +2834,7 @@ sql_create_index(struct Parse *parse, struct Token *token, goto exit_create_index; } user_session->sql_flags |= SQLITE_InternChanges; - index->tnum = db->init.newTnum; + index->def->iid = db->init.index_id; } /* @@ -2880,7 +2867,7 @@ sql_create_index(struct Parse *parse, struct Token *token, sqlite3VdbeChangeP5(vdbe, OPFLAG_SEEKEQ); assert(start != NULL); - space_id = SQLITE_PAGENO_TO_SPACEID(table->tnum); + space_id = table->def->id; index_id = getNewIid(parse, space_id, cursor); sqlite3VdbeAddOp1(vdbe, OP_Close, cursor); createIndex(parse, index, space_id, index_id, sql_stmt); @@ -3578,7 +3565,7 @@ reindexTable(Parse * pParse, Table * pTab, struct coll *coll) for (pIndex = pTab->pIndex; pIndex; pIndex = pIndex->pNext) { if (coll == 0 || collationMatch(coll, pIndex)) { sql_set_multi_write(pParse, false); - sqlite3RefillIndex(pParse, pIndex, -1); + sqlite3RefillIndex(pParse, pIndex); } } } @@ -3672,7 +3659,7 @@ sqlite3Reindex(Parse * pParse, Token * pName1, Token * pName2) pIndex = sqlite3HashFind(&pTab->idxHash, z); if (pIndex != NULL) { sql_set_multi_write(pParse, false); - sqlite3RefillIndex(pParse, pIndex, -1); + sqlite3RefillIndex(pParse, pIndex); return; } diff --git a/src/box/sql/delete.c b/src/box/sql/delete.c index f9d3498..0681177 100644 --- a/src/box/sql/delete.c +++ b/src/box/sql/delete.c @@ -125,7 +125,7 @@ sql_table_delete_from(struct Parse *parse, struct SrcList *tab_list, table = sql_list_lookup_table(parse, tab_list); if (table == NULL) goto delete_from_cleanup; - space_id = SQLITE_PAGENO_TO_SPACEID(table->tnum); + space_id = table->def->id; space = space_by_id(space_id); assert(space != NULL); trigger_list = sql_triggers_exist(table, TK_DELETE, NULL, NULL); diff --git a/src/box/sql/expr.c b/src/box/sql/expr.c index 360558a..d408adb 100644 --- a/src/box/sql/expr.c +++ b/src/box/sql/expr.c @@ -2474,10 +2474,8 @@ sqlite3FindInIndex(Parse * pParse, /* Parsing context */ pIdx->def->name), P4_DYNAMIC); struct space *space = - space_by_id(SQLITE_PAGENO_TO_SPACEID(pIdx->tnum)); - uint32_t idx_id = - SQLITE_PAGENO_TO_INDEXID(pIdx-> - tnum); + space_by_id(pIdx->pTable->def->id); + uint32_t idx_id = pIdx->def->iid; vdbe_emit_open_cursor(pParse, iTab, idx_id, space); VdbeComment((v, "%s", pIdx->def->name)); diff --git a/src/box/sql/fkey.c b/src/box/sql/fkey.c index 8cacfe7..6dd9130 100644 --- a/src/box/sql/fkey.c +++ b/src/box/sql/fkey.c @@ -426,9 +426,9 @@ fkLookupParent(Parse * pParse, /* Parse context */ int regTemp = sqlite3GetTempRange(pParse, nCol); int regRec = sqlite3GetTempReg(pParse); struct space *space = - space_by_id(SQLITE_PAGENO_TO_SPACEID(pIdx->tnum)); - uint32_t idx_id = SQLITE_PAGENO_TO_INDEXID(pIdx->tnum); - vdbe_emit_open_cursor(pParse, iCur, idx_id, space); + space_by_id(pIdx->pTable->def->id); + vdbe_emit_open_cursor(pParse, iCur, pIdx->def->iid, + space); for (i = 0; i < nCol; i++) { sqlite3VdbeAddOp2(v, OP_Copy, aiCol[i] + 1 + regData, @@ -1304,12 +1304,10 @@ fkActionTrigger(struct Parse *pParse, struct Table *pTab, struct FKey *pFKey, &tToCol, 0)); } else if (action == OE_SetDflt) { - uint32_t space_id = - SQLITE_PAGENO_TO_SPACEID( - pFKey->pFrom->tnum); Expr *pDflt = space_column_default_expr( - space_id, (uint32_t)iFromCol); + pFKey->pFrom->def->id, + (uint32_t)iFromCol); if (pDflt) { pNew = sqlite3ExprDup(db, pDflt, diff --git a/src/box/sql/insert.c b/src/box/sql/insert.c index 3af9f9a..231b06c 100644 --- a/src/box/sql/insert.c +++ b/src/box/sql/insert.c @@ -384,7 +384,7 @@ sqlite3Insert(Parse * pParse, /* Parser context */ if (pTab == NULL) goto insert_cleanup; - space_id = SQLITE_PAGENO_TO_SPACEID(pTab->tnum); + space_id = pTab->def->id; /* Figure out if we have any triggers and if the table being * inserted into is a view @@ -742,7 +742,7 @@ sqlite3Insert(Parse * pParse, /* Parser context */ if (i == pTab->iAutoIncPKey) { sqlite3VdbeAddOp2(v, OP_NextAutoincValue, - pTab->tnum, + pTab->def->id, iRegStore); continue; } @@ -1075,9 +1075,7 @@ sqlite3GenerateConstraintChecks(Parse * pParse, /* The parser context */ on_error = ON_CONFLICT_ACTION_ABORT; struct Expr *dflt = NULL; - dflt = space_column_default_expr( - SQLITE_PAGENO_TO_SPACEID(pTab->tnum), - i); + dflt = space_column_default_expr(pTab->def->id, i); if (on_error == ON_CONFLICT_ACTION_REPLACE && dflt == 0) on_error = ON_CONFLICT_ACTION_ABORT; @@ -1124,8 +1122,7 @@ sqlite3GenerateConstraintChecks(Parse * pParse, /* The parser context */ * Get server checks. * Test all CHECK constraints. */ - uint32_t space_id = SQLITE_PAGENO_TO_SPACEID(pTab->tnum); - ExprList *checks = space_checks_expr_list(space_id); + ExprList *checks = space_checks_expr_list(pTab->def->id); if (checks != NULL && (user_session->sql_flags & SQLITE_IgnoreChecks) == 0) { pParse->ckBase = regNewData + 1; @@ -1389,7 +1386,7 @@ sqlite3GenerateConstraintChecks(Parse * pParse, /* The parser context */ ++i, ++part) { char *p4 = (char *) part->coll; x = part->fieldno; - if (pPk->tnum==0) + if (pTab->def->id == 0) x = -1; if (i == (pk_part_count - 1)) { addrJump = addrUniqueOk; @@ -1531,7 +1528,7 @@ sqlite3OpenTableAndIndices(Parse * pParse, /* Parsing context */ *piDataCur = iDataCur; if (piIdxCur) *piIdxCur = iBase; - struct space *space = space_by_id(SQLITE_PAGENO_TO_SPACEID(pTab->tnum)); + struct space *space = space_by_id(pTab->def->id); assert(space != NULL); /* One iteration of this cycle adds OpenRead/OpenWrite which * opens cursor for current index. @@ -1579,10 +1576,9 @@ sqlite3OpenTableAndIndices(Parse * pParse, /* Parsing context */ p5 = 0; } if (aToOpen == 0 || aToOpen[i + 1]) { - int idx_id = - SQLITE_PAGENO_TO_INDEXID(pIdx->tnum); - sqlite3VdbeAddOp4(v, op, iIdxCur, idx_id, 0, - (void *) space, P4_SPACEPTR); + sqlite3VdbeAddOp4(v, op, iIdxCur, pIdx->def->iid, + 0, (void *) space, + P4_SPACEPTR); sqlite3VdbeChangeP5(v, p5); VdbeComment((v, "%s", pIdx->def->name)); } @@ -1781,12 +1777,10 @@ xferOptimization(Parse * pParse, /* Parser context */ } /* Default values for second and subsequent columns need to match. */ if (i > 0) { - uint32_t src_space_id = - SQLITE_PAGENO_TO_SPACEID(pSrc->tnum); + uint32_t src_space_id = pSrc->def->id; struct space *src_space = space_cache_find(src_space_id); - uint32_t dest_space_id = - SQLITE_PAGENO_TO_SPACEID(pDest->tnum); + uint32_t dest_space_id = pDest->def->id; struct space *dest_space = space_cache_find(dest_space_id); assert(src_space != NULL && dest_space != NULL); @@ -1814,10 +1808,8 @@ xferOptimization(Parse * pParse, /* Parser context */ return 0; } /* Get server checks. */ - ExprList *pCheck_src = space_checks_expr_list( - SQLITE_PAGENO_TO_SPACEID(pSrc->tnum)); - ExprList *pCheck_dest = space_checks_expr_list( - SQLITE_PAGENO_TO_SPACEID(pDest->tnum)); + ExprList *pCheck_src = space_checks_expr_list(pSrc->def->id); + ExprList *pCheck_dest = space_checks_expr_list(pDest->def->id); if (pCheck_dest != NULL && sqlite3ExprListCompare(pCheck_src, pCheck_dest, -1) != 0) { /* Tables have different CHECK constraints. Ticket #2252 */ @@ -1885,15 +1877,14 @@ xferOptimization(Parse * pParse, /* Parser context */ } assert(pSrcIdx); struct space *src_space = - space_by_id(SQLITE_PAGENO_TO_SPACEID(pSrcIdx->tnum)); + space_by_id(pSrc->def->id); vdbe_emit_open_cursor(pParse, iSrc, - SQLITE_PAGENO_TO_INDEXID(pSrcIdx->tnum), + pSrcIdx->def->iid, src_space); VdbeComment((v, "%s", pSrcIdx->def->name)); - struct space *dest_space = - space_by_id(SQLITE_PAGENO_TO_SPACEID(pDestIdx->tnum)); + struct space *dest_space = space_by_id(pDest->def->id); vdbe_emit_open_cursor(pParse, iDest, - SQLITE_PAGENO_TO_INDEXID(pDestIdx->tnum), + pDestIdx->def->iid, dest_space); VdbeComment((v, "%s", pDestIdx->def->name)); addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0); diff --git a/src/box/sql/main.c b/src/box/sql/main.c index 85bc7e9..ded3b5b 100644 --- a/src/box/sql/main.c +++ b/src/box/sql/main.c @@ -2388,33 +2388,6 @@ sqlite3_test_control(int op, ...) rc = SQLITE_ERROR; break; } - - /* sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, db, dbName, onOff, tnum); - * - * This test control is used to create imposter tables. "db" is a pointer - * to the database connection. dbName is the database name (ex: "main" or - * "temp") which will receive the imposter. "onOff" turns imposter mode on - * or off. "tnum" is the root page of the b-tree to which the imposter - * table should connect. - * - * Enable imposter mode only when the schema has already been parsed. Then - * run a single CREATE TABLE statement to construct the imposter table in - * the parsed schema. Then turn imposter mode back off again. - * - * If onOff==0 and tnum>0 then reset the schema for all databases, causing - * the schema to be reparsed the next time it is needed. This has the - * effect of erasing all imposter tables. - */ - case SQLITE_TESTCTRL_IMPOSTER:{ - sqlite3 *db = va_arg(ap, sqlite3 *); - db->init.busy = db->init.imposterTable = - va_arg(ap, int); - db->init.newTnum = va_arg(ap, int); - if (db->init.busy == 0 && db->init.newTnum > 0) { - sqlite3ResetAllSchemasOfConnection(db); - } - break; - } } va_end(ap); #endif /* SQLITE_UNTESTABLE */ diff --git a/src/box/sql/pragma.c b/src/box/sql/pragma.c index a258bfc..d427f78 100644 --- a/src/box/sql/pragma.c +++ b/src/box/sql/pragma.c @@ -432,9 +432,7 @@ sqlite3Pragma(Parse * pParse, Token * pId, /* First part of [schema.]id field */ for (i = sqliteHashFirst(&db->pSchema->tblHash); i; i = sqliteHashNext(i)) { Table *pTab = sqliteHashData(i); - uint32_t space_id = - SQLITE_PAGENO_TO_SPACEID(pTab->tnum); - struct space *space = space_by_id(space_id); + struct space *space = space_by_id(pTab->def->id); assert(space != NULL); struct index *pk = space_index(space, 0); size_t avg_tuple_size_pk = @@ -447,10 +445,8 @@ sqlite3Pragma(Parse * pParse, Token * pId, /* First part of [schema.]id field */ sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 4); for (pIdx = pTab->pIndex; pIdx; pIdx = pIdx->pNext) { - uint32_t iid = - SQLITE_PAGENO_TO_INDEXID(pIdx->tnum); struct index *idx = - space_index(space, iid); + space_index(space, pIdx->def->iid); assert(idx != NULL); size_t avg_tuple_size_idx = sql_index_tuple_size(space, idx); @@ -689,12 +685,9 @@ sqlite3Pragma(Parse * pParse, Token * pId, /* First part of [schema.]id field */ struct space *space = space_cache_find(pIdx->pTable-> def->id); - int idx_id = - SQLITE_PAGENO_TO_INDEXID(pIdx-> - tnum); assert(space != NULL); sqlite3VdbeAddOp4(v, OP_OpenRead, i, - idx_id, 0, + pIdx->def->iid, 0, (void *) space, P4_SPACEPTR); diff --git a/src/box/sql/prepare.c b/src/box/sql/prepare.c index 629f68e..14239c4 100644 --- a/src/box/sql/prepare.c +++ b/src/box/sql/prepare.c @@ -44,12 +44,12 @@ * that the database is corrupt. */ static void -corruptSchema(InitData * pData, /* Initialization context */ +corruptSchema(struct init_data *data, /* Initialization context */ const char *zObj, /* Object being parsed at the point of error */ const char *zExtra /* Error information */ ) { - sqlite3 *db = pData->db; + sqlite3 *db = data->db; if (!db->mallocFailed) { char *z; if (zObj == 0) @@ -57,46 +57,30 @@ corruptSchema(InitData * pData, /* Initialization context */ z = sqlite3MPrintf(db, "malformed database schema (%s)", zObj); if (zExtra) z = sqlite3MPrintf(db, "%z - %s", z, zExtra); - sqlite3DbFree(db, *pData->pzErrMsg); - *pData->pzErrMsg = z; + sqlite3DbFree(db, *data->pzErrMsg); + *data->pzErrMsg = z; } - pData->rc = db->mallocFailed ? SQLITE_NOMEM_BKPT : SQLITE_CORRUPT_BKPT; + data->rc = db->mallocFailed ? SQLITE_NOMEM_BKPT : SQLITE_CORRUPT_BKPT; } /* Necessary for appropriate value return in InitCallback. * Otherwise it will return uint32_t instead of 64 bit pointer. */ struct space *space_by_id(uint32_t id); -/* - * This is the callback routine for the code that initializes the - * database. See sqlite3Init() below for additional information. - * This routine is also called from the OP_ParseSchema opcode of the VDBE. - * - * Each callback contains the following information: - * - * argv[0] = name of thing being created - * argv[1] = root page number address. - * argv[2] = SQL text for the CREATE statement. - * - */ + int -sqlite3InitCallback(void *pInit, int argc, char **argv, char **NotUsed) +sql_init_callback(struct init_data *init, const char *name, + uint32_t space_id, uint32_t index_id, const char *sql) { - InitData *pData = (InitData *) pInit; - sqlite3 *db = pData->db; - assert(argc == 3); - UNUSED_PARAMETER2(NotUsed, argc); + sqlite3 *db = init->db; if (db->mallocFailed) { - corruptSchema(pData, argv[0], 0); + corruptSchema(init, name, 0); return 1; } - if (argv == 0) - return 0; /* Might happen if EMPTY_RESULT_CALLBACKS are on */ - if (argv[1] == 0) { - corruptSchema(pData, argv[0], 0); - } else if ((strlen(argv[2]) > 7) && - sqlite3_strnicmp(argv[2], "create ", 7) == 0) { + assert(space_id > 0); + if ((strlen(sql) > 7) && + sqlite3_strnicmp(sql, "create ", 7) == 0) { /* Call the parser to process a CREATE TABLE, INDEX or VIEW. * But because db->init.busy is set to 1, no VDBE code is generated * or executed. All the parser does is build the internal data @@ -107,25 +91,24 @@ sqlite3InitCallback(void *pInit, int argc, char **argv, char **NotUsed) TESTONLY(int rcp); /* Return code from sqlite3_prepare() */ assert(db->init.busy); - db->init.newTnum = *((int *)argv[1]); + db->init.space_id = space_id; + db->init.index_id = index_id; db->init.orphanTrigger = 0; - TESTONLY(rcp =) sqlite3_prepare(db, argv[2], - strlen(argv[2]) + 1, &pStmt, 0); + TESTONLY(rcp =) sqlite3_prepare(db, sql, + strlen(sql) + 1, &pStmt, 0); rc = db->errCode; assert((rc & 0xFF) == (rcp & 0xFF)); if (SQLITE_OK != rc) { - pData->rc = rc; - if (rc == SQLITE_NOMEM) { + init->rc = rc; + if (rc == SQLITE_NOMEM) sqlite3OomFault(db); - } else if (rc != SQLITE_INTERRUPT - && (rc & 0xFF) != SQLITE_LOCKED) { - corruptSchema(pData, argv[0], - sqlite3_errmsg(db)); - } + else if (rc != SQLITE_INTERRUPT && + (rc & 0xFF) != SQLITE_LOCKED) + corruptSchema(init, name, sqlite3_errmsg(db)); } sqlite3_finalize(pStmt); - } else if (argv[0] == 0 || (argv[2] != 0 && argv[2][0] != 0)) { - corruptSchema(pData, argv[0], 0); + } else if (name == NULL || (sql != NULL && sql[0] != 0)) { + corruptSchema(init, name, 0); } else { /* If the SQL column is blank it means this is an index that * was created to be the PRIMARY KEY or to fulfill a UNIQUE @@ -134,12 +117,10 @@ sqlite3InitCallback(void *pInit, int argc, char **argv, char **NotUsed) * to do here is record the root page number for that index. */ Index *pIndex; - long pageNo = *((long *)argv[1]); - int iSpace = (int)SQLITE_PAGENO_TO_SPACEID(pageNo); - struct space *pSpace = space_by_id(iSpace); - const char *zSpace = space_name(pSpace); - pIndex = sqlite3LocateIndex(db, argv[0], zSpace); - if (pIndex == 0) { + struct space *space = space_by_id(space_id); + const char *zSpace = space_name(space); + pIndex = sqlite3LocateIndex(db, name, zSpace); + if (pIndex == NULL) { /* This can occur if there exists an index on a TEMP table which * has the same name as another index on a permanent index. Since * the permanent table is hidden by the TEMP table, we can also @@ -147,7 +128,7 @@ sqlite3InitCallback(void *pInit, int argc, char **argv, char **NotUsed) */ /* Do Nothing */ ; } - pIndex->tnum = pageNo; + pIndex->def->iid = index_id; } return 0; } @@ -161,18 +142,18 @@ extern int sqlite3InitDatabase(sqlite3 * db) { int rc; - InitData initData; + struct init_data init; assert(db->pSchema != NULL); - memset(&initData, 0, sizeof(InitData)); - initData.db = db; + memset(&init, 0, sizeof(init)); + init.db = db; /* Load schema from Tarantool - into the primary db only. */ - tarantoolSqlite3LoadSchema(&initData); + tarantoolSqlite3LoadSchema(&init); - if (initData.rc) { - rc = initData.rc; + if (init.rc) { + rc = init.rc; goto error_out; } @@ -185,7 +166,7 @@ sqlite3InitDatabase(sqlite3 * db) */ assert(db->init.busy); { - rc = initData.rc; + rc = init.rc; if (rc == SQLITE_OK) sql_analysis_load(db); } diff --git a/src/box/sql/select.c b/src/box/sql/select.c index e548021..cf25326 100644 --- a/src/box/sql/select.c +++ b/src/box/sql/select.c @@ -4364,8 +4364,7 @@ is_simple_count(struct Select *select, struct AggInfo *agg_info) select->pSrc->nSrc != 1 || select->pSrc->a[0].pSelect != NULL) { return NULL; } - uint32_t space_id = - SQLITE_PAGENO_TO_SPACEID(select->pSrc->a[0].pTab->tnum); + uint32_t space_id = select->pSrc->a[0].pTab->def->id; struct space *space = space_by_id(space_id); assert(space != NULL && !space->def->opts.is_view); struct Expr *expr = select->pEList->a[0].pExpr; diff --git a/src/box/sql/sqliteInt.h b/src/box/sql/sqliteInt.h index 9ea7c78..a9bfa67 100644 --- a/src/box/sql/sqliteInt.h +++ b/src/box/sql/sqliteInt.h @@ -844,8 +844,7 @@ sqlite3_vfs_find(const char *zVfsName); #define SQLITE_TESTCTRL_BYTEORDER 22 #define SQLITE_TESTCTRL_ISINIT 23 #define SQLITE_TESTCTRL_SORTER_MMAP 24 -#define SQLITE_TESTCTRL_IMPOSTER 25 -#define SQLITE_TESTCTRL_LAST 25 +#define SQLITE_TESTCTRL_LAST 24 int sqlite3_status64(int op, sqlite3_int64 * pCurrent, @@ -1608,7 +1607,8 @@ struct sqlite3 { int aLimit[SQLITE_N_LIMIT]; /* Limits */ int nMaxSorterMmap; /* Maximum size of regions mapped by sorter */ struct sqlite3InitInfo { /* Information used during initialization */ - int newTnum; /* Rootpage of table being initialized */ + uint32_t space_id; + uint32_t index_id; u8 busy; /* TRUE if currently initializing */ u8 orphanTrigger; /* Last statement is orphaned TEMP trigger */ u8 imposterTable; /* Building an imposter table */ @@ -1916,7 +1916,6 @@ struct Table { char *zColAff; /* String defining the affinity of each column */ /* ... also used as column name list in a VIEW */ Hash idxHash; /* All (named) indices indexed by name */ - int tnum; /* Root BTree page for this table */ u32 nTabRef; /* Number of pointers to this Table */ i16 iAutoIncPKey; /* If PK is marked INTEGER PRIMARY KEY AUTOINCREMENT, store column number here, -1 otherwise Tarantool specifics */ @@ -2091,10 +2090,7 @@ enum sql_index_type { * While parsing a CREATE TABLE or CREATE INDEX statement in order to * generate VDBE code (as opposed to reading from Tarantool's _space * space as part of parsing an existing database schema), transient instances - * of this structure may be created. In this case the Index.tnum variable is - * used to store the address of a VDBE instruction, not a database page - * number (it cannot - the database page is not allocated until the VDBE - * program is executed). + * of this structure may be created. */ struct Index { /** The SQL table being indexed. */ @@ -2107,8 +2103,6 @@ struct Index { Schema *pSchema; /** WHERE clause for partial indices. */ Expr *pPartIdxWhere; - /** DB Page containing root of this index. */ - int tnum; /** * Conflict resolution algorithm to employ whenever an * attempt is made to insert a non-unique element in @@ -3129,15 +3123,18 @@ struct StrAccum { #define isMalloced(X) (((X)->printfFlags & SQLITE_PRINTF_MALLOCED)!=0) -/* +/** * A pointer to this structure is used to communicate information - * from sqlite3Init and OP_ParseSchema into the sqlite3InitCallback. - */ -typedef struct { - sqlite3 *db; /* The database being initialized */ - char **pzErrMsg; /* Error message stored here */ - int rc; /* Result code stored here */ -} InitData; + * from sqlite3Init and OP_ParseSchema into the sql_init_callback. + */ +struct init_data { + /** The database being initialized. */ + sqlite3 *db; + /** Error message stored here. */ + char **pzErrMsg; + /** Result code stored here. */ + int rc; +}; /* * Structure containing global configuration data for the SQLite library. @@ -3476,7 +3473,25 @@ void sqlite3ExprListSetName(Parse *, ExprList *, Token *, int); void sqlite3ExprListSetSpan(Parse *, ExprList *, ExprSpan *); u32 sqlite3ExprListFlags(const ExprList *); int sqlite3Init(sqlite3 *); -int sqlite3InitCallback(void *, int, char **, char **); + +/** + * This is the callback routine for the code that initializes the + * database. See sqlite3Init() below for additional information. + * This routine is also called from the OP_ParseSchema2 opcode of + * the VDBE. + * + * @param init Initialization context. + * @param name Name of thing being created. + * @param space_id Space identifier. + * @param index_id Index identifier. + * @param sql Text of SQL query. + * + * @retval 0 on success, 1 otherwise. + */ +int +sql_init_callback(struct init_data *init, const char *name, + uint32_t space_id, uint32_t index_id, const char *sql); + void sqlite3Pragma(Parse *, Token *, Token *, Token *, int); void sqlite3ResetAllSchemasOfConnection(sqlite3 *); void sqlite3CommitInternalChanges(); diff --git a/src/box/sql/tarantoolInt.h b/src/box/sql/tarantoolInt.h index f043a60..e1430a3 100644 --- a/src/box/sql/tarantoolInt.h +++ b/src/box/sql/tarantoolInt.h @@ -28,23 +28,8 @@ #define TARANTOOL_INDEX_INSERT 1 #define TARANTOOL_INDEX_REPLACE 2 -/* - * SQLite uses the root page number to identify a Table or Index BTree. - * We switched it to using Tarantool spaces and indices instead of the - * BTrees. Hence the functions to encode index and space id in - * a page number. - */ -#define SQLITE_PAGENO_FROM_SPACEID_AND_INDEXID(spaceid, iid) \ - (((unsigned)(spaceid) << 10) | (iid)) - -#define SQLITE_PAGENO_TO_SPACEID(pgno) \ - ((unsigned)(pgno) >> 10) - -#define SQLITE_PAGENO_TO_INDEXID(pgno) \ - ((pgno) & 1023) - /* Load database schema from Tarantool. */ -void tarantoolSqlite3LoadSchema(InitData * init); +void tarantoolSqlite3LoadSchema(struct init_data *init); /* Misc */ const char *tarantoolErrorMessage(); @@ -82,10 +67,24 @@ int sql_delete_by_key(struct space *space, char *key, uint32_t key_size); int tarantoolSqlite3ClearTable(struct space *space); -/* Rename table pTab with zNewName by inserting new tuple to _space. - * SQL statement, which creates table with new name is saved in pzSqlStmt. +/** + * Rename the table in _space. Update tuple with corresponding id + * with new name and statement fields and insert back. If sql_stmt + * is NULL, then return from function after getting length of new + * statement: it is the way how to dynamically allocate memory for + * new statement in VDBE. So basically this function should be + * called twice: firstly to get length of CREATE TABLE statement, + * and secondly to make routine of replacing tuple and filling out + * param sql_stmt with new CREATE TABLE statement. + * + * @param space_id Table's space identifier. + * @param new_name new name of table + * @param[out] sql_stmt CREATE TABLE statement for new name table, can be NULL. + * + * @retval SQLITE_OK on success, SQLITE_TARANTOOL_ERROR otherwise. */ -int tarantoolSqlite3RenameTable(int iTab, const char *zNewName, char **zSqlStmt); +int +sql_rename_table(uint32_t space_id, const char *new_name, char **sql_stmt); /* Alter trigger statement after rename table. */ int tarantoolSqlite3RenameTrigger(const char *zTriggerName, diff --git a/src/box/sql/vdbe.c b/src/box/sql/vdbe.c index 195638e..1a75f77 100644 --- a/src/box/sql/vdbe.c +++ b/src/box/sql/vdbe.c @@ -1155,15 +1155,13 @@ case OP_NextAutoincValue: { assert(pOp->p1 > 0); assert(pOp->p2 > 0); - int64_t value; - uint32_t space_id = SQLITE_PAGENO_TO_SPACEID(pOp->p1); - - struct space *space = space_by_id(space_id); + struct space *space = space_by_id(pOp->p1); if (space == NULL) { rc = SQL_TARANTOOL_ERROR; goto abort_due_to_error; } + int64_t value; struct sequence *sequence = space->sequence; if (sequence == NULL || sequence_next(sequence, &value) != 0) { rc = SQL_TARANTOOL_ERROR; @@ -4615,19 +4613,16 @@ case OP_ResetSorter: { * <name, pageno (which is hash(spaceId, indexId)), sql> */ case OP_ParseSchema2: { - InitData initData; + struct init_data init; Mem *pRec, *pRecEnd; - char *argv[4] = {NULL, NULL, NULL, NULL}; - - assert(db->pSchema != NULL); - initData.db = db; - initData.pzErrMsg = &p->zErrMsg; + init.db = db; + init.pzErrMsg = &p->zErrMsg; assert(db->init.busy==0); db->init.busy = 1; - initData.rc = SQLITE_OK; + init.rc = SQLITE_OK; assert(!db->mallocFailed); pRec = &aMem[pOp->p1]; @@ -4641,16 +4636,12 @@ case OP_ParseSchema2: { * * Uppdate the schema. */ - for( ; pRecEnd-pRec>=4 && initData.rc==SQLITE_OK; pRec+=4) { - argv[0] = pRec[0].z; - int pageNo = SQLITE_PAGENO_FROM_SPACEID_AND_INDEXID(pRec[1].u.i, - pRec[2].u.i); - argv[1] = (char *)&pageNo; - argv[2] = pRec[3].z; - sqlite3InitCallback(&initData, 3, argv, NULL); + for(; pRecEnd - pRec >= 4 && init.rc == SQLITE_OK; pRec += 4) { + sql_init_callback(&init, pRec[0].z, pRec[1].u.i, pRec[2].u.i, + pRec[3].z); } - rc = initData.rc; + rc = init.rc; db->init.busy = 0; if (rc) { @@ -4664,7 +4655,7 @@ case OP_ParseSchema2: { } /* Opcode: RenameTable P1 * * P4 * - * Synopsis: P1 = root, P4 = name + * Synopsis: P1 = space_id, P4 = name * * Rename table P1 with name from P4. * Invoke tarantoolSqlite3RenameTable, which updates tuple with @@ -4676,18 +4667,16 @@ case OP_ParseSchema2: { * */ case OP_RenameTable: { - unsigned space_id; + uint32_t space_id; struct space *space; const char *zOldTableName; const char *zNewTableName; Table *pTab; FKey *pFKey; - int iRootPage; - InitData initData; - char *argv[4] = {NULL, NULL, NULL, NULL}; + struct init_data init; char *zSqlStmt; - space_id = SQLITE_PAGENO_TO_SPACEID(pOp->p1); + space_id = pOp->p1; space = space_by_id(space_id); assert(space); /* Rename space op doesn't change triggers. */ @@ -4696,19 +4685,17 @@ case OP_RenameTable: { assert(zOldTableName); pTab = sqlite3HashFind(&db->pSchema->tblHash, zOldTableName); assert(pTab); - iRootPage = pTab->tnum; zNewTableName = pOp->p4.z; zOldTableName = sqlite3DbStrNDup(db, zOldTableName, sqlite3Strlen30(zOldTableName)); - rc = tarantoolSqlite3RenameTable(pTab->tnum, zNewTableName, - &zSqlStmt); + rc = sql_rename_table(space_id, zNewTableName, &zSqlStmt); if (rc) goto abort_due_to_error; /* If it is parent table, all children statements should be updated. */ for (pFKey = sqlite3FkReferences(pTab); pFKey; pFKey = pFKey->pNextTo) { - assert(pFKey->zTo); - assert(pFKey->pFrom); - rc = tarantoolSqlite3RenameParentTable(pFKey->pFrom->tnum, + assert(pFKey->zTo != NULL); + assert(pFKey->pFrom != NULL); + rc = tarantoolSqlite3RenameParentTable(pFKey->pFrom->def->id, pFKey->zTo, zNewTableName); if (rc) goto abort_due_to_error; @@ -4720,17 +4707,14 @@ case OP_RenameTable: { sqlite3UnlinkAndDeleteTable(db, pTab->def->name); - initData.db = db; - initData.pzErrMsg = &p->zErrMsg; + init.db = db; + init.pzErrMsg = &p->zErrMsg; assert(db->init.busy == 0); db->init.busy = 1; - initData.rc = SQLITE_OK; - argv[0] = (char*) zNewTableName; - argv[1] = (char*) &iRootPage; - argv[2] = zSqlStmt; - sqlite3InitCallback(&initData, 3, argv, NULL); + init.rc = SQLITE_OK; + sql_init_callback(&init, zNewTableName, space_id, 0, zSqlStmt); db->init.busy = 0; - rc = initData.rc; + rc = init.rc; if (rc) { sqlite3CommitInternalChanges(); goto abort_due_to_error; diff --git a/src/box/sql/vdbe.h b/src/box/sql/vdbe.h index 03ae44e..cfcc262 100644 --- a/src/box/sql/vdbe.h +++ b/src/box/sql/vdbe.h @@ -234,7 +234,6 @@ void sqlite3VdbeVerifyNoResultRow(Vdbe * p); VdbeOp *sqlite3VdbeAddOpList(Vdbe *, int nOp, VdbeOpList const *aOp, int iLineno); void sqlite3VdbeAddParseSchema2Op(Vdbe * p, int, int); -void sqlite3VdbeAddRenameTableOp(Vdbe * p, int, char *); void sqlite3VdbeChangeOpcode(Vdbe *, u32 addr, u8); void sqlite3VdbeChangeP1(Vdbe *, u32 addr, int P1); void sqlite3VdbeChangeP2(Vdbe *, u32 addr, int P2); diff --git a/src/box/sql/vdbeaux.c b/src/box/sql/vdbeaux.c index c96157a..c71e0fe 100644 --- a/src/box/sql/vdbeaux.c +++ b/src/box/sql/vdbeaux.c @@ -410,12 +410,6 @@ sqlite3VdbeAddParseSchema2Op(Vdbe * p, int iRec, int n) sqlite3VdbeAddOp3(p, OP_ParseSchema2, iRec, n, 0); } -void -sqlite3VdbeAddRenameTableOp(Vdbe * p, int iTab, char* zNewName) -{ - sqlite3VdbeAddOp4(p, OP_RenameTable, iTab, 0, 0, zNewName, P4_DYNAMIC); -} - /* * Add an opcode that includes the p4 value as an integer. */ @@ -4001,8 +3995,7 @@ sqlite3VdbeRecordUnpackMsgpack(struct key_def *key_def, /* Information about the enum on_conflict_action table_column_nullable_action(struct Table *tab, uint32_t column) { - uint32_t space_id = SQLITE_PAGENO_TO_SPACEID(tab->tnum); - struct space *space = space_cache_find(space_id); + struct space *space = space_cache_find(tab->def->id); assert(space != NULL); diff --git a/src/box/sql/where.c b/src/box/sql/where.c index c115c4a..1173576 100644 --- a/src/box/sql/where.c +++ b/src/box/sql/where.c @@ -373,11 +373,10 @@ whereScanInit(WhereScan * pScan, /* The WhereScan object being initialized */ if (pIdx != NULL) { int j = iColumn; /* - * pIdx->def->opts.sql == "fake_autoindex" means that + * pIdx->def->iid == UINT32_MAX means that * pIdx is a fake integer primary key index. */ - if (pIdx->def->opts.sql != NULL && - strcmp(pIdx->def->opts.sql, "fake_autoindex") != 0) { + if (pIdx->def->iid != UINT32_MAX) { iColumn = pIdx->def->key_def->parts[iColumn].fieldno; pScan->idxaff = pIdx->pTable->def->fields[iColumn].affinity; @@ -938,10 +937,9 @@ whereKeyStats(Parse * pParse, /* Database connection */ int roundUp, /* Round up if true. Round down if false */ tRowcnt * aStat) /* OUT: stats written here */ { - uint32_t space_id = SQLITE_PAGENO_TO_SPACEID(pIdx->tnum); - struct space *space = space_by_id(space_id); + struct space *space = space_by_id(pIdx->pTable->def->id); assert(space != NULL); - uint32_t iid = SQLITE_PAGENO_TO_INDEXID(pIdx->tnum); + uint32_t iid = pIdx->def->iid; struct index *idx = space_index(space, iid); assert(idx != NULL && idx->def->opts.stat != NULL); struct index_sample *samples = idx->def->opts.stat->samples; @@ -1217,10 +1215,9 @@ whereRangeSkipScanEst(Parse * pParse, /* Parsing & code generating context */ int *pbDone) /* Set to true if at least one expr. value extracted */ { Index *p = pLoop->pIndex; - struct space *space = space_by_id(SQLITE_PAGENO_TO_SPACEID(p->tnum)); + struct space *space = space_by_id(p->pTable->def->id); assert(space != NULL); - struct index *index = space_index(space, - SQLITE_PAGENO_TO_INDEXID(p->tnum)); + struct index *index = space_index(space, p->def->iid); assert(index != NULL && index->def->opts.stat != NULL); int nEq = pLoop->nEq; sqlite3 *db = pParse->db; @@ -1348,11 +1345,10 @@ whereRangeScanEst(Parse * pParse, /* Parsing & code generating context */ Index *p = pLoop->pIndex; int nEq = pLoop->nEq; - uint32_t space_id = SQLITE_PAGENO_TO_SPACEID(p->tnum); + uint32_t space_id = p->pTable->def->id; struct space *space = space_by_id(space_id); assert(space != NULL); - uint32_t iid = SQLITE_PAGENO_TO_INDEXID(p->tnum); - struct index *idx = space_index(space, iid); + struct index *idx = space_index(space, p->def->iid); assert(idx != NULL); struct index_stat *stat = idx->def->opts.stat; /* @@ -1406,14 +1402,11 @@ whereRangeScanEst(Parse * pParse, /* Parsing & code generating context */ * are in range. */ iLower = 0; - uint32_t space_id = - SQLITE_PAGENO_TO_SPACEID(p->tnum); + uint32_t space_id = p->def->space_id; struct space *space = space_by_id(space_id); assert(space != NULL); - uint32_t iid = - SQLITE_PAGENO_TO_INDEXID(p->tnum); struct index *idx = - space_index(space, iid); + space_index(space, p->def->iid); assert(idx != NULL); iUpper = index_size(idx); } else { @@ -2178,8 +2171,8 @@ whereLoopInsert(WhereLoopBuilder * pBuilder, WhereLoop * pTemplate) } rc = whereLoopXfer(db, p, pTemplate); Index *pIndex = p->pIndex; - if (pIndex && pIndex->tnum == 0) - p->pIndex = 0; + if (pIndex != NULL && pIndex->pTable->def->id == 0) + p->pIndex = NULL; return rc; } @@ -2343,12 +2336,12 @@ whereRangeVectorLen(Parse * pParse, /* Parsing context */ * index pIndex. Try to match one more. * * When this function is called, pBuilder->pNew->nOut contains the - * number of rows expected to be visited by filtering using the nEq - * terms only. If it is modified, this value is restored before this - * function returns. + * number of rows expected to be visited by filtering using the + * nEq terms only. If it is modified, this value is restored before + * this function returns. * - * If pProbe->tnum==0, that means pIndex is a fake index used for the - * INTEGER PRIMARY KEY. + * If pProbe->def->space_id==UIN32_MAX, that means pIndex is a + * fake index used for the INTEGER PRIMARY KEY. */ static int whereLoopAddBtreeIndex(WhereLoopBuilder * pBuilder, /* The WhereLoop factory */ @@ -2391,12 +2384,11 @@ whereLoopAddBtreeIndex(WhereLoopBuilder * pBuilder, /* The WhereLoop factory */ opMask = WO_EQ | WO_IN | WO_GT | WO_GE | WO_LT | WO_LE | WO_ISNULL; } - struct space *space = - space_by_id(SQLITE_PAGENO_TO_SPACEID(pProbe->tnum)); + struct space *space = space_by_id(pProbe->def->space_id); struct index *idx = NULL; struct index_stat *stat = NULL; - if (space != NULL) { - idx = space_index(space, SQLITE_PAGENO_TO_INDEXID(pProbe->tnum)); + if (space != NULL && pProbe->def->iid != UINT32_MAX) { + idx = space_index(space, pProbe->def->iid); assert(idx != NULL); stat = idx->def->opts.stat; } @@ -2514,7 +2506,7 @@ whereLoopAddBtreeIndex(WhereLoopBuilder * pBuilder, /* The WhereLoop factory */ bool index_is_unique_not_null = pProbe->def->key_def->is_nullable && pProbe->def->opts.is_unique; - if (pProbe->tnum != 0 && + if (pProbe->def->space_id != 0 && !index_is_unique_not_null) { pNew->wsFlags |= WHERE_UNQ_WANTED; } else { @@ -2577,7 +2569,7 @@ whereLoopAddBtreeIndex(WhereLoopBuilder * pBuilder, /* The WhereLoop factory */ assert(eOp & (WO_ISNULL | WO_EQ | WO_IN)); assert(pNew->nOut == saved_nOut); - if (pTerm->truthProb <= 0 && pProbe->tnum != 0 ) { + if (pTerm->truthProb <= 0 && pProbe->pTable->def->id != 0) { assert((eOp & WO_IN) || nIn == 0); testcase(eOp & WO_IN); pNew->nOut += pTerm->truthProb; @@ -2639,11 +2631,10 @@ whereLoopAddBtreeIndex(WhereLoopBuilder * pBuilder, /* The WhereLoop factory */ * visiting the rows in the main table. */ struct space *space = - space_by_id(SQLITE_PAGENO_TO_SPACEID(pProbe->tnum)); + space_by_id(pProbe->pTable->def->id); assert(space != NULL); struct index *idx = - space_index(space, - SQLITE_PAGENO_TO_INDEXID(pProbe->tnum)); + space_index(space, pProbe->def->iid); assert(idx != NULL); /* * FIXME: currently, the procedure below makes no @@ -2750,11 +2741,10 @@ static bool index_is_unordered(struct Index *idx) { assert(idx != NULL); - struct space *space = space_by_id(SQLITE_PAGENO_TO_SPACEID(idx->tnum)); + struct space *space = space_by_id(idx->pTable->def->id); if (space == NULL) return false; - uint32_t iid = SQLITE_PAGENO_TO_INDEXID(idx->tnum); - struct index *tnt_idx = space_index(space, iid); + struct index *tnt_idx = space_index(space, idx->def->iid); if (tnt_idx == NULL) return false; if (tnt_idx->def->opts.stat != NULL) @@ -2920,6 +2910,8 @@ whereLoopAddBtree(WhereLoopBuilder * pBuilder, /* WHERE clause information */ sizeof("fake_autoindex") - 1, TREE, &opts, key_def, NULL); key_def_delete(key_def); + /* Special marker for non-existent index. */ + fake_index.def->iid = UINT32_MAX; if (fake_index.def == NULL) { pWInfo->pParse->nErr++; @@ -3026,7 +3018,7 @@ whereLoopAddBtree(WhereLoopBuilder * pBuilder, /* WHERE clause information */ /* The ONEPASS_DESIRED flags never occurs together with ORDER BY */ assert((pWInfo->wctrlFlags & WHERE_ONEPASS_DESIRED) == 0 || b == 0); - if (pProbe->tnum <= 0) { + if (pProbe->def->iid == UINT32_MAX) { /* Integer primary key index */ pNew->wsFlags = WHERE_IPK; @@ -4778,15 +4770,12 @@ sqlite3WhereBegin(Parse * pParse, /* The parser context */ if (op) { if (pIx != NULL) { uint32_t space_id = - SQLITE_PAGENO_TO_SPACEID(pIx-> - tnum); + pIx->pTable->def->id; struct space *space = space_by_id(space_id); - uint32_t idx_id = - SQLITE_PAGENO_TO_INDEXID(pIx-> - tnum); vdbe_emit_open_cursor(pParse, iIndexCur, - idx_id, space); + pIx->def->iid, + space); } else { vdbe_emit_open_cursor(pParse, iIndexCur, idx_def->iid, ^ permalink raw reply [flat|nested] 5+ messages in thread
* [tarantool-patches] Re: [PATCH] sql: get rid off tnum field of struct Table 2018-07-20 14:32 ` Kirill Yukhin @ 2018-07-20 16:12 ` n.pettik 0 siblings, 0 replies; 5+ messages in thread From: n.pettik @ 2018-07-20 16:12 UTC (permalink / raw) To: tarantool-patches; +Cc: Kirill Yukhin LGTM. ^ permalink raw reply [flat|nested] 5+ messages in thread
* [tarantool-patches] Re: [PATCH] sql: get rid off tnum field of struct Table 2018-07-20 11:37 [tarantool-patches] [PATCH] sql: get rid off tnum field of struct Table Kirill Yukhin 2018-07-20 14:07 ` [tarantool-patches] " n.pettik @ 2018-07-20 16:53 ` Kirill Yukhin 1 sibling, 0 replies; 5+ messages in thread From: Kirill Yukhin @ 2018-07-20 16:53 UTC (permalink / raw) To: korablev; +Cc: tarantool-patches Hello, On 20 июл 14:37, Kirill Yukhin wrote: > Basic structures (struct Table/Index) of legacy SQL's data > dictionary used to so-called tnum to refer to engine's > btree structures. Tarantool used this field to store composition > of space_id and index_id. Recently both structures incorporated > native space_def/index_def descriptors. > This patch finally removes tnum field. It also refactors > init_callback machinery, removing varargs from declarations. > > Closes #3482 > --- > Issue: https://github.com/tarantool/tarantool/issues/3482 > Branch: https://github.com/tarantool/tarantool/commits/kyukhin/gh-3482-remove-tnum I've checked the patch into 2.0 branch. -- Regards, Kirill Yukhin ^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2018-07-20 18:17 UTC | newest] Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2018-07-20 11:37 [tarantool-patches] [PATCH] sql: get rid off tnum field of struct Table Kirill Yukhin 2018-07-20 14:07 ` [tarantool-patches] " n.pettik 2018-07-20 14:32 ` Kirill Yukhin 2018-07-20 16:12 ` n.pettik 2018-07-20 16:53 ` Kirill Yukhin
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox