Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Work toward getting the new btree.c integrated with vdbe.c. (CVS 1345) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
bc5a2dafa1df74ba6403b4751ac1c33b |
User & Date: | drh 2004-05-10 23:29:49.000 |
Context
2004-05-11
| ||
00:28 | Change to OP_PutIntKey to use new btree API. (CVS 1346) (check-in: c080fed7b5 user: danielk1977 tags: trunk) | |
2004-05-10
| ||
23:29 | Work toward getting the new btree.c integrated with vdbe.c. (CVS 1345) (check-in: bc5a2dafa1 user: drh tags: trunk) | |
18:45 | The btree.c module passes all tests and is ready for integration. Still need to go back and do coverage testing. (CVS 1343) (check-in: 84506b2336 user: drh tags: trunk) | |
Changes
Changes to src/btree.c.
1 2 3 4 5 6 7 8 9 10 11 | /* ** 2004 April 6 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | /* ** 2004 April 6 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** $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 ** ** Donald E. Knuth, THE ART OF COMPUTER PROGRAMMING, Volume 3: ** "Sorting And Searching", pages 473-480. Addison-Wesley ** Publishing Company, Reading, Massachusetts. |
︙ | ︙ | |||
1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 | return pCur->status; } rc = moveToRoot(pCur); if( rc ) return rc; assert( pCur->pPage ); assert( pCur->pPage->isInit ); if( pCur->isValid==0 ){ assert( pCur->pPage->nCell==0 ); return SQLITE_OK; } for(;;){ int lwr, upr; Pgno chldPg; MemPage *pPage = pCur->pPage; | > | 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 | return pCur->status; } rc = moveToRoot(pCur); if( rc ) return rc; assert( pCur->pPage ); assert( pCur->pPage->isInit ); if( pCur->isValid==0 ){ *pRes = -1; assert( pCur->pPage->nCell==0 ); return SQLITE_OK; } for(;;){ int lwr, upr; Pgno chldPg; MemPage *pPage = pCur->pPage; |
︙ | ︙ | |||
3156 3157 3158 3159 3160 3161 3162 | assert( pPage->isInit ); rc = sqlite3pager_write(pPage->aData); if( rc ) return rc; rc = fillInCell(pPage, newCell, pKey, nKey, pData, nData, &szNew); if( rc ) return rc; assert( szNew==cellSize(pPage, newCell) ); assert( szNew<=sizeof(newCell) ); | | | 3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167 3168 3169 3170 3171 | assert( pPage->isInit ); rc = sqlite3pager_write(pPage->aData); if( rc ) return rc; rc = fillInCell(pPage, newCell, pKey, nKey, pData, nData, &szNew); if( rc ) return rc; assert( szNew==cellSize(pPage, newCell) ); assert( szNew<=sizeof(newCell) ); if( loc==0 && pCur->isValid ){ int szOld; assert( pCur->idx>=0 && pCur->idx<pPage->nCell ); oldCell = pPage->aCell[pCur->idx]; if( !pPage->leaf ){ memcpy(&newCell[2], &oldCell[2], 4); } szOld = cellSize(pPage, oldCell); |
︙ | ︙ | |||
3420 3421 3422 3423 3424 3425 3426 3427 3428 3429 3430 3431 3432 3433 | assert( pBt->pPage1!=0 ); pP1 = pBt->pPage1->aData; rc = sqlite3pager_write(pP1); if( rc ) return rc; put4byte(&pP1[36 + idx*4], iMeta); return SQLITE_OK; } /****************************************************************************** ** The complete implementation of the BTree subsystem is above this line. ** All the code the follows is for testing and troubleshooting the BTree ** subsystem. None of the code that follows is used during normal operation. ******************************************************************************/ | > > > > > > > > > | 3421 3422 3423 3424 3425 3426 3427 3428 3429 3430 3431 3432 3433 3434 3435 3436 3437 3438 3439 3440 3441 3442 3443 | assert( pBt->pPage1!=0 ); pP1 = pBt->pPage1->aData; rc = sqlite3pager_write(pP1); if( rc ) return rc; put4byte(&pP1[36 + idx*4], 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 ** subsystem. None of the code that follows is used during normal operation. ******************************************************************************/ |
︙ | ︙ | |||
3524 3525 3526 3527 3528 3529 3530 | } sqlite3BtreePageDump(pBt, get4byte(&data[hdr+6]), 1); } sqlite3pager_unref(data); fflush(stdout); return SQLITE_OK; } | < < < < < < < < < < | 3534 3535 3536 3537 3538 3539 3540 3541 3542 3543 3544 3545 3546 3547 | } sqlite3BtreePageDump(pBt, get4byte(&data[hdr+6]), 1); } sqlite3pager_unref(data); fflush(stdout); return SQLITE_OK; } #endif #ifdef SQLITE_TEST /* ** Fill aResult[] with information about the entry and page that the ** cursor is pointing to. ** |
︙ | ︙ |
Changes to src/btree.h.
︙ | ︙ | |||
9 10 11 12 13 14 15 | ** May you share freely, never taking more than you give. ** ************************************************************************* ** This header file defines the interface that the sqlite B-Tree file ** subsystem. See comments in the source code for a detailed description ** of what each interface routine does. ** | | | 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | ** May you share freely, never taking more than you give. ** ************************************************************************* ** This header file defines the interface that the sqlite B-Tree file ** subsystem. See comments in the source code for a detailed description ** of what each interface routine does. ** ** @(#) $Id: btree.h,v 1.44 2004/05/10 23:29:50 drh Exp $ */ #ifndef _BTREE_H_ #define _BTREE_H_ /* TODO: This definition is just included so other modules compile. It ** needs to be revisited. */ |
︙ | ︙ | |||
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 | int sqlite3BtreeDelete(BtCursor*); int sqlite3BtreeInsert(BtCursor*, const void *pKey, u64 nKey, const void *pData, int nData); int sqlite3BtreeFirst(BtCursor*, int *pRes); int sqlite3BtreeLast(BtCursor*, int *pRes); int sqlite3BtreeNext(BtCursor*, int *pRes); int sqlite3BtreeEof(BtCursor*); int sqlite3BtreePrevious(BtCursor*, int *pRes); int sqlite3BtreeKeySize(BtCursor*, u64 *pSize); int sqlite3BtreeKey(BtCursor*, u32 offset, u32 amt, void*); void *sqlite3BtreeKeyFetch(BtCursor*); int sqlite3BtreeDataSize(BtCursor*, u32 *pSize); 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*); | > > < | 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 | int sqlite3BtreeDelete(BtCursor*); int sqlite3BtreeInsert(BtCursor*, const void *pKey, u64 nKey, const void *pData, int nData); 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*); void *sqlite3BtreeKeyFetch(BtCursor*); int sqlite3BtreeDataSize(BtCursor*, u32 *pSize); 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 sqlite3BtreePageDump(Btree*, int, int recursive); #endif #endif /* _BTREE_H_ */ |
Changes to src/main.c.
︙ | ︙ | |||
10 11 12 13 14 15 16 | ** ************************************************************************* ** Main file for the SQLite library. The routines in this file ** implement the programmer interface to the library. Routines in ** other files are for internal use by SQLite and should not be ** accessed by users of the library. ** | | | 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | ** ************************************************************************* ** Main file for the SQLite library. The routines in this file ** implement the programmer interface to the library. Routines in ** other files are for internal use by SQLite and should not be ** accessed by users of the library. ** ** $Id: main.c,v 1.169 2004/05/10 23:29:50 drh Exp $ */ #include "sqliteInt.h" #include "os.h" #include <ctype.h> /* ** A pointer to this structure is used to communicate information |
︙ | ︙ | |||
213 214 215 216 217 218 219 | " tbl_name text,\n" " rootpage integer,\n" " sql text\n" ")" ; /* The following SQL will read the schema from the master tables. | < < < < < < < < < < < < < < < < < < < < < < < | 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 | " tbl_name text,\n" " rootpage integer,\n" " sql text\n" ")" ; /* The following SQL will read the schema from the master tables. */ static char init_script[] = "SELECT type, name, rootpage, sql, 1 FROM sqlite_temp_master " "UNION ALL " "SELECT type, name, rootpage, sql, 0 FROM sqlite_master"; assert( iDb>=0 && iDb!=1 && iDb<db->nDb ); /* Construct the schema tables: sqlite_master and sqlite_temp_master */ sqlite3SafetyOff(db); azArg[0] = "table"; |
︙ | ︙ | |||
277 278 279 280 281 282 283 | } sqlite3SafetyOn(db); /* Create a cursor to hold the database open */ if( db->aDb[iDb].pBt==0 ) return SQLITE_OK; rc = sqlite3BtreeCursor(db->aDb[iDb].pBt, MASTER_ROOT, 0, 0, 0, &curMain); | | < > | | | < | | | | > > > | < < < < | | | < > > > > | | < < | | | | | | | | | | > | 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 | } sqlite3SafetyOn(db); /* Create a cursor to hold the database open */ if( db->aDb[iDb].pBt==0 ) return SQLITE_OK; rc = sqlite3BtreeCursor(db->aDb[iDb].pBt, MASTER_ROOT, 0, 0, 0, &curMain); if( rc!=SQLITE_OK && rc!=SQLITE_EMPTY ){ sqlite3SetString(pzErrMsg, sqlite3_error_string(rc), (char*)0); return rc; } /* Get the database meta information */ if( rc==SQLITE_OK ){ int i; for(i=0; rc==SQLITE_OK && i<SQLITE_N_BTREE_META; i++){ rc = sqlite3BtreeGetMeta(db->aDb[iDb].pBt, i+1, &meta[i]); } 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 ){ db->next_cookie = meta[1]; db->file_format = meta[2]; size = meta[3]; if( size==0 ){ size = MAX_PAGES; } db->cache_size = size; db->safety_level = meta[4]; if( meta[6]>0 && meta[6]<=2 && db->temp_store==0 ){ db->temp_store = meta[6]; } if( db->safety_level==0 ) db->safety_level = 2; /* ** file_format==1 Version 3.0.0. */ if( db->file_format==0 ){ /* This happens if the database was initially empty */ 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] ){ if( meta[2]==0 ){ sqlite3SetString(pzErrMsg, "cannot attach empty database: ", db->aDb[iDb].zName, (char*)0); }else{ sqlite3SetString(pzErrMsg, "incompatible file format in auxiliary " "database: ", db->aDb[iDb].zName, (char*)0); } sqlite3BtreeClose(db->aDb[iDb].pBt); db->aDb[iDb].pBt = 0; return SQLITE_FORMAT; } sqlite3BtreeSetCacheSize(db->aDb[iDb].pBt, db->cache_size); sqlite3BtreeSetSafetyLevel(db->aDb[iDb].pBt, meta[4]==0 ? 2 : meta[4]); /* Read the schema information out of the schema tables */ assert( db->init.busy ); sqlite3SafetyOff(db); if( rc==SQLITE_EMPTY ){ /* For an empty database, there is nothing to read */ rc = SQLITE_OK; }else{ 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); } if( sqlite3_malloc_failed ){ sqlite3SetString(pzErrMsg, "out of memory", (char*)0); rc = SQLITE_NOMEM; sqlite3ResetInternalSchema(db, 0); } if( rc==SQLITE_OK ){ DbSetProperty(db, iDb, DB_SchemaLoaded); |
︙ | ︙ |
Changes to src/sqliteInt.h.
1 2 3 4 5 6 7 8 9 10 11 12 13 | /* ** 2001 September 15 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** Internal interface definitions for SQLite. ** | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | /* ** 2001 September 15 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** Internal interface definitions for SQLite. ** ** @(#) $Id: sqliteInt.h,v 1.229 2004/05/10 23:29:50 drh Exp $ */ #include "config.h" #include "sqlite.h" #include "hash.h" #include "parse.h" #include <stdio.h> #include <stdlib.h> |
︙ | ︙ | |||
116 117 118 119 120 121 122 123 124 125 126 127 128 129 | #ifndef INTPTR_TYPE # if SQLITE_PTR_SZ==4 # define INTPTR_TYPE int # else # define INTPTR_TYPE long long # endif #endif typedef UINT64_TYPE u64; /* 8-byte unsigned integer */ typedef UINT32_TYPE u32; /* 4-byte unsigned integer */ typedef UINT16_TYPE u16; /* 2-byte unsigned integer */ typedef UINT8_TYPE u8; /* 1-byte unsigned integer */ typedef UINT8_TYPE i8; /* 1-byte signed integer */ typedef INTPTR_TYPE ptr; /* Big enough to hold a pointer */ typedef unsigned INTPTR_TYPE uptr; /* Big enough to hold a pointer */ | > | 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 | #ifndef INTPTR_TYPE # if SQLITE_PTR_SZ==4 # define INTPTR_TYPE int # else # 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 */ typedef UINT8_TYPE u8; /* 1-byte unsigned integer */ typedef UINT8_TYPE i8; /* 1-byte signed integer */ typedef INTPTR_TYPE ptr; /* Big enough to hold a pointer */ typedef unsigned INTPTR_TYPE uptr; /* Big enough to hold a pointer */ |
︙ | ︙ | |||
363 364 365 366 367 368 369 | int cache_size; /* Number of pages to use in the cache */ int nTable; /* Number of tables in the database */ void *pBusyArg; /* 1st Argument to the busy callback */ int (*xBusyCallback)(void *,const char*,int); /* The busy callback */ void *pCommitArg; /* Argument to xCommitCallback() */ int (*xCommitCallback)(void*);/* Invoked at every commit. */ Hash aFunc; /* All functions that can be in SQL exprs */ | | | | 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 | int cache_size; /* Number of pages to use in the cache */ int nTable; /* Number of tables in the database */ void *pBusyArg; /* 1st Argument to the busy callback */ int (*xBusyCallback)(void *,const char*,int); /* The busy callback */ void *pCommitArg; /* Argument to xCommitCallback() */ int (*xCommitCallback)(void*);/* Invoked at every commit. */ Hash aFunc; /* All functions that can be in SQL exprs */ 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) */ int csChange; /* Current statement change count (see above) */ struct sqlite3InitInfo { /* Information used during initialization */ int iDb; /* When back is being initialized */ int newTnum; /* Rootpage of table being initialized */ |
︙ | ︙ | |||
1283 1284 1285 1286 1287 1288 1289 | void *sqlite3utf8to16be(const unsigned char *pIn, int N); void *sqlite3utf8to16le(const unsigned char *pIn, int N); void sqlite3utf16to16le(void *pData, int N); void sqlite3utf16to16be(void *pData, int N); int sqlite3PutVarint(unsigned char *, u64); int sqlite3GetVarint(const unsigned char *, u64 *); int sqlite3VarintLen(u64 v); | < | 1284 1285 1286 1287 1288 1289 1290 | void *sqlite3utf8to16be(const unsigned char *pIn, int N); void *sqlite3utf8to16le(const unsigned char *pIn, int N); void sqlite3utf16to16le(void *pData, int N); void sqlite3utf16to16be(void *pData, int N); int sqlite3PutVarint(unsigned char *, u64); int sqlite3GetVarint(const unsigned char *, u64 *); int sqlite3VarintLen(u64 v); |
Changes to src/vdbe.c.
︙ | ︙ | |||
39 40 41 42 43 44 45 | ** ** Various scripts scan this source file in order to generate HTML ** documentation, headers files, or other derived files. The formatting ** of the code in this file is, therefore, important. See other comments ** in this file for details. If in doubt, do not deviate from existing ** commenting and indentation practices when changing or adding code. ** | | | 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | ** ** Various scripts scan this source file in order to generate HTML ** documentation, headers files, or other derived files. The formatting ** of the code in this file is, therefore, important. See other comments ** 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.274 2004/05/10 23:29:50 drh Exp $ */ #include "sqliteInt.h" #include "os.h" #include <ctype.h> #include "vdbeInt.h" /* |
︙ | ︙ | |||
2524 2525 2526 2527 2528 2529 2530 | ** temporary tables. ** ** There must be a read-lock on the database (either a transaction ** must be started or there must be an open cursor) before ** executing this instruction. */ case OP_ReadCookie: { | | < < < | < < | < | < < < < < < < < < < < | < < < | 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 | ** temporary tables. ** ** There must be a read-lock on the database (either a transaction ** must be started or there must be an open cursor) before ** executing this instruction. */ case OP_ReadCookie: { int iMeta; assert( pOp->p2<SQLITE_N_BTREE_META ); assert( pOp->p1>=0 && pOp->p1<db->nDb ); assert( db->aDb[pOp->p1].pBt!=0 ); rc = sqlite3BtreeGetMeta(db->aDb[pOp->p1].pBt, pOp->p2+1, &iMeta); pTos++; pTos->i = iMeta; pTos->flags = MEM_Int; break; } /* Opcode: SetCookie P1 P2 * ** ** Write the top of the stack into cookie number P2 of database P1. ** P2==0 is the schema version. P2==1 is the database format. ** P2==2 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. */ case OP_SetCookie: { assert( pOp->p2<SQLITE_N_BTREE_META ); assert( pOp->p1>=0 && pOp->p1<db->nDb ); assert( db->aDb[pOp->p1].pBt!=0 ); assert( pTos>=p->aStack ); Integerify(pTos); rc = sqlite3BtreeUpdateMeta(db->aDb[pOp->p1].pBt, 1+pOp->p2, (int)pTos->i); Release(pTos); pTos--; break; } /* Opcode: VerifyCookie P1 P2 * ** |
︙ | ︙ | |||
2594 2595 2596 2597 2598 2599 2600 | ** and that the current process needs to reread the schema. ** ** Either a transaction needs to have been started or an OP_Open needs ** to be executed (to establish a read lock) before this opcode is ** invoked. */ case OP_VerifyCookie: { | | < < < | < < | | 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 | ** and that the current process needs to reread the schema. ** ** Either a transaction needs to have been started or an OP_Open needs ** to be executed (to establish a read lock) before this opcode is ** invoked. */ case OP_VerifyCookie: { int iMeta; assert( pOp->p1>=0 && pOp->p1<db->nDb ); 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; } break; } /* Opcode: OpenRead P1 P2 P3 |
︙ | ︙ | |||
2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 | case OP_OpenWrite: { int busy = 0; int i = pOp->p1; int p2 = pOp->p2; int wrFlag; Btree *pX; int iDb; assert( pTos>=p->aStack ); Integerify(pTos); iDb = pTos->i; pTos--; assert( iDb>=0 && iDb<db->nDb ); pX = db->aDb[iDb].pBt; | > | 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 | case OP_OpenWrite: { int busy = 0; int i = pOp->p1; int p2 = pOp->p2; int wrFlag; Btree *pX; int iDb; Cursor *pCur; assert( pTos>=p->aStack ); Integerify(pTos); iDb = pTos->i; pTos--; assert( iDb>=0 && iDb<db->nDb ); pX = db->aDb[iDb].pBt; |
︙ | ︙ | |||
2683 2684 2685 2686 2687 2688 2689 | sqlite3SetString(&p->zErrMsg, "root page number less than 2", (char*)0); rc = SQLITE_INTERNAL; break; } } assert( i>=0 ); if( expandCursorArraySize(p, i) ) goto no_mem; | > | | | | > > > | 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 | sqlite3SetString(&p->zErrMsg, "root page number less than 2", (char*)0); rc = SQLITE_INTERNAL; break; } } assert( i>=0 ); if( expandCursorArraySize(p, i) ) goto no_mem; 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, &pCur->pCursor); switch( rc ){ case SQLITE_BUSY: { if( db->xBusyCallback==0 ){ p->pc = pc; p->rc = SQLITE_BUSY; p->pTos = &pTos[1 + (pOp->p2<=0)]; /* Operands must remain on stack */ return SQLITE_BUSY; }else if( (*db->xBusyCallback)(db->pBusyArg, pOp->p3, ++busy)==0 ){ sqlite3SetString(&p->zErrMsg, sqlite3_error_string(rc), (char*)0); busy = 0; } break; } case SQLITE_OK: { int flags = sqlite3BtreeFlags(pCur->pCursor); pCur->intKey = (flags & BTREE_INTKEY)!=0; pCur->zeroData = (flags & BTREE_ZERODATA)!=0; busy = 0; break; } default: { goto abort_due_to_error; } } |
︙ | ︙ | |||
2750 2751 2752 2753 2754 2755 2756 | if( rc==SQLITE_OK ){ rc = sqlite3BtreeBeginTrans(pCx->pBt); } if( rc==SQLITE_OK ){ /* 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 | | > | | 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 | if( rc==SQLITE_OK ){ rc = sqlite3BtreeBeginTrans(pCx->pBt); } if( rc==SQLITE_OK ){ /* 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 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, MASTER_ROOT, 1, 0, 0, &pCx->pCursor); } } break; } /* Opcode: OpenPseudo P1 * * ** |
︙ | ︙ | |||
2833 2834 2835 2836 2837 2838 2839 | assert( pTos>=p->aStack ); assert( i>=0 && i<p->nCursor ); pC = &p->aCsr[i]; if( pC->pCursor!=0 ){ int res, oc; pC->nullRow = 0; | > > | | | | 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 | assert( pTos>=p->aStack ); assert( i>=0 && i<p->nCursor ); pC = &p->aCsr[i]; if( pC->pCursor!=0 ){ int res, oc; pC->nullRow = 0; 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; Release(pTos); pTos--; break; } sqlite3BtreeMoveto(pC->pCursor, 0, (u64)iKey, &res); pC->lastRecno = pTos->i; pC->recnoIsValid = res==0; }else{ Stringify(pTos); sqlite3BtreeMoveto(pC->pCursor, pTos->z, pTos->n, &res); pC->recnoIsValid = 0; } |
︙ | ︙ | |||
2867 2868 2869 2870 2871 2872 2873 | if( res>=0 ){ sqlite3BtreePrevious(pC->pCursor, &res); pC->recnoIsValid = 0; }else{ /* res might be negative because the table is empty. Check to ** see if this is the case. */ | < | | 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 | if( res>=0 ){ sqlite3BtreePrevious(pC->pCursor, &res); pC->recnoIsValid = 0; }else{ /* res might be negative because the table is empty. Check to ** see if this is the case. */ res = sqlite3BtreeEof(pC->pCursor); } if( res && pOp->p2>0 ){ pc = pOp->p2 - 1; } } } Release(pTos); |
︙ | ︙ | |||
2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 | int i = pOp->p1; int alreadyExists = 0; Cursor *pC; assert( pTos>=p->aStack ); assert( i>=0 && i<p->nCursor ); if( (pC = &p->aCsr[i])->pCursor!=0 ){ int res, rx; Stringify(pTos); rx = sqlite3BtreeMoveto(pC->pCursor, pTos->z, pTos->n, &res); alreadyExists = rx==SQLITE_OK && res==0; pC->deferredMoveto = 0; } if( pOp->opcode==OP_Found ){ if( alreadyExists ) pc = pOp->p2 - 1; | > | 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 | int i = pOp->p1; int alreadyExists = 0; Cursor *pC; assert( pTos>=p->aStack ); assert( i>=0 && i<p->nCursor ); 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; pC->deferredMoveto = 0; } if( pOp->opcode==OP_Found ){ if( alreadyExists ) pc = pOp->p2 - 1; |
︙ | ︙ | |||
2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 | ** falls through to the next instruction. ** ** See also: Distinct, NotFound, NotExists, Found */ case OP_IsUnique: { int i = pOp->p1; Mem *pNos = &pTos[-1]; BtCursor *pCrsr; int R; /* Pop the value R off the top of the stack */ assert( pNos>=p->aStack ); Integerify(pTos); R = pTos->i; pTos--; assert( i>=0 && i<=p->nCursor ); | > | > > | 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 | ** falls through to the next instruction. ** ** See also: Distinct, NotFound, NotExists, Found */ case OP_IsUnique: { int i = pOp->p1; Mem *pNos = &pTos[-1]; Cursor *pCx; BtCursor *pCrsr; int R; /* Pop the value R off the top of the stack */ assert( pNos>=p->aStack ); Integerify(pTos); R = pTos->i; pTos--; assert( i>=0 && i<=p->nCursor ); 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 */ int nKey; /* Number of bytes in K */ /* Make sure K is a string and make zKey point to K */ |
︙ | ︙ | |||
3076 3077 3078 3079 3080 3081 3082 | ** Get a new integer record number used as the key to a table. ** The record number is not previously used as a key in the database ** table that cursor P1 points to. The new record number is pushed ** onto the stack. */ case OP_NewRecno: { int i = pOp->p1; | | | | 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 | ** Get a new integer record number used as the key to a table. ** The record number is not previously used as a key in the database ** table that cursor P1 points to. The new record number is pushed ** onto the stack. */ case OP_NewRecno: { int i = pOp->p1; i64 v = 0; Cursor *pC; assert( i>=0 && i<p->nCursor ); if( (pC = &p->aCsr[i])->pCursor==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. ** ** First we attempt to find the largest existing rowid and add one ** to that. But if the largest existing rowid is already the maximum ** positive integer, we have to fall through to the second |
︙ | ︙ | |||
3113 3114 3115 3116 3117 3118 3119 | ** random number generator based on the RC4 algorithm. ** ** To promote locality of reference for repetitive inserts, the ** first few attempts at chosing a random rowid pick values just a little ** larger than the previous rowid. This has been shown experimentally ** to double the speed of the COPY operation. */ | | > > > | | | | | 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 | ** random number generator based on the RC4 algorithm. ** ** To promote locality of reference for repetitive inserts, the ** first few attempts at chosing a random rowid pick values just a little ** larger than the previous rowid. This has been shown experimentally ** to double the speed of the COPY operation. */ 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; }else{ rx = sqlite3BtreeLast(pC->pCursor, &res); if( res ){ v = 1; }else{ sqlite3BtreeKeySize(pC->pCursor, (u64*)&v); v = keyToInt(v); if( v==0x7fffffffffffffff ){ pC->useRandomRowid = 1; }else{ v++; } } } if( v<0x7fffffffffffffff ){ pC->nextRowidValid = 1; pC->nextRowid = v+1; }else{ pC->nextRowidValid = 0; } } if( pC->useRandomRowid ){ v = db->priorNewRowid; cnt = 0; do{ if( v==0 || cnt>2 ){ sqlite3Randomness(sizeof(v), &v); if( cnt<5 ) v &= 0xffffff; }else{ unsigned char r; sqlite3Randomness(1, &r); v += r + 1; } if( v==0 ) continue; x = intToKey(v); rx = sqlite3BtreeMoveto(pC->pCursor, 0, (u64)x, &res); cnt++; }while( cnt<1000 && rx==SQLITE_OK && res==0 ); db->priorNewRowid = v; if( rx==SQLITE_OK && res==0 ){ rc = SQLITE_FULL; goto abort_due_to_error; } |
︙ | ︙ | |||
3513 3514 3515 3516 3517 3518 3519 | ** the key to the current entry in a sequential scan of the database ** file P1. The sequential scan should have been started using the ** Next opcode. */ case OP_Recno: { int i = pOp->p1; Cursor *pC; | | | | 3502 3503 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513 3514 3515 3516 3517 3518 3519 3520 3521 3522 3523 3524 3525 3526 3527 3528 3529 3530 3531 | ** the key to the current entry in a sequential scan of the database ** file P1. The sequential scan should have been started using the ** Next opcode. */ case OP_Recno: { int i = pOp->p1; Cursor *pC; i64 v; assert( i>=0 && i<p->nCursor ); pC = &p->aCsr[i]; sqlite3VdbeCursorMoveto(pC); pTos++; if( pC->recnoIsValid ){ v = pC->lastRecno; }else if( pC->pseudoTable ){ v = keyToInt(pC->iKey); }else if( pC->nullRow || pC->pCursor==0 ){ pTos->flags = MEM_Null; break; }else{ assert( pC->pCursor!=0 ); sqlite3BtreeKeySize(pC->pCursor, (u64*)&v); v = keyToInt(v); } pTos->i = v; pTos->flags = MEM_Int; break; } |
︙ | ︙ | |||
3961 3962 3963 3964 3965 3966 3967 3968 3969 3970 3971 | ** root page of the new index onto the stack. ** ** See documentation on OP_CreateTable for additional information. */ case OP_CreateIndex: case OP_CreateTable: { int pgno; assert( pOp->p3!=0 && pOp->p3type==P3_POINTER ); assert( pOp->p2>=0 && pOp->p2<db->nDb ); assert( db->aDb[pOp->p2].pBt!=0 ); if( pOp->opcode==OP_CreateTable ){ | > | | > | 3950 3951 3952 3953 3954 3955 3956 3957 3958 3959 3960 3961 3962 3963 3964 3965 3966 3967 3968 3969 3970 3971 3972 3973 | ** root page of the new index onto the stack. ** ** See documentation on OP_CreateTable for additional information. */ case OP_CreateIndex: case OP_CreateTable: { int pgno; int flags; assert( pOp->p3!=0 && pOp->p3type==P3_POINTER ); assert( pOp->p2>=0 && pOp->p2<db->nDb ); assert( db->aDb[pOp->p2].pBt!=0 ); if( pOp->opcode==OP_CreateTable ){ flags = BTREE_INTKEY; }else{ flags = BTREE_ZERODATA; } rc = sqlite3BtreeCreateTable(db->aDb[pOp->p2].pBt, &pgno, flags); pTos++; if( rc==SQLITE_OK ){ pTos->i = pgno; pTos->flags = MEM_Int; *(u32*)pOp->p3 = pgno; pOp->p3 = 0; }else{ |
︙ | ︙ |
Changes to src/vdbeInt.h.
︙ | ︙ | |||
13 14 15 16 17 18 19 | ** VDBE. This information used to all be at the top of the single ** source code file "vdbe.c". When that file became too big (over ** 6000 lines long) it was split up into several smaller files and ** this header information was factored out. */ /* | | | | < | | | 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | ** VDBE. This information used to all be at the top of the single ** source code file "vdbe.c". When that file became too big (over ** 6000 lines long) it was split up into several smaller files and ** this header information was factored out. */ /* ** 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) (X ^ 0x8000000000000000) #define intToKey(X) (X ^ 0x8000000000000000) /* ** The makefile scans this source file and creates the following ** array of string constants which are the names of all VDBE opcodes. ** This array is defined in a separate source code file named opcode.c ** which is automatically generated by the makefile. */ |
︙ | ︙ | |||
58 59 60 61 62 63 64 | ** If the Cursor.isTriggerRow flag is set it means that this cursor is ** really a single row that represents the NEW or OLD pseudo-table of ** a row trigger. The data for the row is stored in Cursor.pData and ** the rowid is in Cursor.iKey. */ struct Cursor { BtCursor *pCursor; /* The cursor structure of the backend */ | | | > > | | | 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 | ** If the Cursor.isTriggerRow flag is set it means that this cursor is ** really a single row that represents the NEW or OLD pseudo-table of ** a row trigger. The data for the row is stored in Cursor.pData and ** the rowid is in Cursor.iKey. */ struct Cursor { BtCursor *pCursor; /* The cursor structure of the backend */ 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 */ Bool useRandomRowid; /* Generate new record numbers semi-randomly */ Bool nullRow; /* True if pointing to a row with no data */ 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 */ 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 */ i64 iKey; /* Key for the NEW or OLD pseudo-table row */ }; typedef struct Cursor Cursor; /* ** A sorter builds a list of elements to be sorted. Each element of ** the list is an instance of the following structure. */ |
︙ | ︙ | |||
106 107 108 109 110 111 112 | #define NBFS 32 /* ** A single level of the stack or a single memory cell ** is an instance of the following structure. */ struct Mem { | | | 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 | #define NBFS 32 /* ** A single level of the stack or a single memory cell ** is an instance of the following structure. */ struct Mem { 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 */ char *z; /* String or BLOB value */ char zShort[NBFS]; /* Space for short strings */ }; typedef struct Mem Mem; |
︙ | ︙ |
Changes to test/attach.test.
︙ | ︙ | |||
8 9 10 11 12 13 14 | # May you share freely, never taking more than you give. # #*********************************************************************** # This file implements regression tests for SQLite library. The # focus of this script is testing the ATTACH and DETACH commands # and related functionality. # | | > | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | # May you share freely, never taking more than you give. # #*********************************************************************** # This file implements regression tests for SQLite library. The # focus of this script is testing the ATTACH and DETACH commands # and related functionality. # # $Id: attach.test,v 1.14 2004/05/10 23:29:51 drh Exp $ # set testdir [file dirname $argv0] source $testdir/tester.tcl for {set i 2} {$i<=15} {incr i} { file delete -force test$i.db file delete -force test$i.db-journal } set btree_trace 1 do_test attach-1.1 { execsql { CREATE TABLE t1(a,b); INSERT INTO t1 VALUES(1,2); INSERT INTO t1 VALUES(3,4); SELECT * FROM t1; } |
︙ | ︙ |
Changes to test/tester.tcl.
1 2 3 4 5 6 7 8 9 10 11 12 13 | # 2001 September 15 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # This file implements some common TCL routines used for regression # testing the SQLite library # | | < | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | # 2001 September 15 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # This file implements some common TCL routines used for regression # testing the SQLite library # # $Id: tester.tcl,v 1.31 2004/05/10 23:29:51 drh Exp $ # Make sure tclsqlite was compiled correctly. Abort now with an # error message if not. # if {[sqlite -tcl-uses-utf]} { if {"\u1234"=="u1234"} { puts stderr "***** BUILD PROBLEM *****" puts stderr "$argv0 was linked against an older version" |
︙ | ︙ | |||
59 60 61 62 63 64 65 | catch {db close} file delete -force test.db file delete -force test.db-journal sqlite db ./test.db if {[info exists ::SETUP_SQL]} { db eval $::SETUP_SQL } | < < | 58 59 60 61 62 63 64 65 66 67 68 69 70 71 | catch {db close} file delete -force test.db file delete -force test.db-journal sqlite db ./test.db if {[info exists ::SETUP_SQL]} { db eval $::SETUP_SQL } # Abort early if this script has been run before. # if {[info exists nTest]} return # Set the test counters to zero # |
︙ | ︙ | |||
108 109 110 111 112 113 114 | if {$nErr>100} {puts "*** Giving up..."; finalize_testing} } elseif {[string compare $result $expected]} { puts "\nExpected: \[$expected\]\n Got: \[$result\]" incr nErr lappend ::failList $name if {$nErr>=1} {puts "*** Giving up..."; finalize_testing} } else { | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 105 106 107 108 109 110 111 112 113 114 115 116 117 118 | if {$nErr>100} {puts "*** Giving up..."; finalize_testing} } elseif {[string compare $result $expected]} { puts "\nExpected: \[$expected\]\n Got: \[$result\]" incr nErr lappend ::failList $name if {$nErr>=1} {puts "*** Giving up..."; finalize_testing} } 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 |
︙ | ︙ |