From f328bc80cee5a819e56a135c3a60ea38079c805b Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 10 May 2004 23:29:49 +0000 Subject: [PATCH] Work toward getting the new btree.c integrated with vdbe.c. (CVS 1345) FossilOrigin-Name: bc5a2dafa1df74ba6403b4751ac1c33b0fee2884 --- manifest | 26 ++++++------ manifest.uuid | 2 +- src/btree.c | 24 +++++------ src/btree.h | 5 ++- src/main.c | 87 +++++++++++++++------------------------ src/sqliteInt.h | 8 ++-- src/vdbe.c | 105 ++++++++++++++++++++++------------------------- src/vdbeInt.h | 23 ++++++----- test/attach.test | 3 +- test/tester.tcl | 43 +------------------ 10 files changed, 128 insertions(+), 198 deletions(-) diff --git a/manifest b/manifest index c39854955f..313978e71f 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C The\sbtree.c\smodule\spasses\sall\stests\sand\sis\sready\sfor\sintegration.\nStill\sneed\sto\sgo\sback\sand\sdo\scoverage\stesting.\s(CVS\s1343) -D 2004-05-10T18:45:10 +C Work\stoward\sgetting\sthe\snew\sbtree.c\sintegrated\swith\svdbe.c.\s(CVS\s1345) +D 2004-05-10T23:29:49 F Makefile.in ab7b0d5118e2da97bac66be8684a1034e3500f5a F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906 F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd @@ -23,8 +23,8 @@ F sqlite.def fc4f5734786fe4743cfe2aa98eb2da4b089edb5f F sqlite.pc.in 30552343140c53304c2a658c080fbe810cd09ca2 F src/attach.c fa9a58234406d84eeb900517d0c0adc4b2da051a F src/auth.c 5c2f0bea4729c98c2be3b69d6b466fc51448fe79 -F src/btree.c 3904c06f69df10a29b49bb3f5c651eb4813980ac -F src/btree.h 7c3939a2e5f782c1ebac3bf43c02a16febad6df1 +F src/btree.c 38cff183ac4f1d1a2e3079c9eeda7137d103e06e +F src/btree.h 91343fe6893b8bc35f496bbcecec095a803e5763 F src/btree_rb.c 9d7973e266ee6f9c61ce592f68742ce9cd5b10e5 F src/build.c 8d9965b3ce5dcc1bd4dac60bd0f14524fea269cb F src/copy.c 4d2038602fd0549d80c59bda27d96f13ea9b5e29 @@ -36,7 +36,7 @@ F src/func.c 6cf6501f092b41c8cd9368b09c287016c0576438 F src/hash.c 440c2f8cb373ee1b4e13a0988489c7cd95d55b6f F src/hash.h 762d95f1e567664d1eafc1687de755626be962fb F src/insert.c 2d082257784a8613b1b50cd5bbf42b9466646a0e -F src/main.c 45f0dc84265d18b0e99500dced4975df8a041481 +F src/main.c 5f8fe4e06fbb79571f4d1a8055bcea2067e2243d F src/md5.c 8e39fdae6d8776b87558e91dcc94740c9b635a9c F src/os.c ddcda92f7fd71b4513c57c1ec797917f206d504e F src/os.h fbb2f6595fc34fa351830d88fe1c6b85118f0383 @@ -49,7 +49,7 @@ F src/random.c eff68e3f257e05e81eae6c4d50a51eb88beb4ff3 F src/select.c 9290439282fdc787fdf34d8600dec3a360275c92 F src/shell.c 255b8b9023cb5274f56d87df437e8ce6ef810b91 F src/sqlite.h.in 799c5e726296ec7bc20e6407cdf4df0e0bc00c0c -F src/sqliteInt.h 3151a1c14fc07f96169e904913d28c7ab173d8ca +F src/sqliteInt.h 16365a1a4cb28a9edcaada45d40d104112b3544c F src/table.c af14284fa36c8d41f6829e3f2819dce07d3e2de2 F src/tclsqlite.c a38bf2263a097fcc9603e818c291151de1782c11 F src/test1.c 79956f70dddd1a28f8577bbd61c8cf28e5875eb8 @@ -63,13 +63,13 @@ F src/update.c 6ca82fc4a0fb4d7f134e961921c906f6f3c8bc74 F src/utf.c fc799748d43fe1982d157b871e3e420a19c85d4f F src/util.c 74ee316594f68c41aed1884d737ab4085d479455 F src/vacuum.c c134702e023db8778e6be59ac0ea7b02315b5476 -F src/vdbe.c 5cd18c8a3ab826f02ef1ce88a5798ec744337b30 +F src/vdbe.c 24a2dbe73ad2f283e70fda6f2ce74ac146239005 F src/vdbe.h 2dc4d1161b64f5684faa6a2d292e318a185ecb2e -F src/vdbeInt.h 2567223b73d8807d61f8141d9f5e5f7f2975f50a +F src/vdbeInt.h d5786e1c4f7dadac24e3baeed9847dbfed3016de F src/vdbeaux.c 943484a2437b6cf40d1ffd3d62e48b5c9a043c5a F src/where.c 487e55b1f64c8fbf0f46a9a90c2247fc45ae6a9a F test/all.test 569a92a8ee88f5300c057cc4a8f50fbbc69a3242 -F test/attach.test ba8261d38da6b6a7d4f78ec543c548c4418582ef +F test/attach.test 76f096f384221f775cc0a856e51d5a35f9ee1541 F test/attach2.test ce61e6185b3cd891cc0e9a4c868fcc65eb92fc55 F test/auth.test 5c4d95cdaf539c0c236e20ce1f71a93e7dde9185 F test/bigfile.test ea904b853ce2d703b16c5ce90e2b54951bc1ae81 @@ -133,7 +133,7 @@ F test/table.test 371a1fc1c470982b2f68f9732f903a5d96f949c4 F test/tableapi.test e0c4cce61e58343caa84dab33fa6823cb35fe1e1 F test/tclsqlite.test a684fc191b81e6cded8a81263663d5a130fbb013 F test/temptable.test a770ba6308d7f7332fce985086b8e06bed6430c2 -F test/tester.tcl 64babe2528dec64125ddc8c1af763713710b59c3 +F test/tester.tcl 3780967a81e8d3e32caf167c9db3a66210ff69ff F test/thread1.test 53f050d5be6932d9430df7756edd379366508ff6 F test/threadtest1.c f7f896e62ed46feae1dc411114a48c15a0f82ee2 F test/threadtest2.c d94ca4114fd1504f7e0ae724bcd83d4b40931d86 @@ -188,7 +188,7 @@ F www/sqlite.tcl 3c83b08cf9f18aa2d69453ff441a36c40e431604 F www/tclsqlite.tcl b9271d44dcf147a93c98f8ecf28c927307abd6da F www/vdbe.tcl 9b9095d4495f37697fd1935d10e14c6015e80aa1 F www/whentouse.tcl a8335bce47cc2fddb07f19052cb0cb4d9129a8e4 -P 433ae0d327e5d5b0761e88418ed57fc4cbf4966b -R 2c4d2a423e133f1d66dbfff76eb51821 +P 84506b23365933383397e02a8ec5a980c57c80fc +R 00b64215240cbce0ff6f014e73120057 U drh -Z 4381466dc0ffb9f0d1943a642446ce5b +Z 014c7bdc3d67480b085cd3793f146069 diff --git a/manifest.uuid b/manifest.uuid index 8f5ddd7dbf..5d25ae3117 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -84506b23365933383397e02a8ec5a980c57c80fc \ No newline at end of file +bc5a2dafa1df74ba6403b4751ac1c33b0fee2884 \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index 9947e0e0d1..7daab2a7c5 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.123 2004/05/10 18:45:10 drh Exp $ +** $Id: btree.c,v 1.124 2004/05/10 23:29:49 drh Exp $ ** ** This file implements a external (disk-based) database using BTrees. ** For a detailed discussion of BTrees, refer to @@ -1894,6 +1894,7 @@ int sqlite3BtreeMoveto(BtCursor *pCur, const void *pKey, u64 nKey, int *pRes){ assert( pCur->pPage ); assert( pCur->pPage->isInit ); if( pCur->isValid==0 ){ + *pRes = -1; assert( pCur->pPage->nCell==0 ); return SQLITE_OK; } @@ -3160,7 +3161,7 @@ int sqlite3BtreeInsert( if( rc ) return rc; assert( szNew==cellSize(pPage, newCell) ); assert( szNew<=sizeof(newCell) ); - if( loc==0 ){ + if( loc==0 && pCur->isValid ){ int szOld; assert( pCur->idx>=0 && pCur->idxnCell ); oldCell = pPage->aCell[pCur->idx]; @@ -3425,6 +3426,15 @@ int sqlite3BtreeUpdateMeta(Btree *pBt, int idx, u32 iMeta){ return SQLITE_OK; } +/* +** Return the flag byte at the beginning of the page that the cursor +** is currently pointing to. +*/ +int sqlite3BtreeFlags(BtCursor *pCur){ + MemPage *pPage = pCur->pPage; + return pPage ? pPage->aData[pPage->hdrOffset] : 0; +} + /****************************************************************************** ** The complete implementation of the BTree subsystem is above this line. ** All the code the follows is for testing and troubleshooting the BTree @@ -3530,16 +3540,6 @@ int sqlite3BtreePageDump(Btree *pBt, int pgno, int recursive){ } #endif -#ifdef SQLITE_TEST -/* -** Return the flag byte at the beginning of the page that the cursor -** is currently pointing to. -*/ -int sqlite3BtreeFlags(BtCursor *pCur){ - return pCur->pPage->aData[pCur->pPage->hdrOffset]; -} -#endif - #ifdef SQLITE_TEST /* ** Fill aResult[] with information about the entry and page that the diff --git a/src/btree.h b/src/btree.h index c0904c0a05..625084fc36 100644 --- a/src/btree.h +++ b/src/btree.h @@ -13,7 +13,7 @@ ** subsystem. See comments in the source code for a detailed description ** of what each interface routine does. ** -** @(#) $Id: btree.h,v 1.43 2004/05/09 23:23:57 danielk1977 Exp $ +** @(#) $Id: btree.h,v 1.44 2004/05/10 23:29:50 drh Exp $ */ #ifndef _BTREE_H_ #define _BTREE_H_ @@ -81,6 +81,7 @@ int sqlite3BtreeFirst(BtCursor*, int *pRes); int sqlite3BtreeLast(BtCursor*, int *pRes); int sqlite3BtreeNext(BtCursor*, int *pRes); int sqlite3BtreeEof(BtCursor*); +int sqlite3BtreeFlags(BtCursor*); int sqlite3BtreePrevious(BtCursor*, int *pRes); int sqlite3BtreeKeySize(BtCursor*, u64 *pSize); int sqlite3BtreeKey(BtCursor*, u32 offset, u32 amt, void*); @@ -91,10 +92,10 @@ int sqlite3BtreeData(BtCursor*, u32 offset, u32 amt, void*); char *sqlite3BtreeIntegrityCheck(Btree*, int *aRoot, int nRoot); struct Pager *sqlite3BtreePager(Btree*); + #ifdef SQLITE_TEST int sqlite3BtreeCursorInfo(BtCursor*, int*); void sqlite3BtreeCursorList(Btree*); -int sqlite3BtreeFlags(BtCursor*); int sqlite3BtreePageDump(Btree*, int, int recursive); #endif diff --git a/src/main.c b/src/main.c index 7355428a1c..bcb9b13ebe 100644 --- a/src/main.c +++ b/src/main.c @@ -14,7 +14,7 @@ ** other files are for internal use by SQLite and should not be ** accessed by users of the library. ** -** $Id: main.c,v 1.168 2004/05/10 10:34:43 danielk1977 Exp $ +** $Id: main.c,v 1.169 2004/05/10 23:29:50 drh Exp $ */ #include "sqliteInt.h" #include "os.h" @@ -217,34 +217,11 @@ static int sqlite3InitOne(sqlite *db, int iDb, char **pzErrMsg){ ; /* The following SQL will read the schema from the master tables. - ** The first version works with SQLite file formats 2 or greater. - ** The second version is for format 1 files. - ** - ** Beginning with file format 2, the rowid for new table entries - ** (including entries in sqlite_master) is an increasing integer. - ** So for file format 2 and later, we can play back sqlite_master - ** and all the CREATE statements will appear in the right order. - ** But with file format 1, table entries were random and so we - ** have to make sure the CREATE TABLEs occur before their corresponding - ** CREATE INDEXs. (We don't have to deal with CREATE VIEW or - ** CREATE TRIGGER in file format 1 because those constructs did - ** not exist then.) */ static char init_script[] = -/****** FIX ME "SELECT type, name, rootpage, sql, 1 FROM sqlite_temp_master " "UNION ALL " -*/ "SELECT type, name, rootpage, sql, 0 FROM sqlite_master"; - static char older_init_script[] = - "SELECT type, name, rootpage, sql, 1 FROM sqlite_temp_master " - "UNION ALL " - "SELECT type, name, rootpage, sql, 0 FROM sqlite_master " - "WHERE type='table' " - "UNION ALL " - "SELECT type, name, rootpage, sql, 0 FROM sqlite_master " - "WHERE type='index'"; - assert( iDb>=0 && iDb!=1 && iDbnDb ); @@ -281,23 +258,25 @@ static int sqlite3InitOne(sqlite *db, int iDb, char **pzErrMsg){ */ if( db->aDb[iDb].pBt==0 ) return SQLITE_OK; rc = sqlite3BtreeCursor(db->aDb[iDb].pBt, MASTER_ROOT, 0, 0, 0, &curMain); - if( rc ){ + if( rc!=SQLITE_OK && rc!=SQLITE_EMPTY ){ sqlite3SetString(pzErrMsg, sqlite3_error_string(rc), (char*)0); return rc; } /* Get the database meta information */ - { - int ii; - for(ii=0; rc==SQLITE_OK && iiaDb[iDb].pBt, ii+1, &meta[ii]); + if( rc==SQLITE_OK ){ + int i; + for(i=0; rc==SQLITE_OK && iaDb[iDb].pBt, i+1, &meta[i]); } - } - if( rc ){ - sqlite3SetString(pzErrMsg, sqlite3_error_string(rc), (char*)0); - sqlite3BtreeCloseCursor(curMain); - return rc; + if( rc ){ + sqlite3SetString(pzErrMsg, sqlite3_error_string(rc), (char*)0); + sqlite3BtreeCloseCursor(curMain); + return rc; + } + }else{ + memset(meta, 0, sizeof(meta)); } db->aDb[iDb].schema_cookie = meta[1]; if( iDb==0 ){ @@ -313,22 +292,17 @@ static int sqlite3InitOne(sqlite *db, int iDb, char **pzErrMsg){ if( db->safety_level==0 ) db->safety_level = 2; /* - ** file_format==1 Version 2.1.0. - ** file_format==2 Version 2.2.0. Add support for INTEGER PRIMARY KEY. - ** file_format==3 Version 2.6.0. Fix empty-string index bug. - ** file_format==4 Version 2.7.0. Add support for separate numeric and - ** text datatypes. + ** file_format==1 Version 3.0.0. */ if( db->file_format==0 ){ /* This happens if the database was initially empty */ - db->file_format = 4; - }else if( db->file_format>4 ){ + db->file_format = 1; + }else if( db->file_format>1 ){ sqlite3BtreeCloseCursor(curMain); sqlite3SetString(pzErrMsg, "unsupported file format", (char*)0); return SQLITE_ERROR; } - }else if( db->file_format!=meta[2] || db->file_format<4 ){ - assert( db->file_format>=4 ); + }else if( db->file_format!=meta[2] ){ if( meta[2]==0 ){ sqlite3SetString(pzErrMsg, "cannot attach empty database: ", db->aDb[iDb].zName, (char*)0); @@ -347,20 +321,23 @@ static int sqlite3InitOne(sqlite *db, int iDb, char **pzErrMsg){ */ assert( db->init.busy ); sqlite3SafetyOff(db); - if( iDb==0 ){ - rc = sqlite3_exec(db, - db->file_format>=2 ? init_script : older_init_script, - sqlite3InitCallback, &initData, 0); + if( rc==SQLITE_EMPTY ){ + /* For an empty database, there is nothing to read */ + rc = SQLITE_OK; }else{ - char *zSql = 0; - sqlite3SetString(&zSql, - "SELECT type, name, rootpage, sql, ", zDbNum, " FROM \"", - db->aDb[iDb].zName, "\".sqlite_master", (char*)0); - rc = sqlite3_exec(db, zSql, sqlite3InitCallback, &initData, 0); - sqliteFree(zSql); + if( iDb==0 ){ + rc = sqlite3_exec(db, init_script, sqlite3InitCallback, &initData, 0); + }else{ + char *zSql = 0; + sqlite3SetString(&zSql, + "SELECT type, name, rootpage, sql, ", zDbNum, " FROM \"", + db->aDb[iDb].zName, "\".sqlite_master", (char*)0); + rc = sqlite3_exec(db, zSql, sqlite3InitCallback, &initData, 0); + sqliteFree(zSql); + } + sqlite3SafetyOn(db); + sqlite3BtreeCloseCursor(curMain); } - sqlite3SafetyOn(db); - sqlite3BtreeCloseCursor(curMain); if( sqlite3_malloc_failed ){ sqlite3SetString(pzErrMsg, "out of memory", (char*)0); rc = SQLITE_NOMEM; diff --git a/src/sqliteInt.h b/src/sqliteInt.h index a04fb2c980..117688743c 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -11,7 +11,7 @@ ************************************************************************* ** Internal interface definitions for SQLite. ** -** @(#) $Id: sqliteInt.h,v 1.228 2004/05/10 10:34:52 danielk1977 Exp $ +** @(#) $Id: sqliteInt.h,v 1.229 2004/05/10 23:29:50 drh Exp $ */ #include "config.h" #include "sqlite.h" @@ -120,6 +120,7 @@ # define INTPTR_TYPE long long # endif #endif +typedef INT64_TYPE i64; /* 8-byte signed integer */ typedef UINT64_TYPE u64; /* 8-byte unsigned integer */ typedef UINT32_TYPE u32; /* 4-byte unsigned integer */ typedef UINT16_TYPE u16; /* 2-byte unsigned integer */ @@ -367,8 +368,8 @@ struct sqlite { void *pCommitArg; /* Argument to xCommitCallback() */ int (*xCommitCallback)(void*);/* Invoked at every commit. */ Hash aFunc; /* All functions that can be in SQL exprs */ - int lastRowid; /* ROWID of most recent insert (see above) */ - int priorNewRowid; /* Last randomly generated ROWID */ + i64 lastRowid; /* ROWID of most recent insert (see above) */ + i64 priorNewRowid; /* Last randomly generated ROWID */ int magic; /* Magic number for detect library misuse */ int nChange; /* Number of rows changed (see above) */ int lsChange; /* Last statement change count (see above) */ @@ -1287,4 +1288,3 @@ void sqlite3utf16to16be(void *pData, int N); int sqlite3PutVarint(unsigned char *, u64); int sqlite3GetVarint(const unsigned char *, u64 *); int sqlite3VarintLen(u64 v); - diff --git a/src/vdbe.c b/src/vdbe.c index 4193a9bc21..a963205b76 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.273 2004/05/10 10:35:00 danielk1977 Exp $ +** $Id: vdbe.c,v 1.274 2004/05/10 23:29:50 drh Exp $ */ #include "sqliteInt.h" #include "os.h" @@ -2528,18 +2528,13 @@ case OP_Rollback: { ** executing this instruction. */ case OP_ReadCookie: { - int aMeta[SQLITE_N_BTREE_META]; + int iMeta; assert( pOp->p2p1>=0 && pOp->p1nDb ); assert( db->aDb[pOp->p1].pBt!=0 ); - { - int ii; - for(ii=0; rc==SQLITE_OK && iiaDb[pOp->p1].pBt, ii+1, &aMeta[ii]); - } - } + rc = sqlite3BtreeGetMeta(db->aDb[pOp->p1].pBt, pOp->p2+1, &iMeta); pTos++; - pTos->i = aMeta[1+pOp->p2]; + pTos->i = iMeta; pTos->flags = MEM_Int; break; } @@ -2555,27 +2550,12 @@ case OP_ReadCookie: { ** A transaction must be started before executing this opcode. */ case OP_SetCookie: { - int aMeta[SQLITE_N_BTREE_META]; assert( pOp->p2p1>=0 && pOp->p1nDb ); assert( db->aDb[pOp->p1].pBt!=0 ); assert( pTos>=p->aStack ); - Integerify(pTos) - { - int ii; - for(ii=0; rc==SQLITE_OK && iiaDb[pOp->p1].pBt, ii+1, &aMeta[ii]); - } - } - if( rc==SQLITE_OK ){ - aMeta[1+pOp->p2] = pTos->i; - { - int ii; - for(ii=0; rc==SQLITE_OK && iiaDb[pOp->p1].pBt, ii+1, aMeta[ii]); - } - } - } + Integerify(pTos); + rc = sqlite3BtreeUpdateMeta(db->aDb[pOp->p1].pBt, 1+pOp->p2, (int)pTos->i); Release(pTos); pTos--; break; @@ -2598,15 +2578,10 @@ case OP_SetCookie: { ** invoked. */ case OP_VerifyCookie: { - int aMeta[SQLITE_N_BTREE_META]; + int iMeta; assert( pOp->p1>=0 && pOp->p1nDb ); - { - int ii; - for(ii=0; rc==SQLITE_OK && iiaDb[pOp->p1].pBt, ii+1, &aMeta[ii]); - } - } - if( rc==SQLITE_OK && aMeta[1]!=pOp->p2 ){ + rc = sqlite3BtreeGetMeta(db->aDb[pOp->p1].pBt, 1, &iMeta); + if( rc==SQLITE_OK && iMeta!=pOp->p2 ){ sqlite3SetString(&p->zErrMsg, "database schema has changed", (char*)0); rc = SQLITE_SCHEMA; } @@ -2665,6 +2640,7 @@ case OP_OpenWrite: { int wrFlag; Btree *pX; int iDb; + Cursor *pCur; assert( pTos>=p->aStack ); Integerify(pTos); @@ -2687,12 +2663,13 @@ case OP_OpenWrite: { } assert( i>=0 ); if( expandCursorArraySize(p, i) ) goto no_mem; - sqlite3VdbeCleanupCursor(&p->aCsr[i]); - memset(&p->aCsr[i], 0, sizeof(Cursor)); - p->aCsr[i].nullRow = 1; + pCur = &p->aCsr[i]; + sqlite3VdbeCleanupCursor(pCur); + memset(pCur, 0, sizeof(Cursor)); + pCur->nullRow = 1; if( pX==0 ) break; do{ - rc = sqlite3BtreeCursor(pX, p2, wrFlag, 0, 0, &p->aCsr[i].pCursor); + rc = sqlite3BtreeCursor(pX, p2, wrFlag, 0, 0, &pCur->pCursor); switch( rc ){ case SQLITE_BUSY: { if( db->xBusyCallback==0 ){ @@ -2707,6 +2684,9 @@ case OP_OpenWrite: { break; } case SQLITE_OK: { + int flags = sqlite3BtreeFlags(pCur->pCursor); + pCur->intKey = (flags & BTREE_INTKEY)!=0; + pCur->zeroData = (flags & BTREE_ZERODATA)!=0; busy = 0; break; } @@ -2754,16 +2734,17 @@ case OP_OpenTemp: { /* If a transient index is required, create it by calling ** sqlite3BtreeCreateTable() with the BTREE_ZERODATA flag before ** opening it. If a transient table is required, just use the - ** automatically created table with root-page 2. + ** automatically created table with root-page 1. */ if( pOp->p2 ){ int pgno; rc = sqlite3BtreeCreateTable(pCx->pBt, &pgno, BTREE_ZERODATA); if( rc==SQLITE_OK ){ + assert( pgno==MASTER_ROOT+1 ); rc = sqlite3BtreeCursor(pCx->pBt, pgno, 1, 0, 0, &pCx->pCursor); } }else{ - rc = sqlite3BtreeCursor(pCx->pBt, 2, 1, 0, 0, &pCx->pCursor); + rc = sqlite3BtreeCursor(pCx->pBt, MASTER_ROOT, 1, 0, 0, &pCx->pCursor); } } break; @@ -2837,8 +2818,10 @@ case OP_MoveTo: { if( pC->pCursor!=0 ){ int res, oc; pC->nullRow = 0; - if( pTos->flags & MEM_Int ){ - int iKey = intToKey(pTos->i); + if( pC->intKey ){ + i64 iKey; + assert( pTos->flags & MEM_Int ); + iKey = intToKey(pTos->i); if( pOp->p2==0 && pOp->opcode==OP_MoveTo ){ pC->movetoTarget = iKey; pC->deferredMoveto = 1; @@ -2846,7 +2829,7 @@ case OP_MoveTo: { pTos--; break; } - sqlite3BtreeMoveto(pC->pCursor, (char*)&iKey, sizeof(int), &res); + sqlite3BtreeMoveto(pC->pCursor, 0, (u64)iKey, &res); pC->lastRecno = pTos->i; pC->recnoIsValid = res==0; }else{ @@ -2871,8 +2854,7 @@ case OP_MoveTo: { /* res might be negative because the table is empty. Check to ** see if this is the case. */ - int keysize; - /* TODO: res = sqlite3BtreeKeySize(pC->pCursor,&keysize)!=0 || * keysize==0; */ + res = sqlite3BtreeEof(pC->pCursor); } if( res && pOp->p2>0 ){ pc = pOp->p2 - 1; @@ -2927,6 +2909,7 @@ case OP_Found: { assert( i>=0 && inCursor ); if( (pC = &p->aCsr[i])->pCursor!=0 ){ int res, rx; + assert( pC->intKey==0 ); Stringify(pTos); rx = sqlite3BtreeMoveto(pC->pCursor, pTos->z, pTos->n, &res); alreadyExists = rx==SQLITE_OK && res==0; @@ -2967,6 +2950,7 @@ case OP_Found: { case OP_IsUnique: { int i = pOp->p1; Mem *pNos = &pTos[-1]; + Cursor *pCx; BtCursor *pCrsr; int R; @@ -2977,7 +2961,9 @@ case OP_IsUnique: { R = pTos->i; pTos--; assert( i>=0 && i<=p->nCursor ); - if( (pCrsr = p->aCsr[i].pCursor)!=0 ){ + pCx = &p->aCsr[i]; + pCrsr = pCx->pCursor; + if( pCrsr!=0 ){ int res, rc; int v; /* The record number on the P1 entry that matches K */ char *zKey; /* The value of K */ @@ -3080,11 +3066,11 @@ case OP_NotExists: { */ case OP_NewRecno: { int i = pOp->p1; - int v = 0; + i64 v = 0; Cursor *pC; assert( i>=0 && inCursor ); if( (pC = &p->aCsr[i])->pCursor==0 ){ - v = 0; + /* The zero initialization above is all that is needed */ }else{ /* The next rowid or record number (different terms for the same ** thing) is obtained in a two-step algorithm. @@ -3117,8 +3103,11 @@ case OP_NewRecno: { ** larger than the previous rowid. This has been shown experimentally ** to double the speed of the COPY operation. */ - int res, rx, cnt, x; + int res, rx, cnt; + i64 x; cnt = 0; + assert( (sqlite3BtreeFlags(pC->pCursor) & BTREE_INTKEY)!=0 ); + assert( (sqlite3BtreeFlags(pC->pCursor) & BTREE_ZERODATA)==0 ); if( !pC->useRandomRowid ){ if( pC->nextRowidValid ){ v = pC->nextRowid; @@ -3127,16 +3116,16 @@ case OP_NewRecno: { if( res ){ v = 1; }else{ - sqlite3BtreeKey(pC->pCursor, 0, sizeof(v), (void*)&v); + sqlite3BtreeKeySize(pC->pCursor, (u64*)&v); v = keyToInt(v); - if( v==0x7fffffff ){ + if( v==0x7fffffffffffffff ){ pC->useRandomRowid = 1; }else{ v++; } } } - if( v<0x7fffffff ){ + if( v<0x7fffffffffffffff ){ pC->nextRowidValid = 1; pC->nextRowid = v+1; }else{ @@ -3157,7 +3146,7 @@ case OP_NewRecno: { } if( v==0 ) continue; x = intToKey(v); - rx = sqlite3BtreeMoveto(pC->pCursor, &x, sizeof(int), &res); + rx = sqlite3BtreeMoveto(pC->pCursor, 0, (u64)x, &res); cnt++; }while( cnt<1000 && rx==SQLITE_OK && res==0 ); db->priorNewRowid = v; @@ -3517,7 +3506,7 @@ case OP_Column: { case OP_Recno: { int i = pOp->p1; Cursor *pC; - int v; + i64 v; assert( i>=0 && inCursor ); pC = &p->aCsr[i]; @@ -3532,7 +3521,7 @@ case OP_Recno: { break; }else{ assert( pC->pCursor!=0 ); - sqlite3BtreeKey(pC->pCursor, 0, sizeof(u32), (char*)&v); + sqlite3BtreeKeySize(pC->pCursor, (u64*)&v); v = keyToInt(v); } pTos->i = v; @@ -3965,14 +3954,16 @@ case OP_Clear: { case OP_CreateIndex: case OP_CreateTable: { int pgno; + int flags; assert( pOp->p3!=0 && pOp->p3type==P3_POINTER ); assert( pOp->p2>=0 && pOp->p2nDb ); assert( db->aDb[pOp->p2].pBt!=0 ); if( pOp->opcode==OP_CreateTable ){ - rc = sqlite3BtreeCreateTable(db->aDb[pOp->p2].pBt, &pgno, BTREE_INTKEY); + flags = BTREE_INTKEY; }else{ - rc = sqlite3BtreeCreateTable(db->aDb[pOp->p2].pBt, &pgno, BTREE_ZERODATA); + flags = BTREE_ZERODATA; } + rc = sqlite3BtreeCreateTable(db->aDb[pOp->p2].pBt, &pgno, flags); pTos++; if( rc==SQLITE_OK ){ pTos->i = pgno; diff --git a/src/vdbeInt.h b/src/vdbeInt.h index 9d254f8ccb..2e52ce9a8a 100644 --- a/src/vdbeInt.h +++ b/src/vdbeInt.h @@ -17,13 +17,12 @@ */ /* -** When converting from the native format to the key format and back -** again, in addition to changing the byte order we invert the high-order -** bit of the most significant byte. This causes negative numbers to -** sort before positive numbers in the memcmp() function. +** In the btree layer, a rowid is an unsigned 64-bit integer. In the +** schema layer, a rowid is a signed 64-bit integer. The following macros +** convert between the two in such a way as to preserve sort order. */ -#define keyToInt(X) (sqlite3VdbeByteSwap(X) ^ 0x80000000) -#define intToKey(X) (sqlite3VdbeByteSwap((X) ^ 0x80000000)) +#define keyToInt(X) (X ^ 0x8000000000000000) +#define intToKey(X) (X ^ 0x8000000000000000) /* ** The makefile scans this source file and creates the following @@ -62,8 +61,8 @@ typedef unsigned char Bool; */ struct Cursor { BtCursor *pCursor; /* The cursor structure of the backend */ - int lastRecno; /* Last recno from a Next or NextIdx operation */ - int nextRowid; /* Next rowid returned by OP_NewRowid */ + i64 lastRecno; /* Last recno from a Next or NextIdx operation */ + i64 nextRowid; /* Next rowid returned by OP_NewRowid */ Bool recnoIsValid; /* True if lastRecno is valid */ Bool keyAsData; /* The OP_Column command works on key instead of data */ Bool atFirst; /* True if pointing to first entry */ @@ -72,11 +71,13 @@ struct Cursor { Bool nextRowidValid; /* True if the nextRowid field is valid */ Bool pseudoTable; /* This is a NEW or OLD pseudo-tables of a trigger */ Bool deferredMoveto; /* A call to sqlite3BtreeMoveto() is needed */ - int movetoTarget; /* Argument to the deferred sqlite3BtreeMoveto() */ + Bool intKey; /* True if the table requires integer keys */ + Bool zeroData; /* True if table contains keys only - no data */ + i64 movetoTarget; /* Argument to the deferred sqlite3BtreeMoveto() */ Btree *pBt; /* Separate file holding temporary table */ int nData; /* Number of bytes in pData */ char *pData; /* Data for a NEW or OLD pseudo-table */ - int iKey; /* Key for the NEW or OLD pseudo-table row */ + i64 iKey; /* Key for the NEW or OLD pseudo-table row */ }; typedef struct Cursor Cursor; @@ -110,7 +111,7 @@ struct Sorter { ** is an instance of the following structure. */ struct Mem { - int i; /* Integer value */ + i64 i; /* Integer value */ int n; /* Number of characters in string value, including '\0' */ int flags; /* Some combination of MEM_Null, MEM_Str, MEM_Dyn, etc. */ double r; /* Real value */ diff --git a/test/attach.test b/test/attach.test index 7f1fe8b182..4595dc8d6e 100644 --- a/test/attach.test +++ b/test/attach.test @@ -12,7 +12,7 @@ # focus of this script is testing the ATTACH and DETACH commands # and related functionality. # -# $Id: attach.test,v 1.13 2004/02/14 01:39:50 drh Exp $ +# $Id: attach.test,v 1.14 2004/05/10 23:29:51 drh Exp $ # set testdir [file dirname $argv0] @@ -23,6 +23,7 @@ for {set i 2} {$i<=15} {incr i} { file delete -force test$i.db-journal } +set btree_trace 1 do_test attach-1.1 { execsql { CREATE TABLE t1(a,b); diff --git a/test/tester.tcl b/test/tester.tcl index db9005eb6e..0d1a0d73c2 100644 --- a/test/tester.tcl +++ b/test/tester.tcl @@ -11,9 +11,8 @@ # This file implements some common TCL routines used for regression # testing the SQLite library # -# $Id: tester.tcl,v 1.30 2004/05/07 17:57:50 drh Exp $ +# $Id: tester.tcl,v 1.31 2004/05/10 23:29:51 drh Exp $ -if 0 { # Make sure tclsqlite was compiled correctly. Abort now with an # error message if not. # @@ -63,8 +62,6 @@ sqlite db ./test.db if {[info exists ::SETUP_SQL]} { db eval $::SETUP_SQL } -} -proc db {args} {} # Abort early if this script has been run before. # @@ -116,44 +113,6 @@ proc do_test {name cmd expected} { } } -# Invoke this procedure on a test that is probabilistic -# and might fail sometimes. -# -proc do_probtest {name cmd expected} { - global argv nProb nTest skip_test - if {$skip_test} { - set skip_test 0 - return - } - if {[llength $argv]==0} { - set go 1 - } else { - set go 0 - foreach pattern $argv { - if {[string match $pattern $name]} { - set go 1 - break - } - } - } - if {!$go} return - incr nTest - puts -nonewline $name... - flush stdout - if {[catch {uplevel #0 "$cmd;\n"} result]} { - puts "\nError: $result" - incr nErr - } elseif {[string compare $result $expected]} { - puts "\nExpected: \[$expected\]\n Got: \[$result\]" - puts "NOTE: The results of the previous test depend on system load" - puts "and processor speed. The test may sometimes fail even if the" - puts "library is working correctly." - incr nProb - } else { - puts " Ok" - } -} - # The procedure uses the special "sqlite_malloc_stat" command # (which is only available if SQLite is compiled with -DMEMORY_DEBUG=1) # to see how many malloc()s have not been free()ed. The number