* [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