From: drh Date: Sun, 1 May 2011 22:57:41 +0000 (+0000) Subject: Backport check-ins [0900e35348f4b9bf3] and [4fead8e714c7e50] to the 3.7.2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=7afd98dddbf4bbb1b08d972218e78b854cf4d00f;p=thirdparty%2Fsqlite.git Backport check-ins [0900e35348f4b9bf3] and [4fead8e714c7e50] to the 3.7.2 branch. These check-ins provide hints to the btree layer for when it is possible to use a hash table rather than a btree to implement an index. The SQLite BTree layer does not use these hints, but alternative btree layers might. FossilOrigin-Name: 7155e6f3282671487f262fd51a7cb139dffdbde6 --- diff --git a/manifest b/manifest index 72f0c8b551..a6e5543e6a 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Backport\scheck-in\s[9f9f32882501ac9]\sto\sprovide\sEXPLAIN\sQUERY\sPLAN\soutput\sfor\nthe\scount(*)\soptimization.\s\sAlso\sbackport\scheck-in\s[a8761a9128de945aa]\sto\nprevent\sunordered\sindices\sfrom\sbeing\sused\son\sa\sfull\stable\sscan.\s\sThe\sfirst\nbackport\swas\snecessary\sin\sorder\sto\stest\sthe\ssecond. -D 2011-04-15T15:18:34.932 +C Backport\scheck-ins\s[0900e35348f4b9bf3]\sand\s[4fead8e714c7e50]\sto\sthe\s3.7.2\nbranch.\s\sThese\scheck-ins\sprovide\shints\sto\sthe\sbtree\slayer\sfor\swhen\sit\sis\npossible\sto\suse\sa\shash\stable\srather\sthan\sa\sbtree\sto\simplement\san\sindex.\nThe\sSQLite\sBTree\slayer\sdoes\snot\suse\sthese\shints,\sbut\salternative\sbtree\slayers\nmight. +D 2011-05-01T22:57:41.307 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 543f91f24cd7fee774ecc0a61c19704c0c3e78fd F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -108,21 +108,21 @@ F sqlite3.1 6be1ad09113570e1fc8dcaff84c9b0b337db5ffc F sqlite3.pc.in ae6f59a76e862f5c561eb32a380228a02afc3cad F src/alter.c 8dc27638e7e2553e80b2b621f232be5eb1e85ef3 F src/analyze.c 0a58e3d8228617e619c48a3aa8991a1ff5ad7768 -F src/attach.c 17bec1f18254d9341369f20f90ba24ce35d20d10 +F src/attach.c c689d516ee8cc52bf11bef2067d76eb8b716228a F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34 F src/backup.c 8ff0b7018df253c7f30d3f9702b0b16f19209d5c F src/bitvec.c af50f1c8c0ff54d6bdb7a80e2fceca5a93670bef F src/btmutex.c 96a12f50f7a17475155971a241d85ec5171573ff -F src/btree.c c1d7d81da6a1572291560ef186090f37c0b62dd9 -F src/btree.h b4ba2fdf6b64c7c376bdfffa826af6b786b151d9 -F src/btreeInt.h 5b034ff54800046cc5870605d683ac1f9134bd99 -F src/build.c a3c83d34a7f1e56308175076f65d510ae52dd6dc +F src/btree.c 40c7a36152403d8e7266f99ef157a661c7ab9691 +F src/btree.h 2d1a83ad509047e8cc314fda7e054f99ff52414d +F src/btreeInt.h c424f2f131cc61ddf130f9bd736b3df12c8a51f0 +F src/build.c a8aca43dc4f02b2293fd872eafdc80e487443a80 F src/callback.c da3c38d0ef5d7f04fae371e519bda61aa9cb1704 F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac F src/ctime.c 2e39d3374e785a63117e077bcba9d4a6656df363 F src/date.c 5dd8448a0bfea8d31fb14cff487d0c06ff8c8b20 F src/delete.c 7ed8a8c8b5f748ece92df173d7e0f7810c899ebd -F src/expr.c 9ee507c3dc6eaa5657cbd1dad026cdeda89c559f +F src/expr.c 21ad2494bd7c0826072216ea0f20db86a0a4ac82 F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb F src/fkey.c 58bbf52c6ddd3f64ca40a3230f9e548a83a5cb16 F src/func.c 464b0dc70618b896c402c574eb04bc5eacf35341 @@ -135,7 +135,7 @@ F src/journal.c 552839e54d1bf76fb8f7abe51868b66acacf6a0e F src/legacy.c a199d7683d60cef73089e892409113e69c23a99f F src/lempar.c 7f026423f4d71d989e719a743f98a1cbd4e6d99e F src/loadext.c 6d422ea91cf3d2d00408c5a8f2391cd458da85f8 -F src/main.c 99622181f36d68e9f2a851c7b34263b3dcd03470 +F src/main.c 7f159a4c79b24a45858046e33353bf1c0a2df659 F src/malloc.c 19a468460c7df72de245f10c06bd0625777b7c83 F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem1.c 89d4ea8d5cdd55635cbaa48ad53132af6294cbb2 @@ -156,8 +156,8 @@ F src/os_common.h a8f95b81eca8a1ab8593d23e94f8a35f35d4078f F src/os_os2.c 72d0b2e562952a2464308c4ce5f7913ac10bef3e F src/os_unix.c 11194cbcf6a57456e58022dc537ab8c3497d9bb9 F src/os_win.c 51cb62f76262d961ea4249489383d714501315a7 -F src/pager.c a5f5d9787b11dfb0b6082e6f5846d00b459a8e19 -F src/pager.h ef8c8f71ab022cc2fff768a1175dd32355be9dcd +F src/pager.c ff40d2a98f135c8505b1a0a0b17bbe5f2a3c0cd5 +F src/pager.h 8167a1e720d0b7a2790079007128e594010220ad F src/parse.y 12b7ebd61ea54f0e1b1083ff69cc2c8ce9353d58 F src/pcache.c 1e9aa2dbc0845b52e1b51cc39753b6d1e041cb07 F src/pcache.h c683390d50f856d4cd8e24342ae62027d1bb6050 @@ -168,18 +168,18 @@ F src/printf.c 8ae5082dd38a1b5456030c3755ec3a392cd51506 F src/random.c cd4a67b3953b88019f8cd4ccd81394a8ddfaba50 F src/resolve.c 1c0f32b64f8e3f555fe1f732f9d6f501a7f05706 F src/rowset.c 69afa95a97c524ba6faf3805e717b5b7ae85a697 -F src/select.c a84089eb0147bdc16f487cf6f2670432eb673c2b +F src/select.c 567d1aa0fdf7b253d06c5391ed725669773d5b87 F src/shell.c 8517fc1f9c59ae4007e6cc8b9af91ab231ea2056 F src/sqlite.h.in 2d72a6242df41c517e38eec8791abcf5484a36f1 F src/sqlite3ext.h 69dfb8116af51b84a029cddb3b35062354270c89 -F src/sqliteInt.h 084453ecc60bd7e478d4008fd29a0b68d788126f +F src/sqliteInt.h 81894df40eb6023fc786bb9e4aeef7dcbf54b873 F src/sqliteLimit.h a17dcd3fb775d63b64a43a55c54cb282f9726f44 F src/status.c 496913d4e8441195f6f2a75b1c95993a45b9b30b F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e F src/tclsqlite.c cacee9482417b6fc6043f6bb831ff9496d46242d F src/test1.c 55005c9781b157b1d215ba145768783b9abae78c F src/test2.c 80d323d11e909cf0eb1b6fbb4ac22276483bcf31 -F src/test3.c 4c21700c73a890a47fc685c1097bfb661346ac94 +F src/test3.c 056093cfef69ff4227a6bdb9108564dc7f45e4bc F src/test4.c 0528360b5025688002a5feb6be906ddce52eaaee F src/test5.c e1a19845625144caf038031234a12185e40d315c F src/test6.c c7256cc21d2409486d094277d5b017e8eced44ba @@ -214,13 +214,13 @@ F src/test_vfs.c 702e52636113f6b9721da90ef1bf26e07fff414d F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9 F src/tokenize.c 604607d6813e9551cf5189d899e0a25c12681080 F src/trigger.c b8bedb9c0084ceb51a40f54fcca2ce048c8de852 -F src/update.c 1521162d20c2994af1fdc8833e1a88dae09052c8 +F src/update.c 227e6cd512108b84f69421fc6c7aa1b83d60d6e0 F src/utf.c 1baeeac91707a4df97ccc6141ec0f808278af685 F src/util.c 32aebf04c10e51ad3977a928b7416bed671b620b F src/vacuum.c 241a8386727c1497eba4955933356dfba6ff8c9f -F src/vdbe.c 9fa023047cd97f9607726c5eb60e8855efa7c027 +F src/vdbe.c 67486fbf9c5b8bb5a43ed7b7075cbaf2443b5a98 F src/vdbe.h 4de0efb4b0fdaaa900cf419b35c458933ef1c6d2 -F src/vdbeInt.h ffd68c4d4229227a5089bec53a1c635146177abc +F src/vdbeInt.h a247bd5448039e83394bf4179975b2ae0092874c F src/vdbeapi.c d0f4407e465f261780ad725c1caece7d66a6aa35 F src/vdbeaux.c 157d62a6a8ca22c3792f5957e887df8bda2d58eb F src/vdbeblob.c 258a6010ba7a82b72b327fb24c55790655689256 @@ -756,7 +756,7 @@ F test/triggerA.test eaf11a29db2a11967d2d4b49d37f92bce598194e F test/triggerB.test 56780c031b454abac2340dbb3b71ac5c56c3d7fe F test/triggerC.test 2a23edcc00684d084902ba5ec93e721775c3a70a F test/triggerD.test c6add3817351451e419f6ff9e9a259b02b6e2de7 -F test/types.test 9a825ec8eea4e965d7113b74c76a78bb5240f2ac +F test/types.test bf816ce73c7dfcfe26b700c19f97ef4050d194ff F test/types2.test 3555aacf8ed8dc883356e59efc314707e6247a84 F test/types3.test a0f66bf12f80fad89493535474f7a6d16fa58150 F test/unique.test 083c7fff74695bcc27a71d75699deba3595bc9c2 @@ -849,7 +849,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P 803530209f9c8d4dcf8ed51b5a96aee1766ef79f -R 725597da94f34e4749b884cb2782a777 +P 8d924e160703e02958db9c9bc1fd2c600e01e606 +R 7803554a59050b798bb3c36bfc235df9 U drh -Z 8cf57ecd3590b1d454de4a08c8b4d635 +Z 02cc4f019cee77499bb297aefe853ba9 diff --git a/manifest.uuid b/manifest.uuid index 1c1de6ee89..1b6a94285a 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -8d924e160703e02958db9c9bc1fd2c600e01e606 \ No newline at end of file +7155e6f3282671487f262fd51a7cb139dffdbde6 \ No newline at end of file diff --git a/src/attach.c b/src/attach.c index 30a4207cce..4e1a20d02c 100644 --- a/src/attach.c +++ b/src/attach.c @@ -124,9 +124,8 @@ static void attachFunc( ** it to obtain the database schema. At this point the schema may ** or may not be initialised. */ - rc = sqlite3BtreeFactory(db, zFile, 0, SQLITE_DEFAULT_CACHE_SIZE, - db->openFlags | SQLITE_OPEN_MAIN_DB, - &aNew->pBt); + rc = sqlite3BtreeOpen(zFile, db, &aNew->pBt, 0, + db->openFlags | SQLITE_OPEN_MAIN_DB); db->nDb++; if( rc==SQLITE_CONSTRAINT ){ rc = SQLITE_ERROR; diff --git a/src/btree.c b/src/btree.c index 3cbbdc5c91..f5b75d32cc 100644 --- a/src/btree.c +++ b/src/btree.c @@ -1672,11 +1672,20 @@ static int btreeInvokeBusyHandler(void *pArg){ ** Open a database file. ** ** zFilename is the name of the database file. If zFilename is NULL -** a new database with a random name is created. This randomly named -** database file will be deleted when sqlite3BtreeClose() is called. +** then an ephemeral database is created. The ephemeral database might +** be exclusively in memory, or it might use a disk-based memory cache. +** Either way, the ephemeral database will be automatically deleted +** when sqlite3BtreeClose() is called. +** ** If zFilename is ":memory:" then an in-memory database is created ** that is automatically destroyed when it is closed. ** +** The "flags" parameter is a bitmask that might contain bits +** BTREE_OMIT_JOURNAL and/or BTREE_NO_READLOCK. The BTREE_NO_READLOCK +** bit is also set if the SQLITE_NoReadlock flags is set in db->flags. +** These flags are passed through into sqlite3PagerOpen() and must +** be the same values as PAGER_OMIT_JOURNAL and PAGER_NO_READLOCK. +** ** If the database is already opened in the same database connection ** and we are in shared cache mode, then the open will fail with an ** SQLITE_CONSTRAINT error. We cannot allow two or more BtShared @@ -1698,6 +1707,9 @@ int sqlite3BtreeOpen( u8 nReserve; /* Byte of unused space on each page */ unsigned char zDbHeader[100]; /* Database header content */ + /* True if opening an ephemeral, temporary database */ + const int isTempDb = zFilename==0 || zFilename[0]==0; + /* Set the variable isMemdb to true for an in-memory database, or ** false for a file-based database. This symbol is only required if ** either of the shared-data or autovacuum features are compiled @@ -1707,13 +1719,30 @@ int sqlite3BtreeOpen( #ifdef SQLITE_OMIT_MEMORYDB const int isMemdb = 0; #else - const int isMemdb = zFilename && !strcmp(zFilename, ":memory:"); + const int isMemdb = (zFilename && strcmp(zFilename, ":memory:")==0) + || (isTempDb && sqlite3TempInMemory(db)); #endif #endif assert( db!=0 ); assert( sqlite3_mutex_held(db->mutex) ); + assert( (flags&0xff)==flags ); /* flags fit in 8 bits */ + + /* Only a BTREE_SINGLE database can be BTREE_UNORDERED */ + assert( (flags & BTREE_UNORDERED)==0 || (flags & BTREE_SINGLE)!=0 ); + /* A BTREE_SINGLE database is always a temporary and/or ephemeral */ + assert( (flags & BTREE_SINGLE)==0 || isTempDb ); + + if( db->flags & SQLITE_NoReadlock ){ + flags |= BTREE_NO_READLOCK; + } + if( isMemdb ){ + flags |= BTREE_MEMORY; + } + if( (vfsFlags & SQLITE_OPEN_MAIN_DB)!=0 && (isMemdb || isTempDb) ){ + vfsFlags = (vfsFlags & ~SQLITE_OPEN_MAIN_DB) | SQLITE_OPEN_TEMP_DB; + } pVfs = db->pVfs; p = sqlite3MallocZero(sizeof(Btree)); if( !p ){ @@ -1731,7 +1760,7 @@ int sqlite3BtreeOpen( ** If this Btree is a candidate for shared cache, try to find an ** existing BtShared object that we can share with */ - if( isMemdb==0 && zFilename && zFilename[0] ){ + if( isMemdb==0 && isTempDb==0 ){ if( vfsFlags & SQLITE_OPEN_SHAREDCACHE ){ int nFullPathname = pVfs->mxPathname+1; char *zFullPathname = sqlite3Malloc(nFullPathname); @@ -1806,6 +1835,7 @@ int sqlite3BtreeOpen( if( rc!=SQLITE_OK ){ goto btree_open_out; } + pBt->openFlags = flags; pBt->db = db; sqlite3PagerSetBusyhandler(pBt->pPager, btreeInvokeBusyHandler, pBt); p->pBt = pBt; @@ -1910,6 +1940,14 @@ btree_open_out: sqlite3_free(pBt); sqlite3_free(p); *ppBtree = 0; + }else{ + /* If the B-Tree was successfully opened, set the pager-cache size to the + ** default value. Except, when opening on an existing shared pager-cache, + ** do not change the pager-cache size. + */ + if( sqlite3BtreeSchema(p, 0, 0)==0 ){ + sqlite3PagerSetCachesize(p->pBt->pPager, SQLITE_DEFAULT_CACHE_SIZE); + } } if( mutexOpen ){ assert( sqlite3_mutex_held(mutexOpen) ); @@ -6881,11 +6919,12 @@ int sqlite3BtreeDelete(BtCursor *pCur){ ** BTREE_INTKEY|BTREE_LEAFDATA Used for SQL tables with rowid keys ** BTREE_ZERODATA Used for SQL indices */ -static int btreeCreateTable(Btree *p, int *piTable, int flags){ +static int btreeCreateTable(Btree *p, int *piTable, int createTabFlags){ BtShared *pBt = p->pBt; MemPage *pRoot; Pgno pgnoRoot; int rc; + int ptfFlags; /* Page-type flage for the root page of new table */ assert( sqlite3BtreeHoldsMutex(p) ); assert( pBt->inTransaction==TRANS_WRITE ); @@ -7004,8 +7043,14 @@ static int btreeCreateTable(Btree *p, int *piTable, int flags){ } #endif assert( sqlite3PagerIswriteable(pRoot->pDbPage) ); - zeroPage(pRoot, flags | PTF_LEAF); + if( createTabFlags & BTREE_INTKEY ){ + ptfFlags = PTF_INTKEY | PTF_LEAFDATA | PTF_LEAF; + }else{ + ptfFlags = PTF_ZERODATA | PTF_LEAF; + } + zeroPage(pRoot, ptfFlags); sqlite3PagerUnref(pRoot->pDbPage); + assert( (pBt->openFlags & BTREE_SINGLE)==0 || pgnoRoot==2 ); *piTable = (int)pgnoRoot; return SQLITE_OK; } diff --git a/src/btree.h b/src/btree.h index c989307aad..39af03f961 100644 --- a/src/btree.h +++ b/src/btree.h @@ -67,12 +67,11 @@ int sqlite3BtreeOpen( ** NOTE: These values must match the corresponding PAGER_ values in ** pager.h. */ -#define BTREE_OMIT_JOURNAL 1 /* Do not use journal. No argument */ +#define BTREE_OMIT_JOURNAL 1 /* Do not create or use a rollback journal */ #define BTREE_NO_READLOCK 2 /* Omit readlocks on readonly files */ -#define BTREE_MEMORY 4 /* In-memory DB. No argument */ -#define BTREE_READONLY 8 /* Open the database in read-only mode */ -#define BTREE_READWRITE 16 /* Open for both reading and writing */ -#define BTREE_CREATE 32 /* Create the database if it does not exist */ +#define BTREE_MEMORY 4 /* This is an in-memory DB */ +#define BTREE_SINGLE 8 /* The file contains at most 1 b-tree */ +#define BTREE_UNORDERED 16 /* Use of a hash implementation is OK */ int sqlite3BtreeClose(Btree*); int sqlite3BtreeSetCacheSize(Btree*,int); @@ -108,11 +107,17 @@ int sqlite3BtreeCopyFile(Btree *, Btree *); int sqlite3BtreeIncrVacuum(Btree *); /* The flags parameter to sqlite3BtreeCreateTable can be the bitwise OR -** of the following flags: +** of the flags shown below. +** +** Every SQLite table must have either BTREE_INTKEY or BTREE_BLOBKEY set. +** With BTREE_INTKEY, the table key is a 64-bit integer and arbitrary data +** is stored in the leaves. (BTREE_INTKEY is used for SQL tables.) With +** BTREE_BLOBKEY, the key is an arbitrary BLOB and no content is stored +** anywhere - the key is the content. (BTREE_BLOBKEY is used for SQL +** indices.) */ #define BTREE_INTKEY 1 /* Table has only 64-bit signed integer keys */ -#define BTREE_ZERODATA 2 /* Table has keys only - no data */ -#define BTREE_LEAFDATA 4 /* Data stored in leaves only. Implies INTKEY */ +#define BTREE_BLOBKEY 2 /* Table has keys only - no data */ int sqlite3BtreeDropTable(Btree*, int, int*); int sqlite3BtreeClearTable(Btree*, int, int*); diff --git a/src/btreeInt.h b/src/btreeInt.h index 7b46bcebbd..59597faecb 100644 --- a/src/btreeInt.h +++ b/src/btreeInt.h @@ -409,6 +409,7 @@ struct BtShared { u8 pageSizeFixed; /* True if the page size can no longer be changed */ u8 secureDelete; /* True if secure_delete is enabled */ u8 initiallyEmpty; /* Database is empty at start of transaction */ + u8 openFlags; /* Flags to sqlite3BtreeOpen() */ #ifndef SQLITE_OMIT_AUTOVACUUM u8 autoVacuum; /* True if auto-vacuum is enabled */ u8 incrVacuum; /* True if incr-vacuum is enabled */ diff --git a/src/build.c b/src/build.c index b6316204b5..c20cabffe6 100644 --- a/src/build.c +++ b/src/build.c @@ -3392,7 +3392,7 @@ int sqlite3OpenTempDatabase(Parse *pParse){ SQLITE_OPEN_DELETEONCLOSE | SQLITE_OPEN_TEMP_DB; - rc = sqlite3BtreeFactory(db, 0, 0, SQLITE_DEFAULT_CACHE_SIZE, flags, &pBt); + rc = sqlite3BtreeOpen(0, db, &pBt, 0, flags); if( rc!=SQLITE_OK ){ sqlite3ErrorMsg(pParse, "unable to open a temporary database " "file for storing temporary tables"); diff --git a/src/expr.c b/src/expr.c index 33864b2dae..a23a7b197d 100644 --- a/src/expr.c +++ b/src/expr.c @@ -1535,8 +1535,8 @@ int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){ #endif /* -** Generate code for scalar subqueries used as an expression -** and IN operators. Examples: +** Generate code for scalar subqueries used as a subquery expression, EXISTS, +** or IN operators. Examples: ** ** (SELECT a FROM b) -- subquery ** EXISTS (SELECT a FROM b) -- EXISTS subquery @@ -1599,10 +1599,10 @@ int sqlite3CodeSubselect( switch( pExpr->op ){ case TK_IN: { - char affinity; - KeyInfo keyInfo; - int addr; /* Address of OP_OpenEphemeral instruction */ - Expr *pLeft = pExpr->pLeft; + char affinity; /* Affinity of the LHS of the IN */ + KeyInfo keyInfo; /* Keyinfo for the generated table */ + int addr; /* Address of OP_OpenEphemeral instruction */ + Expr *pLeft = pExpr->pLeft; /* the LHS of the IN operator */ if( rMayHaveNull ){ sqlite3VdbeAddOp2(v, OP_Null, 0, rMayHaveNull); @@ -1625,6 +1625,7 @@ int sqlite3CodeSubselect( */ pExpr->iTable = pParse->nTab++; addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pExpr->iTable, !isRowid); + if( rMayHaveNull==0 ) sqlite3VdbeChangeP5(v, BTREE_UNORDERED); memset(&keyInfo, 0, sizeof(keyInfo)); keyInfo.nField = 1; diff --git a/src/main.c b/src/main.c index b233c8473d..a9c8d10793 100644 --- a/src/main.c +++ b/src/main.c @@ -1350,60 +1350,6 @@ int sqlite3TempInMemory(const sqlite3 *db){ #endif } -/* -** This routine is called to create a connection to a database BTree -** driver. If zFilename is the name of a file, then that file is -** opened and used. If zFilename is the magic name ":memory:" then -** the database is stored in memory (and is thus forgotten as soon as -** the connection is closed.) If zFilename is NULL then the database -** is a "virtual" database for transient use only and is deleted as -** soon as the connection is closed. -** -** A virtual database can be either a disk file (that is automatically -** deleted when the file is closed) or it an be held entirely in memory. -** The sqlite3TempInMemory() function is used to determine which. -*/ -int sqlite3BtreeFactory( - sqlite3 *db, /* Main database when opening aux otherwise 0 */ - const char *zFilename, /* Name of the file containing the BTree database */ - int omitJournal, /* if TRUE then do not journal this file */ - int nCache, /* How many pages in the page cache */ - int vfsFlags, /* Flags passed through to vfsOpen */ - Btree **ppBtree /* Pointer to new Btree object written here */ -){ - int btFlags = 0; - int rc; - - assert( sqlite3_mutex_held(db->mutex) ); - assert( ppBtree != 0); - if( omitJournal ){ - btFlags |= BTREE_OMIT_JOURNAL; - } - if( db->flags & SQLITE_NoReadlock ){ - btFlags |= BTREE_NO_READLOCK; - } -#ifndef SQLITE_OMIT_MEMORYDB - if( zFilename==0 && sqlite3TempInMemory(db) ){ - zFilename = ":memory:"; - } -#endif - - if( (vfsFlags & SQLITE_OPEN_MAIN_DB)!=0 && (zFilename==0 || *zFilename==0) ){ - vfsFlags = (vfsFlags & ~SQLITE_OPEN_MAIN_DB) | SQLITE_OPEN_TEMP_DB; - } - rc = sqlite3BtreeOpen(zFilename, (sqlite3 *)db, ppBtree, btFlags, vfsFlags); - - /* If the B-Tree was successfully opened, set the pager-cache size to the - ** default value. Except, if the call to BtreeOpen() returned a handle - ** open on an existing shared pager-cache, do not change the pager-cache - ** size. - */ - if( rc==SQLITE_OK && 0==sqlite3BtreeSchema(*ppBtree, 0, 0) ){ - sqlite3BtreeSetCacheSize(*ppBtree, nCache); - } - return rc; -} - /* ** Return UTF-8 encoded English language explanation of the most recent ** error. @@ -1785,9 +1731,8 @@ static int openDatabase( /* Open the backend database driver */ db->openFlags = flags; - rc = sqlite3BtreeFactory(db, zFilename, 0, SQLITE_DEFAULT_CACHE_SIZE, - flags | SQLITE_OPEN_MAIN_DB, - &db->aDb[0].pBt); + rc = sqlite3BtreeOpen(zFilename, db, &db->aDb[0].pBt, 0, + flags | SQLITE_OPEN_MAIN_DB); if( rc!=SQLITE_OK ){ if( rc==SQLITE_IOERR_NOMEM ){ rc = SQLITE_NOMEM; diff --git a/src/pager.c b/src/pager.c index f0b5b77544..d07f0b62d7 100644 --- a/src/pager.c +++ b/src/pager.c @@ -4226,6 +4226,13 @@ int sqlite3PagerOpen( /* Set the output variable to NULL in case an error occurs. */ *ppPager = 0; +#ifndef SQLITE_OMIT_MEMORYDB + if( flags & PAGER_MEMORY ){ + memDb = 1; + zFilename = 0; + } +#endif + /* Compute and store the full pathname in an allocated buffer pointed ** to by zPathname, length nPathname. Or, if this is a temporary file, ** leave both nPathname and zPathname set to 0. @@ -4236,17 +4243,8 @@ int sqlite3PagerOpen( if( zPathname==0 ){ return SQLITE_NOMEM; } -#ifndef SQLITE_OMIT_MEMORYDB - if( strcmp(zFilename,":memory:")==0 ){ - memDb = 1; - zPathname[0] = 0; - }else -#endif - { - zPathname[0] = 0; /* Make sure initialized even if FullPathname() fails */ - rc = sqlite3OsFullPathname(pVfs, zFilename, nPathname, zPathname); - } - + zPathname[0] = 0; /* Make sure initialized even if FullPathname() fails */ + rc = sqlite3OsFullPathname(pVfs, zFilename, nPathname, zPathname); nPathname = sqlite3Strlen30(zPathname); if( rc==SQLITE_OK && nPathname+8>pVfs->mxPathname ){ /* This branch is taken when the journal path required by diff --git a/src/pager.h b/src/pager.h index 0f100d5cd7..c12afa7b8b 100644 --- a/src/pager.h +++ b/src/pager.h @@ -59,6 +59,7 @@ typedef struct PgHdr DbPage; */ #define PAGER_OMIT_JOURNAL 0x0001 /* Do not use a rollback journal */ #define PAGER_NO_READLOCK 0x0002 /* Omit readlocks on readonly files */ +#define PAGER_MEMORY 0x0004 /* In-memory database */ /* ** Valid values for the second argument to sqlite3PagerLockingMode(). diff --git a/src/select.c b/src/select.c index 191c580abc..0f24c6838a 100644 --- a/src/select.c +++ b/src/select.c @@ -1506,6 +1506,7 @@ static int multiSelect( if( dest.eDest==SRT_EphemTab ){ assert( p->pEList ); sqlite3VdbeAddOp2(v, OP_OpenEphemeral, dest.iParm, p->pEList->nExpr); + sqlite3VdbeChangeP5(v, BTREE_UNORDERED); dest.eDest = SRT_Table; } @@ -3813,6 +3814,7 @@ int sqlite3Select( pKeyInfo = keyInfoFromExprList(pParse, p->pEList); sqlite3VdbeAddOp4(v, OP_OpenEphemeral, distinct, 0, 0, (char*)pKeyInfo, P4_KEYINFO_HANDOFF); + sqlite3VdbeChangeP5(v, BTREE_UNORDERED); }else{ distinct = -1; } diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 9aba3be830..fece2ba33f 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -2805,8 +2805,6 @@ void sqlite3DeferForeignKey(Parse*, int); #endif void sqlite3Attach(Parse*, Expr*, Expr*, Expr*); void sqlite3Detach(Parse*, Expr*); -int sqlite3BtreeFactory(sqlite3 *db, const char *zFilename, - int omitJournal, int nCache, int flags, Btree **ppBtree); int sqlite3FixInit(DbFixer*, Parse*, int, const char*, const Token*); int sqlite3FixSrcList(DbFixer*, SrcList*); int sqlite3FixSelect(DbFixer*, Select*); diff --git a/src/test3.c b/src/test3.c index 68f5648a4f..ef004ca713 100644 --- a/src/test3.c +++ b/src/test3.c @@ -53,7 +53,7 @@ static sqlite3 sDb; static int nRefSqlite3 = 0; /* -** Usage: btree_open FILENAME NCACHE FLAGS +** Usage: btree_open FILENAME NCACHE ** ** Open a new database */ @@ -64,22 +64,21 @@ static int btree_open( const char **argv /* Text of each argument */ ){ Btree *pBt; - int rc, nCache, flags; + int rc, nCache; char zBuf[100]; - if( argc!=4 ){ + if( argc!=3 ){ Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " FILENAME NCACHE FLAGS\"", 0); return TCL_ERROR; } if( Tcl_GetInt(interp, argv[2], &nCache) ) return TCL_ERROR; - if( Tcl_GetInt(interp, argv[3], &flags) ) return TCL_ERROR; nRefSqlite3++; if( nRefSqlite3==1 ){ sDb.pVfs = sqlite3_vfs_find(0); sDb.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_RECURSIVE); sqlite3_mutex_enter(sDb.mutex); } - rc = sqlite3BtreeOpen(argv[1], &sDb, &pBt, flags, + rc = sqlite3BtreeOpen(argv[1], &sDb, &pBt, 0, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_MAIN_DB); if( rc!=SQLITE_OK ){ Tcl_AppendResult(interp, errorName(rc), 0); diff --git a/src/update.c b/src/update.c index 44f047b488..8bf58d7666 100644 --- a/src/update.c +++ b/src/update.c @@ -638,6 +638,7 @@ static void updateVirtualTable( assert( v ); ephemTab = pParse->nTab++; sqlite3VdbeAddOp2(v, OP_OpenEphemeral, ephemTab, pTab->nCol+1+(pRowid!=0)); + sqlite3VdbeChangeP5(v, BTREE_UNORDERED); /* fill the ephemeral table */ diff --git a/src/vdbe.c b/src/vdbe.c index 38ff7fbcaf..7c5b41b50d 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -3013,6 +3013,7 @@ case OP_OpenWrite: { pCur = allocateCursor(p, pOp->p1, nField, iDb, 1); if( pCur==0 ) goto no_mem; pCur->nullRow = 1; + pCur->isOrdered = 1; rc = sqlite3BtreeCursor(pX, p2, wrFlag, pKeyInfo, pCur->pCursor); pCur->pKeyInfo = pKeyInfo; @@ -3063,7 +3064,7 @@ case OP_OpenWrite: { case OP_OpenAutoindex: case OP_OpenEphemeral: { VdbeCursor *pCx; - static const int openFlags = + static const int vfsFlags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_EXCLUSIVE | @@ -3074,21 +3075,21 @@ case OP_OpenEphemeral: { pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, 1); if( pCx==0 ) goto no_mem; pCx->nullRow = 1; - rc = sqlite3BtreeFactory(db, 0, 1, SQLITE_DEFAULT_TEMP_CACHE_SIZE, openFlags, - &pCx->pBt); + rc = sqlite3BtreeOpen(0, db, &pCx->pBt, + BTREE_OMIT_JOURNAL | BTREE_SINGLE | pOp->p5, vfsFlags); if( rc==SQLITE_OK ){ rc = sqlite3BtreeBeginTrans(pCx->pBt, 1); } if( rc==SQLITE_OK ){ /* If a transient index is required, create it by calling - ** sqlite3BtreeCreateTable() with the BTREE_ZERODATA flag before + ** sqlite3BtreeCreateTable() with the BTREE_BLOBKEY flag before ** opening it. If a transient table is required, just use the - ** automatically created table with root-page 1 (an INTKEY table). + ** automatically created table with root-page 1 (an BLOB_INTKEY table). */ if( pOp->p4.pKeyInfo ){ int pgno; assert( pOp->p4type==P4_KEYINFO ); - rc = sqlite3BtreeCreateTable(pCx->pBt, &pgno, BTREE_ZERODATA); + rc = sqlite3BtreeCreateTable(pCx->pBt, &pgno, BTREE_BLOBKEY); if( rc==SQLITE_OK ){ assert( pgno==MASTER_ROOT+1 ); rc = sqlite3BtreeCursor(pCx->pBt, pgno, 1, @@ -3102,6 +3103,7 @@ case OP_OpenEphemeral: { pCx->isTable = 1; } } + pCx->isOrdered = (pOp->p5!=BTREE_UNORDERED); pCx->isIndex = !pCx->isTable; break; } @@ -3217,6 +3219,7 @@ case OP_SeekGt: { /* jump, in3 */ assert( OP_SeekLe == OP_SeekLt+1 ); assert( OP_SeekGe == OP_SeekLt+2 ); assert( OP_SeekGt == OP_SeekLt+3 ); + assert( pC->isOrdered ); if( pC->pCursor!=0 ){ oc = pOp->opcode; pC->nullRow = 0; @@ -4386,6 +4389,7 @@ case OP_IdxGE: { /* jump */ assert( pOp->p1>=0 && pOp->p1nCursor ); pC = p->apCsr[pOp->p1]; assert( pC!=0 ); + assert( pC->isOrdered ); if( ALWAYS(pC->pCursor!=0) ){ assert( pC->deferredMoveto==0 ); assert( pOp->p5==0 || pOp->p5==1 ); @@ -4538,9 +4542,9 @@ case OP_CreateTable: { /* out2-prerelease */ assert( pDb->pBt!=0 ); if( pOp->opcode==OP_CreateTable ){ /* flags = BTREE_INTKEY; */ - flags = BTREE_LEAFDATA|BTREE_INTKEY; + flags = BTREE_INTKEY; }else{ - flags = BTREE_ZERODATA; + flags = BTREE_BLOBKEY; } rc = sqlite3BtreeCreateTable(pDb->pBt, &pgno, flags); pOut->u.i = pgno; diff --git a/src/vdbeInt.h b/src/vdbeInt.h index 4a19f14c2d..c6096e1654 100644 --- a/src/vdbeInt.h +++ b/src/vdbeInt.h @@ -57,6 +57,7 @@ struct VdbeCursor { Bool deferredMoveto; /* A call to sqlite3BtreeMoveto() is needed */ Bool isTable; /* True if a table requiring integer keys */ Bool isIndex; /* True if an index containing keys only - no data */ + Bool isOrdered; /* True if the underlying table is BTREE_UNORDERED */ i64 movetoTarget; /* Argument to the deferred sqlite3BtreeMoveto() */ Btree *pBt; /* Separate file holding temporary table */ int pseudoTableReg; /* Register holding pseudotable content. */ diff --git a/test/types.test b/test/types.test index a2dd632251..62a8efca82 100644 --- a/test/types.test +++ b/test/types.test @@ -135,7 +135,7 @@ execsql { # level. Return a list that is the length of each record # in the table, in the tables default scanning order. proc record_sizes {rootpage} { - set bt [btree_open test.db 10 0] + set bt [btree_open test.db 10] btree_begin_transaction $bt set c [btree_cursor $bt $rootpage 0] btree_first $c