diff --git a/extra/mkpragmatab.tcl b/extra/mkpragmatab.tcl index 3b8a0f77cf0a2b3963c636dcfaf788d7c8603f1b..4be65a6f8e57be8e33c439f47773fb4496f3b326 100644 --- a/extra/mkpragmatab.tcl +++ b/extra/mkpragmatab.tcl @@ -56,10 +56,6 @@ set pragma_def { ARG: SQLITE_CkptFullFSync IF: !defined(SQLITE_OMIT_FLAG_PRAGMAS) - NAME: cache_spill - FLAG: Result0 SchemaReq NoColumns1 - IF: !defined(SQLITE_OMIT_FLAG_PRAGMAS) - NAME: reverse_unordered_selects TYPE: FLAG ARG: SQLITE_ReverseOrder diff --git a/src/box/sql/btree.c b/src/box/sql/btree.c index 9e81f779de1aca9eea17bed002da20addcdb21d1..650d83e7cd269c415f64c0e82f84c8c333d29ca6 100644 --- a/src/box/sql/btree.c +++ b/src/box/sql/btree.c @@ -3092,7 +3092,7 @@ int sqlite3BtreeNewDb(Btree *p){ ** when A already has a read lock, we encourage A to give up and let B ** proceed. */ -int sqlite3BtreeBeginTrans(Btree *p, int wrflag){ +int sqlite3BtreeBeginTrans(Btree *p, int nSavepoint, int wrflag){ BtShared *pBt = p->pBt; int rc = SQLITE_OK; @@ -3224,7 +3224,7 @@ int sqlite3BtreeBeginTrans(Btree *p, int wrflag){ ** open savepoints. If the second parameter is greater than 0 and ** the sub-journal is not already open, then it will be opened here. */ - rc = sqlite3PagerOpenSavepoint(pBt->pPager, p->db->nSavepoint); + rc = sqlite3PagerOpenSavepoint(pBt->pPager, nSavepoint); } btreeIntegrity(p); @@ -3949,14 +3949,14 @@ int sqlite3BtreeRollback(Btree *p, int tripCode, int writeOnly){ ** iStatement is 1. This anonymous savepoint can be released or rolled back ** using the sqlite3BtreeSavepoint() function. */ -int sqlite3BtreeBeginStmt(Btree *p, int iStatement){ +int sqlite3BtreeBeginStmt(Btree *p, int iStatement, int nSavepoint){ int rc; BtShared *pBt = p->pBt; sqlite3BtreeEnter(p); assert( p->inTrans==TRANS_WRITE ); assert( (pBt->btsFlags & BTS_READ_ONLY)==0 ); assert( iStatement>0 ); - assert( iStatement>p->db->nSavepoint ); + assert( iStatement>nSavepoint ); assert( pBt->inTransaction==TRANS_WRITE ); /* At the pager level, a statement transaction is a savepoint with ** an index greater than all savepoints created explicitly using @@ -9666,11 +9666,11 @@ int sqlite3BtreeSetVersion(Btree *pBtree, int iVersion){ pBt->btsFlags &= ~BTS_NO_WAL; if( iVersion==1 ) pBt->btsFlags |= BTS_NO_WAL; - rc = sqlite3BtreeBeginTrans(pBtree, 0); + rc = sqlite3BtreeBeginTrans(pBtree, 0, 0); if( rc==SQLITE_OK ){ u8 *aData = pBt->pPage1->aData; if( aData[18]!=(u8)iVersion || aData[19]!=(u8)iVersion ){ - rc = sqlite3BtreeBeginTrans(pBtree, 2); + rc = sqlite3BtreeBeginTrans(pBtree, 0, 2); if( rc==SQLITE_OK ){ rc = sqlite3PagerWrite(pBt->pPage1->pDbPage); if( rc==SQLITE_OK ){ diff --git a/src/box/sql/btree.h b/src/box/sql/btree.h index 99470c7b8b641cf24e8aaae638440bf08aa1155d..1fb066eb587bb8ae5dc90c5e4ca7ff5f63a8e69c 100644 --- a/src/box/sql/btree.h +++ b/src/box/sql/btree.h @@ -78,12 +78,12 @@ int sqlite3BtreeGetOptimalReserve(Btree*); int sqlite3BtreeGetReserveNoMutex(Btree *p); int sqlite3BtreeSetAutoVacuum(Btree *, int); int sqlite3BtreeGetAutoVacuum(Btree *); -int sqlite3BtreeBeginTrans(Btree*,int); +int sqlite3BtreeBeginTrans(Btree*,int,int); int sqlite3BtreeCommitPhaseOne(Btree*, const char *zMaster); int sqlite3BtreeCommitPhaseTwo(Btree*, int); int sqlite3BtreeCommit(Btree*); int sqlite3BtreeRollback(Btree*,int,int); -int sqlite3BtreeBeginStmt(Btree*,int); +int sqlite3BtreeBeginStmt(Btree*,int,int); int sqlite3BtreeCreateTable(Btree*, int*, int flags); int sqlite3BtreeIsInTrans(Btree*); int sqlite3BtreeIsInReadTrans(Btree*); diff --git a/src/box/sql/loadext.c b/src/box/sql/loadext.c index 08d50f0c10ee984319edadd0c4a4d498a5c0c263..9fa36316aa7f96325c7e852ffadec3a03a11b368 100644 --- a/src/box/sql/loadext.c +++ b/src/box/sql/loadext.c @@ -157,7 +157,6 @@ static const sqlite3_api_routines sqlite3Apis = { sqlite3_finalize, sqlite3_free, sqlite3_free_table, - sqlite3_get_autocommit, sqlite3_get_auxdata, sqlite3_get_table, 0, /* Was sqlite3_global_recover(), but that function is deprecated */ diff --git a/src/box/sql/main.c b/src/box/sql/main.c index 471bc197bccd9bdb23f805e0efe336f81e08bb81..ac6179a2412bc99b6c506c3cb643a1cd6cfc0edc 100644 --- a/src/box/sql/main.c +++ b/src/box/sql/main.c @@ -15,6 +15,7 @@ ** accessed by users of the library. */ #include "sqliteInt.h" +#include "vdbeInt.h" #ifdef SQLITE_ENABLE_FTS3 # include "fts3.h" @@ -945,15 +946,15 @@ int sqlite3_total_changes(sqlite3 *db){ ** database handle object, it does not close any savepoints that may be open ** at the b-tree/pager level. */ -void sqlite3CloseSavepoints(sqlite3 *db){ - while( db->pSavepoint ){ - Savepoint *pTmp = db->pSavepoint; - db->pSavepoint = pTmp->pNext; - sqlite3DbFree(db, pTmp); +void sqlite3CloseSavepoints(Vdbe *pVdbe){ + while( pVdbe->pSavepoint && pVdbe->pSavepoint->pNext ){ + Savepoint *pTmp = pVdbe->pSavepoint; + pVdbe->pSavepoint = pTmp->pNext; + sqlite3DbFree(pVdbe->db, pTmp); } - db->nSavepoint = 0; - db->nStatement = 0; - db->isTransactionSavepoint = 0; + pVdbe->nSavepoint = 0; + pVdbe->nStatement = 0; + pVdbe->isTransactionSavepoint = 0; } /* @@ -1085,7 +1086,8 @@ int sqlite3_close_v2(sqlite3 *db){ return sqlite3Close(db,1); } ** attempts to use that cursor. Read cursors remain open and valid ** but are "saved" in case the table pages are moved around. */ -void sqlite3RollbackAll(sqlite3 *db, int tripCode){ +void sqlite3RollbackAll(Vdbe *pVdbe, int tripCode){ + sqlite3 *db = pVdbe->db; int inTrans = 0; int schemaChange; assert( sqlite3_mutex_held(db->mutex) ); @@ -1118,12 +1120,12 @@ void sqlite3RollbackAll(sqlite3 *db, int tripCode){ sqlite3BtreeLeaveAll(db); /* Any deferred constraint violations have now been resolved. */ - db->nDeferredCons = 0; - db->nDeferredImmCons = 0; + pVdbe->nDeferredCons = 0; + pVdbe->nDeferredImmCons = 0; db->flags &= ~SQLITE_DeferFKs; /* If one has been configured, invoke the rollback-hook callback */ - if( db->xRollbackCallback && (inTrans || !db->autoCommit) ){ + if( db->xRollbackCallback && (inTrans || !pVdbe->autoCommit) ){ db->xRollbackCallback(db->pRollbackArg); } } @@ -2510,7 +2512,6 @@ static int openDatabase( assert( sizeof(db->aLimit)==sizeof(aHardLimit) ); memcpy(db->aLimit, aHardLimit, sizeof(db->aLimit)); db->aLimit[SQLITE_LIMIT_WORKER_THREADS] = SQLITE_DEFAULT_WORKER_THREADS; - db->autoCommit = 1; db->nextAutovac = -1; db->szMmap = sqlite3GlobalConfig.szMmap; db->nextPagesize = 0; @@ -2874,22 +2875,6 @@ int sqlite3_global_recover(void){ } #endif -/* -** Test to see whether or not the database connection is in autocommit -** mode. Return TRUE if it is and FALSE if not. Autocommit mode is on -** by default. Autocommit is disabled by a BEGIN statement and reenabled -** by the next COMMIT or ROLLBACK. -*/ -int sqlite3_get_autocommit(sqlite3 *db){ -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) ){ - (void)SQLITE_MISUSE_BKPT; - return 0; - } -#endif - return db->autoCommit; -} - /* ** The following routines are substitutes for constants SQLITE_CORRUPT, ** SQLITE_MISUSE, SQLITE_CANTOPEN, SQLITE_NOMEM and possibly other error diff --git a/src/box/sql/pragma.c b/src/box/sql/pragma.c index d743b3e5fb73c81c1ba86a37fe524fab6da77283..ef00a265bf6e169ca020495f413d91a03c99cc30 100644 --- a/src/box/sql/pragma.c +++ b/src/box/sql/pragma.c @@ -12,6 +12,7 @@ ** This file contains code used to implement the PRAGMA command. */ #include "sqliteInt.h" +#include "vdbeInt.h" #if !defined(SQLITE_ENABLE_LOCKING_STYLE) # if defined(__APPLE__) @@ -34,13 +35,13 @@ ** that includes the PragType_XXXX macro definitions and the aPragmaName[] ** object. This ensures that the aPragmaName[] table is arranged in ** lexicographical order to facility a binary search of the pragma name. -** Do not edit pragma.h directly. Edit and rerun the script in at +** Do not edit pragma.h directly. Edit and rerun the script in at ** ../tool/mkpragmatab.tcl. */ #include "pragma.h" /* ** Interpret the given string as a safety level. Return 0 for OFF, -** 1 for ON or NORMAL, 2 for FULL, and 3 for EXTRA. Return 1 for an empty or +** 1 for ON or NORMAL, 2 for FULL, and 3 for EXTRA. Return 1 for an empty or ** unrecognized string argument. The FULL and EXTRA option is disallowed ** if the omitFull parameter it 1. ** @@ -99,7 +100,7 @@ static int getLockingMode(const char *z){ /* ** Interpret the given string as an auto-vacuum mode value. ** -** The following strings, "none", "full" and "incremental" are +** The following strings, "none", "full" and "incremental" are ** acceptable, as are their numeric equivalents: 0, 1 and 2 respectively. */ static int getAutoVacuum(const char *z){ @@ -171,32 +172,6 @@ static void returnSingleText( } } - -/* -** Set the safety_level and pager flags for pager iDb. Or if iDb<0 -** set these values for all pagers. -*/ -#ifndef SQLITE_OMIT_PAGER_PRAGMAS -static void setAllPagerFlags(sqlite3 *db){ - if( db->autoCommit ){ - Db *pDb = &db->mdb; - assert( SQLITE_FullFSync==PAGER_FULLFSYNC ); - assert( SQLITE_CkptFullFSync==PAGER_CKPT_FULLFSYNC ); - assert( SQLITE_CacheSpill==PAGER_CACHESPILL ); - assert( (PAGER_FULLFSYNC | PAGER_CKPT_FULLFSYNC | PAGER_CACHESPILL) - == PAGER_FLAGS_MASK ); - assert( (pDb->safety_level & PAGER_SYNCHRONOUS_MASK)==pDb->safety_level ); - if( db->mdb.pBt ){ - sqlite3BtreeSetPagerFlags(db->mdb.pBt, - pDb->safety_level | (db->flags & PAGER_FLAGS_MASK) ); - } - } -} -#else -# define setAllPagerFlags(X) /* no-op */ -#endif - - /* ** Return a human-readable name for a constraint resolution action. */ @@ -208,7 +183,7 @@ static const char *actionName(u8 action){ case OE_SetDflt: zName = "SET DEFAULT"; break; case OE_Cascade: zName = "CASCADE"; break; case OE_Restrict: zName = "RESTRICT"; break; - default: zName = "NO ACTION"; + default: zName = "NO ACTION"; assert( action==OE_None ); break; } return zName; @@ -258,7 +233,7 @@ static const PragmaName *pragmaLocate(const char *zName){ } /* -** Process a pragma statement. +** Process a pragma statement. ** ** Pragmas are of this form: ** @@ -273,7 +248,7 @@ static const PragmaName *pragmaLocate(const char *zName){ ** id and pId2 is any empty string. */ void sqlite3Pragma( - Parse *pParse, + Parse *pParse, Token *pId1, /* First part of [schema.]id field */ Token *pId2, /* Second part of [schema.]id field, or NULL */ Token *pValue, /* Token for <value>, or NULL */ @@ -363,8 +338,8 @@ void sqlite3Pragma( /* Register the result column names for pragmas that return results */ if ((pPragma->mPragFlg & PragFlg_NoColumns) == 0 - && ((pPragma->mPragFlg & PragFlg_NoColumns1) == 0 || zRight == 0) - ) { + && ((pPragma->mPragFlg & PragFlg_NoColumns1) == 0 || zRight == 0) + ) { setPragmaResultColumnNames(v, pPragma); } @@ -424,15 +399,15 @@ void sqlite3Pragma( #endif /* !SQLITE_OMIT_PAGER_PRAGMAS && !SQLITE_OMIT_DEPRECATED */ #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) - /* - ** PRAGMA [schema.]page_size - ** PRAGMA [schema.]page_size=N - ** - ** The first form reports the current setting for the - ** database page size in bytes. The second form sets the - ** database page size value. The value can only be set if - ** the database has not yet been created. - */ + /* + ** PRAGMA [schema.]page_size + ** PRAGMA [schema.]page_size=N + ** + ** The first form reports the current setting for the + ** database page size in bytes. The second form sets the + ** database page size value. The value can only be set if + ** the database has not yet been created. + */ case PragTyp_PAGE_SIZE: { Btree *pBt = pDb->pBt; assert(pBt != 0); @@ -451,14 +426,14 @@ void sqlite3Pragma( break; } - /* - ** PRAGMA [schema.]secure_delete - ** PRAGMA [schema.]secure_delete=ON/OFF - ** - ** The first form reports the current setting for the - ** secure_delete flag. The second form changes the secure_delete - ** flag setting and reports thenew value. - */ + /* + ** PRAGMA [schema.]secure_delete + ** PRAGMA [schema.]secure_delete=ON/OFF + ** + ** The first form reports the current setting for the + ** secure_delete flag. The second form changes the secure_delete + ** flag setting and reports thenew value. + */ case PragTyp_SECURE_DELETE: { Btree *pBt = pDb->pBt; int b = -1; @@ -474,23 +449,23 @@ void sqlite3Pragma( break; } - /* - ** PRAGMA [schema.]max_page_count - ** PRAGMA [schema.]max_page_count=N - ** - ** The first form reports the current setting for the - ** maximum number of pages in the database file. The - ** second form attempts to change this setting. Both - ** forms return the current setting. - ** - ** The absolute value of N is used. This is undocumented and might - ** change. The only purpose is to provide an easy way to test - ** the sqlite3AbsInt32() function. - ** - ** PRAGMA [schema.]page_count - ** - ** Return the number of pages in the specified database. - */ + /* + ** PRAGMA [schema.]max_page_count + ** PRAGMA [schema.]max_page_count=N + ** + ** The first form reports the current setting for the + ** maximum number of pages in the database file. The + ** second form attempts to change this setting. Both + ** forms return the current setting. + ** + ** The absolute value of N is used. This is undocumented and might + ** change. The only purpose is to provide an easy way to test + ** the sqlite3AbsInt32() function. + ** + ** PRAGMA [schema.]page_count + ** + ** Return the number of pages in the specified database. + */ case PragTyp_PAGE_COUNT: { int iReg; sqlite3CodeVerifySchema(pParse); @@ -505,20 +480,20 @@ void sqlite3Pragma( break; } - /* - ** PRAGMA [schema.]locking_mode - ** PRAGMA [schema.]locking_mode = (normal|exclusive) - */ + /* + ** PRAGMA [schema.]locking_mode + ** PRAGMA [schema.]locking_mode = (normal|exclusive) + */ case PragTyp_LOCKING_MODE: { const char *zRet = "normal"; int eMode = getLockingMode(zRight); if (pId2->n == 0 && eMode == PAGER_LOCKINGMODE_QUERY) { - /* Simple "PRAGMA locking_mode;" statement. This is a query for - ** the current default locking mode (which may be different to - ** the locking-mode of the main database). - */ - eMode = db->dfltLockMode; + /* Simple "PRAGMA locking_mode;" statement. This is a query for + ** the current default locking mode (which may be different to + ** the locking-mode of the main database). + */ + eMode = db->dfltLockMode; } else { Pager *pPager; if (pId2->n == 0) { @@ -547,23 +522,23 @@ void sqlite3Pragma( break; } - /* - ** PRAGMA [schema.]journal_mode - ** PRAGMA [schema.]journal_mode = - ** (delete|persist|off|truncate|memory|wal|off) - */ + /* + ** PRAGMA [schema.]journal_mode + ** PRAGMA [schema.]journal_mode = + ** (delete|persist|off|truncate|memory|wal|off) + */ case PragTyp_JOURNAL_MODE: { int eMode; /* One of the PAGER_JOURNALMODE_XXX symbols */ if (zRight == 0) { - /* If there is no "=MODE" part of the pragma, do a query for the - ** current mode */ - eMode = PAGER_JOURNALMODE_QUERY; + /* If there is no "=MODE" part of the pragma, do a query for the + ** current mode */ + eMode = PAGER_JOURNALMODE_QUERY; } else { const char *zMode; int n = sqlite3Strlen30(zRight); for (eMode = 0; (zMode = sqlite3JournalModename(eMode)) != 0; eMode++) { - if (sqlite3StrNICmp(zRight, zMode, n) == 0) break; + if (sqlite3StrNICmp(zRight, zMode, n) == 0) break; } if (!zMode) { /* If the "=MODE" part does not match any known journal mode, @@ -583,18 +558,18 @@ void sqlite3Pragma( break; } - /* - ** PRAGMA [schema.]journal_size_limit - ** PRAGMA [schema.]journal_size_limit=N - ** - ** Get or set the size limit on rollback journal files. - */ + /* + ** PRAGMA [schema.]journal_size_limit + ** PRAGMA [schema.]journal_size_limit=N + ** + ** Get or set the size limit on rollback journal files. + */ case PragTyp_JOURNAL_SIZE_LIMIT: { Pager *pPager = sqlite3BtreePager(pDb->pBt); i64 iLimit = -2; if (zRight) { - sqlite3DecOrHexToI64(zRight, &iLimit); - if (iLimit < -1) iLimit = -1; + sqlite3DecOrHexToI64(zRight, &iLimit); + if (iLimit < -1) iLimit = -1; } iLimit = sqlite3PagerJournalSizeLimit(pPager, iLimit); returnSingleInt(v, iLimit); @@ -603,13 +578,13 @@ void sqlite3Pragma( #endif /* SQLITE_OMIT_PAGER_PRAGMAS */ - /* - ** PRAGMA [schema.]auto_vacuum - ** PRAGMA [schema.]auto_vacuum=N - ** - ** Get or set the value of the database 'auto-vacuum' parameter. - ** The value is one of: 0 NONE 1 FULL 2 INCREMENTAL - */ + /* + ** PRAGMA [schema.]auto_vacuum + ** PRAGMA [schema.]auto_vacuum=N + ** + ** Get or set the value of the database 'auto-vacuum' parameter. + ** The value is one of: 0 NONE 1 FULL 2 INCREMENTAL + */ #ifndef SQLITE_OMIT_AUTOVACUUM case PragTyp_AUTO_VACUUM: { Btree *pBt = pDb->pBt; @@ -657,11 +632,11 @@ void sqlite3Pragma( } #endif - /* - ** PRAGMA [schema.]incremental_vacuum(N) - ** - ** Do N steps of incremental vacuuming on a database. - */ + /* + ** PRAGMA [schema.]incremental_vacuum(N) + ** + ** Do N steps of incremental vacuuming on a database. + */ #ifndef SQLITE_OMIT_AUTOVACUUM case PragTyp_INCREMENTAL_VACUUM: { int iLimit, addr; @@ -680,86 +655,43 @@ void sqlite3Pragma( #endif #ifndef SQLITE_OMIT_PAGER_PRAGMAS - /* - ** PRAGMA [schema.]cache_size - ** PRAGMA [schema.]cache_size=N - ** - ** The first form reports the current local setting for the - ** page cache size. The second form sets the local - ** page cache size value. If N is positive then that is the - ** number of pages in the cache. If N is negative, then the - ** number of pages is adjusted so that the cache uses -N kibibytes - ** of memory. - */ + /* + ** PRAGMA [schema.]cache_size + ** PRAGMA [schema.]cache_size=N + ** + ** The first form reports the current local setting for the + ** page cache size. The second form sets the local + ** page cache size value. If N is positive then that is the + ** number of pages in the cache. If N is negative, then the + ** number of pages is adjusted so that the cache uses -N kibibytes + ** of memory. + */ case PragTyp_CACHE_SIZE: { assert(sqlite3SchemaMutexHeld(db, 0)); if (!zRight) { - returnSingleInt(v, pDb->pSchema->cache_size); - } else { - int size = sqlite3Atoi(zRight); - pDb->pSchema->cache_size = size; - sqlite3BtreeSetCacheSize(pDb->pBt, pDb->pSchema->cache_size); - } - break; - } - - /* - ** PRAGMA [schema.]cache_spill - ** PRAGMA cache_spill=BOOLEAN - ** PRAGMA [schema.]cache_spill=N - ** - ** The first form reports the current local setting for the - ** page cache spill size. The second form turns cache spill on - ** or off. When turnning cache spill on, the size is set to the - ** current cache_size. The third form sets a spill size that - ** may be different form the cache size. - ** If N is positive then that is the - ** number of pages in the cache. If N is negative, then the - ** number of pages is adjusted so that the cache uses -N kibibytes - ** of memory. - ** - ** If the number of cache_spill pages is less then the number of - ** cache_size pages, no spilling occurs until the page count exceeds - ** the number of cache_size pages. - ** - ** The cache_spill=BOOLEAN setting applies to all attached schemas, - ** not just the schema specified. - */ - case PragTyp_CACHE_SPILL: { - assert(sqlite3SchemaMutexHeld(db, 0)); - if (!zRight) { - returnSingleInt(v, - (db->flags & SQLITE_CacheSpill) == 0 ? 0 : - sqlite3BtreeSetSpillSize(pDb->pBt, 0)); + returnSingleInt(v, pDb->pSchema->cache_size); } else { - int size = 1; - if (sqlite3GetInt32(zRight, &size)) { - sqlite3BtreeSetSpillSize(pDb->pBt, size); - } - if (sqlite3GetBoolean(zRight, size != 0)) { - db->flags |= SQLITE_CacheSpill; - } else { - db->flags &= ~SQLITE_CacheSpill; - } - setAllPagerFlags(db); + int size = sqlite3Atoi(zRight); + pDb->pSchema->cache_size = size; + sqlite3BtreeSetCacheSize(pDb->pBt, pDb->pSchema->cache_size); } break; } - /* - ** PRAGMA [schema.]mmap_size(N) - ** - ** Used to set mapping size limit. The mapping size limit is - ** used to limit the aggregate size of all memory mapped regions of the - ** database file. If this parameter is set to zero, then memory mapping - ** is not used at all. If N is negative, then the default memory map - ** limit determined by sqlite3_config(SQLITE_CONFIG_MMAP_SIZE) is set. - ** The parameter N is measured in bytes. - ** - ** This value is advisory. The underlying VFS is free to memory map - ** as little or as much as it wants. Except, if N is set to 0 then the - ** upper layers will never invoke the xFetch interfaces to the VFS. - */ + /* + ** PRAGMA [schema.]mmap_size(N) + ** + ** Used to set mapping size limit. The mapping size limit is + ** used to limit the aggregate size of all memory mapped regions of the + ** database file. If this parameter is set to zero, then memory mapping + ** is not used at all. If N is negative, then the default memory map + ** limit determined by sqlite3_config(SQLITE_CONFIG_MMAP_SIZE) is set. + ** The parameter N is measured in bytes. + ** + ** This value is advisory. The underlying VFS is free to memory map + ** as little or as much as it wants. Except, if N is set to 0 then the + ** upper layers will never invoke the xFetch interfaces to the VFS. + */ case PragTyp_MMAP_SIZE: { sqlite3_int64 sz; #if SQLITE_MAX_MMAP_SIZE > 0 @@ -770,7 +702,7 @@ void sqlite3Pragma( if (sz < 0) sz = sqlite3GlobalConfig.szMmap; if (pId2->n == 0) db->szMmap = sz; if (db->mdb.pBt && pId2->n == 0) { - sqlite3BtreeSetMmapLimit(db->mdb.pBt, sz); + sqlite3BtreeSetMmapLimit(db->mdb.pBt, sz); } } sz = -1; @@ -828,14 +760,14 @@ void sqlite3Pragma( #endif #if SQLITE_ENABLE_LOCKING_STYLE - /* - ** PRAGMA [schema.]lock_proxy_file - ** PRAGMA [schema.]lock_proxy_file = ":auto:"|"lock_file_path" - ** - ** Return or set the value of the lock_proxy_file flag. Changing - ** the value sets a specific file to be used for database access locks. - ** - */ + /* + ** PRAGMA [schema.]lock_proxy_file + ** PRAGMA [schema.]lock_proxy_file = ":auto:"|"lock_file_path" + ** + ** Return or set the value of the lock_proxy_file flag. Changing + ** the value sets a specific file to be used for database access locks. + ** + */ case PragTyp_LOCK_PROXY_FILE: { if (!zRight) { Pager *pPager = sqlite3BtreePager(pDb->pBt); @@ -864,29 +796,27 @@ void sqlite3Pragma( } #endif /* SQLITE_ENABLE_LOCKING_STYLE */ - /* - ** PRAGMA [schema.]synchronous - ** PRAGMA [schema.]synchronous=OFF|ON|NORMAL|FULL|EXTRA - ** - ** Return or set the local value of the synchronous flag. Changing - ** the local value does not make changes to the disk file and the - ** default value will be restored the next time the database is - ** opened. - */ + /* + ** PRAGMA [schema.]synchronous + ** PRAGMA [schema.]synchronous=OFF|ON|NORMAL|FULL|EXTRA + ** + ** Return or set the local value of the synchronous flag. Changing + ** the local value does not make changes to the disk file and the + ** default value will be restored the next time the database is + ** opened. + */ case PragTyp_SYNCHRONOUS: { if (!zRight) { returnSingleInt(v, pDb->safety_level - 1); } else { - if (!db->autoCommit) { - sqlite3ErrorMsg(pParse, - "Safety level may not be changed inside a transaction"); - } else { - int iLevel = (getSafetyLevel(zRight, 0, 1) + 1) & PAGER_SYNCHRONOUS_MASK; - if (iLevel == 0) iLevel = 1; - pDb->safety_level = iLevel; - pDb->bSyncSet = 1; - setAllPagerFlags(db); - } + /* + ** Autocommit is default VDBE state. Only OP_Savepoint may change it to 0 + ** Thats why we shouldn't check it + */ + int iLevel = (getSafetyLevel(zRight, 0, 1) + 1) & PAGER_SYNCHRONOUS_MASK; + if (iLevel == 0) iLevel = 1; + pDb->safety_level = iLevel; + pDb->bSyncSet = 1; } break; } @@ -899,11 +829,6 @@ void sqlite3Pragma( returnSingleInt(v, (db->flags & pPragma->iArg) != 0); } else { int mask = pPragma->iArg; /* Mask of bits to set or clear. */ - if (db->autoCommit == 0) { - /* Foreign key support may not be enabled or disabled while not - ** in auto-commit mode. */ - mask &= ~(SQLITE_ForeignKeys); - } #if SQLITE_USER_AUTHENTICATION if( db->auth.authLevel==UAUTH_User ){ /* Do not allow non-admin users to modify the schema arbitrarily */ @@ -915,7 +840,13 @@ void sqlite3Pragma( db->flags |= mask; } else { db->flags &= ~mask; - if (mask == SQLITE_DeferFKs) db->nDeferredImmCons = 0; + if (mask == SQLITE_DeferFKs) { + Vdbe * v = db->pVdbe; + while( v->pNext ) { + v->nDeferredImmCons = 0; + v = v->pNext; + } + } } /* Many of the flag-pragmas modify the code generated by the SQL @@ -923,25 +854,24 @@ void sqlite3Pragma( ** compiled SQL statements after modifying a pragma value. */ sqlite3VdbeAddOp0(v, OP_Expire); - setAllPagerFlags(db); } break; } #endif /* SQLITE_OMIT_FLAG_PRAGMAS */ #ifndef SQLITE_OMIT_SCHEMA_PRAGMAS - /* - ** PRAGMA table_info(<table>) - ** - ** Return a single row for each column of the named table. The columns of - ** the returned data set are: - ** - ** cid: Column id (numbered from left to right, starting at 0) - ** name: Column name - ** type: Column declaration type. - ** notnull: True if 'NOT NULL' is part of column declaration - ** dflt_value: The default value for the column, if any. - */ + /* + ** PRAGMA table_info(<table>) + ** + ** Return a single row for each column of the named table. The columns of + ** the returned data set are: + ** + ** cid: Column id (numbered from left to right, starting at 0) + ** name: Column name + ** type: Column declaration type. + ** notnull: True if 'NOT NULL' is part of column declaration + ** dflt_value: The default value for the column, if any. + */ case PragTyp_TABLE_INFO: if (zRight) { Table *pTab; @@ -994,11 +924,11 @@ void sqlite3Pragma( pTab->nRowLogEst); sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 4); for (pIdx = pTab->pIndex; pIdx; pIdx = pIdx->pNext) { - sqlite3VdbeMultiLoad(v, 2, "sii", - pIdx->zName, - pIdx->szIdxRow, - pIdx->aiRowLogEst[0]); - sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 4); + sqlite3VdbeMultiLoad(v, 2, "sii", + pIdx->zName, + pIdx->szIdxRow, + pIdx->aiRowLogEst[0]); + sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 4); } } } @@ -1157,75 +1087,75 @@ void sqlite3Pragma( k = sqliteHashNext(k); } if (pTab == 0 || pTab->pFKey == 0) continue; - sqlite3TableLock(pParse, pTab->tnum, 0, pTab->zName); - if (pTab->nCol + regRow > pParse->nMem) pParse->nMem = pTab->nCol + regRow; - sqlite3OpenTable(pParse, 0, pTab, OP_OpenRead); - sqlite3VdbeLoadString(v, regResult, pTab->zName); - for (i = 1, pFK = pTab->pFKey; pFK; i++, pFK = pFK->pNextFrom) { - pParent = sqlite3FindTable(db, pFK->zTo); - if (pParent == 0) continue; - pIdx = 0; - sqlite3TableLock(pParse, pParent->tnum, 0, pParent->zName); - x = sqlite3FkLocateIndex(pParse, pParent, pFK, &pIdx, 0); - if (x == 0) { - if (pIdx == 0) { - sqlite3OpenTable(pParse, i, pParent, OP_OpenRead); - } else { - sqlite3VdbeAddOp3(v, OP_OpenRead, i, pIdx->tnum, iDb); - sqlite3VdbeSetP4KeyInfo(pParse, pIdx); - } + sqlite3TableLock(pParse, pTab->tnum, 0, pTab->zName); + if (pTab->nCol + regRow > pParse->nMem) pParse->nMem = pTab->nCol + regRow; + sqlite3OpenTable(pParse, 0, pTab, OP_OpenRead); + sqlite3VdbeLoadString(v, regResult, pTab->zName); + for (i = 1, pFK = pTab->pFKey; pFK; i++, pFK = pFK->pNextFrom) { + pParent = sqlite3FindTable(db, pFK->zTo); + if (pParent == 0) continue; + pIdx = 0; + sqlite3TableLock(pParse, pParent->tnum, 0, pParent->zName); + x = sqlite3FkLocateIndex(pParse, pParent, pFK, &pIdx, 0); + if (x == 0) { + if (pIdx == 0) { + sqlite3OpenTable(pParse, i, pParent, OP_OpenRead); } else { - k = 0; - break; - } - } - assert(pParse->nErr > 0 || pFK == 0); - if (pFK) break; - if (pParse->nTab < i) pParse->nTab = i; - addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, 0); VdbeCoverage(v); - for (i = 1, pFK = pTab->pFKey; pFK; i++, pFK = pFK->pNextFrom) { - pParent = sqlite3FindTable(db, pFK->zTo); - pIdx = 0; - aiCols = 0; - if (pParent) { - x = sqlite3FkLocateIndex(pParse, pParent, pFK, &pIdx, &aiCols); - assert(x == 0); + sqlite3VdbeAddOp3(v, OP_OpenRead, i, pIdx->tnum, iDb); + sqlite3VdbeSetP4KeyInfo(pParse, pIdx); } - addrOk = sqlite3VdbeMakeLabel(v); - if (pParent && pIdx == 0) { - int iKey = pFK->aCol[0].iFrom; - assert(iKey >= 0 && iKey < pTab->nCol); - if (iKey != pTab->iPKey) { - sqlite3VdbeAddOp3(v, OP_Column, 0, iKey, regRow); - sqlite3ColumnDefault(v, pTab, iKey, regRow); - sqlite3VdbeAddOp2(v, OP_IsNull, regRow, addrOk); VdbeCoverage(v); - } else { - sqlite3VdbeAddOp2(v, OP_Rowid, 0, regRow); - } - sqlite3VdbeAddOp3(v, OP_SeekRowid, i, 0, regRow); VdbeCoverage(v); - sqlite3VdbeGoto(v, addrOk); - sqlite3VdbeJumpHere(v, sqlite3VdbeCurrentAddr(v) - 2); + } else { + k = 0; + break; + } + } + assert(pParse->nErr > 0 || pFK == 0); + if (pFK) break; + if (pParse->nTab < i) pParse->nTab = i; + addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, 0); VdbeCoverage(v); + for (i = 1, pFK = pTab->pFKey; pFK; i++, pFK = pFK->pNextFrom) { + pParent = sqlite3FindTable(db, pFK->zTo); + pIdx = 0; + aiCols = 0; + if (pParent) { + x = sqlite3FkLocateIndex(pParse, pParent, pFK, &pIdx, &aiCols); + assert(x == 0); + } + addrOk = sqlite3VdbeMakeLabel(v); + if (pParent && pIdx == 0) { + int iKey = pFK->aCol[0].iFrom; + assert(iKey >= 0 && iKey < pTab->nCol); + if (iKey != pTab->iPKey) { + sqlite3VdbeAddOp3(v, OP_Column, 0, iKey, regRow); + sqlite3ColumnDefault(v, pTab, iKey, regRow); + sqlite3VdbeAddOp2(v, OP_IsNull, regRow, addrOk); VdbeCoverage(v); } else { - for (j = 0; j < pFK->nCol; j++) { - sqlite3ExprCodeGetColumnOfTable(v, pTab, 0, - aiCols ? aiCols[j] : pFK->aCol[j].iFrom, regRow + j); - sqlite3VdbeAddOp2(v, OP_IsNull, regRow + j, addrOk); VdbeCoverage(v); - } - if (pParent) { - sqlite3VdbeAddOp4(v, OP_MakeRecord, regRow, pFK->nCol, regKey, - sqlite3IndexAffinityStr(db, pIdx), pFK->nCol); - sqlite3VdbeAddOp4Int(v, OP_Found, i, addrOk, regKey, 0); - VdbeCoverage(v); - } + sqlite3VdbeAddOp2(v, OP_Rowid, 0, regRow); + } + sqlite3VdbeAddOp3(v, OP_SeekRowid, i, 0, regRow); VdbeCoverage(v); + sqlite3VdbeGoto(v, addrOk); + sqlite3VdbeJumpHere(v, sqlite3VdbeCurrentAddr(v) - 2); + } else { + for (j = 0; j < pFK->nCol; j++) { + sqlite3ExprCodeGetColumnOfTable(v, pTab, 0, + aiCols ? aiCols[j] : pFK->aCol[j].iFrom, regRow + j); + sqlite3VdbeAddOp2(v, OP_IsNull, regRow + j, addrOk); VdbeCoverage(v); + } + if (pParent) { + sqlite3VdbeAddOp4(v, OP_MakeRecord, regRow, pFK->nCol, regKey, + sqlite3IndexAffinityStr(db, pIdx), pFK->nCol); + sqlite3VdbeAddOp4Int(v, OP_Found, i, addrOk, regKey, 0); + VdbeCoverage(v); } - sqlite3VdbeAddOp2(v, OP_Rowid, 0, regResult + 1); - sqlite3VdbeMultiLoad(v, regResult + 2, "si", pFK->zTo, i - 1); - sqlite3VdbeAddOp2(v, OP_ResultRow, regResult, 4); - sqlite3VdbeResolveLabel(v, addrOk); - sqlite3DbFree(db, aiCols); } - sqlite3VdbeAddOp2(v, OP_Next, 0, addrTop + 1); VdbeCoverage(v); - sqlite3VdbeJumpHere(v, addrTop); + sqlite3VdbeAddOp2(v, OP_Rowid, 0, regResult + 1); + sqlite3VdbeMultiLoad(v, regResult + 2, "si", pFK->zTo, i - 1); + sqlite3VdbeAddOp2(v, OP_ResultRow, regResult, 4); + sqlite3VdbeResolveLabel(v, addrOk); + sqlite3DbFree(db, aiCols); + } + sqlite3VdbeAddOp2(v, OP_Next, 0, addrTop + 1); VdbeCoverage(v); + sqlite3VdbeJumpHere(v, addrTop); } } break; @@ -1245,25 +1175,25 @@ void sqlite3Pragma( break; #endif - /* Reinstall the LIKE and GLOB functions. The variant of LIKE - ** used will be case sensitive or not depending on the RHS. - */ + /* Reinstall the LIKE and GLOB functions. The variant of LIKE + ** used will be case sensitive or not depending on the RHS. + */ case PragTyp_CASE_SENSITIVE_LIKE: { if (zRight) { sqlite3RegisterLikeFunctions(db, sqlite3GetBoolean(zRight, 0)); } } - break; + break; #ifndef SQLITE_INTEGRITY_CHECK_ERROR_MAX # define SQLITE_INTEGRITY_CHECK_ERROR_MAX 100 #endif #ifndef SQLITE_OMIT_INTEGRITY_CHECK - /* Pragma "quick_check" is reduced version of - ** integrity_check designed to detect most database corruption - ** without most of the overhead of a full integrity-check. - */ + /* Pragma "quick_check" is reduced version of + ** integrity_check designed to detect most database corruption + ** without most of the overhead of a full integrity-check. + */ case PragTyp_INTEGRITY_CHECK: { int i, j, addr, mxErr; @@ -1487,155 +1417,155 @@ void sqlite3Pragma( break; #endif /* SQLITE_OMIT_INTEGRITY_CHECK */ - /* - ** PRAGMA encoding - ** PRAGMA encoding = "utf-8" - ** - ** In its first form, this pragma returns the encoding of the main - ** database. If the database is not initialized, it is initialized now. - ** - ** The second form of this pragma is a no-op if the main database file - ** has not already been initialized. In this case it sets the default - ** encoding that will be used for the main database file if a new file - ** is created. If an existing main database file is opened, then the - ** default text encoding for the existing database is used. - ** - ** In all cases new databases created using the ATTACH command are - ** created to use the same default text encoding as the main database. If - ** the main database has not been initialized and/or created when ATTACH - ** is executed, this is done before the ATTACH operation. - ** - ** In the second form this pragma sets the text encoding to be used in - ** new database files created using this database handle. It is only - ** useful if invoked immediately after the main database i + /* + ** PRAGMA encoding + ** PRAGMA encoding = "utf-8" + ** + ** In its first form, this pragma returns the encoding of the main + ** database. If the database is not initialized, it is initialized now. + ** + ** The second form of this pragma is a no-op if the main database file + ** has not already been initialized. In this case it sets the default + ** encoding that will be used for the main database file if a new file + ** is created. If an existing main database file is opened, then the + ** default text encoding for the existing database is used. + ** + ** In all cases new databases created using the ATTACH command are + ** created to use the same default text encoding as the main database. If + ** the main database has not been initialized and/or created when ATTACH + ** is executed, this is done before the ATTACH operation. + ** + ** In the second form this pragma sets the text encoding to be used in + ** new database files created using this database handle. It is only + ** useful if invoked immediately after the main database i + */ + case PragTyp_ENCODING: { + static const struct EncName { + char *zName; + u8 enc; + } encnames[] = { + {"UTF8", SQLITE_UTF8}, + {"UTF-8", SQLITE_UTF8}, /* Must be element [1] */ + {0, 0} + }; + const struct EncName *pEnc; + if (!zRight) { /* "PRAGMA encoding" */ + if (sqlite3ReadSchema(pParse)) goto pragma_out; + assert(encnames[SQLITE_UTF8].enc == SQLITE_UTF8); + returnSingleText(v, encnames[ENC(pParse->db)].zName); + } else { /* "PRAGMA encoding = XXX" */ + /* Only change the value of sqlite.enc if the database handle is not + ** initialized. If the main database exists, the new sqlite.enc value + ** will be overwritten when the schema is next loaded. If it does not + ** already exists, it will be created to use the new encoding value. */ - case PragTyp_ENCODING: { - static const struct EncName { - char *zName; - u8 enc; - } encnames[] = { - {"UTF8", SQLITE_UTF8}, - {"UTF-8", SQLITE_UTF8}, /* Must be element [1] */ - {0, 0} - }; - const struct EncName *pEnc; - if (!zRight) { /* "PRAGMA encoding" */ - if (sqlite3ReadSchema(pParse)) goto pragma_out; - assert(encnames[SQLITE_UTF8].enc == SQLITE_UTF8); - returnSingleText(v, encnames[ENC(pParse->db)].zName); - } else { /* "PRAGMA encoding = XXX" */ - /* Only change the value of sqlite.enc if the database handle is not - ** initialized. If the main database exists, the new sqlite.enc value - ** will be overwritten when the schema is next loaded. If it does not - ** already exists, it will be created to use the new encoding value. - */ - if ( - !(DbHasProperty(db, DB_SchemaLoaded)) || - DbHasProperty(db, DB_Empty) - ) { - for (pEnc = &encnames[0]; pEnc->zName; pEnc++) { - if (0 == sqlite3StrICmp(zRight, pEnc->zName)) { - SCHEMA_ENC(db) = ENC(db) = pEnc->enc; - break; - } - } - if (!pEnc->zName) { - sqlite3ErrorMsg(pParse, "unsupported encoding: %s", zRight); - } + if ( + !(DbHasProperty(db, DB_SchemaLoaded)) || + DbHasProperty(db, DB_Empty) + ) { + for (pEnc = &encnames[0]; pEnc->zName; pEnc++) { + if (0 == sqlite3StrICmp(zRight, pEnc->zName)) { + SCHEMA_ENC(db) = ENC(db) = pEnc->enc; + break; } } - } - break; + if (!pEnc->zName) { + sqlite3ErrorMsg(pParse, "unsupported encoding: %s", zRight); + } + } + } + } + break; #ifndef SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS - /* - ** PRAGMA [schema.]schema_version - ** PRAGMA [schema.]schema_version = <integer> - ** - ** PRAGMA [schema.]user_version - ** PRAGMA [schema.]user_version = <integer> - ** - ** PRAGMA [schema.]freelist_count - ** - ** PRAGMA [schema.]data_version - ** - ** PRAGMA [schema.]application_id - ** PRAGMA [schema.]application_id = <integer> - ** - ** The pragma's schema_version and user_version are used to set or get - ** the value of the schema-version and user-version, respectively. Both - ** the schema-version and the user-version are 32-bit signed integers - ** stored in the database header. - ** - ** The schema-cookie is usually only manipulated internally by SQLite. It - ** is incremented by SQLite whenever the database schema is modified (by - ** creating or dropping a table or index). The schema version is used by - ** SQLite each time a query is executed to ensure that the internal cache - ** of the schema used when compiling the SQL query matches the schema of - ** the database against which the compiled query is actually executed. - ** Subverting this mechanism by using "PRAGMA schema_version" to modify - ** the schema-version is potentially dangerous and may lead to program - ** crashes or database corruption. Use with caution! - ** - ** The user-version is not used internally by SQLite. It may be used by - ** applications for any purpose. - */ - case PragTyp_HEADER_VALUE: { - int iCookie = pPragma->iArg; /* Which cookie to read or write */ - sqlite3VdbeUsesBtree(v); - if (zRight && (pPragma->mPragFlg & PragFlg_ReadOnly) == 0) { - /* Write the specified cookie value */ - static const VdbeOpList setCookie[] = { - {OP_Transaction, 0, 1, 0}, /* 0 */ - {OP_SetCookie, 0, 0, 0}, /* 1 */ - }; - VdbeOp *aOp; - sqlite3VdbeVerifyNoMallocRequired(v, ArraySize(setCookie)); - aOp = sqlite3VdbeAddOpList(v, ArraySize(setCookie), setCookie, 0); - if (ONLY_IF_REALLOC_STRESS(aOp == 0)) break; - aOp[0].p1 = iDb; - aOp[1].p1 = iDb; - aOp[1].p2 = iCookie; - aOp[1].p3 = sqlite3Atoi(zRight); - } else { - /* Read the specified cookie value */ - static const VdbeOpList readCookie[] = { - {OP_Transaction, 0, 0, 0}, /* 0 */ - {OP_ReadCookie, 0, 1, 0}, /* 1 */ - {OP_ResultRow, 1, 1, 0} - }; - VdbeOp *aOp; - sqlite3VdbeVerifyNoMallocRequired(v, ArraySize(readCookie)); - aOp = sqlite3VdbeAddOpList(v, ArraySize(readCookie), readCookie, 0); - if (ONLY_IF_REALLOC_STRESS(aOp == 0)) break; - aOp[0].p1 = iDb; - aOp[1].p1 = iDb; - aOp[1].p3 = iCookie; - sqlite3VdbeReusable(v); - } + /* + ** PRAGMA [schema.]schema_version + ** PRAGMA [schema.]schema_version = <integer> + ** + ** PRAGMA [schema.]user_version + ** PRAGMA [schema.]user_version = <integer> + ** + ** PRAGMA [schema.]freelist_count + ** + ** PRAGMA [schema.]data_version + ** + ** PRAGMA [schema.]application_id + ** PRAGMA [schema.]application_id = <integer> + ** + ** The pragma's schema_version and user_version are used to set or get + ** the value of the schema-version and user-version, respectively. Both + ** the schema-version and the user-version are 32-bit signed integers + ** stored in the database header. + ** + ** The schema-cookie is usually only manipulated internally by SQLite. It + ** is incremented by SQLite whenever the database schema is modified (by + ** creating or dropping a table or index). The schema version is used by + ** SQLite each time a query is executed to ensure that the internal cache + ** of the schema used when compiling the SQL query matches the schema of + ** the database against which the compiled query is actually executed. + ** Subverting this mechanism by using "PRAGMA schema_version" to modify + ** the schema-version is potentially dangerous and may lead to program + ** crashes or database corruption. Use with caution! + ** + ** The user-version is not used internally by SQLite. It may be used by + ** applications for any purpose. + */ + case PragTyp_HEADER_VALUE: { + int iCookie = pPragma->iArg; /* Which cookie to read or write */ + sqlite3VdbeUsesBtree(v); + if (zRight && (pPragma->mPragFlg & PragFlg_ReadOnly) == 0) { + /* Write the specified cookie value */ + static const VdbeOpList setCookie[] = { + {OP_Transaction, 0, 1, 0}, /* 0 */ + {OP_SetCookie, 0, 0, 0}, /* 1 */ + }; + VdbeOp *aOp; + sqlite3VdbeVerifyNoMallocRequired(v, ArraySize(setCookie)); + aOp = sqlite3VdbeAddOpList(v, ArraySize(setCookie), setCookie, 0); + if (ONLY_IF_REALLOC_STRESS(aOp == 0)) break; + aOp[0].p1 = iDb; + aOp[1].p1 = iDb; + aOp[1].p2 = iCookie; + aOp[1].p3 = sqlite3Atoi(zRight); + } else { + /* Read the specified cookie value */ + static const VdbeOpList readCookie[] = { + {OP_Transaction, 0, 0, 0}, /* 0 */ + {OP_ReadCookie, 0, 1, 0}, /* 1 */ + {OP_ResultRow, 1, 1, 0} + }; + VdbeOp *aOp; + sqlite3VdbeVerifyNoMallocRequired(v, ArraySize(readCookie)); + aOp = sqlite3VdbeAddOpList(v, ArraySize(readCookie), readCookie, 0); + if (ONLY_IF_REALLOC_STRESS(aOp == 0)) break; + aOp[0].p1 = iDb; + aOp[1].p1 = iDb; + aOp[1].p3 = iCookie; + sqlite3VdbeReusable(v); } - break; + } + break; #endif /* SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS */ /* Tarantool: TODO: comment this so far, since native SQLite WAL was remoced. This might be used with native Tarantool's WAL. */ #if 0 - /* - ** PRAGMA [schema.]wal_checkpoint = passive|full|restart|truncate - ** - ** Checkpoint the database. - */ - case PragTyp_WAL_CHECKPOINT: { - int iBt = (pId2->z?iDb:SQLITE_MAX_ATTACHED); - int eMode = SQLITE_CHECKPOINT_PASSIVE; - if( zRight ){ - if( sqlite3StrICmp(zRight, "full")==0 ){ - eMode = SQLITE_CHECKPOINT_FULL; - }else if( sqlite3StrICmp(zRight, "restart")==0 ){ - eMode = SQLITE_CHECKPOINT_RESTART; - }else if( sqlite3StrICmp(zRight, "truncate")==0 ){ - eMode = SQLITE_CHECKPOINT_TRUNCATE; - } + /* + ** PRAGMA [schema.]wal_checkpoint = passive|full|restart|truncate + ** + ** Checkpoint the database. + */ + case PragTyp_WAL_CHECKPOINT: { + int iBt = (pId2->z?iDb:SQLITE_MAX_ATTACHED); + int eMode = SQLITE_CHECKPOINT_PASSIVE; + if( zRight ){ + if( sqlite3StrICmp(zRight, "full")==0 ){ + eMode = SQLITE_CHECKPOINT_FULL; + }else if( sqlite3StrICmp(zRight, "restart")==0 ){ + eMode = SQLITE_CHECKPOINT_RESTART; + }else if( sqlite3StrICmp(zRight, "truncate")==0 ){ + eMode = SQLITE_CHECKPOINT_TRUNCATE; + } } pParse->nMem = 3; sqlite3VdbeAddOp3(v, OP_Checkpoint, iBt, eMode, 1); @@ -1651,40 +1581,40 @@ void sqlite3Pragma( ** after accumulating N frames in the log. Or query for the current value ** of N. */ - case PragTyp_WAL_AUTOCHECKPOINT: { - if( zRight ){ - sqlite3_wal_autocheckpoint(db, sqlite3Atoi(zRight)); - } - returnSingleInt(v, - db->xWalCallback==sqlite3WalDefaultHook ? - SQLITE_PTR_TO_INT(db->pWalArg) : 0); + case PragTyp_WAL_AUTOCHECKPOINT: { + if( zRight ){ + sqlite3_wal_autocheckpoint(db, sqlite3Atoi(zRight)); } - break; + returnSingleInt(v, + db->xWalCallback==sqlite3WalDefaultHook ? + SQLITE_PTR_TO_INT(db->pWalArg) : 0); + } + break; #endif - /* - ** PRAGMA shrink_memory - ** - ** IMPLEMENTATION-OF: R-23445-46109 This pragma causes the database - ** connection on which it is invoked to free up as much memory as it - ** can, by calling sqlite3_db_release_memory(). - */ - case PragTyp_SHRINK_MEMORY: { - sqlite3_db_release_memory(db); - break; - } + /* + ** PRAGMA shrink_memory + ** + ** IMPLEMENTATION-OF: R-23445-46109 This pragma causes the database + ** connection on which it is invoked to free up as much memory as it + ** can, by calling sqlite3_db_release_memory(). + */ + case PragTyp_SHRINK_MEMORY: { + sqlite3_db_release_memory(db); + break; + } - /* - ** PRAGMA busy_timeout - ** PRAGMA busy_timeout = N - ** - ** Call sqlite3_busy_timeout(db, N). Return the current timeout value - ** if one is set. If no busy handler or a different busy handler is set - ** then 0 is returned. Setting the busy_timeout to 0 or negative - ** disables the timeout. - */ - /*case PragTyp_BUSY_TIMEOUT*/ default: { - assert(pPragma->ePragTyp == PragTyp_BUSY_TIMEOUT); + /* + ** PRAGMA busy_timeout + ** PRAGMA busy_timeout = N + ** + ** Call sqlite3_busy_timeout(db, N). Return the current timeout value + ** if one is set. If no busy handler or a different busy handler is set + ** then 0 is returned. Setting the busy_timeout to 0 or negative + ** disables the timeout. + */ + /*case PragTyp_BUSY_TIMEOUT*/ default: { + assert(pPragma->ePragTyp == PragTyp_BUSY_TIMEOUT); if (zRight) { sqlite3_busy_timeout(db, sqlite3Atoi(zRight)); } @@ -1692,128 +1622,128 @@ void sqlite3Pragma( break; } - /* - ** PRAGMA soft_heap_limit - ** PRAGMA soft_heap_limit = N - ** - ** IMPLEMENTATION-OF: R-26343-45930 This pragma invokes the - ** sqlite3_soft_heap_limit64() interface with the argument N, if N is - ** specified and is a non-negative integer. - ** IMPLEMENTATION-OF: R-64451-07163 The soft_heap_limit pragma always - ** returns the same integer that would be returned by the - ** sqlite3_soft_heap_limit64(-1) C-language function. - */ - case PragTyp_SOFT_HEAP_LIMIT: { - sqlite3_int64 N; - if (zRight && sqlite3DecOrHexToI64(zRight, &N) == SQLITE_OK) { - sqlite3_soft_heap_limit64(N); - } - returnSingleInt(v, sqlite3_soft_heap_limit64(-1)); - break; + /* + ** PRAGMA soft_heap_limit + ** PRAGMA soft_heap_limit = N + ** + ** IMPLEMENTATION-OF: R-26343-45930 This pragma invokes the + ** sqlite3_soft_heap_limit64() interface with the argument N, if N is + ** specified and is a non-negative integer. + ** IMPLEMENTATION-OF: R-64451-07163 The soft_heap_limit pragma always + ** returns the same integer that would be returned by the + ** sqlite3_soft_heap_limit64(-1) C-language function. + */ + case PragTyp_SOFT_HEAP_LIMIT: { + sqlite3_int64 N; + if (zRight && sqlite3DecOrHexToI64(zRight, &N) == SQLITE_OK) { + sqlite3_soft_heap_limit64(N); } + returnSingleInt(v, sqlite3_soft_heap_limit64(-1)); + break; + } - /* - ** PRAGMA threads - ** PRAGMA threads = N - ** - ** Configure the maximum number of worker threads. Return the new - ** maximum, which might be less than requested. - */ - case PragTyp_THREADS: { - sqlite3_int64 N; - if (zRight - && sqlite3DecOrHexToI64(zRight, &N) == SQLITE_OK - && N >= 0 - ) { - sqlite3_limit(db, SQLITE_LIMIT_WORKER_THREADS, (int) (N & 0x7fffffff)); - } - returnSingleInt(v, sqlite3_limit(db, SQLITE_LIMIT_WORKER_THREADS, -1)); - break; + /* + ** PRAGMA threads + ** PRAGMA threads = N + ** + ** Configure the maximum number of worker threads. Return the new + ** maximum, which might be less than requested. + */ + case PragTyp_THREADS: { + sqlite3_int64 N; + if (zRight + && sqlite3DecOrHexToI64(zRight, &N) == SQLITE_OK + && N >= 0 + ) { + sqlite3_limit(db, SQLITE_LIMIT_WORKER_THREADS, (int) (N & 0x7fffffff)); } + returnSingleInt(v, sqlite3_limit(db, SQLITE_LIMIT_WORKER_THREADS, -1)); + break; + } #if defined(SQLITE_DEBUG) || defined(SQLITE_TEST) - /* - ** Report the current state of file logs for all databases - */ - case PragTyp_LOCK_STATUS: { - static const char *const azLockName[] = { - "unlocked", "shared", "reserved", "pending", "exclusive" - }; - pParse->nMem = 2; - Btree *pBt; - const char *zState = "unknown"; - int j; - assert(db->mdb.zDbSName); - pBt = db->mdb.pBt; - if (pBt == 0 || sqlite3BtreePager(pBt) == 0) { - zState = "closed"; - } else if (sqlite3_file_control(db, 0 ? db->mdb.zDbSName : 0, - SQLITE_FCNTL_LOCKSTATE, &j) == SQLITE_OK) { - zState = azLockName[j]; - } - sqlite3VdbeMultiLoad(v, 1, "ss", db->mdb.zDbSName, zState); - sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 2); - break; + /* + ** Report the current state of file logs for all databases + */ + case PragTyp_LOCK_STATUS: { + static const char *const azLockName[] = { + "unlocked", "shared", "reserved", "pending", "exclusive" + }; + pParse->nMem = 2; + Btree *pBt; + const char *zState = "unknown"; + int j; + assert(db->mdb.zDbSName); + pBt = db->mdb.pBt; + if (pBt == 0 || sqlite3BtreePager(pBt) == 0) { + zState = "closed"; + } else if (sqlite3_file_control(db, 0 ? db->mdb.zDbSName : 0, + SQLITE_FCNTL_LOCKSTATE, &j) == SQLITE_OK) { + zState = azLockName[j]; } + sqlite3VdbeMultiLoad(v, 1, "ss", db->mdb.zDbSName, zState); + sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 2); + break; + } #endif #ifdef SQLITE_HAS_CODEC - case PragTyp_KEY: { - if( zRight ) sqlite3_key_v2(db, zDb, zRight, sqlite3Strlen30(zRight)); - break; - } - case PragTyp_REKEY: { - if( zRight ) sqlite3_rekey_v2(db, zDb, zRight, sqlite3Strlen30(zRight)); - break; - } - case PragTyp_HEXKEY: { - if( zRight ){ - u8 iByte; - int i; - char zKey[40]; - for(i=0, iByte=0; i<sizeof(zKey)*2 && sqlite3Isxdigit(zRight[i]); i++){ - iByte = (iByte<<4) + sqlite3HexToInt(zRight[i]); - if( (i&1)!=0 ) zKey[i/2] = iByte; - } - if( (zLeft[3] & 0xf)==0xb ){ - sqlite3_key_v2(db, zDb, zKey, i/2); - }else{ - sqlite3_rekey_v2(db, zDb, zKey, i/2); - } + case PragTyp_KEY: { + if( zRight ) sqlite3_key_v2(db, zDb, zRight, sqlite3Strlen30(zRight)); + break; + } + case PragTyp_REKEY: { + if( zRight ) sqlite3_rekey_v2(db, zDb, zRight, sqlite3Strlen30(zRight)); + break; + } + case PragTyp_HEXKEY: { + if( zRight ){ + u8 iByte; + int i; + char zKey[40]; + for(i=0, iByte=0; i<sizeof(zKey)*2 && sqlite3Isxdigit(zRight[i]); i++){ + iByte = (iByte<<4) + sqlite3HexToInt(zRight[i]); + if( (i&1)!=0 ) zKey[i/2] = iByte; + } + if( (zLeft[3] & 0xf)==0xb ){ + sqlite3_key_v2(db, zDb, zKey, i/2); + }else{ + sqlite3_rekey_v2(db, zDb, zKey, i/2); } - break; } + break; + } #endif #if defined(SQLITE_HAS_CODEC) || defined(SQLITE_ENABLE_CEROD) - case PragTyp_ACTIVATE_EXTENSIONS: if( zRight ){ + case PragTyp_ACTIVATE_EXTENSIONS: if( zRight ){ #ifdef SQLITE_HAS_CODEC - if( sqlite3StrNICmp(zRight, "see-", 4)==0 ){ - sqlite3_activate_see(&zRight[4]); - } + if( sqlite3StrNICmp(zRight, "see-", 4)==0 ){ + sqlite3_activate_see(&zRight[4]); + } #endif #ifdef SQLITE_ENABLE_CEROD - if( sqlite3StrNICmp(zRight, "cerod-", 6)==0 ){ - sqlite3_activate_cerod(&zRight[6]); - } -#endif + if( sqlite3StrNICmp(zRight, "cerod-", 6)==0 ){ + sqlite3_activate_cerod(&zRight[6]); } - break; +#endif + } + break; #endif } /* End of the PRAGMA switch */ - /* The following block is a no-op unless SQLITE_DEBUG is defined. Its only - ** purpose is to execute assert() statements to verify that if the - ** PragFlg_NoColumns1 flag is set and the caller specified an argument - ** to the PRAGMA, the implementation has not added any OP_ResultRow - ** instructions to the VM. */ - if ((pPragma->mPragFlg & PragFlg_NoColumns1) && zRight) { - sqlite3VdbeVerifyNoResultRow(v); - } + /* The following block is a no-op unless SQLITE_DEBUG is defined. Its only + ** purpose is to execute assert() statements to verify that if the + ** PragFlg_NoColumns1 flag is set and the caller specified an argument + ** to the PRAGMA, the implementation has not added any OP_ResultRow + ** instructions to the VM. */ + if ((pPragma->mPragFlg & PragFlg_NoColumns1) && zRight) { + sqlite3VdbeVerifyNoResultRow(v); + } - pragma_out: - sqlite3DbFree(db, zLeft); - sqlite3DbFree(db, zRight); + pragma_out: + sqlite3DbFree(db, zLeft); + sqlite3DbFree(db, zRight); } } #ifndef SQLITE_OMIT_VIRTUALTABLE @@ -1837,7 +1767,7 @@ struct PragmaVtabCursor { char *azArg[2]; /* Value of the argument and schema */ }; -/* +/* ** Pragma virtual table module xConnect method. */ static int pragmaVtabConnect( @@ -1900,7 +1830,7 @@ static int pragmaVtabConnect( return rc; } -/* +/* ** Pragma virtual table module xDisconnect method. */ static int pragmaVtabDisconnect(sqlite3_vtab *pVtab){ @@ -1998,11 +1928,11 @@ static int pragmaVtabNext(sqlite3_vtab_cursor *pVtabCursor){ return rc; } -/* +/* ** Pragma virtual table module xFilter method. */ static int pragmaVtabFilter( - sqlite3_vtab_cursor *pVtabCursor, + sqlite3_vtab_cursor *pVtabCursor, int idxNum, const char *idxStr, int argc, sqlite3_value **argv ){ @@ -2053,11 +1983,11 @@ static int pragmaVtabEof(sqlite3_vtab_cursor *pVtabCursor){ } /* The xColumn method simply returns the corresponding column from -** the PRAGMA. +** the PRAGMA. */ static int pragmaVtabColumn( - sqlite3_vtab_cursor *pVtabCursor, - sqlite3_context *ctx, + sqlite3_vtab_cursor *pVtabCursor, + sqlite3_context *ctx, int i ){ PragmaVtabCursor *pCsr = (PragmaVtabCursor*)pVtabCursor; @@ -2070,7 +2000,7 @@ static int pragmaVtabColumn( return SQLITE_OK; } -/* +/* ** Pragma virtual table module xRowid method. */ static int pragmaVtabRowid(sqlite3_vtab_cursor *pVtabCursor, sqlite_int64 *p){ diff --git a/src/box/sql/pragma.h b/src/box/sql/pragma.h index a339fc0cdcc892522c835bb633c0573c55c7d52d..452e3fe2ceaa60c929e7013f6813dfbd9c97b194 100644 --- a/src/box/sql/pragma.h +++ b/src/box/sql/pragma.h @@ -10,42 +10,41 @@ #define PragTyp_FLAG 2 #define PragTyp_BUSY_TIMEOUT 3 #define PragTyp_CACHE_SIZE 4 -#define PragTyp_CACHE_SPILL 5 -#define PragTyp_CASE_SENSITIVE_LIKE 6 -#define PragTyp_COLLATION_LIST 7 -#define PragTyp_COMPILE_OPTIONS 8 -#define PragTyp_DATA_STORE_DIRECTORY 9 -#define PragTyp_DATABASE_LIST 10 -#define PragTyp_DEFAULT_CACHE_SIZE 11 -#define PragTyp_ENCODING 12 -#define PragTyp_FOREIGN_KEY_CHECK 13 -#define PragTyp_FOREIGN_KEY_LIST 14 -#define PragTyp_INCREMENTAL_VACUUM 15 -#define PragTyp_INDEX_INFO 16 -#define PragTyp_INDEX_LIST 17 -#define PragTyp_INTEGRITY_CHECK 18 -#define PragTyp_JOURNAL_MODE 19 -#define PragTyp_JOURNAL_SIZE_LIMIT 20 -#define PragTyp_LOCK_PROXY_FILE 21 -#define PragTyp_LOCKING_MODE 22 -#define PragTyp_PAGE_COUNT 23 -#define PragTyp_MMAP_SIZE 24 -#define PragTyp_PAGE_SIZE 25 -#define PragTyp_SECURE_DELETE 26 -#define PragTyp_SHRINK_MEMORY 27 -#define PragTyp_SOFT_HEAP_LIMIT 28 -#define PragTyp_STATS 29 -#define PragTyp_SYNCHRONOUS 30 -#define PragTyp_TABLE_INFO 31 -#define PragTyp_THREADS 32 -#define PragTyp_WAL_AUTOCHECKPOINT 33 -#define PragTyp_WAL_CHECKPOINT 34 -#define PragTyp_ACTIVATE_EXTENSIONS 35 -#define PragTyp_HEXKEY 36 -#define PragTyp_KEY 37 -#define PragTyp_REKEY 38 -#define PragTyp_LOCK_STATUS 39 -#define PragTyp_PARSER_TRACE 40 +#define PragTyp_CASE_SENSITIVE_LIKE 5 +#define PragTyp_COLLATION_LIST 6 +#define PragTyp_COMPILE_OPTIONS 7 +#define PragTyp_DATA_STORE_DIRECTORY 8 +#define PragTyp_DATABASE_LIST 9 +#define PragTyp_DEFAULT_CACHE_SIZE 10 +#define PragTyp_ENCODING 11 +#define PragTyp_FOREIGN_KEY_CHECK 12 +#define PragTyp_FOREIGN_KEY_LIST 13 +#define PragTyp_INCREMENTAL_VACUUM 14 +#define PragTyp_INDEX_INFO 15 +#define PragTyp_INDEX_LIST 16 +#define PragTyp_INTEGRITY_CHECK 17 +#define PragTyp_JOURNAL_MODE 18 +#define PragTyp_JOURNAL_SIZE_LIMIT 19 +#define PragTyp_LOCK_PROXY_FILE 20 +#define PragTyp_LOCKING_MODE 21 +#define PragTyp_PAGE_COUNT 22 +#define PragTyp_MMAP_SIZE 23 +#define PragTyp_PAGE_SIZE 24 +#define PragTyp_SECURE_DELETE 25 +#define PragTyp_SHRINK_MEMORY 26 +#define PragTyp_SOFT_HEAP_LIMIT 27 +#define PragTyp_STATS 28 +#define PragTyp_SYNCHRONOUS 29 +#define PragTyp_TABLE_INFO 30 +#define PragTyp_THREADS 31 +#define PragTyp_WAL_AUTOCHECKPOINT 32 +#define PragTyp_WAL_CHECKPOINT 33 +#define PragTyp_ACTIVATE_EXTENSIONS 34 +#define PragTyp_HEXKEY 35 +#define PragTyp_KEY 36 +#define PragTyp_REKEY 37 +#define PragTyp_LOCK_STATUS 38 +#define PragTyp_PARSER_TRACE 39 /* Property flags associated with various pragma. */ #define PragFlg_NeedSchema 0x01 /* Force schema load before running */ @@ -163,13 +162,6 @@ static const PragmaName aPragmaName[] = { /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq|PragFlg_NoColumns1, /* ColNames: */ 0, 0, /* iArg: */ 0 }, -#endif -#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) - {/* zName: */ "cache_spill", - /* ePragTyp: */ PragTyp_CACHE_SPILL, - /* ePragFlg: */ PragFlg_Result0|PragFlg_SchemaReq|PragFlg_NoColumns1, - /* ColNames: */ 0, 0, - /* iArg: */ 0 }, #endif {/* zName: */ "case_sensitive_like", /* ePragTyp: */ PragTyp_CASE_SENSITIVE_LIKE, @@ -590,4 +582,4 @@ static const PragmaName aPragmaName[] = { /* iArg: */ SQLITE_WriteSchema|SQLITE_RecoveryMode }, #endif }; -/* Number of pragmas: 58 on by default, 71 total. */ +/* Number of pragmas: 57 on by default, 70 total. */ diff --git a/src/box/sql/prepare.c b/src/box/sql/prepare.c index 3a94c6a5f65b41cd85ce34276d0bd656b992cf80..e0d8c006cc748ca9724e2a1e7409580890a94b02 100644 --- a/src/box/sql/prepare.c +++ b/src/box/sql/prepare.c @@ -187,7 +187,7 @@ extern int sqlite3InitDatabase(sqlite3 *db, char **pzErrMsg){ ** will be closed before this function returns. */ sqlite3BtreeEnter(pDb->pBt); if( !sqlite3BtreeIsInReadTrans(pDb->pBt) ){ - rc = sqlite3BtreeBeginTrans(pDb->pBt, 0); + rc = sqlite3BtreeBeginTrans(pDb->pBt, 0, 0); if( rc!=SQLITE_OK ){ sqlite3SetString(pzErrMsg, db, sqlite3ErrStr(rc)); goto initone_error_out; @@ -397,7 +397,7 @@ static void schemaIsValid(Parse *pParse){ ** on the b-tree database, open one now. If a transaction is opened, it ** will be closed immediately after reading the meta-value. */ if( !sqlite3BtreeIsInReadTrans(pBt) ){ - rc = sqlite3BtreeBeginTrans(pBt, 0); + rc = sqlite3BtreeBeginTrans(pBt, 0, 0); if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){ sqlite3OomFault(db); } diff --git a/src/box/sql/sqlite3ext.h b/src/box/sql/sqlite3ext.h index 00c3e3f0bce9d345e933b70576345f5abd586188..a385557fa32b19da62b9593b8189d85f4c810a23 100644 --- a/src/box/sql/sqlite3ext.h +++ b/src/box/sql/sqlite3ext.h @@ -83,7 +83,6 @@ struct sqlite3_api_routines { int (*finalize)(sqlite3_stmt*pStmt); void (*free)(void*); void (*free_table)(char**result); - int (*get_autocommit)(sqlite3*); void * (*get_auxdata)(sqlite3_context*,int); int (*get_table)(sqlite3*,const char*,char***,int*,int*,char**); int (*global_recover)(void); @@ -327,7 +326,6 @@ typedef int (*sqlite3_loadext_entry)( #define sqlite3_finalize sqlite3_api->finalize #define sqlite3_free sqlite3_api->free #define sqlite3_free_table sqlite3_api->free_table -#define sqlite3_get_autocommit sqlite3_api->get_autocommit #define sqlite3_get_auxdata sqlite3_api->get_auxdata #define sqlite3_get_table sqlite3_api->get_table #ifndef SQLITE_OMIT_DEPRECATED diff --git a/src/box/sql/sqliteInt.h b/src/box/sql/sqliteInt.h index 700984066eac6fa59de67624062ed8e12a6b3bc2..eed00980e1a47291396da2f8f92179cc5ac5a7e4 100644 --- a/src/box/sql/sqliteInt.h +++ b/src/box/sql/sqliteInt.h @@ -1272,7 +1272,6 @@ struct sqlite3 { int iSysErrno; /* Errno value from last system error */ u16 dbOptFlags; /* Flags to enable/disable optimizations */ u8 enc; /* Text encoding */ - u8 autoCommit; /* The auto-commit flag. */ u8 temp_store; /* 1: file 2: memory 0: default */ u8 mallocFailed; /* True if we have seen a malloc failure */ u8 bBenignMalloc; /* Do not require OOMs if true */ @@ -1280,7 +1279,6 @@ struct sqlite3 { signed char nextAutovac; /* Autovac setting after VACUUM if >=0 */ u8 suppressErr; /* Do not issue error messages if true */ u8 vtabOnConflict; /* Value to return for s3_vtab_on_conflict() */ - u8 isTransactionSavepoint; /* True if the outermost savepoint is a TS */ u8 mTrace; /* zero or more SQLITE_TRACE flags */ int nextPagesize; /* Pagesize after VACUUM if >0 */ u32 magic; /* Magic number for detect library misuse */ @@ -1347,12 +1345,7 @@ struct sqlite3 { Hash aFunc; /* Hash table of connection functions */ Hash aCollSeq; /* All collating sequences */ BusyHandler busyHandler; /* Busy callback */ - Savepoint *pSavepoint; /* List of active savepoints */ int busyTimeout; /* Busy handler timeout, in msec */ - int nSavepoint; /* Number of non-transaction savepoints */ - int nStatement; /* Number of nested statement-transactions */ - i64 nDeferredCons; /* Net deferred constraints this transaction. */ - i64 nDeferredImmCons; /* Net deferred immediate constraints */ int *pnBytesFreed; /* If not NULL, increment this in DbFree() */ #ifdef SQLITE_ENABLE_UNLOCK_NOTIFY /* The following variables are all protected by the STATIC_MASTER @@ -3705,14 +3698,14 @@ Vdbe *sqlite3GetVdbe(Parse*); void sqlite3PrngSaveState(void); void sqlite3PrngRestoreState(void); #endif -void sqlite3RollbackAll(sqlite3*,int); +void sqlite3RollbackAll(Vdbe*,int); void sqlite3CodeVerifySchema(Parse*); void sqlite3CodeVerifyNamedSchema(Parse*, const char *zDb); void sqlite3BeginTransaction(Parse*, int); void sqlite3CommitTransaction(Parse*); void sqlite3RollbackTransaction(Parse*); void sqlite3Savepoint(Parse*, int, Token*); -void sqlite3CloseSavepoints(sqlite3 *); +void sqlite3CloseSavepoints(Vdbe *); int sqlite3ExprIsConstant(Expr*); int sqlite3ExprIsConstantNotJoin(Expr*); int sqlite3ExprIsConstantOrFunction(Expr*, u8); @@ -4071,7 +4064,7 @@ void sqlite3VtabArgExtend(Parse*, Token*); int sqlite3VtabCallCreate(sqlite3*, int, const char *, char **); int sqlite3VtabCallConnect(Parse*, Table*); int sqlite3VtabCallDestroy(sqlite3*, int, const char *); -int sqlite3VtabBegin(sqlite3 *, VTable *); +int sqlite3VtabBegin(sqlite3 *, Vdbe *, VTable *); FuncDef *sqlite3VtabOverloadFunction(sqlite3 *,FuncDef*, int nArg, Expr*); void sqlite3InvalidFunction(sqlite3_context*,int,sqlite3_value**); sqlite3_int64 sqlite3StmtCurrentTime(sqlite3_context*); diff --git a/src/box/sql/status.c b/src/box/sql/status.c index e0b4e47d18ff8a87184ff8dcb09590fff791bc20..d649afd997c4a44d615c82c0a23616de7316edc9 100644 --- a/src/box/sql/status.c +++ b/src/box/sql/status.c @@ -15,7 +15,6 @@ */ #include "sqliteInt.h" #include "vdbeInt.h" - /* ** Variables in which to record status information. */ @@ -214,7 +213,7 @@ int sqlite3_db_status( break; } - /* + /* ** Return an approximation for the amount of memory currently used ** by all pagers associated with the given database connection. The ** highwater mark is meaningless and is returned as zero. @@ -302,7 +301,7 @@ int sqlite3_db_status( /* ** Set *pCurrent to the total cache hits or misses encountered by all - ** pagers the database handle is connected to. *pHighwater is always set + ** pagers the database handle is connected to. *pHighwater is always set ** to zero. */ case SQLITE_DBSTATUS_CACHE_HIT: @@ -329,7 +328,11 @@ int sqlite3_db_status( */ case SQLITE_DBSTATUS_DEFERRED_FKS: { *pHighwater = 0; /* IMP: R-11967-56545 */ - *pCurrent = db->nDeferredImmCons>0 || db->nDeferredCons>0; + Vdbe * v = db->pVdbe; + while( v->pNext ) { + *pCurrent = v->nDeferredImmCons>0 || v->nDeferredCons>0; + v = v->pNext; + } break; } diff --git a/src/box/sql/vdbe.c b/src/box/sql/vdbe.c index 6071cbc9103710b42819a961bcd3f3bd290f29ab..9e15a9214eeb50d666571abec56e69df64f88608 100644 --- a/src/box/sql/vdbe.c +++ b/src/box/sql/vdbe.c @@ -144,7 +144,7 @@ int sql_found_count = 0; static void vdbeTakeBranch(int iSrcLine, u8 I, u8 M){ if( iSrcLine<=2 && ALWAYS(iSrcLine>0) ){ M = iSrcLine; - /* Assert the truth of VdbeCoverageAlwaysTaken() and + /* Assert the truth of VdbeCoverageAlwaysTaken() and ** VdbeCoverageNeverTaken() */ assert( (M & I)==I ); }else{ @@ -193,7 +193,7 @@ static VdbeCursor *allocateCursor( u8 eCurType /* Type of the new cursor */ ){ /* Find the memory cell that will be used to store the blob of memory - ** required for this VdbeCursor structure. It is convenient to use a + ** required for this VdbeCursor structure. It is convenient to use a ** vdbe memory cell to manage the memory allocation required for a ** VdbeCursor structure for the following reasons: ** @@ -214,7 +214,7 @@ static VdbeCursor *allocateCursor( int nByte; VdbeCursor *pCx = 0; - nByte = + nByte = ROUND8(sizeof(VdbeCursor)) + sizeof(u32)*nField + (eCurType==CURTYPE_BTREE?sqlite3BtreeCursorSize():0); @@ -275,7 +275,7 @@ static void applyNumericAffinity(Mem *pRec, int bTryForInt){ ** SQLITE_AFF_INTEGER: ** SQLITE_AFF_REAL: ** SQLITE_AFF_NUMERIC: -** Try to convert pRec to an integer representation or a +** Try to convert pRec to an integer representation or a ** floating-point representation if an integer representation ** is not possible. Note that the integer representation is ** always preferred, even if the affinity is REAL, because @@ -305,7 +305,7 @@ static void applyAffinity( }else if( affinity==SQLITE_AFF_TEXT ){ /* Only attempt the conversion to TEXT if there is an integer or real ** representation (blob and NULL do not get converted) but no string - ** representation. It would be harmless to repeat the conversion if + ** representation. It would be harmless to repeat the conversion if ** there is already a string rep, but it is pointless to waste those ** CPU cycles. */ if( 0==(pRec->flags&MEM_Str) ){ /*OPTIMIZATION-IF-FALSE*/ @@ -334,12 +334,12 @@ int sqlite3_value_numeric_type(sqlite3_value *pVal){ } /* -** Exported version of applyAffinity(). This one works on sqlite3_value*, +** Exported version of applyAffinity(). This one works on sqlite3_value*, ** not the internal Mem* type. */ void sqlite3ValueApplyAffinity( - sqlite3_value *pVal, - u8 affinity, + sqlite3_value *pVal, + u8 affinity, u8 enc ){ applyAffinity((Mem *)pVal, affinity, enc); @@ -365,7 +365,7 @@ static u16 SQLITE_NOINLINE computeNumericType(Mem *pMem){ /* ** Return the numeric type for pMem, either MEM_Int or MEM_Real or both or -** none. +** none. ** ** Unlike applyNumericAffinity(), this routine does not modify pMem->flags. ** But it does set pMem->u.r and pMem->u.i appropriately. @@ -505,8 +505,8 @@ static void registerTrace(int iReg, Mem *p){ #ifdef VDBE_PROFILE -/* -** hwtime.h contains inline assembler code for implementing +/* +** hwtime.h contains inline assembler code for implementing ** high-performance timing routines. */ #include "hwtime.h" @@ -517,18 +517,18 @@ static void registerTrace(int iReg, Mem *p){ /* ** This function is only called from within an assert() expression. It ** checks that the sqlite3.nTransaction variable is correctly set to -** the number of non-transaction savepoints currently in the +** the number of non-transaction savepoints currently in the ** linked list starting at sqlite3.pSavepoint. -** +** ** Usage: ** ** assert( checkSavepointCount(db) ); */ -static int checkSavepointCount(sqlite3 *db){ +static int checkSavepointCount(Vdbe *v){ int n = 0; Savepoint *p; - for(p=db->pSavepoint; p; p=p->pNext) n++; - assert( n==(db->nSavepoint + db->isTransactionSavepoint) ); + for(p=v->pSavepoint; p; p=p->pNext) n++; + assert( n==(v->nSavepoint + v->isTransactionSavepoint) ); return 1; } #endif @@ -559,7 +559,7 @@ static Mem *out2Prerelease(Vdbe *p, VdbeOp *pOp){ /* ** Execute as much of a VDBE program as we can. -** This is the core of sqlite3_step(). +** This is the core of sqlite3_step(). */ int sqlite3VdbeExec( Vdbe *p /* The VDBE */ @@ -664,7 +664,7 @@ int sqlite3VdbeExec( sqlite3VdbePrintOp(stdout, (int)(pOp - aOp), pOp); } #endif - + /* Check to see if we need to simulate an interrupt. This only happens ** if we have a special test build. @@ -718,7 +718,7 @@ int sqlite3VdbeExec( #if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE) pOrigOp = pOp; #endif - + switch( pOp->opcode ){ /***************************************************************************** @@ -759,7 +759,7 @@ int sqlite3VdbeExec( /* Opcode: Goto * P2 * * * ** ** An unconditional jump to address P2. -** The next instruction executed will be +** The next instruction executed will be ** the one at index P2 from the beginning of ** the program. ** @@ -775,7 +775,7 @@ case OP_Goto: { /* jump */ /* Opcodes that are used as the bottom of a loop (OP_Next, OP_Prev, ** OP_VNext, OP_RowSetNext, or OP_SorterNext) all jump here upon ** completion. Check to see if sqlite3_interrupt() has been called - ** or if the progress callback needs to be invoked. + ** or if the progress callback needs to be invoked. ** ** This code uses unstructured "goto" statements and does not look clean. ** But that is not due to sloppy coding habits. The code is written this @@ -800,7 +800,7 @@ case OP_Goto: { /* jump */ } } #endif - + break; } @@ -932,7 +932,7 @@ case OP_HaltIfNull: { /* in3 */ ** whether or not to rollback the current transaction. Do not rollback ** if P2==OE_Fail. Do the rollback if P2==OE_Rollback. If P2==OE_Abort, ** then back out all changes that have occurred during this execution of the -** VDBE, but do not rollback the transaction. +** VDBE, but do not rollback the transaction. ** ** If P4 is not null then it is an error message string. ** @@ -965,7 +965,7 @@ case OP_Halt: { pcx = sqlite3VdbeFrameRestore(pFrame); lastRowid = db->lastRowid; if( pOp->p2==OE_Ignore ){ - /* Instruction pcx is the OP_Program that invoked the sub-program + /* Instruction pcx is the OP_Program that invoked the sub-program ** currently being halted. If the p2 instruction of this OP_Halt ** instruction is set to OE_Ignore, then the sub-program is throwing ** an IGNORE exception. In this case jump to the address specified @@ -1004,7 +1004,7 @@ case OP_Halt: { p->rc = SQLITE_BUSY; }else{ assert( rc==SQLITE_OK || (p->rc&0xff)==SQLITE_CONSTRAINT ); - assert( rc==SQLITE_OK || db->nDeferredCons>0 || db->nDeferredImmCons>0 ); + assert( rc==SQLITE_OK || p->nDeferredCons>0 || p->nDeferredImmCons>0 ); rc = p->rc ? SQLITE_ERROR : SQLITE_DONE; } goto vdbe_return; @@ -1053,7 +1053,7 @@ case OP_Real: { /* same as TK_FLOAT, out2 */ /* Opcode: String8 * P2 * P4 * ** Synopsis: r[P2]='P4' ** -** P4 points to a nul terminated UTF-8 string. This opcode is transformed +** P4 points to a nul terminated UTF-8 string. This opcode is transformed ** into a String opcode before it is executed for the first time. During ** this transformation, the length of string P4 is computed and stored ** as the P1 parameter. @@ -1088,7 +1088,7 @@ case OP_String8: { /* same as TK_STRING, out2 */ assert( rc==SQLITE_OK ); /* Fall through to the next case, OP_String */ } - + /* Opcode: String P1 P2 P3 P4 P5 ** Synopsis: r[P2]='P4' (len=P1) ** @@ -1355,8 +1355,8 @@ case OP_ResultRow: { goto abort_due_to_error; } - /* If the SQLITE_CountRows flag is set in sqlite3.flags mask, then - ** DML statements invoke this opcode to return the number of rows + /* If the SQLITE_CountRows flag is set in sqlite3.flags mask, then + ** DML statements invoke this opcode to return the number of rows ** modified to the user. This is the only way that a VM that ** opens a statement transaction may invoke this opcode. ** @@ -1477,14 +1477,14 @@ case OP_Concat: { /* same as TK_CONCAT, in1, in2, out3 */ ** Synopsis: r[P3]=r[P2]/r[P1] ** ** Divide the value in register P1 by the value in register P2 -** and store the result in register P3 (P3=P2/P1). If the value in -** register P1 is zero, then the result is NULL. If either input is +** and store the result in register P3 (P3=P2/P1). If the value in +** register P1 is zero, then the result is NULL. If either input is ** NULL, the result is NULL. */ /* Opcode: Remainder P1 P2 P3 * * ** Synopsis: r[P3]=r[P2]%r[P1] ** -** Compute the remainder after integer register P2 is divided by +** Compute the remainder after integer register P2 is divided by ** register P1 and store the result in register P3. ** If the value in register P1 is zero the result is NULL. ** If either operand is NULL, the result is NULL. @@ -2779,10 +2779,10 @@ case OP_Savepoint: { /* Assert that the p1 parameter is valid. Also that if there is no open ** transaction, then there cannot be any savepoints. */ - assert( db->pSavepoint==0 || db->autoCommit==0 ); + assert( p->pSavepoint==0 || p->autoCommit==0 ); assert( p1==SAVEPOINT_BEGIN||p1==SAVEPOINT_RELEASE||p1==SAVEPOINT_ROLLBACK ); - assert( db->pSavepoint || db->isTransactionSavepoint==0 ); - assert( checkSavepointCount(db) ); + assert( p->pSavepoint || p->isTransactionSavepoint==0 ); + assert( checkSavepointCount(p) ); assert( p->bIsReader ); if( p1==SAVEPOINT_BEGIN ){ @@ -2800,9 +2800,9 @@ case OP_Savepoint: { ** savepoint (and therefore should not prompt xSavepoint()) callbacks. ** If this is a transaction savepoint being opened, it is guaranteed ** that the db->aVTrans[] array is empty. */ - assert( db->autoCommit==0 || db->nVTrans==0 ); + assert( p->autoCommit==0 || db->nVTrans==0 ); rc = sqlite3VtabSavepoint(db, SAVEPOINT_BEGIN, - db->nStatement+db->nSavepoint); + p->nStatement+p->nSavepoint); if( rc!=SQLITE_OK ) goto abort_due_to_error; #endif @@ -2811,21 +2811,21 @@ case OP_Savepoint: { if( pNew ){ pNew->zName = (char *)&pNew[1]; memcpy(pNew->zName, zName, nName+1); - + /* If there is no open transaction, then mark this as a special ** "transaction savepoint". */ - if( db->autoCommit ){ - db->autoCommit = 0; - db->isTransactionSavepoint = 1; + if( p->autoCommit ){ + p->autoCommit = 0; + p->isTransactionSavepoint = 1; }else{ - db->nSavepoint++; + p->nSavepoint++; } /* Link the new savepoint into the database handle's list. */ - pNew->pNext = db->pSavepoint; - db->pSavepoint = pNew; - pNew->nDeferredCons = db->nDeferredCons; - pNew->nDeferredImmCons = db->nDeferredImmCons; + pNew->pNext = p->pSavepoint; + p->pSavepoint = pNew; + pNew->nDeferredCons = p->nDeferredCons; + pNew->nDeferredImmCons = p->nDeferredImmCons; } } }else{ @@ -2834,7 +2834,7 @@ case OP_Savepoint: { /* Find the named savepoint. If there is no such savepoint, then an ** an error is returned to the user. */ for( - pSavepoint = db->pSavepoint; + pSavepoint = p->pSavepoint; pSavepoint && sqlite3StrICmp(pSavepoint->zName, zName); pSavepoint = pSavepoint->pNext ){ @@ -2844,7 +2844,7 @@ case OP_Savepoint: { sqlite3VdbeError(p, "no such savepoint: %s", zName); rc = SQLITE_ERROR; }else if( db->nVdbeWrite>0 && p1==SAVEPOINT_RELEASE ){ - /* It is not possible to release (commit) a savepoint if there are + /* It is not possible to release (commit) a savepoint if there are ** active write statements. */ sqlite3VdbeError(p, "cannot release savepoint - " @@ -2853,26 +2853,26 @@ case OP_Savepoint: { }else{ /* Determine whether or not this is a transaction savepoint. If so, - ** and this is a RELEASE command, then the current transaction - ** is committed. + ** and this is a RELEASE command, then the current transaction + ** is committed. */ - int isTransaction = pSavepoint->pNext==0 && db->isTransactionSavepoint; + int isTransaction = pSavepoint->pNext==0 && p->isTransactionSavepoint; if( isTransaction && p1==SAVEPOINT_RELEASE ){ if( (rc = sqlite3VdbeCheckFk(p, 1))!=SQLITE_OK ){ goto vdbe_return; } - db->autoCommit = 1; + p->autoCommit = 1; if( sqlite3VdbeHalt(p)==SQLITE_BUSY ){ p->pc = (int)(pOp - aOp); - db->autoCommit = 0; + p->autoCommit = 0; p->rc = rc = SQLITE_BUSY; goto vdbe_return; } - db->isTransactionSavepoint = 0; + p->isTransactionSavepoint = 0; rc = p->rc; }else{ int isSchemaChange; - iSavepoint = db->nSavepoint - iSavepoint - 1; + iSavepoint = p->nSavepoint - iSavepoint - 1; if( p1==SAVEPOINT_ROLLBACK ){ isSchemaChange = (db->flags & SQLITE_InternChanges)!=0; rc = sqlite3BtreeTripAllCursors(db->mdb.pBt, @@ -2892,30 +2892,30 @@ case OP_Savepoint: { db->flags = (db->flags | SQLITE_InternChanges); } } - - /* Regardless of whether this is a RELEASE or ROLLBACK, destroy all + + /* Regardless of whether this is a RELEASE or ROLLBACK, destroy all ** savepoints nested inside of the savepoint being operated on. */ - while( db->pSavepoint!=pSavepoint ){ - pTmp = db->pSavepoint; - db->pSavepoint = pTmp->pNext; + while( p->pSavepoint!=pSavepoint ){ + pTmp = p->pSavepoint; + p->pSavepoint = pTmp->pNext; sqlite3DbFree(db, pTmp); - db->nSavepoint--; + p->nSavepoint--; } - /* If it is a RELEASE, then destroy the savepoint being operated on - ** too. If it is a ROLLBACK TO, then set the number of deferred + /* If it is a RELEASE, then destroy the savepoint being operated on + ** too. If it is a ROLLBACK TO, then set the number of deferred ** constraint violations present in the database to the value stored ** when the savepoint was created. */ if( p1==SAVEPOINT_RELEASE ){ - assert( pSavepoint==db->pSavepoint ); - db->pSavepoint = pSavepoint->pNext; + assert( pSavepoint==p->pSavepoint ); + p->pSavepoint = pSavepoint->pNext; sqlite3DbFree(db, pSavepoint); if( !isTransaction ){ - db->nSavepoint--; + p->nSavepoint--; } }else{ - db->nDeferredCons = pSavepoint->nDeferredCons; - db->nDeferredImmCons = pSavepoint->nDeferredImmCons; + p->nDeferredCons = pSavepoint->nDeferredCons; + p->nDeferredImmCons = pSavepoint->nDeferredImmCons; } if( !isTransaction || p1==SAVEPOINT_ROLLBACK ){ @@ -2949,15 +2949,15 @@ case OP_AutoCommit: { assert( db->nVdbeActive>0 ); /* At least this one VM is active */ assert( p->bIsReader ); - if( desiredAutoCommit!=db->autoCommit ){ + if( desiredAutoCommit!=p->autoCommit ){ if( iRollback ){ assert( desiredAutoCommit==1 ); box_txn_rollback(); - sqlite3RollbackAll(db, SQLITE_ABORT_ROLLBACK); - db->autoCommit = 1; + sqlite3RollbackAll(p, SQLITE_ABORT_ROLLBACK); + p->autoCommit = 1; }else if( desiredAutoCommit && db->nVdbeWrite>0 ){ /* If this instruction implements a COMMIT and other VMs are writing - ** return an error indicating that the other VMs must complete first. + ** return an error indicating that the other VMs must complete first. */ sqlite3VdbeError(p, "cannot commit transaction - " "SQL statements in progress"); @@ -2966,16 +2966,16 @@ case OP_AutoCommit: { }else if( (rc = sqlite3VdbeCheckFk(p, 1))!=SQLITE_OK ){ goto vdbe_return; }else{ - db->autoCommit = (u8)desiredAutoCommit; + p->autoCommit = (u8)desiredAutoCommit; } if( sqlite3VdbeHalt(p)==SQLITE_BUSY ){ p->pc = (int)(pOp - aOp); - db->autoCommit = (u8)(1-desiredAutoCommit); + p->autoCommit = (u8)(1-desiredAutoCommit); p->rc = rc = SQLITE_BUSY; goto vdbe_return; } - assert( db->nStatement==0 ); - sqlite3CloseSavepoints(db); + assert( p->nStatement==0 ); + sqlite3CloseSavepoints(p); if( p->rc==SQLITE_OK ){ rc = SQLITE_DONE; }else{ @@ -2987,7 +2987,7 @@ case OP_AutoCommit: { (!desiredAutoCommit)?"cannot start a transaction within a transaction":( (iRollback)?"cannot rollback - no transaction is active": "cannot commit - no transaction is active")); - + rc = SQLITE_ERROR; goto abort_due_to_error; } @@ -2998,7 +2998,7 @@ case OP_AutoCommit: { ** ** Begin a transaction on database P1 if a transaction is not already ** active. -** If P2 is non-zero, then a write-transaction is started, or if a +** If P2 is non-zero, then a write-transaction is started, or if a ** read-transaction is already active, it is upgraded to a write-transaction. ** If P2 is zero, then a read-transaction is started. ** @@ -3010,7 +3010,7 @@ case OP_AutoCommit: { ** If a write-transaction is started and the Vdbe.usesStmtJournal flag is ** true (this flag is set if the Vdbe may modify more than one row and may ** throw an ABORT exception), a statement transaction may also be opened. -** More specifically, a statement transaction is opened iff the database +** More specifically, a statement transaction is opened if the database ** connection is currently not in autocommit mode, or if there are other ** active statements. A statement transaction allows the changes made by this ** VDBE to be rolled back after an error without having to roll back the @@ -3044,7 +3044,7 @@ case OP_Transaction: { pBt = db->mdb.pBt; if( pBt ){ - rc = sqlite3BtreeBeginTrans(pBt, pOp->p2); + rc = sqlite3BtreeBeginTrans(pBt, p->nSavepoint, pOp->p2); testcase( rc==SQLITE_BUSY_SNAPSHOT ); testcase( rc==SQLITE_BUSY_RECOVERY ); if( rc!=SQLITE_OK ){ @@ -3056,26 +3056,26 @@ case OP_Transaction: { goto abort_due_to_error; } - if( pOp->p2 && p->usesStmtJournal - && (db->autoCommit==0 || db->nVdbeRead>1) + if( pOp->p2 && p->usesStmtJournal + && (p->autoCommit==0 || db->nVdbeRead>1 ) ){ assert( sqlite3BtreeIsInTrans(pBt) ); if( p->iStatement==0 ){ - assert( db->nStatement>=0 && db->nSavepoint>=0 ); - db->nStatement++; - p->iStatement = db->nSavepoint + db->nStatement; + assert( p->nStatement>=0 && p->nSavepoint>=0 ); + p->nStatement++; + p->iStatement = p->nSavepoint + p->nStatement; } rc = sqlite3VtabSavepoint(db, SAVEPOINT_BEGIN, p->iStatement-1); if( rc==SQLITE_OK ){ - rc = sqlite3BtreeBeginStmt(pBt, p->iStatement); + rc = sqlite3BtreeBeginStmt(pBt, p->iStatement, p->nSavepoint); } /* Store the current value of the database handles deferred constraint ** counter. If the statement transaction needs to be rolled back, ** the value of this counter needs to be restored too. */ - p->nStmtDefCons = db->nDeferredCons; - p->nStmtDefImmCons = db->nDeferredImmCons; + p->nStmtDefCons = p->nDeferredCons; + p->nStmtDefImmCons = p->nDeferredImmCons; } /* Gather the schema version number for checking: @@ -3092,7 +3092,7 @@ case OP_Transaction: { if( pOp->p5 && (iMeta!=pOp->p3 || iGen!=pOp->p4.i) ){ sqlite3DbFree(db, p->zErrMsg); p->zErrMsg = sqlite3DbStrDup(db, "database schema has changed"); - /* If the schema-cookie from the database file matches the cookie + /* If the schema-cookie from the database file matches the cookie ** stored with the in-memory representation of the schema, do ** not reload the schema from the database file. ** @@ -3102,7 +3102,7 @@ case OP_Transaction: { ** prepared queries. If such a query is out-of-date, we do not want to ** discard the database schema, as the user code implementing the ** v-table would have to be ready for the sqlite3_vtab structure itself - ** to be invalidated whenever sqlite3_step() is called from within + ** to be invalidated whenever sqlite3_step() is called from within ** a v-table method. */ if( db->mdb.pSchema->schema_cookie!=iMeta ){ @@ -3123,13 +3123,14 @@ case OP_Transaction: { ** Auto commit mode is disabled by OP_Transaction. */ case OP_TTransaction: - { - int rc; - if (db->autoCommit) - rc = box_txn_begin() == 0 ? SQLITE_OK : SQLITE_TARANTOOL_ERROR; - break; - } - +{ + int rc; + if (p->autoCommit) { + rc = box_txn_begin() == 0 ? SQLITE_OK : SQLITE_TARANTOOL_ERROR; + } + break; +} + /* Opcode: ReadCookie P1 P2 P3 * * ** ** Read cookie number P3 from database P1 and write it into register P2. @@ -3165,8 +3166,8 @@ case OP_ReadCookie: { /* out2 */ ** ** Write the integer value P3 into cookie number P2 of database P1. ** P2==1 is the schema version. P2==2 is the database format. -** P2==3 is the recommended pager cache -** size, and so forth. P1==0 is the main database file and P1==1 is the +** P2==3 is the recommended pager cache +** size, and so forth. P1==0 is the main database file and P1==1 is the ** database file used to store temporary tables. ** ** A transaction must be started before executing this opcode. @@ -3204,8 +3205,8 @@ case OP_SetCookie: { ** Synopsis: root=P2 iDb=P3 ** ** Open a read-only cursor for the database table whose root page is -** P2 in a database file. The database file is determined by P3. -** P3==0 means the main database, P3==1 means the database used for +** P2 in a database file. The database file is determined by P3. +** P3==0 means the main database, P3==1 means the database used for ** temporary tables, and P3>1 means used the corresponding attached ** database. Give the new cursor an identifier of P1. The P1 ** values need not be contiguous but all P1 values should be small integers. @@ -3224,9 +3225,9 @@ case OP_SetCookie: { ** SQLITE_BUSY error code. ** ** The P4 value may be either an integer (P4_INT32) or a pointer to -** a KeyInfo structure (P4_KEYINFO). If it is a pointer to a KeyInfo -** structure, then said structure defines the content and collating -** sequence of the index being opened. Otherwise, if P4 is an integer +** a KeyInfo structure (P4_KEYINFO). If it is a pointer to a KeyInfo +** structure, then said structure defines the content and collating +** sequence of the index being opened. Otherwise, if P4 is an integer ** value, it is set to the number of columns in the table. ** ** See also: OpenWrite, ReopenIdx @@ -3253,9 +3254,9 @@ case OP_SetCookie: { ** root page. ** ** The P4 value may be either an integer (P4_INT32) or a pointer to -** a KeyInfo structure (P4_KEYINFO). If it is a pointer to a KeyInfo -** structure, then said structure defines the content and collating -** sequence of the index being opened. Otherwise, if P4 is an integer +** a KeyInfo structure (P4_KEYINFO). If it is a pointer to a KeyInfo +** structure, then said structure defines the content and collating +** sequence of the index being opened. Otherwise, if P4 is an integer ** value, it is set to the number of columns in the table, or to the ** largest index of any column of the table that is actually used. ** @@ -3354,7 +3355,7 @@ case OP_OpenWrite: /* Set the VdbeCursor.isTable variable. Previous versions of ** SQLite used to check if the root-page flags were sane at this point ** and report database corruption if they were not, but this check has - ** since moved into the btree layer. */ + ** since moved into the btree layer. */ pCur->isTable = pOp->p4type!=P4_KEYINFO; open_cursor_set_hints: @@ -3374,7 +3375,7 @@ case OP_OpenWrite: ** Synopsis: nColumn=P2 ** ** Open a new cursor P1 to a transient table. -** The cursor is always opened read/write even if +** The cursor is always opened read/write even if ** the main database is read-only. The ephemeral ** table is deleted automatically when the cursor is closed. ** @@ -3396,12 +3397,12 @@ case OP_OpenWrite: ** by this opcode will be used for automatically created transient ** indices in joins. */ -case OP_OpenAutoindex: +case OP_OpenAutoindex: case OP_OpenEphemeral: { VdbeCursor *pCx; KeyInfo *pKeyInfo; - static const int vfsFlags = + static const int vfsFlags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_EXCLUSIVE | @@ -3413,10 +3414,10 @@ case OP_OpenEphemeral: { if( pCx==0 ) goto no_mem; pCx->nullRow = 1; pCx->isEphemeral = 1; - rc = sqlite3BtreeOpen(db->pVfs, 0, db, &pCx->pBtx, + rc = sqlite3BtreeOpen(db->pVfs, 0, db, &pCx->pBtx, BTREE_OMIT_JOURNAL | BTREE_SINGLE | pOp->p5, vfsFlags); if( rc==SQLITE_OK ){ - rc = sqlite3BtreeBeginTrans(pCx->pBtx, 1); + rc = sqlite3BtreeBeginTrans(pCx->pBtx, p->nSavepoint, 1); } if( rc==SQLITE_OK ){ /* If a transient index is required, create it by calling @@ -3427,7 +3428,7 @@ case OP_OpenEphemeral: { if( (pCx->pKeyInfo = pKeyInfo = pOp->p4.pKeyInfo)!=0 ){ int pgno; assert( pOp->p4type==P4_KEYINFO ); - rc = sqlite3BtreeCreateTable(pCx->pBtx, &pgno, BTREE_BLOBKEY | pOp->p5); + rc = sqlite3BtreeCreateTable(pCx->pBtx, &pgno, BTREE_BLOBKEY | pOp->p5); if( rc==SQLITE_OK ){ assert( pgno==MASTER_ROOT+1 ); assert( pKeyInfo->db==db ); @@ -3495,7 +3496,7 @@ case OP_SequenceTest: { ** ** Open a new cursor that points to a fake table that contains a single ** row of data. The content of that one row is the content of memory -** register P2. In other words, cursor P1 becomes an alias for the +** register P2. In other words, cursor P1 becomes an alias for the ** MEM_Blob content contained in register P2. ** ** A pseudo-table created by this opcode is used to hold a single @@ -3555,13 +3556,13 @@ case OP_ColumnsUsed: { /* Opcode: SeekGE P1 P2 P3 P4 * ** Synopsis: key=r[P3@P4] ** -** If cursor P1 refers to an SQL table (B-Tree that uses integer keys), -** use the value in register P3 as the key. If cursor P1 refers -** to an SQL index, then P3 is the first in an array of P4 registers -** that are used as an unpacked index key. +** If cursor P1 refers to an SQL table (B-Tree that uses integer keys), +** use the value in register P3 as the key. If cursor P1 refers +** to an SQL index, then P3 is the first in an array of P4 registers +** that are used as an unpacked index key. ** -** Reposition cursor P1 so that it points to the smallest entry that -** is greater than or equal to the key value. If there are no records +** Reposition cursor P1 so that it points to the smallest entry that +** is greater than or equal to the key value. If there are no records ** greater than or equal to the key and P2 is not zero, then jump to P2. ** ** If the cursor P1 was opened using the OPFLAG_SEEKEQ flag, then this @@ -3580,13 +3581,13 @@ case OP_ColumnsUsed: { /* Opcode: SeekGT P1 P2 P3 P4 * ** Synopsis: key=r[P3@P4] ** -** If cursor P1 refers to an SQL table (B-Tree that uses integer keys), -** use the value in register P3 as a key. If cursor P1 refers -** to an SQL index, then P3 is the first in an array of P4 registers -** that are used as an unpacked index key. +** If cursor P1 refers to an SQL table (B-Tree that uses integer keys), +** use the value in register P3 as a key. If cursor P1 refers +** to an SQL index, then P3 is the first in an array of P4 registers +** that are used as an unpacked index key. ** -** Reposition cursor P1 so that it points to the smallest entry that -** is greater than the key value. If there are no records greater than +** Reposition cursor P1 so that it points to the smallest entry that +** is greater than the key value. If there are no records greater than ** the key and P2 is not zero, then jump to P2. ** ** This opcode leaves the cursor configured to move in forward order, @@ -3595,16 +3596,16 @@ case OP_ColumnsUsed: { ** ** See also: Found, NotFound, SeekLt, SeekGe, SeekLe */ -/* Opcode: SeekLT P1 P2 P3 P4 * +/* Opcode: SeekLT P1 P2 P3 P4 * ** Synopsis: key=r[P3@P4] ** -** If cursor P1 refers to an SQL table (B-Tree that uses integer keys), -** use the value in register P3 as a key. If cursor P1 refers -** to an SQL index, then P3 is the first in an array of P4 registers -** that are used as an unpacked index key. +** If cursor P1 refers to an SQL table (B-Tree that uses integer keys), +** use the value in register P3 as a key. If cursor P1 refers +** to an SQL index, then P3 is the first in an array of P4 registers +** that are used as an unpacked index key. ** -** Reposition cursor P1 so that it points to the largest entry that -** is less than the key value. If there are no records less than +** Reposition cursor P1 so that it points to the largest entry that +** is less than the key value. If there are no records less than ** the key and P2 is not zero, then jump to P2. ** ** This opcode leaves the cursor configured to move in reverse order, @@ -3616,13 +3617,13 @@ case OP_ColumnsUsed: { /* Opcode: SeekLE P1 P2 P3 P4 * ** Synopsis: key=r[P3@P4] ** -** If cursor P1 refers to an SQL table (B-Tree that uses integer keys), -** use the value in register P3 as a key. If cursor P1 refers -** to an SQL index, then P3 is the first in an array of P4 registers -** that are used as an unpacked index key. +** If cursor P1 refers to an SQL table (B-Tree that uses integer keys), +** use the value in register P3 as a key. If cursor P1 refers +** to an SQL index, then P3 is the first in an array of P4 registers +** that are used as an unpacked index key. ** -** Reposition cursor P1 so that it points to the largest entry that -** is less than or equal to the key value. If there are no records +** Reposition cursor P1 so that it points to the largest entry that +** is less than or equal to the key value. If there are no records ** less than or equal to the key and P2 is not zero, then jump to P2. ** ** This opcode leaves the cursor configured to move in reverse order, @@ -3699,7 +3700,7 @@ case OP_SeekGT: { /* jump, in3 */ ** (x <= 4.9) -> (x < 5) */ if( pIn3->u.r<(double)iKey ){ - assert( OP_SeekGE==(OP_SeekGT-1) ); + assert( OP_SeekGE==(OP_SeekGT-1) ); assert( OP_SeekLT==(OP_SeekLE-1) ); assert( (OP_SeekLE & 0x0001)==(OP_SeekGT & 0x0001) ); if( (oc & 0x0001)==(OP_SeekGT & 0x0001) ) oc--; @@ -3713,7 +3714,7 @@ case OP_SeekGT: { /* jump, in3 */ assert( (OP_SeekLT & 0x0001)==(OP_SeekGE & 0x0001) ); if( (oc & 0x0001)==(OP_SeekLT & 0x0001) ) oc++; } - } + } rc = sqlite3BtreeMovetoUnpacked(pC->uc.pCursor, 0, (u64)iKey, 0, &res); pC->movetoTarget = iKey; /* Used by OP_Delete */ if( rc!=SQLITE_OK ){ @@ -3822,9 +3823,9 @@ case OP_SeekGT: { /* jump, in3 */ ** If P4==0 then register P3 holds a blob constructed by MakeRecord. If ** P4>0 then register P3 is the first of P4 registers that form an unpacked ** record. -** +** ** Cursor P1 is on an index btree. If the record identified by P3 and P4 -** is not the prefix of any entry in P1 then a jump is made to P2. If P1 +** is not the prefix of any entry in P1 then a jump is made to P2. If P1 ** does contain an entry whose prefix matches the P3/P4 record then control ** falls through to the next instruction and P1 is left pointing at the ** matching entry. @@ -3841,7 +3842,7 @@ case OP_SeekGT: { /* jump, in3 */ ** If P4==0 then register P3 holds a blob constructed by MakeRecord. If ** P4>0 then register P3 is the first of P4 registers that form an unpacked ** record. -** +** ** Cursor P1 is on an index btree. If the record identified by P3 and P4 ** contains any NULL value, jump immediately to P2. If all terms of the ** record are not-NULL then a check is done to determine if any row in the @@ -3944,9 +3945,9 @@ case OP_Found: { /* jump, in3 */ ** ** P1 is the index of a cursor open on an SQL table btree (with integer ** keys). If register P3 does not contain an integer or if P1 does not -** contain a record with rowid P3 then jump immediately to P2. +** contain a record with rowid P3 then jump immediately to P2. ** Or, if P2 is 0, raise an SQLITE_CORRUPT error. If P1 does contain -** a record with rowid P3 then +** a record with rowid P3 then ** leave the cursor pointing at that record and fall through to the next ** instruction. ** @@ -3969,7 +3970,7 @@ case OP_Found: { /* jump, in3 */ ** P1 is the index of a cursor open on an SQL table btree (with integer ** keys). P3 is an integer rowid. If P1 does not contain a record with ** rowid P3 then jump immediately to P2. Or, if P2 is 0, raise an -** SQLITE_CORRUPT error. If P1 does contain a record with rowid P3 then +** SQLITE_CORRUPT error. If P1 does contain a record with rowid P3 then ** leave the cursor pointing at that record and fall through to the next ** instruction. ** @@ -4039,7 +4040,7 @@ case OP_NotExists: /* jump, in3 */ ** Find the next available sequence number for cursor P1. ** Write the sequence number into register P2. ** The sequence number on the cursor is incremented after this -** instruction. +** instruction. */ case OP_Sequence: { /* out2 */ assert( pOp->p1>=0 && pOp->p1<p->nCursor ); @@ -4059,9 +4060,9 @@ case OP_Sequence: { /* out2 */ ** table that cursor P1 points to. The new record number is written ** written to register P2. ** -** If P3>0 then P3 is a register in the root frame of this VDBE that holds +** If P3>0 then P3 is a register in the root frame of this VDBE that holds ** the largest previously generated record number. No new record numbers are -** allowed to be less than this value. When this value reaches its maximum, +** allowed to be less than this value. When this value reaches its maximum, ** an SQLITE_FULL error is generated. The P3 register is updated with the ' ** generated record number. This P3 mechanism is used to help implement the ** AUTOINCREMENT feature. @@ -4209,8 +4210,8 @@ case OP_NewRowid: { /* out2 */ ** is part of an INSERT operation. The difference is only important to ** the update hook. ** -** Parameter P4 may point to a Table structure, or may be NULL. If it is -** not NULL, then the update-hook (sqlite3.xUpdateCallback) is invoked +** Parameter P4 may point to a Table structure, or may be NULL. If it is +** not NULL, then the update-hook (sqlite3.xUpdateCallback) is invoked ** following a successful insert. ** ** (WARNING/TODO: If P1 is a pseudo-cursor and P2 is dynamically @@ -4228,7 +4229,7 @@ case OP_NewRowid: { /* out2 */ ** This works exactly like OP_Insert except that the key is the ** integer value P3, not the value of the integer stored in register P3. */ -case OP_Insert: +case OP_Insert: case OP_InsertInt: { Mem *pData; /* MEM cell holding data for the record to be inserted */ Mem *pKey; /* MEM cell holding key for the record */ @@ -4276,7 +4277,7 @@ case OP_InsertInt: { #ifdef SQLITE_ENABLE_PREUPDATE_HOOK /* Invoke the pre-update hook, if any */ - if( db->xPreUpdateCallback + if( db->xPreUpdateCallback && pOp->p4type==P4_TABLE && !(pOp->p5 & OPFLAG_ISUPDATE) ){ @@ -4323,7 +4324,7 @@ case OP_InsertInt: { ** the cursor will be left pointing at either the next or the previous ** record in the table. If it is left pointing at the next record, then ** the next Next instruction will be a no-op. As a result, in this case -** it is ok to delete a record from within a Next loop. If +** it is ok to delete a record from within a Next loop. If ** OPFLAG_SAVEPOSITION bit of P5 is clear, then the cursor will be ** left in an undefined state. ** @@ -4339,11 +4340,11 @@ case OP_InsertInt: { ** P1 must not be pseudo-table. It has to be a real table with ** multiple rows. ** -** If P4 is not NULL then it points to a Table object. In this case either +** If P4 is not NULL then it points to a Table object. In this case either ** the update or pre-update hook, or both, may be invoked. The P1 cursor must -** have been positioned using OP_NotFound prior to invoking this opcode in -** this case. Specifically, if one is configured, the pre-update hook is -** invoked if P4 is not NULL. The update-hook is invoked if one is configured, +** have been positioned using OP_NotFound prior to invoking this opcode in +** this case. Specifically, if one is configured, the pre-update hook is +** invoked if P4 is not NULL. The update-hook is invoked if one is configured, ** P4 is not NULL, and the OPFLAG_NCHANGE flag is set in P2. ** ** If the OPFLAG_ISUPDATE flag is set in P2, then P3 contains the address @@ -4377,7 +4378,7 @@ case OP_Delete: { /* If the update-hook or pre-update-hook will be invoked, set zDb to ** the name of the db to pass as to it. Also set local pTab to a copy ** of p4.pTab. Finally, if p5 is true, indicating that this cursor was - ** last moved with OP_Next or OP_Prev, not Seek or NotFound, set + ** last moved with OP_Next or OP_Prev, not Seek or NotFound, set ** VdbeCursor.movetoTarget to the current rowid. */ if( pOp->p4type==P4_TABLE && HAS_UPDATE_HOOK(db) ){ assert( pC->iDb==0 ); @@ -4397,15 +4398,15 @@ case OP_Delete: { if( db->xPreUpdateCallback && pOp->p4.pTab && HasRowid(pTab) ){ assert( !(opflags & OPFLAG_ISUPDATE) || (aMem[pOp->p3].flags & MEM_Int) ); sqlite3VdbePreUpdateHook(p, pC, - (opflags & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_DELETE, + (opflags & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_DELETE, zDb, pTab, pC->movetoTarget, pOp->p3 ); } if( opflags & OPFLAG_ISNOOP ) break; #endif - - /* Only flags that can be set are SAVEPOISTION and AUXDELETE */ + + /* Only flags that can be set are SAVEPOISTION and AUXDELETE */ assert( (pOp->p5 & ~(OPFLAG_SAVEPOSITION|OPFLAG_AUXDELETE))==0 ); assert( OPFLAG_SAVEPOSITION==BTREE_SAVEPOSITION ); assert( OPFLAG_AUXDELETE==BTREE_AUXDELETE ); @@ -4458,7 +4459,7 @@ case OP_ResetCount: { ** Synopsis: if key(P1)!=trim(r[P3],P4) goto P2 ** ** P1 is a sorter cursor. This instruction compares a prefix of the -** record blob in register P3 against a prefix of the entry that +** record blob in register P3 against a prefix of the entry that ** the sorter cursor currently points to. Only the first P4 fields ** of r[P3] and the sorter record are compared. ** @@ -4516,10 +4517,10 @@ case OP_SorterData: { /* Opcode: RowData P1 P2 * * * ** Synopsis: r[P2]=data ** -** Write into register P2 the complete row content for the row at +** Write into register P2 the complete row content for the row at ** which cursor P1 is currently pointing. -** There is no interpretation of the data. -** It is just copied onto the P2 register exactly as +** There is no interpretation of the data. +** It is just copied onto the P2 register exactly as ** it is found in the database file. ** ** If cursor P1 is an index, then the content is the key of the row. @@ -4652,7 +4653,7 @@ case OP_NullRow: { /* Opcode: Last P1 P2 P3 * * ** -** The next use of the Rowid or Column or Prev instruction for P1 +** The next use of the Rowid or Column or Prev instruction for P1 ** will refer to the last entry in the database table or index. ** If the table or index is empty and P2>0, then jump immediately to P2. ** If P2 is 0 or if the table or index is not empty, fall through @@ -4734,10 +4735,10 @@ case OP_Sort: { /* jump */ } /* Opcode: Rewind P1 P2 * * * ** -** The next use of the Rowid or Column or Next instruction for P1 +** The next use of the Rowid or Column or Next instruction for P1 ** will refer to the first entry in the database table or index. ** If the table or index is empty, jump immediately to P2. -** If the table or index is not empty, fall through to the following +** If the table or index is not empty, fall through to the following ** instruction. ** ** This opcode leaves the cursor configured to move in forward order, @@ -4924,7 +4925,7 @@ case OP_Next: /* jump */ ** run faster by avoiding an unnecessary seek on cursor P1. However, ** the OPFLAG_USESEEKRESULT flag must only be set if there have been no prior ** seeks on the cursor or if the most recent seek used a key equivalent -** to P2. +** to P2. ** ** This instruction only works for indices. The equivalent instruction ** for tables is OP_Insert. @@ -4960,7 +4961,7 @@ case OP_IdxInsert: { /* in2 */ x.aMem = aMem + pOp->p3; x.nMem = (u16)pOp->p4.i; rc = sqlite3BtreeInsert(pC->uc.pCursor, &x, - (pOp->p5 & OPFLAG_APPEND)!=0, + (pOp->p5 & OPFLAG_APPEND)!=0, ((pOp->p5 & OPFLAG_USESEEKRESULT) ? pC->seekResult : 0) ); assert( pC->deferredMoveto==0 ); @@ -4974,7 +4975,7 @@ case OP_IdxInsert: { /* in2 */ ** Synopsis: key=r[P2@P3] ** ** The content of P3 registers starting at register P2 form -** an unpacked index key. This opcode removes that entry from the +** an unpacked index key. This opcode removes that entry from the ** index opened by cursor P1. */ case OP_IdxDelete: { @@ -5022,8 +5023,8 @@ case OP_IdxDelete: { ** ** P4 may be an array of integers (type P4_INTARRAY) containing ** one entry for each column in the P3 table. If array entry a(i) -** is non-zero, then reading column a(i)-1 from cursor P3 is -** equivalent to performing the deferred seek and then reading column i +** is non-zero, then reading column a(i)-1 from cursor P3 is +** equivalent to performing the deferred seek and then reading column i ** from P1. This information is stored in P3 and used to redirect ** reads against P3 over to P1, thus possibly avoiding the need to ** seek and read cursor P3. @@ -5095,9 +5096,9 @@ case OP_IdxRowid: { /* out2 */ /* Opcode: IdxGE P1 P2 P3 P4 P5 ** Synopsis: key=r[P3@P4] ** -** The P4 register values beginning with P3 form an unpacked index -** key that omits the PRIMARY KEY. Compare this key value against the index -** that P1 is currently pointing to, ignoring the PRIMARY KEY or ROWID +** The P4 register values beginning with P3 form an unpacked index +** key that omits the PRIMARY KEY. Compare this key value against the index +** that P1 is currently pointing to, ignoring the PRIMARY KEY or ROWID ** fields at the end. ** ** If the P1 index entry is greater than or equal to the key value @@ -5106,9 +5107,9 @@ case OP_IdxRowid: { /* out2 */ /* Opcode: IdxGT P1 P2 P3 P4 P5 ** Synopsis: key=r[P3@P4] ** -** The P4 register values beginning with P3 form an unpacked index -** key that omits the PRIMARY KEY. Compare this key value against the index -** that P1 is currently pointing to, ignoring the PRIMARY KEY or ROWID +** The P4 register values beginning with P3 form an unpacked index +** key that omits the PRIMARY KEY. Compare this key value against the index +** that P1 is currently pointing to, ignoring the PRIMARY KEY or ROWID ** fields at the end. ** ** If the P1 index entry is greater than the key value @@ -5117,7 +5118,7 @@ case OP_IdxRowid: { /* out2 */ /* Opcode: IdxLT P1 P2 P3 P4 P5 ** Synopsis: key=r[P3@P4] ** -** The P4 register values beginning with P3 form an unpacked index +** The P4 register values beginning with P3 form an unpacked index ** key that omits the PRIMARY KEY or ROWID. Compare this key value against ** the index that P1 is currently pointing to, ignoring the PRIMARY KEY or ** ROWID on the P1 index. @@ -5128,7 +5129,7 @@ case OP_IdxRowid: { /* out2 */ /* Opcode: IdxLE P1 P2 P3 P4 P5 ** Synopsis: key=r[P3@P4] ** -** The P4 register values beginning with P3 form an unpacked index +** The P4 register values beginning with P3 form an unpacked index ** key that omits the PRIMARY KEY or ROWID. Compare this key value against ** the index that P1 is currently pointing to, ignoring the PRIMARY KEY or ** ROWID on the P1 index. @@ -5195,8 +5196,8 @@ case OP_IdxGE: { /* jump */ ** might be moved into the newly deleted root page in order to keep all ** root pages contiguous at the beginning of the database. The former ** value of the root page that moved - its value before the move occurred - -** is stored in register P2. If no page -** movement was required (because the table being dropped was already +** is stored in register P2. If no page +** movement was required (because the table being dropped was already ** the last one in the database) then a zero is stored in register P2. ** If AUTOVACUUM is disabled then a zero is stored in register P2. ** @@ -5245,8 +5246,8 @@ case OP_Destroy: { /* out2 */ ** that is used to store tables create using CREATE TEMPORARY TABLE. ** ** If the P3 value is non-zero, then the table referred to must be an -** intkey table (an SQL table, not an index). In this case the row change -** count is incremented by the number of rows in the table being cleared. +** intkey table (an SQL table, not an index). In this case the row change +** count is incremented by the number of rows in the table being cleared. ** If P3 is greater than zero, then the value stored in register P3 is ** also incremented by the number of rows in the table being cleared. ** @@ -5270,7 +5271,7 @@ case OP_Clear: { */ case OP_ResetSorter: { VdbeCursor *pC; - + assert( pOp->p1>=0 && pOp->p1<p->nCursor ); pC = p->apCsr[pOp->p1]; assert( pC!=0 ); @@ -5337,7 +5338,7 @@ case OP_CreateTable: { /* out2 */ /* Opcode: ParseSchema P1 * * P4 * ** ** Read and parse all entries from the SQLITE_MASTER table of database P1 -** that match the WHERE clause P4. +** that match the WHERE clause P4. ** ** This opcode invokes the parser to create a new virtual machine, ** then runs the new virtual machine. It is thus a re-entrant opcode. @@ -5349,7 +5350,7 @@ case OP_ParseSchema: { InitData initData; /* Any prepared statement that invokes this opcode will hold mutexes - ** on every btree. This is a prerequisite for invoking + ** on every btree. This is a prerequisite for invoking ** sqlite3InitCallback(). */ #ifdef SQLITE_DEBUG @@ -5387,7 +5388,7 @@ case OP_ParseSchema: { } goto abort_due_to_error; } - break; + break; } /* Opcode: ParseSchema2 P1 P2 P3 * * @@ -5521,7 +5522,7 @@ case OP_LoadAnalysis: { assert( pOp->p1==0 ); rc = sqlite3AnalysisLoad(db); if( rc ) goto abort_due_to_error; - break; + break; } #endif /* !defined(SQLITE_OMIT_ANALYZE) */ @@ -5529,7 +5530,7 @@ case OP_LoadAnalysis: { ** ** Remove the internal (in-memory) data structures that describe ** the table named P4 in database P1. This is called after a table -** is dropped from disk (using the Destroy opcode) in order to keep +** is dropped from disk (using the Destroy opcode) in order to keep ** the internal representation of the ** schema consistent with what is on disk. */ @@ -5555,7 +5556,7 @@ case OP_DropIndex: { ** ** Remove the internal (in-memory) data structures that describe ** the trigger named P4 in database P1. This is called after a trigger -** is dropped from disk (using the Destroy opcode) in order to keep +** is dropped from disk (using the Destroy opcode) in order to keep ** the internal representation of the ** schema consistent with what is on disk. */ @@ -5574,7 +5575,7 @@ case OP_DropTrigger: { ** ** The register P3 contains the maximum number of allowed errors. ** At most reg(P3) errors will be reported. -** In other words, the analysis stops as soon as reg(P1) errors are +** In other words, the analysis stops as soon as reg(P1) errors are ** seen. Reg(P1) is updated with the number of errors remaining. ** ** The root page numbers of all tables in the database are integers @@ -5651,7 +5652,7 @@ case OP_RowSetRead: { /* jump, in1, out3 */ i64 val; pIn1 = &aMem[pOp->p1]; - if( (pIn1->flags & MEM_RowSet)==0 + if( (pIn1->flags & MEM_RowSet)==0 || sqlite3RowSetNext(pIn1->u.pRowSet, &val)==0 ){ /* The boolean index is empty */ @@ -5725,13 +5726,13 @@ case OP_RowSetTest: { /* jump, in1, in3 */ /* Opcode: Program P1 P2 P3 P4 P5 ** -** Execute the trigger program passed as P4 (type P4_SUBPROGRAM). +** Execute the trigger program passed as P4 (type P4_SUBPROGRAM). ** -** P1 contains the address of the memory cell that contains the first memory -** cell in an array of values used as arguments to the sub-program. P2 -** contains the address to jump to if the sub-program throws an IGNORE -** exception using the RAISE() function. Register P3 contains the address -** of a memory cell in this (the parent) VM that is used to allocate the +** P1 contains the address of the memory cell that contains the first memory +** cell in an array of values used as arguments to the sub-program. P2 +** contains the address to jump to if the sub-program throws an IGNORE +** exception using the RAISE() function. Register P3 contains the address +** of a memory cell in this (the parent) VM that is used to allocate the ** memory required by the sub-vdbe at runtime. ** ** P4 is a pointer to the VM containing the trigger program. @@ -5751,17 +5752,17 @@ case OP_Program: { /* jump */ pProgram = pOp->p4.pProgram; pRt = &aMem[pOp->p3]; assert( pProgram->nOp>0 ); - - /* If the p5 flag is clear, then recursive invocation of triggers is + + /* If the p5 flag is clear, then recursive invocation of triggers is ** disabled for backwards compatibility (p5 is set if this sub-program ** is really a trigger, not a foreign key action, and the flag set ** and cleared by the "PRAGMA recursive_triggers" command is clear). - ** - ** It is recursive invocation of triggers, at the SQL level, that is - ** disabled. In some cases a single trigger may generate more than one - ** SubProgram (if the trigger may be executed with more than one different + ** + ** It is recursive invocation of triggers, at the SQL level, that is + ** disabled. In some cases a single trigger may generate more than one + ** SubProgram (if the trigger may be executed with more than one different ** ON CONFLICT algorithm). SubProgram structures associated with a - ** single trigger all have the same value for the SubProgram.token + ** single trigger all have the same value for the SubProgram.token ** variable. */ if( pOp->p5 ){ t = pProgram->token; @@ -5777,10 +5778,10 @@ case OP_Program: { /* jump */ /* Register pRt is used to store the memory required to save the state ** of the current program, and the memory required at runtime to execute - ** the trigger program. If this trigger has been fired before, then pRt + ** the trigger program. If this trigger has been fired before, then pRt ** is already allocated. Otherwise, it must be initialized. */ if( (pRt->flags&MEM_Frame)==0 ){ - /* SubProgram.nMem is set to the number of memory cells used by the + /* SubProgram.nMem is set to the number of memory cells used by the ** program stored in SubProgram.aOp. As well as these, one memory ** cell is required for each cursor used by the program. Set local ** variable nMem (and later, VdbeFrame.nChildMem) to this value. @@ -5821,7 +5822,7 @@ case OP_Program: { /* jump */ } }else{ pFrame = pRt->u.pFrame; - assert( pProgram->nMem+pProgram->nCsr==pFrame->nChildMem + assert( pProgram->nMem+pProgram->nCsr==pFrame->nChildMem || (pProgram->nCsr==0 && pProgram->nMem+1==pFrame->nChildMem) ); assert( pProgram->nCsr==pFrame->nChildCsr ); assert( (int)(pOp - aOp)==pFrame->pc ); @@ -5853,10 +5854,10 @@ case OP_Program: { /* jump */ /* Opcode: Param P1 P2 * * * ** -** This opcode is only ever present in sub-programs called via the -** OP_Program instruction. Copy a value currently stored in a memory -** cell of the calling (parent) frame to cell P2 in the current frames -** address space. This is used by trigger programs to access the new.* +** This opcode is only ever present in sub-programs called via the +** OP_Program instruction. Copy a value currently stored in a memory +** cell of the calling (parent) frame to cell P2 in the current frames +** address space. This is used by trigger programs to access the new.* ** and old.* values. ** ** The address of the cell in the parent frame is determined by adding @@ -5868,7 +5869,7 @@ case OP_Param: { /* out2 */ Mem *pIn; pOut = out2Prerelease(p, pOp); pFrame = p->pFrame; - pIn = &pFrame->aMem[pOp->p1 + pFrame->aOp[pFrame->pc].p1]; + pIn = &pFrame->aMem[pOp->p1 + pFrame->aOp[pFrame->pc].p1]; sqlite3VdbeMemShallowCopy(pOut, pIn, MEM_Ephem); break; } @@ -5880,15 +5881,15 @@ case OP_Param: { /* out2 */ ** Synopsis: fkctr[P1]+=P2 ** ** Increment a "constraint counter" by P2 (P2 may be negative or positive). -** If P1 is non-zero, the database constraint counter is incremented -** (deferred foreign key constraints). Otherwise, if P1 is zero, the +** If P1 is non-zero, the database constraint counter is incremented +** (deferred foreign key constraints). Otherwise, if P1 is zero, the ** statement counter is incremented (immediate foreign key constraints). */ case OP_FkCounter: { if( db->flags & SQLITE_DeferFKs ){ - db->nDeferredImmCons += pOp->p2; + p->nDeferredImmCons += pOp->p2; }else if( pOp->p1 ){ - db->nDeferredCons += pOp->p2; + p->nDeferredCons += pOp->p2; }else{ p->nFkConstraint += pOp->p2; } @@ -5899,7 +5900,7 @@ case OP_FkCounter: { ** Synopsis: if fkctr[P1]==0 goto P2 ** ** This opcode tests if a foreign key constraint-counter is currently zero. -** If so, jump to instruction P2. Otherwise, fall through to the next +** If so, jump to instruction P2. Otherwise, fall through to the next ** instruction. ** ** If P1 is non-zero, then the jump is taken if the database constraint-counter @@ -5909,11 +5910,11 @@ case OP_FkCounter: { */ case OP_FkIfZero: { /* jump */ if( pOp->p1 ){ - VdbeBranchTaken(db->nDeferredCons==0 && db->nDeferredImmCons==0, 2); - if( db->nDeferredCons==0 && db->nDeferredImmCons==0 ) goto jump_to_p2; + VdbeBranchTaken(db->nDeferredCons==0 && p->nDeferredImmCons==0, 2); + if( p->nDeferredCons==0 && p->nDeferredImmCons==0 ) goto jump_to_p2; }else{ - VdbeBranchTaken(p->nFkConstraint==0 && db->nDeferredImmCons==0, 2); - if( p->nFkConstraint==0 && db->nDeferredImmCons==0 ) goto jump_to_p2; + VdbeBranchTaken(p->nFkConstraint==0 && p->nDeferredImmCons==0, 2); + if( p->nFkConstraint==0 && p->nDeferredImmCons==0 ) goto jump_to_p2; } break; } @@ -5925,7 +5926,7 @@ case OP_FkIfZero: { /* jump */ ** ** P1 is a register in the root frame of this VM (the root frame is ** different from the current frame if this instruction is being executed -** within a sub-program). Set the value of register P1 to the maximum of +** within a sub-program). Set the value of register P1 to the maximum of ** its current value and the value in register P2. ** ** This instruction throws an error if the memory cell is not initially @@ -5985,7 +5986,7 @@ case OP_IfPos: { /* jump, in1 */ ** and r[P2] is set to be the value of the LIMIT, r[P1]. ** ** if r[P1] is zero or negative, that means there is no LIMIT -** and r[P2] is set to -1. +** and r[P2] is set to -1. ** ** Otherwise, r[P2] is set to the sum of r[P1] and r[P3]. */ @@ -6017,7 +6018,7 @@ case OP_OffsetLimit: { /* in1, out2, in3 */ ** ** Register P1 must contain an integer. If the content of register P1 is ** initially greater than zero, then decrement the value in register P1. -** If it is non-zero (negative or positive) and then also jump to P2. +** If it is non-zero (negative or positive) and then also jump to P2. ** If register P1 is initially zero, leave it unchanged and fall through. */ case OP_IfNotZero: { /* jump, in1 */ @@ -6216,9 +6217,9 @@ case OP_Checkpoint: { } for(i=0, pMem = &aMem[pOp->p3]; i<3; i++, pMem++){ sqlite3VdbeMemSetInt64(pMem, (i64)aRes[i]); - } + } break; -}; +}; #endif #ifndef SQLITE_OMIT_PRAGMA @@ -6244,9 +6245,9 @@ case OP_JournalMode: { /* out2 */ pOut = out2Prerelease(p, pOp); eNew = pOp->p3; - assert( eNew==PAGER_JOURNALMODE_DELETE - || eNew==PAGER_JOURNALMODE_TRUNCATE - || eNew==PAGER_JOURNALMODE_PERSIST + assert( eNew==PAGER_JOURNALMODE_DELETE + || eNew==PAGER_JOURNALMODE_TRUNCATE + || eNew==PAGER_JOURNALMODE_PERSIST || eNew==PAGER_JOURNALMODE_OFF || eNew==PAGER_JOURNALMODE_MEMORY || eNew==PAGER_JOURNALMODE_WAL @@ -6319,7 +6320,7 @@ case OP_IncrVacuum: { /* jump */ ** is executed using sqlite3_step() it will either automatically ** reprepare itself (if it was originally created using sqlite3_prepare_v2()) ** or it will fail with SQLITE_SCHEMA. -** +** ** If P1 is 0, then all SQL statements become expired. If P1 is non-zero, ** then only the currently executing statement is expired. */ @@ -6337,7 +6338,7 @@ case OP_Expire: { ** Synopsis: iDb=P1 root=P2 write=P3 ** ** Obtain a lock on a particular table. This instruction is only used when -** the shared-cache feature is enabled. +** the shared-cache feature is enabled. ** ** P1 is the index of the database in sqlite3.aDb[] of the database ** on which the lock is acquired. A readlock is obtained if P3==0 or @@ -6351,7 +6352,7 @@ case OP_Expire: { case OP_TableLock: { u8 isWriteLock = (u8)pOp->p3; if( isWriteLock || 0==(db->flags&SQLITE_ReadUncommitted) ){ - int p1 = pOp->p1; + int p1 = pOp->p1; assert( p1==0 ); assert( DbMaskTest(p->btreeMask, p1) ); assert( isWriteLock==0 || isWriteLock==1 ); @@ -6371,7 +6372,7 @@ case OP_TableLock: { #ifndef SQLITE_OMIT_VIRTUALTABLE /* Opcode: VBegin * * * P4 * ** -** P4 may be a pointer to an sqlite3_vtab structure. If so, call the +** P4 may be a pointer to an sqlite3_vtab structure. If so, call the ** xBegin method for that table. ** ** Also, whether or not P4 is set, check that this is not being called from @@ -6381,7 +6382,7 @@ case OP_TableLock: { case OP_VBegin: { VTable *pVTab; pVTab = pOp->p4.pVtab; - rc = sqlite3VtabBegin(db, pVTab); + rc = sqlite3VtabBegin(db, p, pVTab); if( pVTab ) sqlite3VtabImportErrmsg(p, pVTab->pVtab); if( rc ) goto abort_due_to_error; break; @@ -6391,7 +6392,7 @@ case OP_VBegin: { #ifndef SQLITE_OMIT_VIRTUALTABLE /* Opcode: VCreate P1 P2 * * * ** -** P2 is a register that holds the name of a virtual table in database +** P2 is a register that holds the name of a virtual table in database ** P1. Call the xCreate method for that table. */ case OP_VCreate: { @@ -6545,7 +6546,7 @@ case OP_VFilter: { /* jump */ ** Synopsis: r[P3]=vcolumn(P2) ** ** Store the value of the P2-th column of -** the row of the virtual-table that the +** the row of the virtual-table that the ** P1 cursor is pointing to into register P3. */ case OP_VColumn: { @@ -6611,7 +6612,7 @@ case OP_VNext: { /* jump */ /* Invoke the xNext() method of the module. There is no way for the ** underlying implementation to return an error if one occurs during - ** xNext(). Instead, if an error occurs, true is returned (indicating that + ** xNext(). Instead, if an error occurs, true is returned (indicating that ** data is available) and the error code returned when xColumn or ** some other method is next invoked on the save virtual table cursor. */ @@ -6665,23 +6666,23 @@ case OP_VRename: { ** ** P4 is a pointer to a virtual table object, an sqlite3_vtab structure. ** This opcode invokes the corresponding xUpdate method. P2 values -** are contiguous memory cells starting at P3 to pass to the xUpdate -** invocation. The value in register (P3+P2-1) corresponds to the +** are contiguous memory cells starting at P3 to pass to the xUpdate +** invocation. The value in register (P3+P2-1) corresponds to the ** p2th element of the argv array passed to xUpdate. ** ** The xUpdate method will do a DELETE or an INSERT or both. ** The argv[0] element (which corresponds to memory cell P3) -** is the rowid of a row to delete. If argv[0] is NULL then no -** deletion occurs. The argv[1] element is the rowid of the new -** row. This can be NULL to have the virtual table select the new -** rowid for itself. The subsequent elements in the array are +** is the rowid of a row to delete. If argv[0] is NULL then no +** deletion occurs. The argv[1] element is the rowid of the new +** row. This can be NULL to have the virtual table select the new +** rowid for itself. The subsequent elements in the array are ** the values of columns in the new row. ** ** If P2==1 then no insert is performed. argv[0] is the rowid of ** a row to delete. ** ** P1 is a boolean flag. If it is set to true and the xUpdate call -** is successful, then the value returned by sqlite3_last_insert_rowid() +** is successful, then the value returned by sqlite3_last_insert_rowid() ** is set to the value of the rowid for the row just inserted. ** ** P5 is the error actions (OE_Replace, OE_Fail, OE_Ignore, etc) to @@ -6696,7 +6697,7 @@ case OP_VUpdate: { Mem **apArg; Mem *pX; - assert( pOp->p2==1 || pOp->p5==OE_Fail || pOp->p5==OE_Rollback + assert( pOp->p2==1 || pOp->p5==OE_Fail || pOp->p5==OE_Rollback || pOp->p5==OE_Abort || pOp->p5==OE_Ignore || pOp->p5==OE_Replace ); assert( p->readOnly==0 ); @@ -6970,7 +6971,7 @@ default: { /* This is really OP_Noop and OP_Explain */ p->rc = rc; sqlite3SystemError(db, rc); testcase( sqlite3GlobalConfig.xLog!=0 ); - sqlite3_log(rc, "statement aborts at %d: [%s] %s", + sqlite3_log(rc, "statement aborts at %d: [%s] %s", (int)(pOp - aOp), p->zSql, p->zErrMsg); sqlite3VdbeHalt(p); if( rc==SQLITE_IOERR_NOMEM ) sqlite3OomFault(db); @@ -6987,8 +6988,8 @@ default: { /* This is really OP_Noop and OP_Explain */ testcase( nVmStep>0 ); p->aCounter[SQLITE_STMTSTATUS_VM_STEP] += (int)nVmStep; sqlite3VdbeLeave(p); - assert( rc!=SQLITE_OK || nExtraDelete==0 - || sqlite3_strlike("DELETE%",p->zSql,0)!=0 + assert( rc!=SQLITE_OK || nExtraDelete==0 + || sqlite3_strlike("DELETE%",p->zSql,0)!=0 ); return rc; diff --git a/src/box/sql/vdbeInt.h b/src/box/sql/vdbeInt.h index 86ca82875495fd393a077298a25df031d1150317..2af1b4ef06da09a5edddd62ea6eb840d2fc54c00 100644 --- a/src/box/sql/vdbeInt.h +++ b/src/box/sql/vdbeInt.h @@ -341,69 +341,77 @@ struct ScanStatus { ** is really a pointer to an instance of this structure. */ struct Vdbe { - sqlite3 *db; /* The database connection that owns this statement */ - Vdbe *pPrev,*pNext; /* Linked list of VDBEs with the same Vdbe.db */ - Parse *pParse; /* Parsing context used to create this Vdbe */ - ynVar nVar; /* Number of entries in aVar[] */ - u32 magic; /* Magic number for sanity checking */ - int nMem; /* Number of memory locations currently allocated */ - int nCursor; /* Number of slots in apCsr[] */ - u32 cacheCtr; /* VdbeCursor row cache generation counter */ - int pc; /* The program counter */ - int rc; /* Value to return */ - int nChange; /* Number of db changes made since last reset */ - int iStatement; /* Statement number (or 0 if has not opened stmt) */ - i64 iCurrentTime; /* Value of julianday('now') for this statement */ - i64 nFkConstraint; /* Number of imm. FK constraints this VM */ - i64 nStmtDefCons; /* Number of def. constraints when stmt started */ - i64 nStmtDefImmCons; /* Number of def. imm constraints when stmt started */ + sqlite3 *db; /* The database connection that owns this statement */ + Vdbe *pPrev,*pNext; /* Linked list of VDBEs with the same Vdbe.db */ + Parse *pParse; /* Parsing context used to create this Vdbe */ + ynVar nVar; /* Number of entries in aVar[] */ + u32 magic; /* Magic number for sanity checking */ + int nMem; /* Number of memory locations currently allocated */ + int nCursor; /* Number of slots in apCsr[] */ + u32 cacheCtr; /* VdbeCursor row cache generation counter */ + int pc; /* The program counter */ + int rc; /* Value to return */ + int nChange; /* Number of db changes made since last reset */ + int iStatement; /* Statement number (or 0 if has not opened stmt) */ + i64 iCurrentTime; /* Value of julianday('now') for this statement */ + i64 nFkConstraint; /* Number of imm. FK constraints this VM */ + i64 nStmtDefCons; /* Number of def. constraints when stmt started */ + i64 nStmtDefImmCons; /* Number of def. imm constraints when stmt started */ + + u8 autoCommit; /* The auto-commit flag. */ + u8 isTransactionSavepoint; /* True if the outermost savepoint is a TS */ + Savepoint *pSavepoint; /* List of active savepoints */ + int nSavepoint; /* Number of non-transaction savepoints */ + int nStatement; /* Number of nested statement-transactions */ + i64 nDeferredCons; /* Net deferred constraints this transaction. */ + i64 nDeferredImmCons; /* Net deferred immediate constraints */ /* When allocating a new Vdbe object, all of the fields below should be ** initialized to zero or NULL */ - Op *aOp; /* Space to hold the virtual machine's program */ - Mem *aMem; /* The memory locations */ - Mem **apArg; /* Arguments to currently executing user function */ - Mem *aColName; /* Column names to return */ - Mem *pResultSet; /* Pointer to an array of results */ - char *zErrMsg; /* Error message written here */ - VdbeCursor **apCsr; /* One element of this array for each open cursor */ - Mem *aVar; /* Values for the OP_Variable opcode. */ - VList *pVList; /* Name of variables */ + Op *aOp; /* Space to hold the virtual machine's program */ + Mem *aMem; /* The memory locations */ + Mem **apArg; /* Arguments to currently executing user function */ + Mem *aColName; /* Column names to return */ + Mem *pResultSet; /* Pointer to an array of results */ + char *zErrMsg; /* Error message written here */ + VdbeCursor **apCsr; /* One element of this array for each open cursor */ + Mem *aVar; /* Values for the OP_Variable opcode. */ + VList *pVList; /* Name of variables */ #ifndef SQLITE_OMIT_TRACE - i64 startTime; /* Time when query started - used for profiling */ + i64 startTime; /* Time when query started - used for profiling */ #endif - int nOp; /* Number of instructions in the program */ + int nOp; /* Number of instructions in the program */ #ifdef SQLITE_DEBUG - int rcApp; /* errcode set by sqlite3_result_error_code() */ + int rcApp; /* errcode set by sqlite3_result_error_code() */ #endif - u16 nResColumn; /* Number of columns in one row of the result set */ - u8 errorAction; /* Recovery action to do in case of an error */ - u8 minWriteFileFormat; /* Minimum file format for writable database files */ - bft expired:1; /* True if the VM needs to be recompiled */ - bft doingRerun:1; /* True if rerunning after an auto-reprepare */ - 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 readOnly:1; /* True for statements that do not write */ - bft bIsReader:1; /* True for statements that read */ - bft isPrepareV2:1; /* True if prepared with prepare_v2() */ - yDbMask btreeMask; /* Bitmask of db->aDb[] entries referenced */ - yDbMask lockMask; /* Subset of btreeMask that requires a lock */ - u32 aCounter[5]; /* Counters used by sqlite3_stmt_status() */ - char *zSql; /* Text of the SQL statement that generated this */ - void *pFree; /* Free this when deleting the vdbe */ - VdbeFrame *pFrame; /* Parent frame */ - VdbeFrame *pDelFrame; /* List of frame objects to free on VM reset */ - int nFrame; /* Number of frames in pFrame list */ - u32 expmask; /* Binding to these vars invalidates VM */ - SubProgram *pProgram; /* Linked list of all sub-programs used by VM */ - AuxData *pAuxData; /* Linked list of auxdata allocations */ + u16 nResColumn; /* Number of columns in one row of the result set */ + u8 errorAction; /* Recovery action to do in case of an error */ + u8 minWriteFileFormat; /* Minimum file format for writable database files */ + bft expired:1; /* True if the VM needs to be recompiled */ + bft doingRerun:1; /* True if rerunning after an auto-reprepare */ + 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 readOnly:1; /* True for statements that do not write */ + bft bIsReader:1; /* True for statements that read */ + bft isPrepareV2:1; /* True if prepared with prepare_v2() */ + yDbMask btreeMask; /* Bitmask of db->aDb[] entries referenced */ + yDbMask lockMask; /* Subset of btreeMask that requires a lock */ + u32 aCounter[5]; /* Counters used by sqlite3_stmt_status() */ + char *zSql; /* Text of the SQL statement that generated this */ + void *pFree; /* Free this when deleting the vdbe */ + VdbeFrame *pFrame; /* Parent frame */ + VdbeFrame *pDelFrame; /* List of frame objects to free on VM reset */ + int nFrame; /* Number of frames in pFrame list */ + u32 expmask; /* Binding to these vars invalidates VM */ + SubProgram *pProgram; /* Linked list of all sub-programs used by VM */ + AuxData *pAuxData; /* Linked list of auxdata allocations */ #ifdef SQLITE_ENABLE_STMT_SCANSTATUS - i64 *anExec; /* Number of times each op has been executed */ - int nScan; /* Entries in aScan[] */ - ScanStatus *aScan; /* Scan definitions for sqlite3_stmt_scanstatus() */ + i64 *anExec; /* Number of times each op has been executed */ + int nScan; /* Entries in aScan[] */ + ScanStatus *aScan; /* Scan definitions for sqlite3_stmt_scanstatus() */ #endif }; diff --git a/src/box/sql/vdbeapi.c b/src/box/sql/vdbeapi.c index 7e33b0ae2f35f38caf240d9611b03d06eb8a1d87..82d883db736f6d91521a0d3a1691fecc0c595995 100644 --- a/src/box/sql/vdbeapi.c +++ b/src/box/sql/vdbeapi.c @@ -507,8 +507,8 @@ static int sqlite3Step(Vdbe *p){ db->u1.isInterrupted = 0; } - assert( db->nVdbeWrite>0 || db->autoCommit==0 - || (db->nDeferredCons==0 && db->nDeferredImmCons==0) + assert( db->nVdbeWrite>0 || p->autoCommit==0 + || (p->nDeferredCons==0 && p->nDeferredImmCons==0) ); #ifndef SQLITE_OMIT_TRACE diff --git a/src/box/sql/vdbeaux.c b/src/box/sql/vdbeaux.c index c747c099b9cd50a8b657b18a587055ef4560c97a..e796057d4e32c265bb86532333233049cc640094 100644 --- a/src/box/sql/vdbeaux.c +++ b/src/box/sql/vdbeaux.c @@ -32,11 +32,20 @@ Vdbe *sqlite3VdbeCreate(Parse *pParse){ if( db->pVdbe ){ db->pVdbe->pPrev = p; } + p->pNext = db->pVdbe; p->pPrev = 0; db->pVdbe = p; p->magic = VDBE_MAGIC_INIT; p->pParse = pParse; + p->autoCommit = (char)box_txn() == 0 ? 1 : 0; + p->isTransactionSavepoint = 0; + p->nStatement = 0; + p->nSavepoint = 0; + p->pSavepoint = 0; + p->nDeferredCons = 0; + p->nDeferredImmCons = 0; + assert( pParse->aLabel==0 ); assert( pParse->nLabel==0 ); assert( pParse->nOpAlloc==0 ); @@ -2507,12 +2516,12 @@ int sqlite3VdbeCloseStatement(Vdbe *p, int eOp){ ** is that an IO error may have occurred, causing an emergency rollback. ** In this case (db->nStatement==0), and there is nothing to do. */ - if( db->nStatement && p->iStatement ){ + if( p->nStatement && p->iStatement ){ const int iSavepoint = p->iStatement-1; assert( eOp==SAVEPOINT_ROLLBACK || eOp==SAVEPOINT_RELEASE); - assert( db->nStatement>0 ); - assert( p->iStatement==(db->nStatement+db->nSavepoint) ); + assert( p->nStatement>0 ); + assert( p->iStatement==(p->nStatement+p->nSavepoint) ); int rc2 = SQLITE_OK; Btree *pBt = db->mdb.pBt; @@ -2527,7 +2536,7 @@ int sqlite3VdbeCloseStatement(Vdbe *p, int eOp){ rc = rc2; } } - db->nStatement--; + p->nStatement--; p->iStatement = 0; if( rc==SQLITE_OK ){ @@ -2543,8 +2552,8 @@ int sqlite3VdbeCloseStatement(Vdbe *p, int eOp){ ** database handles deferred constraint counter to the value it had when ** the statement transaction was opened. */ if( eOp==SAVEPOINT_ROLLBACK ){ - db->nDeferredCons = p->nStmtDefCons; - db->nDeferredImmCons = p->nStmtDefImmCons; + p->nDeferredCons = p->nStmtDefCons; + p->nDeferredImmCons = p->nStmtDefImmCons; } } return rc; @@ -2563,7 +2572,7 @@ int sqlite3VdbeCloseStatement(Vdbe *p, int eOp){ #ifndef SQLITE_OMIT_FOREIGN_KEY int sqlite3VdbeCheckFk(Vdbe *p, int deferred){ sqlite3 *db = p->db; - if( (deferred && (db->nDeferredCons+db->nDeferredImmCons)>0) + if( (deferred && (p->nDeferredCons+p->nDeferredImmCons)>0) || (!deferred && p->nFkConstraint>0) ){ p->rc = SQLITE_CONSTRAINT_FOREIGNKEY; @@ -2653,9 +2662,9 @@ int sqlite3VdbeHalt(Vdbe *p){ */ box_txn_rollback(); closeCursorsAndFree(p); - sqlite3RollbackAll(db, SQLITE_ABORT_ROLLBACK); - sqlite3CloseSavepoints(db); - db->autoCommit = 1; + sqlite3RollbackAll(p, SQLITE_ABORT_ROLLBACK); + sqlite3CloseSavepoints(p); + p->autoCommit = 1; p->nChange = 0; } } @@ -2673,8 +2682,8 @@ int sqlite3VdbeHalt(Vdbe *p){ ** above has occurred. */ if( !sqlite3VtabInSync(db) - && db->autoCommit - && db->nVdbeWrite==(p->readOnly==0) + && p->autoCommit + && db->nVdbeWrite==(p->readOnly==0) ){ if( p->rc==SQLITE_OK || (p->errorAction==OE_Fail && !isSpecialError) ){ rc = sqlite3VdbeCheckFk(p, 1); @@ -2703,21 +2712,21 @@ int sqlite3VdbeHalt(Vdbe *p){ p->rc = rc; box_txn_rollback(); closeCursorsAndFree(p); - sqlite3RollbackAll(db, SQLITE_OK); + sqlite3RollbackAll(p, SQLITE_OK); p->nChange = 0; }else{ - db->nDeferredCons = 0; - db->nDeferredImmCons = 0; + p->nDeferredCons = 0; + p->nDeferredImmCons = 0; db->flags &= ~SQLITE_DeferFKs; sqlite3CommitInternalChanges(db); } }else{ box_txn_rollback(); closeCursorsAndFree(p); - sqlite3RollbackAll(db, SQLITE_OK); + sqlite3RollbackAll(p, SQLITE_OK); p->nChange = 0; } - db->nStatement = 0; + p->nStatement = 0; }else if( eStatementOp==0 ){ if( p->rc==SQLITE_OK || p->errorAction==OE_Fail ){ eStatementOp = SAVEPOINT_RELEASE; @@ -2726,9 +2735,9 @@ int sqlite3VdbeHalt(Vdbe *p){ }else{ box_txn_rollback(); closeCursorsAndFree(p); - sqlite3RollbackAll(db, SQLITE_ABORT_ROLLBACK); - sqlite3CloseSavepoints(db); - db->autoCommit = 1; + sqlite3RollbackAll(p, SQLITE_ABORT_ROLLBACK); + sqlite3CloseSavepoints(p); + p->autoCommit = 1; p->nChange = 0; } } @@ -2749,9 +2758,9 @@ int sqlite3VdbeHalt(Vdbe *p){ p->zErrMsg = 0; } closeCursorsAndFree(p); - sqlite3RollbackAll(db, SQLITE_ABORT_ROLLBACK); - sqlite3CloseSavepoints(db); - db->autoCommit = 1; + sqlite3RollbackAll(p, SQLITE_ABORT_ROLLBACK); + sqlite3CloseSavepoints(p); + p->autoCommit = 1; p->nChange = 0; } } @@ -2793,11 +2802,11 @@ int sqlite3VdbeHalt(Vdbe *p){ ** by connection db have now been released. Call sqlite3ConnectionUnlocked() ** to invoke any required unlock-notify callbacks. */ - if( db->autoCommit ){ + if( p->autoCommit ){ sqlite3ConnectionUnlocked(db); } - assert( db->nVdbeActive>0 || db->autoCommit==0 || db->nStatement==0 ); + assert( db->nVdbeActive>0 || p->autoCommit==0 || p->nStatement==0 ); return (p->rc==SQLITE_BUSY ? SQLITE_BUSY : SQLITE_OK); } diff --git a/src/box/sql/vtab.c b/src/box/sql/vtab.c index fa8d241ca1ebb947fe8db5d2313485936f116152..5743511d60c6fa8c8f2f78d22cfff9fb9d731cb4 100644 --- a/src/box/sql/vtab.c +++ b/src/box/sql/vtab.c @@ -13,6 +13,7 @@ */ #ifndef SQLITE_OMIT_VIRTUALTABLE #include "sqliteInt.h" +#include "vdbeInt.h" /* ** Before a virtual table xCreate() or xConnect() method is invoked, the @@ -929,7 +930,7 @@ int sqlite3VtabCommit(sqlite3 *db){ ** If the xBegin call is successful, place the sqlite3_vtab pointer ** in the sqlite3.aVTrans array. */ -int sqlite3VtabBegin(sqlite3 *db, VTable *pVTab){ +int sqlite3VtabBegin(sqlite3 *db, Vdbe * pVdbe, VTable *pVTab){ int rc = SQLITE_OK; const sqlite3_module *pModule; @@ -962,7 +963,7 @@ int sqlite3VtabBegin(sqlite3 *db, VTable *pVTab){ if( rc==SQLITE_OK ){ rc = pModule->xBegin(pVTab->pVtab); if( rc==SQLITE_OK ){ - int iSvpt = db->nStatement + db->nSavepoint; + int iSvpt = pVdbe->nStatement + pVdbe->nSavepoint; addToVTrans(db, pVTab); if( iSvpt && pModule->xSavepoint ){ pVTab->iSavepoint = iSvpt; diff --git a/src/lib/msgpuck b/src/lib/msgpuck index 3b8f3e59b62d74f0198e01cbec0beb9c6a3082fb..40e24ccf3ec191e6f576da967a64630ca2160bfc 160000 --- a/src/lib/msgpuck +++ b/src/lib/msgpuck @@ -1 +1 @@ -Subproject commit 3b8f3e59b62d74f0198e01cbec0beb9c6a3082fb +Subproject commit 40e24ccf3ec191e6f576da967a64630ca2160bfc diff --git a/src/lib/small b/src/lib/small index 386541c10feebe6396529480dc44e9ddea46c315..e32601a34a3e47d4c3234e611c34cb7efe202ceb 160000 --- a/src/lib/small +++ b/src/lib/small @@ -1 +1 @@ -Subproject commit 386541c10feebe6396529480dc44e9ddea46c315 +Subproject commit e32601a34a3e47d4c3234e611c34cb7efe202ceb diff --git a/src/start-server.lua b/src/start-server.lua deleted file mode 100644 index 1f05b370f572bc036c07e4323e396cf0b1ef86b4..0000000000000000000000000000000000000000 --- a/src/start-server.lua +++ /dev/null @@ -1,21 +0,0 @@ -box.cfg{} - -local create_table_statement = [[ - CREATE TABLE sbtest1( - id INTEGER, - k INTEGER DEFAULT '0' NOT NULL, - c CHAR(120) DEFAULT '' NOT NULL, - pad CHAR(60) DEFAULT '' NOT NULL, - PRIMARY KEY (id)); - ]] - -box.sql.execute("DROP TABLE IF EXISTS sbtest1") -box.sql.execute(create_table_statement) - -for i=1,2000,1 do box.sql.execute("INSERT INTO sbtest1 VALUES (".. i ..", ".. i ..", 'blabla', 'bloblo')") end - -box.sql.execute("CREATE INDEX k_1 ON sbtest1(k)") - -box.cfg{listen=3301} - - diff --git a/src/start-thread.lua b/src/start-thread.lua deleted file mode 100644 index 527a520acdbeb705f4b61af87f5e78eafb930e94..0000000000000000000000000000000000000000 --- a/src/start-thread.lua +++ /dev/null @@ -1,4 +0,0 @@ -remote = require('net.box') -cn = remote.connect(3301) - -for i=1, 1100 ,1 do cn:execute("UPDATE sbtest1 SET c='lalala' WHERE id="..i.."") end