From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from localhost (localhost [127.0.0.1]) by turing.freelists.org (Avenir Technologies Mail Multiplex) with ESMTP id 780322BDD1 for ; Tue, 3 Apr 2018 12:15:26 -0400 (EDT) Received: from turing.freelists.org ([127.0.0.1]) by localhost (turing.freelists.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id kHIkzN4LzXgA for ; Tue, 3 Apr 2018 12:15:26 -0400 (EDT) Received: from smtp48.i.mail.ru (smtp48.i.mail.ru [94.100.177.108]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by turing.freelists.org (Avenir Technologies Mail Multiplex) with ESMTPS id D07392BDC1 for ; Tue, 3 Apr 2018 12:15:25 -0400 (EDT) From: Nikita Pettik Subject: [tarantool-patches] [PATCH 1/2] sql: remove obsolete SQLite routine Date: Tue, 3 Apr 2018 19:14:56 +0300 Message-Id: <0e28c9181b19643504f335a164f8d098fdab6614.1522769126.git.korablev@tarantool.org> In-Reply-To: References: In-Reply-To: References: Sender: tarantool-patches-bounce@freelists.org Errors-to: tarantool-patches-bounce@freelists.org Reply-To: tarantool-patches@freelists.org List-help: List-unsubscribe: List-software: Ecartis version 1.0.0 List-Id: tarantool-patches List-subscribe: List-owner: List-post: List-archive: To: tarantool-patches@freelists.org Cc: v.shpilevoy@tarantool.org, Nikita Pettik Some of legacy functions seem to be useless, since they serve as wrappers around others; the rest rely on capabilities which are no longer relevant. This patch provides slight refactoring of such functions. Removed entities: - sqlite3LocateTableItem() - replaced with sqlite3LocateTable(); - sqlite3FindTable() - replaced with sqlite3HashFind(); - sqlite3ColumnOfIndex() - in Tarantool order of columns always the same; - sqlite3FindIndex() - replaced with sqlite3LocateIndex(); - sqlite3CodeVerifySchema(); - sqlite3SchemaToIndex(); - sqlite3MultiWrite(); - Parse->cookieMast; - Vdbe->usesStmtJournal; --- src/box/sql/alter.c | 13 ++- src/box/sql/analyze.c | 25 +++--- src/box/sql/build.c | 213 ++++++++++-------------------------------------- src/box/sql/delete.c | 5 +- src/box/sql/expr.c | 9 +- src/box/sql/fkey.c | 3 +- src/box/sql/insert.c | 10 +-- src/box/sql/pragma.c | 18 ++-- src/box/sql/prepare.c | 29 ------- src/box/sql/select.c | 4 +- src/box/sql/sqliteInt.h | 11 +-- src/box/sql/trigger.c | 7 +- src/box/sql/update.c | 2 +- src/box/sql/vdbe.c | 1 - src/box/sql/vdbeInt.h | 1 - src/box/sql/vdbeaux.c | 1 - src/box/sql/where.c | 2 - src/box/sql/wherecode.c | 7 +- 18 files changed, 83 insertions(+), 278 deletions(-) diff --git a/src/box/sql/alter.c b/src/box/sql/alter.c index 054c0856c..a19324ed2 100644 --- a/src/box/sql/alter.c +++ b/src/box/sql/alter.c @@ -84,10 +84,9 @@ sqlite3AlterRenameTable(Parse * pParse, /* Parser context. */ goto exit_rename_table; assert(pSrc->nSrc == 1); - pTab = sqlite3LocateTableItem(pParse, 0, &pSrc->a[0]); + pTab = sqlite3LocateTable(pParse, 0, pSrc->a[0].zName); if (!pTab) goto exit_rename_table; - assert(sqlite3SchemaToIndex(pParse->db, pTab->pSchema) == 0); user_session->sql_flags |= SQLITE_PreferBuiltin; @@ -99,7 +98,7 @@ sqlite3AlterRenameTable(Parse * pParse, /* Parser context. */ /* Check that a table named 'zName' does not already exist * in database. If so, this is an error. */ - if (sqlite3FindTable(db, zName)) { + if (sqlite3HashFind(&db->pSchema->tblHash, zName) != NULL) { sqlite3ErrorMsg(pParse, "there is already another table or index with this name: %s", zName); @@ -122,7 +121,7 @@ sqlite3AlterRenameTable(Parse * pParse, /* Parser context. */ if (v == 0) { goto exit_rename_table; } - sqlite3BeginWriteOperation(pParse, false); + sql_set_multi_write(pParse, false); /* Drop and reload the internal table schema. */ reloadTableSchema(pParse, pTab, zName); @@ -163,7 +162,7 @@ sqlite3AlterFinishAddColumn(Parse * pParse, Token * pColDef) zTab = &pNew->zName[16]; /* Skip the "sqlite_altertab_" prefix on the name */ pCol = &pNew->aCol[pNew->nCol - 1]; pDflt = pCol->pDflt; - pTab = sqlite3FindTable(db, zTab); + pTab = sqlite3HashFind(&db->pSchema->tblHash, zTab);; assert(pTab); /* If the default value for the new column was specified with a @@ -257,7 +256,7 @@ sqlite3AlterBeginAddColumn(Parse * pParse, SrcList * pSrc) assert(pParse->pNewTable == 0); if (db->mallocFailed) goto exit_begin_add_column; - pTab = sqlite3LocateTableItem(pParse, 0, &pSrc->a[0]); + pTab = sqlite3LocateTable(pParse, 0, pSrc->a[0].zName); if (!pTab) goto exit_begin_add_column; @@ -305,7 +304,7 @@ sqlite3AlterBeginAddColumn(Parse * pParse, SrcList * pSrc) pNew->nTabRef = 1; /* Begin a transaction and increment the schema cookie. */ - sqlite3BeginWriteOperation(pParse, 0); + sql_set_multi_write(pParse, 0); v = sqlite3GetVdbe(pParse); if (!v) goto exit_begin_add_column; diff --git a/src/box/sql/analyze.c b/src/box/sql/analyze.c index fb46641a2..25e93aa15 100644 --- a/src/box/sql/analyze.c +++ b/src/box/sql/analyze.c @@ -156,7 +156,7 @@ openStatTable(Parse * pParse, /* Parsing context */ const char *zTab = aTable[i]; Table *pStat; /* The table already exists, because it is a system space */ - pStat = sqlite3FindTable(db, zTab); + pStat = sqlite3HashFind(&db->pSchema->tblHash, zTab); aRoot[i] = pStat->tnum; aCreateTbl[i] = 0; if (zWhere) { @@ -831,7 +831,6 @@ analyzeOneTable(Parse * pParse, /* Parser context */ /* Do not gather statistics on system tables */ return; } - assert(sqlite3SchemaToIndex(db, pTab->pSchema) == 0); /* Establish a read-lock on the table at the shared-cache level. * Open a read-only cursor on the table. Also allocate a cursor number @@ -907,7 +906,6 @@ analyzeOneTable(Parse * pParse, /* Parser context */ pParse->nMem = MAX(pParse->nMem, regPrev + nColTest); /* Open a read-only cursor on the index being analyzed. */ - assert(sqlite3SchemaToIndex(db, pIdx->pSchema) == 0); struct space *space = space_by_id(SQLITE_PAGENO_TO_SPACEID(pIdx->tnum)); assert(space != NULL); @@ -1028,7 +1026,7 @@ analyzeOneTable(Parse * pParse, /* Parser context */ int nPkColumn = (int)index_column_count(pPk); regKeyStat = sqlite3GetTempRange(pParse, nPkColumn); for (j = 0; j < nPkColumn; j++) { - k = sqlite3ColumnOfIndex(pIdx, pPk->aiColumn[j]); + k = pPk->aiColumn[j]; assert(k >= 0 && k < pTab->nCol); sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, k, regKeyStat + j); VdbeComment((v, "%s", pTab->aCol[pPk->aiColumn[j]].zName)); @@ -1124,7 +1122,7 @@ analyzeDatabase(Parse * pParse) int iMem; int iTab; - sqlite3BeginWriteOperation(pParse, 0); + sql_set_multi_write(pParse, 0); iStatCur = pParse->nTab; pParse->nTab += 3; openStatTable(pParse, iStatCur, 0, 0); @@ -1148,8 +1146,7 @@ analyzeTable(Parse * pParse, Table * pTab, Index * pOnlyIdx) int iStatCur; assert(pTab != 0); - assert(sqlite3SchemaToIndex(pParse->db, pTab->pSchema) == 0); - sqlite3BeginWriteOperation(pParse, 0); + sql_set_multi_write(pParse, 0); iStatCur = pParse->nTab; pParse->nTab += 3; if (pOnlyIdx) { @@ -1296,7 +1293,7 @@ analysisLoader(void *pData, int argc, char **argv, char **NotUsed) if (argv == 0 || argv[0] == 0 || argv[2] == 0) { return 0; } - pTable = sqlite3FindTable(pInfo->db, argv[0]); + pTable = sqlite3HashFind(&pInfo->db->pSchema->tblHash, argv[0]); if (pTable == 0) { return 0; } @@ -1305,7 +1302,7 @@ analysisLoader(void *pData, int argc, char **argv, char **NotUsed) } else if (sqlite3_stricmp(argv[0], argv[1]) == 0) { pIndex = sqlite3PrimaryKeyIndex(pTable); } else { - pIndex = sqlite3FindIndex(pInfo->db, argv[1], pTable); + pIndex = sqlite3HashFind(&pTable->idxHash, argv[1]); } z = argv[2]; @@ -1638,14 +1635,14 @@ loadStat4(sqlite3 * db) Table *pTab = 0; /* Pointer to stat table */ assert(db->lookaside.bDisable); - pTab = sqlite3FindTable(db, "_sql_stat4"); + pTab = sqlite3HashFind(&db->pSchema->tblHash, "_sql_stat4"); if (pTab) { rc = loadStatTbl(db, pTab, "SELECT \"tbl\",\"idx\",count(*) FROM \"_sql_stat4\" GROUP BY \"tbl\",\"idx\"", "SELECT \"tbl\",\"idx\",\"neq\",\"nlt\",\"ndlt\",\"sample\" FROM \"_sql_stat4\""); } - + return rc; } @@ -1690,10 +1687,8 @@ sqlite3AnalysisLoad(sqlite3 * db) /* Load new statistics out of the _sql_stat1 table */ sInfo.db = db; - if (sqlite3FindTable(db, "_sql_stat1") != 0) { - zSql = "SELECT \"tbl\",\"idx\",\"stat\" FROM \"_sql_stat1\""; - rc = sqlite3_exec(db, zSql, analysisLoader, &sInfo, 0); - } + zSql = "SELECT \"tbl\",\"idx\",\"stat\" FROM \"_sql_stat1\""; + rc = sqlite3_exec(db, zSql, analysisLoader, &sInfo, 0); /* Set appropriate defaults on all indexes not in the _sql_stat1 table */ for (j = sqliteHashFirst(&db->pSchema->tblHash); j; diff --git a/src/box/sql/build.c b/src/box/sql/build.c index 5e3ed0f39..61194e06b 100644 --- a/src/box/sql/build.c +++ b/src/box/sql/build.c @@ -93,23 +93,16 @@ sqlite3FinishCoding(Parse * pParse) * transaction on each used database and to verify the schema cookie * on each used database. */ - if (db->mallocFailed == 0 - && (DbMaskNonZero(pParse->cookieMask) || pParse->pConstExpr) - ) { + if (db->mallocFailed == 0 || pParse->pConstExpr) { int i; assert(sqlite3VdbeGetOp(v, 0)->opcode == OP_Init); sqlite3VdbeJumpHere(v, 0); - if (DbMaskTest(pParse->cookieMask, 0) != 0) { - if (pParse->initiateTTrans) - sqlite3VdbeAddOp0(v, OP_TTransaction); - - if (db->init.busy == 0) - sqlite3VdbeChangeP5(v, 1); - - VdbeComment((v, "usesStmtJournal=%d", - pParse->mayAbort - && pParse->isMultiWrite)); - } + if (pParse->initiateTTrans) + sqlite3VdbeAddOp0(v, OP_TTransaction); + if (db->init.busy == 0) + sqlite3VdbeChangeP5(v, 1); + VdbeComment((v, "Multiple changes: %d, may abort: %d", + pParse->isMultiWrite, pParse->mayAbort)); /* Code constant expressions that where factored out of inner loops */ if (pParse->pConstExpr) { @@ -183,32 +176,10 @@ sqlite3NestedParse(Parse * pParse, const char *zFormat, ...) pParse->nested--; } -/* - * Locate the in-memory structure that describes a particular database - * table given the name of that table and (optionally) the name of the - * database containing the table. Return NULL if not found. - * - * If zDatabase is 0, all databases are searched for the table and the - * first matching table is returned. (No checking for duplicate table - * names is done.) The search order is TEMP first, then MAIN, then any - * auxiliary databases added using the ATTACH command. - * - * See also sqlite3LocateTable(). - */ -Table * -sqlite3FindTable(sqlite3 * db, const char *zName) -{ - return sqlite3HashFind(&db->pSchema->tblHash, zName); -} - /* * Locate the in-memory structure that describes a particular database * table given the name of that table. Return NULL if not found. * Also leave an error message in pParse->zErrMsg. - * - * The difference between this routine and sqlite3FindTable() is that this - * routine leaves an error message in pParse->zErrMsg where - * sqlite3FindTable() does not. */ Table * sqlite3LocateTable(Parse * pParse, /* context in which to report errors */ @@ -220,7 +191,7 @@ sqlite3LocateTable(Parse * pParse, /* context in which to report errors */ assert(pParse->db->pSchema != NULL); - p = sqlite3FindTable(pParse->db, zName); + p = sqlite3HashFind(&pParse->db->pSchema->tblHash, zName); if (p == 0) { const char *zMsg = flags & LOCATE_VIEW ? "no such view" : "no such table"; @@ -233,48 +204,19 @@ sqlite3LocateTable(Parse * pParse, /* context in which to report errors */ return p; } -/* - * Locate the table identified by *p. - * - * This is a wrapper around sqlite3LocateTable(). The difference between - * sqlite3LocateTable() and this function is that this function restricts - * the search to schema (p->pSchema) if it is not NULL. p->pSchema may be - * non-NULL if it is part of a view or trigger program definition. See - * sqlite3FixSrcList() for details. - */ -Table * -sqlite3LocateTableItem(Parse * pParse, u32 flags, struct SrcList_item * p) -{ - return sqlite3LocateTable(pParse, flags, p->zName); -} - -/* - * Locate the in-memory structure that describes - * a particular index given the name of that index - * and the name of the database that contains the index. - * Return NULL if not found. - */ -Index * -sqlite3FindIndex(MAYBE_UNUSED sqlite3 * db, const char *zName, Table * pTab) -{ - assert(pTab); - - return sqlite3HashFind(&pTab->idxHash, zName); -} - Index * sqlite3LocateIndex(sqlite3 * db, const char *zName, const char *zTable) { assert(zName); assert(zTable); - Table *pTab = sqlite3FindTable(db, zTable); + Table *pTab = sqlite3HashFind(&db->pSchema->tblHash, zTable); if (pTab == 0) { return 0; } - return sqlite3FindIndex(db, zName, pTab); + return sqlite3HashFind(&pTab->idxHash, zName); } /* @@ -557,18 +499,6 @@ sqlite3PrimaryKeyIndex(Table * pTab) return p; } -/* - * Return the column of index pIdx that corresponds to table - * column iCol. Return -1 if not found. - */ -i16 -sqlite3ColumnOfIndex(Index * pIdx, i16 iCol) -{ - /* TARANTOOL: Data layout is the same in every index. */ - (void) pIdx; - return iCol; -} - /* * Begin constructing a new table representation in memory. This is * the first of several action routines that get called in response @@ -614,7 +544,7 @@ sqlite3StartTable(Parse *pParse, Token *pName, int noErr) return; assert(db->pSchema != NULL); - pTable = sqlite3FindTable(db, zName); + pTable = sqlite3HashFind(&db->pSchema->tblHash, zName); if (pTable) { if (!noErr) { sqlite3ErrorMsg(pParse, @@ -622,7 +552,6 @@ sqlite3StartTable(Parse *pParse, Token *pName, int noErr) zName); } else { assert(!db->init.busy || CORRUPT_DB); - sqlite3CodeVerifySchema(pParse); } goto begin_table_error; } @@ -654,7 +583,7 @@ sqlite3StartTable(Parse *pParse, Token *pName, int noErr) * now. */ if (!db->init.busy && (v = sqlite3GetVdbe(pParse)) != 0) - sqlite3BeginWriteOperation(pParse, 1); + sql_set_multi_write(pParse, 1); /* Normal (non-error) return. */ return; @@ -2039,7 +1968,6 @@ sqlite3CreateView(Parse * pParse, /* The parsing context */ p = pParse->pNewTable; if (p == 0 || pParse->nErr) goto create_view_fail; - sqlite3SchemaToIndex(db, p->pSchema); sqlite3FixInit(&sFix, pParse, "view", pName); if (sqlite3FixSelect(&sFix, pSelect)) goto create_view_fail; @@ -2206,26 +2134,22 @@ sqliteViewResetAll(sqlite3 * db) #define sqliteViewResetAll(A,B) #endif /* SQLITE_OMIT_VIEW */ -/* - * Remove entries from the sqlite_statN tables (for N in (1,2,3)) - * after a DROP INDEX or DROP TABLE command. +/** + * Remove entries from the _sql_stat1 and _sql_stat4 + * system spaces after a DROP INDEX or DROP TABLE command. + * + * @param pParse Parsing context. + * @param zType Type of entry to be deleted: + * 'idx' or 'tbl' string literal. + * @param zName Name of index or table. */ static void -sqlite3ClearStatTables(Parse * pParse, /* The parsing context */ - const char *zType, /* "idx" or "tbl" */ - const char *zName /* Name of index or table */ - ) +sql_clear_stat_spaces(Parse * pParse, const char *zType, const char *zName) { - int i; - for (i = 1; i <= 4; i++) { - char zTab[24]; - sqlite3_snprintf(sizeof(zTab), zTab, "_sql_stat%d", i); - if (sqlite3FindTable(pParse->db, zTab)) { - sqlite3NestedParse(pParse, - "DELETE FROM \"%s\" WHERE \"%s\"=%Q", - zTab, zType, zName); - } - } + sqlite3NestedParse(pParse, "DELETE FROM \"_sql_stat1\" WHERE \"%s\"=%Q", + zType, zName); + sqlite3NestedParse(pParse, "DELETE FROM \"_sql_stat4\" WHERE \"%s\"=%Q", + zType, zName); } /* @@ -2240,7 +2164,6 @@ sqlite3CodeDropTable(Parse * pParse, Table * pTab, int isView) v = sqlite3GetVdbe(pParse); assert(v != 0); - sqlite3BeginWriteOperation(pParse, 1); /* * Drop all triggers associated with the table being * dropped. Code is generated to remove entries from @@ -2376,15 +2299,12 @@ sqlite3DropTable(Parse * pParse, SrcList * pName, int isView, int noErr) if (noErr) db->suppressErr++; assert(isView == 0 || isView == LOCATE_VIEW); - pTab = sqlite3LocateTableItem(pParse, isView, &pName->a[0]); + pTab = sqlite3LocateTable(pParse, isView, pName->a[0].zName); if (noErr) db->suppressErr--; - if (pTab == 0) { - if (noErr) - sqlite3CodeVerifySchema(pParse); + if (pTab == 0) goto exit_drop_table; - } #ifndef SQLITE_OMIT_VIEW /* Ensure DROP TABLE is not used on a view, and DROP VIEW is not used * on a table. @@ -2414,8 +2334,8 @@ sqlite3DropTable(Parse * pParse, SrcList * pName, int isView, int noErr) * space_id from _space. */ - sqlite3BeginWriteOperation(pParse, 1); - sqlite3ClearStatTables(pParse, "tbl", pTab->zName); + sql_set_multi_write(pParse, 1); + sql_clear_stat_spaces(pParse, "tbl", pTab->zName); sqlite3FkDropTable(pParse, pName, pTab); sqlite3CodeDropTable(pParse, pTab, isView); @@ -2881,7 +2801,7 @@ sqlite3CreateIndex(Parse * pParse, /* All information about this parse */ */ assert(0); } - pTab = sqlite3LocateTableItem(pParse, 0, &pTblName->a[0]); + pTab = sqlite3LocateTable(pParse, 0, pTblName->a[0].zName); assert(db->mallocFailed == 0 || pTab == 0); if (pTab == 0) goto exit_create_index; @@ -2921,21 +2841,20 @@ sqlite3CreateIndex(Parse * pParse, /* All information about this parse */ goto exit_create_index; assert(pName->z != 0); if (!db->init.busy) { - if (sqlite3FindTable(db, zName) != 0) { + if (sqlite3HashFind(&db->pSchema->tblHash, zName) != 0) { sqlite3ErrorMsg(pParse, "there is already a table named %s", zName); goto exit_create_index; } } - if (sqlite3FindIndex(db, zName, pTab) != 0) { + if (sqlite3HashFind(&pTab->idxHash, zName) != 0) { if (!ifNotExist) { sqlite3ErrorMsg(pParse, "index %s.%s already exists", pTab->zName, zName); } else { assert(!db->init.busy); - sqlite3CodeVerifySchema(pParse); } goto exit_create_index; } @@ -3080,9 +2999,6 @@ sqlite3CreateIndex(Parse * pParse, /* All information about this parse */ if (pParse->pNewTable == 0) estimateIndexWidth(pIndex); - assert(pTab->iPKey < 0 - || sqlite3ColumnOfIndex(pIndex, pTab->iPKey) >= 0); - if (pTab == pParse->pNewTable) { /* This routine has been called to create an automatic index as a * result of a PRIMARY KEY or UNIQUE clause on a column definition, or @@ -3191,7 +3107,7 @@ sqlite3CreateIndex(Parse * pParse, /* All information about this parse */ if (v == 0) goto exit_create_index; - sqlite3BeginWriteOperation(pParse, 1); + sql_set_multi_write(pParse, 1); sqlite3VdbeAddOp2(v, OP_SIDtoPtr, BOX_INDEX_ID, @@ -3387,8 +3303,6 @@ sqlite3DropIndex(Parse * pParse, SrcList * pName, Token * pName2, int ifExists) if (!ifExists) { sqlite3ErrorMsg(pParse, "no such index: %s.%S", zTableName, pName, 0); - } else { - sqlite3CodeVerifySchema(pParse); } pParse->checkSchema = 1; goto exit_drop_index; @@ -3417,7 +3331,7 @@ sqlite3DropIndex(Parse * pParse, SrcList * pName, Token * pName2, int ifExists) * But firstly, delete statistics since schema * changes after DDL. */ - sqlite3ClearStatTables(pParse, "idx", pIndex->zName); + sql_clear_stat_spaces(pParse, "idx", pIndex->zName); int record_reg = ++pParse->nMem; int space_id_reg = ++pParse->nMem; sqlite3VdbeAddOp2(v, OP_Integer, SQLITE_PAGENO_TO_SPACEID(pIndex->tnum), @@ -3934,58 +3848,18 @@ sqlite3Savepoint(Parse * pParse, int op, Token * pName) } } -/* - * Record the fact that the schema cookie will need to be verified - * for database. The code to actually verify the schema cookie - * will occur at the end of the top-level VDBE and will be generated - * later, by sqlite3FinishCoding(). - */ -void -sqlite3CodeVerifySchema(Parse * pParse) -{ - Parse *pToplevel = sqlite3ParseToplevel(pParse); - - if (DbMaskTest(pToplevel->cookieMask, 0) == 0) { - DbMaskSet(pToplevel->cookieMask, 0); - } -} - -/* - * Generate VDBE code that prepares for doing an operation that - * might change the database. - * - * This routine starts a new transaction if we are not already within - * a transaction. If we are already within a transaction, then a checkpoint - * is set if the setStatement parameter is true. A checkpoint should - * be set for operations that might fail (due to a constraint) part of - * the way through and which will need to undo some writes without having to - * rollback the whole transaction. For operations where all constraints - * can be checked before any changes are made to the database, it is never - * necessary to undo a write and the checkpoint should not be set. +/** + * Set flag in parse context, which indicates that during query + * execution multiple insertion/updates may occur. */ void -sqlite3BeginWriteOperation(Parse * pParse, int setStatement) +sql_set_multi_write(Parse *pParse, int setStatement) { Parse *pToplevel = sqlite3ParseToplevel(pParse); - sqlite3CodeVerifySchema(pParse); DbMaskSet(pToplevel->writeMask, 0); pToplevel->isMultiWrite |= setStatement; } -/* - * Indicate that the statement currently under construction might write - * more than one entry (example: deleting one row then inserting another, - * inserting multiple rows in a table, or inserting a row and index entries.) - * If an abort occurs after some of these writes have completed, then it will - * be necessary to undo the completed writes. - */ -void -sqlite3MultiWrite(Parse * pParse) -{ - Parse *pToplevel = sqlite3ParseToplevel(pParse); - pToplevel->isMultiWrite = 1; -} - /* * The code generator calls this routine if is discovers that it is * possible to abort a statement prior to completion. In order to @@ -4100,7 +3974,7 @@ reindexTable(Parse * pParse, Table * pTab, char const *zColl) for (pIndex = pTab->pIndex; pIndex; pIndex = pIndex->pNext) { if (zColl == 0 || collationMatch(zColl, pIndex)) { - sqlite3BeginWriteOperation(pParse, 0); + sql_set_multi_write(pParse, 0); sqlite3RefillIndex(pParse, pIndex, -1); } } @@ -4175,7 +4049,7 @@ sqlite3Reindex(Parse * pParse, Token * pName1, Token * pName2) z = sqlite3NameFromToken(db, pName1); if (z == 0) return; - pTab = sqlite3FindTable(db, z); + pTab = sqlite3HashFind(&db->pSchema->tblHash, z); if (pTab) { reindexTable(pParse, pTab, 0); sqlite3DbFree(db, z); @@ -4185,16 +4059,15 @@ sqlite3Reindex(Parse * pParse, Token * pName1, Token * pName2) zTable = sqlite3NameFromToken(db, pName2); } - pTab = sqlite3FindTable(db, zTable); + pTab = sqlite3HashFind(&db->pSchema->tblHash, zTable); if (pTab == 0) { sqlite3ErrorMsg(pParse, "no such table: %s", zTable); goto exit_reindex; } - pIndex = sqlite3FindIndex(db, z, pTab); - + pIndex = sqlite3HashFind(&pTab->idxHash, z); if (pIndex) { - sqlite3BeginWriteOperation(pParse, 0); + sql_set_multi_write(pParse, 0); sqlite3RefillIndex(pParse, pIndex, -1); return; } diff --git a/src/box/sql/delete.c b/src/box/sql/delete.c index 7d1d71577..a07ef1980 100644 --- a/src/box/sql/delete.c +++ b/src/box/sql/delete.c @@ -56,7 +56,7 @@ sqlite3SrcListLookup(Parse * pParse, SrcList * pSrc) struct SrcList_item *pItem = pSrc->a; Table *pTab; assert(pItem && pSrc->nSrc == 1); - pTab = sqlite3LocateTableItem(pParse, 0, pItem); + pTab = sqlite3LocateTable(pParse, 0, pItem->zName); sqlite3DeleteTable(pParse->db, pItem->pTab); pItem->pTab = pTab; if (pTab) { @@ -113,7 +113,6 @@ sqlite3MaterializeView(Parse * pParse, /* Parsing context */ Select *pSel; SrcList *pFrom; sqlite3 *db = pParse->db; - assert(sqlite3SchemaToIndex(db, pView->pSchema) == 0); pWhere = sqlite3ExprDup(db, pWhere, 0); pFrom = sqlite3SrcListAppend(db, 0, 0); if (pFrom) { @@ -325,7 +324,7 @@ sqlite3DeleteFrom(Parse * pParse, /* The parser context */ } if (pParse->nested == 0) sqlite3VdbeCountChanges(v); - sqlite3BeginWriteOperation(pParse, 1); + sql_set_multi_write(pParse, 1); /* If we are trying to delete from a view, realize that view into * an ephemeral table. diff --git a/src/box/sql/expr.c b/src/box/sql/expr.c index f4e3cf735..d981790e6 100644 --- a/src/box/sql/expr.c +++ b/src/box/sql/expr.c @@ -2455,9 +2455,6 @@ sqlite3FindInIndex(Parse * pParse, /* Parsing context */ assert(p->pEList->a[0].pExpr != 0); /* Because of isCandidateForInOpt(p) */ assert(p->pSrc != 0); /* Because of isCandidateForInOpt(p) */ pTab = p->pSrc->a[0].pTab; - - sqlite3CodeVerifySchema(pParse); - assert(v); /* sqlite3GetVdbe() has always been previously called */ Index *pIdx; /* Iterator variable */ @@ -3585,8 +3582,7 @@ sqlite3ExprCodeGetColumnOfTable(Vdbe * v, /* The VDBE under construction */ int regOut /* Extract the value into this register */ ) { - int x = sqlite3ColumnOfIndex(sqlite3PrimaryKeyIndex(pTab), iCol); - sqlite3VdbeAddOp3(v, OP_Column, iTabCur, x, regOut); + sqlite3VdbeAddOp3(v, OP_Column, iTabCur, iCol, regOut); if (iCol >= 0) { sqlite3ColumnDefault(v, pTab, iCol, regOut); } @@ -5315,8 +5311,7 @@ exprIdxCover(Walker * pWalker, Expr * pExpr) { if (pExpr->op == TK_COLUMN && pExpr->iTable == pWalker->u.pIdxCover->iCur - && sqlite3ColumnOfIndex(pWalker->u.pIdxCover->pIdx, - pExpr->iColumn) < 0) { + && pExpr->iColumn < 0) { pWalker->eCode = 1; return WRC_Abort; } diff --git a/src/box/sql/fkey.c b/src/box/sql/fkey.c index f4a6b2707..f56b6d9cd 100644 --- a/src/box/sql/fkey.c +++ b/src/box/sql/fkey.c @@ -961,7 +961,8 @@ sqlite3FkCheck(Parse * pParse, /* Parse context */ * early. */ if (pParse->disableTriggers) { - pTo = sqlite3FindTable(db, pFKey->zTo); + pTo = sqlite3HashFind(&db->pSchema->tblHash, + pFKey->zTo); } else { pTo = sqlite3LocateTable(pParse, 0, pFKey->zTo); } diff --git a/src/box/sql/insert.c b/src/box/sql/insert.c index 4a57b23f5..2719bbaf4 100644 --- a/src/box/sql/insert.c +++ b/src/box/sql/insert.c @@ -422,7 +422,7 @@ sqlite3Insert(Parse * pParse, /* Parser context */ goto insert_cleanup; if (pParse->nested == 0) sqlite3VdbeCountChanges(v); - sqlite3BeginWriteOperation(pParse, pSelect || pTrigger); + sql_set_multi_write(pParse, pSelect || pTrigger); #ifndef SQLITE_OMIT_XFER_OPT /* If the statement is of the form @@ -1398,8 +1398,7 @@ sqlite3GenerateConstraintChecks(Parse * pParse, /* The parser context */ if (pIdx != pPk) { for (i = 0; i < nPkCol; i++) { assert(pPk->aiColumn[i] >= 0); - x = sqlite3ColumnOfIndex(pIdx, - pPk->aiColumn[i]); + x = pPk->aiColumn[i]; sqlite3VdbeAddOp3(v, OP_Column, iThisCur, x, regR + i); VdbeComment((v, "%s.%s", pTab->zName, @@ -1462,7 +1461,7 @@ sqlite3GenerateConstraintChecks(Parse * pParse, /* The parser context */ default: { Trigger *pTrigger = 0; assert(onError == ON_CONFLICT_ACTION_REPLACE); - sqlite3MultiWrite(pParse); + sql_set_multi_write(pParse, 1); if (user_session-> sql_flags & SQLITE_RecTriggers) { pTrigger = @@ -1833,7 +1832,7 @@ xferOptimization(Parse * pParse, /* Parser context */ * we have to check the semantics. */ pItem = pSelect->pSrc->a; - pSrc = sqlite3LocateTableItem(pParse, 0, pItem); + pSrc = sqlite3LocateTable(pParse, 0, pItem->zName); if (pSrc == 0) { return 0; /* FROM clause does not contain a real table */ } @@ -1919,7 +1918,6 @@ xferOptimization(Parse * pParse, /* Parser context */ sqlite3_xferopt_count++; #endif v = sqlite3GetVdbe(pParse); - sqlite3CodeVerifySchema(pParse); iSrc = pParse->nTab++; iDest = pParse->nTab++; regData = sqlite3GetTempReg(pParse); diff --git a/src/box/sql/pragma.c b/src/box/sql/pragma.c index 23b4c73b5..04b4020dd 100644 --- a/src/box/sql/pragma.c +++ b/src/box/sql/pragma.c @@ -358,7 +358,6 @@ sqlite3Pragma(Parse * pParse, Token * pId, /* First part of [schema.]id field */ Column *pCol; Index *pPk = sqlite3PrimaryKeyIndex(pTab); pParse->nMem = 6; - sqlite3CodeVerifySchema(pParse); sqlite3ViewGetColumnNames(pParse, pTab); for (i = 0, pCol = pTab->aCol; i < pTab->nCol; i++, pCol++) { @@ -397,7 +396,6 @@ sqlite3Pragma(Parse * pParse, Token * pId, /* First part of [schema.]id field */ Index *pIdx; HashElem *i; pParse->nMem = 4; - sqlite3CodeVerifySchema(pParse); for (i = sqliteHashFirst(&db->pSchema->tblHash); i; i = sqliteHashNext(i)) { Table *pTab = sqliteHashData(i); @@ -441,7 +439,6 @@ sqlite3Pragma(Parse * pParse, Token * pId, /* First part of [schema.]id field */ pParse->nMem = 3; } mx = index_column_count(pIdx); - sqlite3CodeVerifySchema(pParse); assert(pParse->nMem <= pPragma->nPragCName); for (i = 0; i < mx; i++) { @@ -481,10 +478,10 @@ sqlite3Pragma(Parse * pParse, Token * pId, /* First part of [schema.]id field */ Index *pIdx; Table *pTab; int i; - pTab = sqlite3FindTable(db, zRight); + pTab = sqlite3HashFind(&db->pSchema->tblHash, + zRight); if (pTab) { pParse->nMem = 5; - sqlite3CodeVerifySchema(pParse); for (pIdx = pTab->pIndex, i = 0; pIdx; pIdx = pIdx->pNext, i++) { const char *azOrigin[] = @@ -541,13 +538,13 @@ sqlite3Pragma(Parse * pParse, Token * pId, /* First part of [schema.]id field */ if (zRight) { FKey *pFK; Table *pTab; - pTab = sqlite3FindTable(db, zRight); + pTab = sqlite3HashFind(&db->pSchema->tblHash, + zRight); if (pTab) { pFK = pTab->pFKey; if (pFK) { int i = 0; pParse->nMem = 8; - sqlite3CodeVerifySchema(pParse); while (pFK) { int j; for (j = 0; @@ -597,7 +594,6 @@ sqlite3Pragma(Parse * pParse, Token * pId, /* First part of [schema.]id field */ pParse->nMem += 4; regKey = ++pParse->nMem; regRow = ++pParse->nMem; - sqlite3CodeVerifySchema(pParse); k = sqliteHashFirst(&db->pSchema->tblHash); while (k) { if (zRight) { @@ -619,7 +615,8 @@ sqlite3Pragma(Parse * pParse, Token * pId, /* First part of [schema.]id field */ for (i = 1, pFK = pTab->pFKey; pFK; i++, pFK = pFK->pNextFrom) { pParent = - sqlite3FindTable(db, pFK->zTo); + sqlite3HashFind(&db->pSchema->tblHash, + pFK->zTo); if (pParent == 0) continue; pIdx = 0; @@ -657,7 +654,8 @@ sqlite3Pragma(Parse * pParse, Token * pId, /* First part of [schema.]id field */ for (i = 1, pFK = pTab->pFKey; pFK; i++, pFK = pFK->pNextFrom) { pParent = - sqlite3FindTable(db, pFK->zTo); + sqlite3HashFind(&db->pSchema->tblHash, + pFK->zTo); pIdx = 0; aiCols = 0; if (pParent) { diff --git a/src/box/sql/prepare.c b/src/box/sql/prepare.c index 0ea181d44..7a16074dc 100644 --- a/src/box/sql/prepare.c +++ b/src/box/sql/prepare.c @@ -204,35 +204,6 @@ sqlite3InitDatabase(sqlite3 * db) return rc; } -/* - * Convert a schema pointer into the 0 index that indicates - * that schema refers to a single database. - * This method is inherited from SQLite, which has several dbs. - * But we have only one, so it is used only in assertions. - */ -int -sqlite3SchemaToIndex(sqlite3 * db, Schema * pSchema) -{ - int i = -1000000; - - /* If pSchema is NULL, then return -1000000. This happens when code in - * expr.c is trying to resolve a reference to a transient table (i.e. one - * created by a sub-select). In this case the return value of this - * function should never be used. - * - * We return -1000000 instead of the more usual -1 simply because using - * -1000000 as the incorrect index into db->aDb[] is much - * more likely to cause a segfault than -1 (of course there are assert() - * statements too, but it never hurts to play the odds). - */ - if (pSchema) { - if (db->pSchema == pSchema) { - i = 0; - } - assert(i == 0); - } - return i; -} /* * Free all memory allocations in the pParse object diff --git a/src/box/sql/select.c b/src/box/sql/select.c index c7f87f340..6ff8dc25e 100644 --- a/src/box/sql/select.c +++ b/src/box/sql/select.c @@ -4745,7 +4745,7 @@ selectExpander(Walker * pWalker, Select * p) /* An ordinary table or view name in the FROM clause */ assert(pFrom->pTab == 0); pFrom->pTab = pTab = - sqlite3LocateTableItem(pParse, 0, pFrom); + sqlite3LocateTable(pParse, 0, pFrom->zName); if (pTab == 0) return WRC_Abort; if (pTab->nTabRef >= 0xffff) { @@ -6155,8 +6155,6 @@ sqlite3Select(Parse * pParse, /* The parser context */ Index *pBest; /* Best index found so far */ int iRoot = pTab->tnum; /* Root page of scanned b-tree */ - sqlite3CodeVerifySchema(pParse); - /* Search for the index that has the lowest scan cost. * * (2011-04-15) Do not do a full scan of an unordered index. diff --git a/src/box/sql/sqliteInt.h b/src/box/sql/sqliteInt.h index f43711a7f..fcafb65b4 100644 --- a/src/box/sql/sqliteInt.h +++ b/src/box/sql/sqliteInt.h @@ -2947,7 +2947,6 @@ struct Parse { ExprList *pConstExpr; /* Constant expressions */ Token constraintName; /* Name of the constraint currently being parsed */ yDbMask writeMask; /* Start a write transaction on these databases */ - yDbMask cookieMask; /* Bitmask of schema verified databases */ int regRoot; /* Register holding root page number for new objects */ int nMaxArg; /* Max args passed to user function by sub-program */ #ifdef SELECTTRACE_ENABLED @@ -3550,7 +3549,6 @@ int sqlite3ColumnsFromExprList(Parse *, ExprList *, i16 *, Column **); void sqlite3SelectAddColumnTypeAndCollation(Parse *, Table *, Select *); Table *sqlite3ResultSetOfSelect(Parse *, Select *); Index *sqlite3PrimaryKeyIndex(Table *); -i16 sqlite3ColumnOfIndex(Index *, i16); void sqlite3StartTable(Parse *, Token *, int); void sqlite3AddColumn(Parse *, Token *, Token *); void sqlite3AddNotNull(Parse *, int); @@ -3669,12 +3667,9 @@ int sqlite3ExprCodeExprList(Parse *, ExprList *, int, int, u8); void sqlite3ExprIfTrue(Parse *, Expr *, int, int); void sqlite3ExprIfFalse(Parse *, Expr *, int, int); void sqlite3ExprIfFalseDup(Parse *, Expr *, int, int); -Table *sqlite3FindTable(sqlite3 *, const char *); #define LOCATE_VIEW 0x01 #define LOCATE_NOERR 0x02 Table *sqlite3LocateTable(Parse *, u32 flags, const char *); -Table *sqlite3LocateTableItem(Parse *, u32 flags, struct SrcList_item *); -Index *sqlite3FindIndex(sqlite3 *, const char *, Table *); Index *sqlite3LocateIndex(sqlite3 *, const char *, const char *); void sqlite3UnlinkAndDeleteTable(sqlite3 *, const char *); void sqlite3UnlinkAndDeleteIndex(sqlite3 *, Index *); @@ -3692,7 +3687,6 @@ void sqlite3PrngSaveState(void); void sqlite3PrngRestoreState(void); #endif void sqlite3RollbackAll(Vdbe *, int); -void sqlite3CodeVerifySchema(Parse *); void sqlite3BeginTransaction(Parse *, int); void sqlite3CommitTransaction(Parse *); void sqlite3RollbackTransaction(Parse *); @@ -3718,7 +3712,7 @@ void sqlite3GenerateConstraintChecks(Parse *, Table *, int *, int, int, int, void sqlite3CompleteInsertion(Parse *, Table *, int, int *, int, u8); int sqlite3OpenTableAndIndices(Parse *, Table *, int, u8, int, u8 *, int *, int *, u8, u8); -void sqlite3BeginWriteOperation(Parse *, int); +void sql_set_multi_write(Parse *, int); void sqlite3MultiWrite(Parse *); void sqlite3MayAbort(Parse *); void sqlite3HaltConstraint(Parse *, int, int, char *, i8, u8); @@ -3912,8 +3906,6 @@ struct coll *sqlite3GetCollSeq(Parse *, struct coll *, const char *); char sqlite3AffinityType(const char *, u8 *); void sqlite3Analyze(Parse *, Token *); int sqlite3InvokeBusyHandler(BusyHandler *); -int sqlite3FindDb(sqlite3 *, Token *); -int sqlite3FindDbName(const char *); int sqlite3AnalysisLoad(sqlite3 *); void sqlite3DeleteIndexSamples(sqlite3 *, Index *); void sqlite3DefaultRowEst(Index *); @@ -3925,7 +3917,6 @@ void sqlite3RegisterLikeFunctions(sqlite3 *, int); int sqlite3IsLikeFunction(sqlite3 *, Expr *, int *, char *); void sqlite3SchemaClear(sqlite3 *); Schema *sqlite3SchemaCreate(sqlite3 *); -int sqlite3SchemaToIndex(sqlite3 * db, Schema *); KeyInfo *sqlite3KeyInfoAlloc(sqlite3 *, int, int); void sqlite3KeyInfoUnref(KeyInfo *); KeyInfo *sqlite3KeyInfoRef(KeyInfo *); diff --git a/src/box/sql/trigger.c b/src/box/sql/trigger.c index 859b421db..decbc8c21 100644 --- a/src/box/sql/trigger.c +++ b/src/box/sql/trigger.c @@ -129,7 +129,6 @@ sqlite3BeginTrigger(Parse * pParse, /* The parse context of the CREATE TRIGGER s zName); } else { assert(!db->init.busy); - sqlite3CodeVerifySchema(pParse); } goto trigger_cleanup; } @@ -215,7 +214,6 @@ sqlite3FinishTrigger(Parse * pParse, /* Parser context */ if (NEVER(pParse->nErr) || !pTrig) goto triggerfinish_cleanup; zName = pTrig->zName; - assert(sqlite3SchemaToIndex(pParse->db, pTrig->pSchema) == 0); pTrig->step_list = pStepList; while (pStepList) { pStepList->pTrig = pTrig; @@ -295,7 +293,7 @@ sqlite3FinishTrigger(Parse * pParse, /* Parser context */ iFirstCol = pParse->nMem + 1; pParse->nMem += 2; - sqlite3BeginWriteOperation(pParse, 0); + sql_set_multi_write(pParse, 0); sqlite3VdbeAddOp4(v, OP_String8, 0, iFirstCol, 0, zName, P4_STATIC); @@ -528,8 +526,6 @@ sqlite3DropTrigger(Parse * pParse, SrcList * pName, int noErr) if (!noErr) { sqlite3ErrorMsg(pParse, "no such trigger: %S", pName, 0); - } else { - sqlite3CodeVerifySchema(pParse); } pParse->checkSchema = 1; goto drop_trigger_cleanup; @@ -674,7 +670,6 @@ targetSrcList(Parse * pParse, /* The parsing context */ assert(pSrc->nSrc > 0); pSrc->a[pSrc->nSrc - 1].zName = sqlite3DbStrDup(db, pStep->zTarget); - assert(sqlite3SchemaToIndex(db, pStep->pTrig->pSchema) == 0); } return pSrc; } diff --git a/src/box/sql/update.c b/src/box/sql/update.c index 7727ae5d5..ad6aad5e6 100644 --- a/src/box/sql/update.c +++ b/src/box/sql/update.c @@ -288,7 +288,7 @@ sqlite3Update(Parse * pParse, /* The parser context */ goto update_cleanup; if (pParse->nested == 0) sqlite3VdbeCountChanges(v); - sqlite3BeginWriteOperation(pParse, 1); + sql_set_multi_write(pParse, 1); /* Allocate required registers. */ regOldPk = regNewPk = ++pParse->nMem; diff --git a/src/box/sql/vdbe.c b/src/box/sql/vdbe.c index 329d46886..6de1b917a 100644 --- a/src/box/sql/vdbe.c +++ b/src/box/sql/vdbe.c @@ -1419,7 +1419,6 @@ case OP_ResultRow: { */ if (SQLITE_OK!=(rc = sqlite3VdbeCheckFk(p, 0))) { assert(user_session->sql_flags&SQLITE_CountRows); - assert(p->usesStmtJournal); goto abort_due_to_error; } diff --git a/src/box/sql/vdbeInt.h b/src/box/sql/vdbeInt.h index fcb45c8a8..f23879b1c 100644 --- a/src/box/sql/vdbeInt.h +++ b/src/box/sql/vdbeInt.h @@ -428,7 +428,6 @@ struct Vdbe { bft explain:2; /* True if EXPLAIN present on SQL command */ bft changeCntOn:1; /* True to update the change-counter */ bft runOnlyOnce:1; /* Automatically expire on reset */ - bft usesStmtJournal:1; /* True if uses a statement journal */ bft isPrepareV2:1; /* True if prepared with prepare_v2() */ u32 aCounter[5]; /* Counters used by sqlite3_stmt_status() */ char *zSql; /* Text of the SQL statement that generated this */ diff --git a/src/box/sql/vdbeaux.c b/src/box/sql/vdbeaux.c index e4335524a..bb121a318 100644 --- a/src/box/sql/vdbeaux.c +++ b/src/box/sql/vdbeaux.c @@ -2148,7 +2148,6 @@ sqlite3VdbeMakeReady(Vdbe * p, /* The VDBE */ assert(EIGHT_BYTE_ALIGNMENT(&x.pSpace[x.nFree])); resolveP2Values(p, &nArg); - p->usesStmtJournal = (u8) (pParse->isMultiWrite && pParse->mayAbort); if (pParse->explain && nMem < 10) { nMem = 10; } diff --git a/src/box/sql/where.c b/src/box/sql/where.c index 79de5d69a..d34faef9e 100644 --- a/src/box/sql/where.c +++ b/src/box/sql/where.c @@ -4616,7 +4616,6 @@ sqlite3WhereBegin(Parse * pParse, /* The parser context */ #endif /* SQLITE_ENABLE_COLUMN_USED_MASK */ } } - sqlite3CodeVerifySchema(pParse); } pWInfo->iTop = sqlite3VdbeCurrentAddr(v); if (db->mallocFailed) @@ -4814,7 +4813,6 @@ sqlite3WhereEnd(WhereInfo * pWInfo) if (pOp->opcode == OP_Column) { int x = pOp->p2; assert(pIdx->pTable == pTab); - x = sqlite3ColumnOfIndex(pIdx, x); if (x >= 0) { pOp->p2 = x; pOp->p1 = pLevel->iIdxCur; diff --git a/src/box/sql/wherecode.c b/src/box/sql/wherecode.c index 8b06baeff..53cd30f14 100644 --- a/src/box/sql/wherecode.c +++ b/src/box/sql/wherecode.c @@ -847,7 +847,7 @@ codeCursorHintCheckExpr(Walker * pWalker, Expr * pExpr) assert(pHint->pIdx != 0); if (pExpr->op == TK_COLUMN && pExpr->iTable == pHint->iTabCur - && sqlite3ColumnOfIndex(pHint->pIdx, pExpr->iColumn) < 0) { + && (pExpr->iColumn < 0)) { pWalker->eCode = 1; } return WRC_Continue; @@ -921,8 +921,6 @@ codeCursorHintFixExpr(Walker * pWalker, Expr * pExpr) pExpr->iTable = reg; } else if (pHint->pIdx != 0) { pExpr->iTable = pHint->iIdxCur; - pExpr->iColumn = - sqlite3ColumnOfIndex(pHint->pIdx, pExpr->iColumn); assert(pExpr->iColumn >= 0); } } else if (pExpr->op == TK_AGG_FUNCTION) { @@ -1517,8 +1515,7 @@ sqlite3WhereCodeOneLoopStart(WhereInfo * pWInfo, /* Complete information about t int nPkCol = index_column_count(pPk); int iKeyReg = sqlite3GetTempRange(pParse, nPkCol); for (j = 0; j < nPkCol; j++) { - k = sqlite3ColumnOfIndex(pIdx, - pPk->aiColumn[j]); + k = pPk->aiColumn[j]; sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, k, iKeyReg + j); } -- 2.15.1