From 172114a02e9d201f35e97947c2e0cf80c081fa3f Mon Sep 17 00:00:00 2001 From: danielk1977 Date: Tue, 7 Jul 2009 15:47:12 +0000 Subject: [PATCH] Do not load the root-page of a b-tree table/index when opening a cursor. Instead, allow it to be loaded when the cursor is first used (in function moveToRoot()). Also move the root-page flags sanity checks that were a part of the OP_OpenRead/OpenWrite opcodes into the moveToRoot() function. (CVS 6856) FossilOrigin-Name: 06dcfe72a6ff3f63639eeb00ec5b5022d10fc55b --- manifest | 14 ++++++------- manifest.uuid | 2 +- src/btree.c | 23 ++++++++++++--------- src/vdbe.c | 56 +++++++++++++++------------------------------------ 4 files changed, 38 insertions(+), 57 deletions(-) diff --git a/manifest b/manifest index e2cccad031..3869340de4 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C If\san\serror\soccurs\sin\sPagerBegin(),\scall\spager_end_transaction()\sto\sreset\sthe\sinternal\sstate\sof\sthe\spager\sobject.\s(CVS\s6855) -D 2009-07-07T13:56:24 +C Do\snot\sload\sthe\sroot-page\sof\sa\sb-tree\stable/index\swhen\sopening\sa\scursor.\sInstead,\sallow\sit\sto\sbe\sloaded\swhen\sthe\scursor\sis\sfirst\sused\s(in\sfunction\smoveToRoot()).\sAlso\smove\sthe\sroot-page\sflags\ssanity\schecks\sthat\swere\sa\spart\sof\sthe\sOP_OpenRead/OpenWrite\sopcodes\sinto\sthe\smoveToRoot()\sfunction.\s(CVS\s6856) +D 2009-07-07T15:47:12 F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0 F Makefile.in df9359da7a726ccb67a45db905c5447d5c00c6ef F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654 @@ -106,7 +106,7 @@ F src/auth.c 802a9439dfa0b8c208b10055cba400e82ef18025 F src/backup.c 6f1c2d9862c8a3feb7739dfcca02c1f5352e37f3 F src/bitvec.c 0ef0651714728055d43de7a4cdd95e703fac0119 F src/btmutex.c 9b899c0d8df3bd68f527b0afe03088321b696d3c -F src/btree.c 8f4c2ebdc9f0e0139f5878fac8ac96b12528b014 +F src/btree.c 0cc9c503015fa4970b41833c1a253410ad055ce5 F src/btree.h e761619e76a1125d2d82bd3613b5a7ac7d1ee6f7 F src/btreeInt.h b31e5ac04181c7e2892c33ab06228c551df6233c F src/build.c 867028ee9f63f7bc8eb8d4a720bb98cf9b9a12b4 @@ -204,7 +204,7 @@ F src/update.c a1bbe774bce495d62dce3df3f42a5f04c1de173a F src/utf.c 9541d28f40441812c0b40f00334372a0542c00ff F src/util.c 861d5b5c58be4921f0a254489ea94cb15f550ef8 F src/vacuum.c 3fe0eebea6d2311c1c2ab2962887d11f7a4dcfb0 -F src/vdbe.c bdf25930bddbf57b18a0be7b1127b357306d2094 +F src/vdbe.c 4f702761ce1829192e191de461671e214a778386 F src/vdbe.h 35a648bc3279a120da24f34d9a25213ec15daf8a F src/vdbeInt.h 831c254a6eef237ef4664c8381a0137586567007 F src/vdbeapi.c 0ab8ada7260b32031ca97f338caecf0812460624 @@ -740,7 +740,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/vdbe-compress.tcl 672f81d693a03f80f5ae60bfefacd8a349e76746 -P ec1e27e33b89e809a03e4140b351f6c8674c0233 -R e28c07bc21fb6fc8bda63e0e4a6adcc7 +P ea7ed16628da29cf4a127a25cbac8ae553e2ac1f +R 6a1dd7b7ae30a801861a4c4d841bbfb1 U danielk1977 -Z 890ee77caf3f4dd632bdc59421b0f5cb +Z 0d744ad2ad4529f2f9b6cce7c155c49a diff --git a/manifest.uuid b/manifest.uuid index 89d5b03104..0340bba21b 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -ea7ed16628da29cf4a127a25cbac8ae553e2ac1f \ No newline at end of file +06dcfe72a6ff3f63639eeb00ec5b5022d10fc55b \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index 67753f363e..d1f581f796 100644 --- a/src/btree.c +++ b/src/btree.c @@ -9,7 +9,7 @@ ** May you share freely, never taking more than you give. ** ************************************************************************* -** $Id: btree.c,v 1.655 2009/07/07 11:39:59 drh Exp $ +** $Id: btree.c,v 1.656 2009/07/07 15:47:12 danielk1977 Exp $ ** ** This file implements a external (disk-based) database using BTrees. ** See the header comment on "btreeInt.h" for additional information. @@ -3238,15 +3238,10 @@ static int btreeCursor( return SQLITE_EMPTY; } - pCur->pgnoRoot = (Pgno)iTable; - rc = getAndInitPage(pBt, pCur->pgnoRoot, &pCur->apPage[0]); - if( rc!=SQLITE_OK ){ - assert( pCur->apPage[0]==0 ); - return rc; - } - /* Now that no other errors can occur, finish filling in the BtCursor ** variables and link the cursor into the BtShared list. */ + pCur->pgnoRoot = (Pgno)iTable; + pCur->iPage = -1; pCur->pKeyInfo = pKeyInfo; pCur->pBtree = p; pCur->pBt = pBt; @@ -3991,6 +3986,7 @@ static int moveToRoot(BtCursor *pCur){ for(i=1; i<=pCur->iPage; i++){ releasePage(pCur->apPage[i]); } + pCur->iPage = 0; }else{ if( SQLITE_OK!=(rc = getAndInitPage(pBt, pCur->pgnoRoot, &pCur->apPage[0])) @@ -3998,11 +3994,20 @@ static int moveToRoot(BtCursor *pCur){ pCur->eState = CURSOR_INVALID; return rc; } + pCur->iPage = 0; + + /* If pCur->pKeyInfo is not NULL, then the caller that opened this cursor + ** expected to open it on an index b-tree. Otherwise, if pKeyInfo is + ** NULL, the caller expects a table b-tree. If this is not the case, + ** return an SQLITE_CORRUPT error. */ + assert( pCur->apPage[0]->intKey==1 || pCur->apPage[0]->intKey==0 ); + if( (pCur->pKeyInfo==0)!=pCur->apPage[0]->intKey ){ + return SQLITE_CORRUPT_BKPT; + } } pRoot = pCur->apPage[0]; assert( pRoot->pgno==pCur->pgnoRoot ); - pCur->iPage = 0; pCur->aiIdx[0] = 0; pCur->info.nSize = 0; pCur->atLast = 0; diff --git a/src/vdbe.c b/src/vdbe.c index 6a95fca75a..9d380d1b44 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -43,7 +43,7 @@ ** in this file for details. If in doubt, do not deviate from existing ** commenting and indentation practices when changing or adding code. ** -** $Id: vdbe.c,v 1.869 2009/07/03 16:25:07 danielk1977 Exp $ +** $Id: vdbe.c,v 1.870 2009/07/07 15:47:12 danielk1977 Exp $ */ #include "sqliteInt.h" #include "vdbeInt.h" @@ -2913,7 +2913,6 @@ case OP_OpenWrite: { Btree *pX; VdbeCursor *pCur; Db *pDb; - int flags; nField = 0; pKeyInfo = 0; @@ -2961,45 +2960,22 @@ case OP_OpenWrite: { rc = sqlite3BtreeCursor(pX, p2, wrFlag, pKeyInfo, pCur->pCursor); pCur->pKeyInfo = pKeyInfo; - switch( rc ){ - case SQLITE_OK: { - flags = sqlite3BtreeFlags(pCur->pCursor); - - /* Sanity checking. Only the lower four bits of the flags byte should - ** be used. Bit 3 (mask 0x08) is unpredictable. The lower 3 bits - ** (mask 0x07) should be either 5 (intkey+leafdata for tables) or - ** 2 (zerodata for indices). If these conditions are not met it can - ** only mean that we are dealing with a corrupt database file. - ** Note: All of the above is checked already in sqlite3BtreeCursor(). - */ - assert( (flags & 0xf0)==0 ); - assert( (flags & 0x07)==5 || (flags & 0x07)==2 ); - - pCur->isTable = (flags & BTREE_INTKEY)!=0 ?1:0; - pCur->isIndex = (flags & BTREE_ZERODATA)!=0 ?1:0; - /* If P4==0 it means we are expected to open a table. If P4!=0 then - ** we expect to be opening an index. If this is not what happened, - ** then the database is corrupt - */ - if( (pCur->isTable && pOp->p4type==P4_KEYINFO) - || (pCur->isIndex && pOp->p4type!=P4_KEYINFO) ){ - rc = SQLITE_CORRUPT_BKPT; - goto abort_due_to_error; - } - break; - } - case SQLITE_EMPTY: { - pCur->isTable = pOp->p4type!=P4_KEYINFO; - pCur->isIndex = !pCur->isTable; - pCur->pCursor = 0; - rc = SQLITE_OK; - break; - } - default: { - assert( rc!=SQLITE_BUSY ); /* Busy conditions detected earlier */ - goto abort_due_to_error; - } + /* Since it performs no memory allocation or IO, the only values that + ** sqlite3BtreeCursor() may return are SQLITE_EMPTY and SQLITE_OK. + ** SQLITE_EMPTY is only returned when attempting to open the table + ** rooted at page 1 of a zero-byte database. */ + assert( rc==SQLITE_EMPTY || rc==SQLITE_OK ); + if( rc==SQLITE_EMPTY ){ + pCur->pCursor = 0; + rc = SQLITE_OK; } + + /* Set the VdbeCursor.isTable and isIndex variables. 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. */ + pCur->isTable = pOp->p4type!=P4_KEYINFO; + pCur->isIndex = !pCur->isTable; break; }