]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Make the freelist format a separate feature from the page-level locking.
authordan <dan@noemail.net>
Thu, 13 Jul 2017 21:06:51 +0000 (21:06 +0000)
committerdan <dan@noemail.net>
Thu, 13 Jul 2017 21:06:51 +0000 (21:06 +0000)
Freelist format is now configure using "PRAGMA freelist_format".

FossilOrigin-Name: dcc407972aa213d28f95cbaf4da5ab7d89ddbad2740f41cfb44b2c2ce20a3132

manifest
manifest.uuid
src/btree.c
src/btree.h
src/pragma.c
src/pragma.h
src/vdbe.c
tool/mkpragmatab.tcl

index 082a6844815f4755c49022aa3c9ea9ca6f147ef8..c0d590d61937b9b6f7b57f7790d82cdb3ae443ff 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Add\sSQL\sfunction\susleep()\sto\stest\sprogram\stserver.c.
-D 2017-07-11T18:38:26.799
+C Make\sthe\sfreelist\sformat\sa\sseparate\sfeature\sfrom\sthe\spage-level\slocking.\nFreelist\sformat\sis\snow\sconfigure\susing\s"PRAGMA\sfreelist_format".
+D 2017-07-13T21:06:51.922
 F Makefile.in 081e48dfe7f995d57ce1a88ddf4d2917b4349158648a6cd45b42beae30de3a12
 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
 F Makefile.msc 4ebb1d257cac7fb1bcb4ba59278416d410ff1c4bf59447a9c37a415f3516056a
@@ -391,8 +391,8 @@ F src/auth.c 79f96c6f33bf0e5da8d1c282cee5ebb1852bb8a6ccca3e485d7c459b035d9c3c
 F src/backup.c faf17e60b43233c214aae6a8179d24503a61e83b
 F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33
 F src/btmutex.c 0e9ce2d56159b89b9bc8e197e023ee11e39ff8ca
-F src/btree.c 0e1bcecde07e3e022a1a1f16cdfa6817267c25eb4a48ea21fe9359b973837762
-F src/btree.h 3edc5329bc59534d2d15b4f069a9f54b779a7e51289e98fa481ae3c0e526a5ca
+F src/btree.c 85cd6d97be767b660a030d841534b082d8e50df506c9eaaa0bcc0c5c15f77da9
+F src/btree.h d1f64c5683e9ade8afa968b49abeb108acd430fc33f2cae2a62a2cfc601087d8
 F src/btreeInt.h a392d353104b4add58b4a59cb185f5d5693dde832c565b77d8d4c343ed98f610
 F src/build.c 32107046e8cda19a917b4a397175c7eb5f2e234d19fae2fc6164859e4a3d4704
 F src/callback.c 8e14b60d1ed1c87c02cb5f121ecda99224f2aea6524a77ee6f72c9b5c7110f84
@@ -441,8 +441,8 @@ F src/parse.y f732ca9ef4dbee9ba19d6d30d2d1f7ac0834d8642515dedbd8f6ebd16ab2a8e3
 F src/pcache.c 62835bed959e2914edd26afadfecce29ece0e870
 F src/pcache.h 521bb9610d38ef17a3cc9b5ddafd4546c2ea67fa3d0e464823d73c2a28d50e11
 F src/pcache1.c 1195a21fe28e223e024f900b2011e80df53793f0356a24caace4188b098540dc
-F src/pragma.c 3f9456edac7eaf171041d51510c5cc922c9b3bd56a713fb7ad6d5b85aa72f1f6
-F src/pragma.h 99d3df4a3d2f12c5227ad403f767334910e6356325b6d155a9a99b4037093460
+F src/pragma.c 09fe2d45a92a16d3dfcab3f18a4992b3bedaacdeed93704cc9dee4b8525717c8
+F src/pragma.h 10b1af34882f96d68b7d3bb07c00fda3283f270f83f58e1ebea6d3b694c95553
 F src/prepare.c 4b84ae7458febe1df3e04ae62ba56abc851f771340e460d14426e6802c5615f4
 F src/printf.c 8757834f1b54dae512fb25eb1acc8e94a0d15dd2290b58f2563f65973265adb2
 F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384
@@ -517,7 +517,7 @@ F src/update.c c443935c652af9365e033f756550b5032d02e1b06eb2cb890ed7511ae0c051dc
 F src/utf.c 699001c79f28e48e9bcdf8a463da029ea660540c
 F src/util.c fc081ec6f63448dcd80d3dfad35baecfa104823254a815b081a4d9fe76e1db23
 F src/vacuum.c 874c0f2f15ab2908748297d587d22d485ea96d55aaec91d4775dddb2e24d2ecf
-F src/vdbe.c e4493b09cc603a1b031c982785e94bbe637799c9e7fc974d37036c04ad2d79e0
+F src/vdbe.c 51a564ddea23a62589424c7d1755dfa245a4e3ffdc3630b1dac9939cecdbbcdd
 F src/vdbe.h dde459b1e8a02b8445ecfd5959f38cd5ebb6b0ad392d491d8b159ac8193d231a
 F src/vdbeInt.h 8dd7548d86a98b77b6ed910d8014d0e9e0666356b56f3d16ab7063aad4f102f5
 F src/vdbeapi.c 899d8f021c89ab348708b3a9b00b855f5ecc3c0f949a75359a61a3c621021281
@@ -1573,7 +1573,7 @@ F tool/mkmsvcmin.tcl cbd93f1cfa3a0a9ae56fc958510aa3fc3ac65e29cb111716199e3d0e66e
 F tool/mkopcodec.tcl d1b6362bd3aa80d5520d4d6f3765badf01f6c43c
 F tool/mkopcodeh.tcl a01d2c1d8a6205b03fc635adf3735b4c523befd3
 F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e
-F tool/mkpragmatab.tcl aa94395a91b5bd47022b7db0c08126f047887e0d299cc19ec1c23a9e5b136961
+F tool/mkpragmatab.tcl 983057a16468b7e5f7c8a1a0f9ba515b4e188d04f326b781ea96c2cf814b3b9f
 F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97
 F tool/mksqlite3c-noext.tcl fef88397668ae83166735c41af99d79f56afaabb
 F tool/mksqlite3c.tcl 4b17864d0ae7664b2a82ac852afbe52e7d1db65c996b72941e149704b5e3cc15
@@ -1636,7 +1636,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
 F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P b6157267f9d4ecdffbdf4b1e591b8d6baaaa964c418ec247a24ccb82146f9041
-R d431332999db79016ab1852b88d53c44
+P 8cbe8f2b2fe0a5a246401718da8db8d487ced232ada73b53bdc9f9608c47d50e
+R e2a1314b3947fa4a991aa95e4137779f
 U dan
-Z 974e699f24a083c2cc24ed8a142caee5
+Z 013d31178aa545fe252ff8393248759a
index 9643b9844d92aed40be150b2202107368f2be50e..3a4b9e09fab406cb1f3b885e035dba75c8d6e100 100644 (file)
@@ -1 +1 @@
-8cbe8f2b2fe0a5a246401718da8db8d487ced232ada73b53bdc9f9608c47d50e
\ No newline at end of file
+dcc407972aa213d28f95cbaf4da5ab7d89ddbad2740f41cfb44b2c2ce20a3132
\ No newline at end of file
index 6410f228df006480be61babd6157d10d627c6d9e..7fdcba4a704e4ade71a7cbd07c1b414b55849ed5 100644 (file)
@@ -238,6 +238,15 @@ static int hasReadConflicts(Btree *pBtree, Pgno iRoot){
 }
 #endif    /* #ifdef SQLITE_DEBUG */
 
+#ifdef SQLITE_SERVER_EDITION
+/*
+** Return true if the b-tree uses free-list format 2. Or false otherwise.
+*/
+static int btreeFreelistFormat2(BtShared *pBt){
+  return (pBt->pPage1->aData[18] > 2);
+}
+#endif
+
 /*
 ** Query to see if Btree handle p may obtain a lock of type eLock 
 ** (READ_LOCK or WRITE_LOCK) on the table with root-page iTab. Return
@@ -2927,6 +2936,15 @@ static int lockBtree(BtShared *pBt){
     u32 pageSize;
     u32 usableSize;
     u8 *page1 = pPage1->aData;
+    u8 i18 = page1[18];
+    u8 i19 = page1[19];
+#ifdef SQLITE_SERVER_EDITION
+    if( i18==i19 && i18>2 ){
+      i18 -= 2;
+      i19 -= 2;
+    }
+#endif
+
     rc = SQLITE_NOTADB;
     /* EVIDENCE-OF: R-43737-39999 Every valid SQLite database file begins
     ** with the following 16 bytes (in hex): 53 51 4c 69 74 65 20 66 6f 72 6d
@@ -2936,17 +2954,17 @@ static int lockBtree(BtShared *pBt){
     }
 
 #ifdef SQLITE_OMIT_WAL
-    if( page1[18]>1 ){
+    if( i18>1 ){
       pBt->btsFlags |= BTS_READ_ONLY;
     }
-    if( page1[19]>1 ){
+    if( i19>1 ){
       goto page1_init_failed;
     }
 #else
-    if( page1[18]>2 ){
+    if( i18>2 ){
       pBt->btsFlags |= BTS_READ_ONLY;
     }
-    if( page1[19]>2 ){
+    if( i19>2 ){
       goto page1_init_failed;
     }
 
@@ -2958,7 +2976,7 @@ static int lockBtree(BtShared *pBt){
     ** may not be the latest version - there may be a newer one in the log
     ** file.
     */
-    if( page1[19]==2 && (pBt->btsFlags & BTS_NO_WAL)==0 ){
+    if( i19==2 && (pBt->btsFlags & BTS_NO_WAL)==0 ){
       int isOpen = 0;
       rc = sqlite3PagerOpenWal(pBt->pPager, &isOpen);
       if( rc!=SQLITE_OK ){
@@ -5900,7 +5918,7 @@ static int allocateBtreePage(
   MemPage *pPrevTrunk = 0;
   Pgno mxPage;     /* Total size of the database file */
 
-  if( sqlite3PagerIsServer(pBt->pPager) ){
+  if( btreeFreelistFormat2(pBt) ){
     return allocateServerPage(pBt, ppPage, pPgno, nearby, eMode); 
   }
 
@@ -6243,7 +6261,7 @@ static int freePage2(BtShared *pBt, MemPage *pMemPage, Pgno iPage){
     memset(pPage->aData, 0, pPage->pBt->pageSize);
   }
   
-  if( sqlite3PagerIsServer(pBt->pPager) ){
+  if( btreeFreelistFormat2(pBt) ){
     rc = freeServerPage2(pBt, pPage, iPage);
     goto freepage_out;
   }
@@ -9816,7 +9834,7 @@ char *sqlite3BtreeIntegrityCheck(
   */
   sCheck.zPfx = "Main freelist: ";
 #ifdef SQLITE_SERVER_EDITION
-  if( sqlite3PagerIsServer(pBt->pPager) ){
+  if( btreeFreelistFormat2(pBt) ){
     checkServerList(&sCheck);
   }else
 #endif
@@ -10092,6 +10110,37 @@ void sqlite3BtreeIncrblobCursor(BtCursor *pCur){
 }
 #endif
 
+int btreeSetVersion(Btree *pBtree, int iVersion, int iFreelistFmt){
+  BtShared *pBt = pBtree->pBt;
+  int rc = sqlite3BtreeBeginTrans(pBtree, 0);
+  if( rc==SQLITE_OK ){
+    u8 iVal;
+    u8 *aData = pBt->pPage1->aData;
+
+    assert( (iVersion==0 && (iFreelistFmt==1 || iFreelistFmt==2))
+         || (iFreelistFmt==0 && (iVersion==1 || iVersion==2))
+    );
+    if( iVersion==0 ){
+      iVal = ((aData[18] & 0x01) ? 1 : 2) + (u8)(iFreelistFmt==2 ? 2 : 0);
+    }else{
+      iVal = (u8)iVersion + (u8)(aData[18]>2 ? 2 : 0);
+    }
+
+    if( aData[18]!=iVal || aData[19]!=iVal ){
+      rc = sqlite3BtreeBeginTrans(pBtree, 2);
+      if( rc==SQLITE_OK ){
+        rc = sqlite3PagerWrite(pBt->pPage1->pDbPage);
+        if( rc==SQLITE_OK ){
+          aData[18] = iVal;
+          aData[19] = iVal;
+        }
+      }
+    }
+  }
+
+  return rc;
+}
+
 /*
 ** Set both the "read version" (single byte at byte offset 18) and 
 ** "write version" (single byte at byte offset 19) fields in the database
@@ -10108,23 +10157,22 @@ int sqlite3BtreeSetVersion(Btree *pBtree, int iVersion){
   */
   pBt->btsFlags &= ~BTS_NO_WAL;
   if( iVersion==1 ) pBt->btsFlags |= BTS_NO_WAL;
+  rc = btreeSetVersion(pBtree, iVersion, 0); 
+  pBt->btsFlags &= ~BTS_NO_WAL;
+  return rc;
+}
 
-  rc = sqlite3BtreeBeginTrans(pBtree, 0);
-  if( rc==SQLITE_OK ){
-    u8 *aData = pBt->pPage1->aData;
-    if( aData[18]!=(u8)iVersion || aData[19]!=(u8)iVersion ){
-      rc = sqlite3BtreeBeginTrans(pBtree, 2);
-      if( rc==SQLITE_OK ){
-        rc = sqlite3PagerWrite(pBt->pPage1->pDbPage);
-        if( rc==SQLITE_OK ){
-          aData[18] = (u8)iVersion;
-          aData[19] = (u8)iVersion;
-        }
-      }
+int sqlite3BtreeFreelistFormat(Btree *p, int eParam, int *peFmt){
+  int rc = SQLITE_OK;
+  sqlite3BtreeEnter(p);
+  if( eParam ){
+    u8 *aData = p->pBt->pPage1->aData;
+    if( 0==get4byte(&aData[32]) ){
+      rc = btreeSetVersion(p, 0, eParam);
     }
   }
-
-  pBt->btsFlags &= ~BTS_NO_WAL;
+  *peFmt = (btreeFreelistFormat2(p->pBt) ? 2 : 1);
+  sqlite3BtreeLeave(p);
   return rc;
 }
 
index b56eb85e68f36e7b5e24ccf7fcec676ec90ddbd9..4f9714c141fe0acb470a466fb1033f573793fdfb 100644 (file)
@@ -367,5 +367,8 @@ void sqlite3BtreeCursorList(Btree*);
 # define sqlite3SchemaMutexHeld(X,Y,Z) 1
 #endif
 
+#ifdef SQLITE_SERVER_EDITION
+int sqlite3BtreeFreelistFormat(Btree *p, int eParam, int *peFmt);
+#endif
 
 #endif /* SQLITE_BTREE_H */
index 7135f07553b73b02802658ef3319827b069adee6..fb6893de72526281b08e9d02616610e969940c1e 100644 (file)
@@ -656,6 +656,33 @@ void sqlite3Pragma(
     break;
   }
 
+#ifdef SQLITE_SERVER_EDITION
+  /*
+  **  PRAGMA [schema.]freelist_format
+  **  PRAGMA [schema.]freelist_format = (1|2)
+  */
+  case PragTyp_FREELIST_FORMAT: {
+    sqlite3VdbeUsesBtree(v, iDb);
+    static const VdbeOpList freelist[] = {
+      { OP_Transaction,    0,  0,  0},    /* 0 */
+      { OP_FreelistFmt,    0,  1,  0},    /* 1 */
+      { OP_ResultRow,      1,  1,  0}     /* 2 */
+    };
+    VdbeOp *aOp;
+    sqlite3VdbeVerifyNoMallocRequired(v, ArraySize(freelist));
+    aOp = sqlite3VdbeAddOpList(v, ArraySize(freelist), freelist,0);
+    aOp[0].p1 = iDb;
+    aOp[1].p1 = iDb;
+
+    if( zRight && (zRight[0]=='1' || zRight[0]=='2') && zRight[1]=='\0' ){
+      aOp[0].p2 = 1;              /* Open a write transaction */
+      aOp[1].p3 = (int)(zRight[0] - '0');
+    }
+
+    break;
+  }
+#endif
+
   /*
   **  PRAGMA [schema.]journal_size_limit
   **  PRAGMA [schema.]journal_size_limit=N
index 76e59cbc6bb7a8bf4957774500feabb0f6c51d13..a21b70aacef592fd10ef70d74bdb0b4b3d8edd1c 100644 (file)
 #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_OPTIMIZE                      25
-#define PragTyp_PAGE_SIZE                     26
-#define PragTyp_SECURE_DELETE                 27
-#define PragTyp_SHRINK_MEMORY                 28
-#define PragTyp_SOFT_HEAP_LIMIT               29
-#define PragTyp_SYNCHRONOUS                   30
-#define PragTyp_TABLE_INFO                    31
-#define PragTyp_TEMP_STORE                    32
-#define PragTyp_TEMP_STORE_DIRECTORY          33
-#define PragTyp_THREADS                       34
-#define PragTyp_WAL_AUTOCHECKPOINT            35
-#define PragTyp_WAL_CHECKPOINT                36
-#define PragTyp_ACTIVATE_EXTENSIONS           37
-#define PragTyp_HEXKEY                        38
-#define PragTyp_KEY                           39
-#define PragTyp_REKEY                         40
-#define PragTyp_LOCK_STATUS                   41
-#define PragTyp_PARSER_TRACE                  42
-#define PragTyp_STATS                         43
+#define PragTyp_FREELIST_FORMAT               15
+#define PragTyp_INCREMENTAL_VACUUM            16
+#define PragTyp_INDEX_INFO                    17
+#define PragTyp_INDEX_LIST                    18
+#define PragTyp_INTEGRITY_CHECK               19
+#define PragTyp_JOURNAL_MODE                  20
+#define PragTyp_JOURNAL_SIZE_LIMIT            21
+#define PragTyp_LOCK_PROXY_FILE               22
+#define PragTyp_LOCKING_MODE                  23
+#define PragTyp_PAGE_COUNT                    24
+#define PragTyp_MMAP_SIZE                     25
+#define PragTyp_OPTIMIZE                      26
+#define PragTyp_PAGE_SIZE                     27
+#define PragTyp_SECURE_DELETE                 28
+#define PragTyp_SHRINK_MEMORY                 29
+#define PragTyp_SOFT_HEAP_LIMIT               30
+#define PragTyp_SYNCHRONOUS                   31
+#define PragTyp_TABLE_INFO                    32
+#define PragTyp_TEMP_STORE                    33
+#define PragTyp_TEMP_STORE_DIRECTORY          34
+#define PragTyp_THREADS                       35
+#define PragTyp_WAL_AUTOCHECKPOINT            36
+#define PragTyp_WAL_CHECKPOINT                37
+#define PragTyp_ACTIVATE_EXTENSIONS           38
+#define PragTyp_HEXKEY                        39
+#define PragTyp_KEY                           40
+#define PragTyp_REKEY                         41
+#define PragTyp_LOCK_STATUS                   42
+#define PragTyp_PARSER_TRACE                  43
+#define PragTyp_STATS                         44
 
 /* Property flags associated with various pragma. */
 #define PragFlg_NeedSchema 0x01 /* Force schema load before running */
@@ -294,6 +295,13 @@ static const PragmaName aPragmaName[] = {
   /* ColNames:  */ 0, 0,
   /* iArg:      */ BTREE_FREE_PAGE_COUNT },
 #endif
+#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && defined(SQLITE_SERVER_EDITION)
+ {/* zName:     */ "freelist_format",
+  /* ePragTyp:  */ PragTyp_FREELIST_FORMAT,
+  /* ePragFlg:  */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq,
+  /* ColNames:  */ 0, 0,
+  /* iArg:      */ 0 },
+#endif
 #if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
  {/* zName:     */ "full_column_names",
   /* ePragTyp:  */ PragTyp_FLAG,
@@ -613,4 +621,4 @@ static const PragmaName aPragmaName[] = {
   /* iArg:      */ SQLITE_WriteSchema },
 #endif
 };
-/* Number of pragmas: 60 on by default, 74 total. */
+/* Number of pragmas: 60 on by default, 75 total. */
index 6242d6545df00afd7ed14bcf3a4ab82e160e4f95..8705ff0b5352c71b52ab24a26fd237c6d2ec3a72 100644 (file)
@@ -3377,6 +3377,33 @@ case OP_SetCookie: {
   break;
 }
 
+#ifdef SQLITE_SERVER_EDITION
+/* Opcode: FreelistFmt P1 P2 P3 * *
+**
+** Parameter P3 must be 0, 1 or 2. If it is not 0, attempt to set the
+** freelist format of database P1 to format 1 or format 2. Before
+** returning, store the final freelist format (either 1 or 2) of 
+** database P1 into register P2.
+*/
+case OP_FreelistFmt: {  /* out2 */
+  Db *pDb;
+  int iVal;
+
+  assert( pOp->p1>=0 && pOp->p1<db->nDb );
+  assert( DbMaskTest(p->btreeMask, pOp->p1) );
+  assert( sqlite3SchemaMutexHeld(db, pOp->p1, 0) );
+  pDb = &db->aDb[pOp->p1];
+  assert( pDb->pBt!=0 );
+
+  pOut = out2Prerelease(p, pOp);
+  rc = sqlite3BtreeFreelistFormat(pDb->pBt, pOp->p3, &iVal);
+  if( rc ) goto abort_due_to_error;
+  pOut->u.i = iVal;
+
+  break;
+}
+#endif
+
 /* Opcode: OpenRead P1 P2 P3 P4 P5
 ** Synopsis: root=P2 iDb=P3
 **
index c7001dc33997ff853f2fc025d6dbc3e78f9ff87a..2ba65a8c90d14bf753e0b8fa7f878cab7a479d80 100644 (file)
@@ -364,6 +364,10 @@ set pragma_def {
 
   NAME: optimize
   FLAG: Result1 NeedSchema
+
+  NAME: freelist_format
+  FLAG: NeedSchema Result0 SchemaReq
+  IF:   !defined(SQLITE_OMIT_PAGER_PRAGMAS) && defined(SQLITE_SERVER_EDITION)
 }
 
 # Open the output file