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