Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | A complete run of quick.test with mutex debugging enabled. (CVS 4266) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
783e07d561d1f5509de9475f3b9f3831 |
User & Date: | drh 2007-08-22 02:56:43.000 |
Context
2007-08-22
| ||
02:57 | Remove a debugging btree_breakpoint from vtab1.test. (CVS 4267) (check-in: 6cc8641ed2 user: drh tags: trunk) | |
02:56 | A complete run of quick.test with mutex debugging enabled. (CVS 4266) (check-in: 783e07d561 user: drh tags: trunk) | |
00:39 | Reenable the memory management logic. The quick.test script now runs with SQLITE_MEMDEBUG and SQLITE_ENABLE_MEMORY_MANAGEMENT. 7 minor errors. (CVS 4265) (check-in: 1914044b88 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.408 2007/08/22 02:56:43 drh Exp $ ** ** This file implements a external (disk-based) database using BTrees. ** See the header comment on "btreeInt.h" for additional information. ** Including a description of file format and an overview of operation. */ #include "btreeInt.h" |
︙ | ︙ | |||
92 93 94 95 96 97 98 | ** SQLITE_OK if the lock may be obtained (by calling lockTable()), or ** SQLITE_LOCKED if not. */ static int queryTableLock(Btree *p, Pgno iTab, u8 eLock){ BtShared *pBt = p->pBt; BtLock *pIter; | | | 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 | ** SQLITE_OK if the lock may be obtained (by calling lockTable()), or ** SQLITE_LOCKED if not. */ static int queryTableLock(Btree *p, Pgno iTab, u8 eLock){ BtShared *pBt = p->pBt; BtLock *pIter; assert( sqlite3BtreeMutexHeld(pBt->mutex) ); /* This is a no-op if the shared-cache is not enabled */ if( !p->sharable ){ return SQLITE_OK; } /* This (along with lockTable()) is where the ReadUncommitted flag is |
︙ | ︙ | |||
144 145 146 147 148 149 150 | ** SQLITE_NOMEM may also be returned. */ static int lockTable(Btree *p, Pgno iTable, u8 eLock){ BtShared *pBt = p->pBt; BtLock *pLock = 0; BtLock *pIter; | | | 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 | ** SQLITE_NOMEM may also be returned. */ static int lockTable(Btree *p, Pgno iTable, u8 eLock){ BtShared *pBt = p->pBt; BtLock *pLock = 0; BtLock *pIter; assert( sqlite3BtreeMutexHeld(pBt->mutex) ); /* This is a no-op if the shared-cache is not enabled */ if( !p->sharable ){ return SQLITE_OK; } assert( SQLITE_OK==queryTableLock(p, iTable, eLock) ); |
︙ | ︙ | |||
210 211 212 213 214 215 216 | /* ** Release all the table locks (locks obtained via calls to the lockTable() ** procedure) held by Btree handle p. */ static void unlockAllTables(Btree *p){ BtLock **ppIter = &p->pBt->pLock; | | | 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 | /* ** Release all the table locks (locks obtained via calls to the lockTable() ** procedure) held by Btree handle p. */ static void unlockAllTables(Btree *p){ BtLock **ppIter = &p->pBt->pLock; assert( sqlite3BtreeMutexHeld(p->pBt->mutex) ); assert( p->sharable || 0==*ppIter ); while( *ppIter ){ BtLock *pLock = *ppIter; if( pLock->pBtree==p ){ *ppIter = pLock->pNext; sqlite3_free(pLock); |
︙ | ︙ | |||
242 243 244 245 246 247 248 | /* ** Invalidate the overflow page-list cache for all cursors opened ** on the shared btree structure pBt. */ static void invalidateAllOverflowCache(BtShared *pBt){ BtCursor *p; | | | | 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 | /* ** Invalidate the overflow page-list cache for all cursors opened ** on the shared btree structure pBt. */ static void invalidateAllOverflowCache(BtShared *pBt){ BtCursor *p; assert( sqlite3BtreeMutexHeld(pBt->mutex) ); for(p=pBt->pCursor; p; p=p->pNext){ invalidateOverflowCache(p); } } #else #define invalidateOverflowCache(x) #define invalidateAllOverflowCache(x) #endif /* ** Save the current cursor position in the variables BtCursor.nKey ** and BtCursor.pKey. The cursor's state is set to CURSOR_REQUIRESEEK. */ static int saveCursorPosition(BtCursor *pCur){ int rc; assert( CURSOR_VALID==pCur->eState ); assert( 0==pCur->pKey ); assert( sqlite3BtreeMutexHeld(pCur->pBtree->pBt->mutex) ); rc = sqlite3BtreeKeySize(pCur, &pCur->nKey); /* If this is an intKey table, then the above call to BtreeKeySize() ** stores the integer key in pCur->nKey. In this case this value is ** all that is required. Otherwise, if pCur is not open on an intKey ** table, then malloc space for and store the pCur->nKey bytes of key |
︙ | ︙ | |||
303 304 305 306 307 308 309 | /* ** Save the positions of all cursors except pExcept open on the table ** with root-page iRoot. Usually, this is called just before cursor ** pExcept is used to modify the table (BtreeDelete() or BtreeInsert()). */ static int saveAllCursors(BtShared *pBt, Pgno iRoot, BtCursor *pExcept){ BtCursor *p; | | | | 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 | /* ** Save the positions of all cursors except pExcept open on the table ** with root-page iRoot. Usually, this is called just before cursor ** pExcept is used to modify the table (BtreeDelete() or BtreeInsert()). */ static int saveAllCursors(BtShared *pBt, Pgno iRoot, BtCursor *pExcept){ BtCursor *p; assert( sqlite3BtreeMutexHeld(pBt->mutex) ); for(p=pBt->pCursor; p; p=p->pNext){ if( p!=pExcept && (0==iRoot || p->pgnoRoot==iRoot) && p->eState==CURSOR_VALID ){ int rc = saveCursorPosition(p); if( SQLITE_OK!=rc ){ return rc; } } } return SQLITE_OK; } /* ** Clear the current cursor position. */ static void clearCursorPosition(BtCursor *pCur){ assert( sqlite3BtreeMutexHeld(pCur->pBtree->pBt->mutex) ); sqlite3_free(pCur->pKey); pCur->pKey = 0; pCur->eState = CURSOR_INVALID; } /* ** Restore the cursor to the position it was in (or as close to as possible) |
︙ | ︙ | |||
368 369 370 371 372 373 374 | /* ** Given a page number of a regular database page, return the page ** number for the pointer-map page that contains the entry for the ** input page number. */ static Pgno ptrmapPageno(BtShared *pBt, Pgno pgno){ int nPagesPerMapPage, iPtrMap, ret; | | | 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 | /* ** Given a page number of a regular database page, return the page ** number for the pointer-map page that contains the entry for the ** input page number. */ static Pgno ptrmapPageno(BtShared *pBt, Pgno pgno){ int nPagesPerMapPage, iPtrMap, ret; assert( sqlite3BtreeMutexHeld(pBt->mutex) ); nPagesPerMapPage = (pBt->usableSize/5)+1; iPtrMap = (pgno-2)/nPagesPerMapPage; ret = (iPtrMap*nPagesPerMapPage) + 2; if( ret==PENDING_BYTE_PAGE(pBt) ){ ret++; } return ret; |
︙ | ︙ | |||
392 393 394 395 396 397 398 | static int ptrmapPut(BtShared *pBt, Pgno key, u8 eType, Pgno parent){ DbPage *pDbPage; /* The pointer map page */ u8 *pPtrmap; /* The pointer map data */ Pgno iPtrmap; /* The pointer map page number */ int offset; /* Offset in pointer map page */ int rc; | | | 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 | static int ptrmapPut(BtShared *pBt, Pgno key, u8 eType, Pgno parent){ DbPage *pDbPage; /* The pointer map page */ u8 *pPtrmap; /* The pointer map data */ Pgno iPtrmap; /* The pointer map page number */ int offset; /* Offset in pointer map page */ int rc; assert( sqlite3BtreeMutexHeld(pBt->mutex) ); /* The master-journal page number must never be used as a pointer map page */ assert( 0==PTRMAP_ISPAGE(pBt, PENDING_BYTE_PAGE(pBt)) ); assert( pBt->autoVacuum ); if( key==0 ){ return SQLITE_CORRUPT_BKPT; } |
︙ | ︙ | |||
435 436 437 438 439 440 441 | static int ptrmapGet(BtShared *pBt, Pgno key, u8 *pEType, Pgno *pPgno){ DbPage *pDbPage; /* The pointer map page */ int iPtrmap; /* Pointer map page index */ u8 *pPtrmap; /* Pointer map page data */ int offset; /* Offset of entry in pointer map */ int rc; | | | 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 | static int ptrmapGet(BtShared *pBt, Pgno key, u8 *pEType, Pgno *pPgno){ DbPage *pDbPage; /* The pointer map page */ int iPtrmap; /* Pointer map page index */ u8 *pPtrmap; /* Pointer map page data */ int offset; /* Offset of entry in pointer map */ int rc; assert( sqlite3BtreeMutexHeld(pBt->mutex) ); iPtrmap = PTRMAP_PAGENO(pBt, key); rc = sqlite3PagerGet(pBt->pPager, iPtrmap, &pDbPage); if( rc!=0 ){ return rc; } pPtrmap = (u8 *)sqlite3PagerGetData(pDbPage); |
︙ | ︙ | |||
479 480 481 482 483 484 485 | /* ** This a more complex version of sqlite3BtreeFindCell() that works for ** pages that do contain overflow cells. See insert */ static u8 *findOverflowCell(MemPage *pPage, int iCell){ int i; | | | 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 | /* ** This a more complex version of sqlite3BtreeFindCell() that works for ** pages that do contain overflow cells. See insert */ static u8 *findOverflowCell(MemPage *pPage, int iCell){ int i; assert( sqlite3BtreeMutexHeld(pPage->pBt->mutex) ); for(i=pPage->nOverflow-1; i>=0; i--){ int k; struct _OvflCell *pOvfl; pOvfl = &pPage->aOvfl[i]; k = pOvfl->idx; if( k<=iCell ){ if( k==iCell ){ |
︙ | ︙ | |||
512 513 514 515 516 517 518 | MemPage *pPage, /* Page containing the cell */ u8 *pCell, /* Pointer to the cell text. */ CellInfo *pInfo /* Fill in this structure */ ){ int n; /* Number bytes in cell content header */ u32 nPayload; /* Number of bytes of cell payload */ | | | 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 | MemPage *pPage, /* Page containing the cell */ u8 *pCell, /* Pointer to the cell text. */ CellInfo *pInfo /* Fill in this structure */ ){ int n; /* Number bytes in cell content header */ u32 nPayload; /* Number of bytes of cell payload */ assert( sqlite3BtreeMutexHeld(pPage->pBt->mutex) ); pInfo->pCell = pCell; assert( pPage->leaf==0 || pPage->leaf==1 ); n = pPage->childPtrSize; assert( n==4-4*pPage->leaf ); if( pPage->hasData ){ n += getVarint32(&pCell[n], &nPayload); |
︙ | ︙ | |||
626 627 628 629 630 631 632 | /* ** If the cell with index iCell on page pPage contains a pointer ** to an overflow page, insert an entry into the pointer-map ** for the overflow page. */ static int ptrmapPutOvfl(MemPage *pPage, int iCell){ u8 *pCell; | | | 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 | /* ** If the cell with index iCell on page pPage contains a pointer ** to an overflow page, insert an entry into the pointer-map ** for the overflow page. */ static int ptrmapPutOvfl(MemPage *pPage, int iCell){ u8 *pCell; assert( sqlite3BtreeMutexHeld(pPage->pBt->mutex) ); pCell = findOverflowCell(pPage, iCell); return ptrmapPutOvflPtr(pPage, pCell); } #endif /* |
︙ | ︙ | |||
656 657 658 659 660 661 662 | unsigned char *data; /* The page data */ unsigned char *temp; /* Temp area for cell content */ assert( sqlite3PagerIswriteable(pPage->pDbPage) ); assert( pPage->pBt!=0 ); assert( pPage->pBt->usableSize <= SQLITE_MAX_PAGE_SIZE ); assert( pPage->nOverflow==0 ); | | | 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 | unsigned char *data; /* The page data */ unsigned char *temp; /* Temp area for cell content */ assert( sqlite3PagerIswriteable(pPage->pDbPage) ); assert( pPage->pBt!=0 ); assert( pPage->pBt->usableSize <= SQLITE_MAX_PAGE_SIZE ); assert( pPage->nOverflow==0 ); assert( sqlite3BtreeMutexHeld(pPage->pBt->mutex) ); temp = sqlite3_malloc( pPage->pBt->pageSize ); if( temp==0 ) return SQLITE_NOMEM; data = pPage->aData; hdr = pPage->hdrOffset; cellOffset = pPage->cellOffset; nCell = pPage->nCell; assert( nCell==get2byte(&data[hdr+3]) ); |
︙ | ︙ | |||
713 714 715 716 717 718 719 | int nCell; int cellOffset; unsigned char *data; data = pPage->aData; assert( sqlite3PagerIswriteable(pPage->pDbPage) ); assert( pPage->pBt ); | | | 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 | int nCell; int cellOffset; unsigned char *data; data = pPage->aData; assert( sqlite3PagerIswriteable(pPage->pDbPage) ); assert( pPage->pBt ); assert( sqlite3BtreeMutexHeld(pPage->pBt->mutex) ); if( nByte<4 ) nByte = 4; if( pPage->nFree<nByte || pPage->nOverflow>0 ) return 0; pPage->nFree -= nByte; hdr = pPage->hdrOffset; nFrag = data[hdr+7]; if( nFrag<60 ){ |
︙ | ︙ | |||
772 773 774 775 776 777 778 | int addr, pbegin, hdr; unsigned char *data = pPage->aData; assert( pPage->pBt!=0 ); assert( sqlite3PagerIswriteable(pPage->pDbPage) ); assert( start>=pPage->hdrOffset+6+(pPage->leaf?0:4) ); assert( (start + size)<=pPage->pBt->usableSize ); | | | 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 | int addr, pbegin, hdr; unsigned char *data = pPage->aData; assert( pPage->pBt!=0 ); assert( sqlite3PagerIswriteable(pPage->pDbPage) ); assert( start>=pPage->hdrOffset+6+(pPage->leaf?0:4) ); assert( (start + size)<=pPage->pBt->usableSize ); assert( sqlite3BtreeMutexHeld(pPage->pBt->mutex) ); if( size<4 ) size = 4; #ifdef SQLITE_SECURE_DELETE /* Overwrite deleted information with zeros when the SECURE_DELETE ** option is enabled at compile-time */ memset(&data[start], 0, size); #endif |
︙ | ︙ | |||
833 834 835 836 837 838 839 | ** Decode the flags byte (the first byte of the header) for a page ** and initialize fields of the MemPage structure accordingly. */ static void decodeFlags(MemPage *pPage, int flagByte){ BtShared *pBt; /* A copy of pPage->pBt */ assert( pPage->hdrOffset==(pPage->pgno==1 ? 100 : 0) ); | | | 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 | ** Decode the flags byte (the first byte of the header) for a page ** and initialize fields of the MemPage structure accordingly. */ static void decodeFlags(MemPage *pPage, int flagByte){ BtShared *pBt; /* A copy of pPage->pBt */ assert( pPage->hdrOffset==(pPage->pgno==1 ? 100 : 0) ); assert( sqlite3BtreeMutexHeld(pPage->pBt->mutex) ); pPage->intKey = (flagByte & (PTF_INTKEY|PTF_LEAFDATA))!=0; pPage->zeroData = (flagByte & PTF_ZERODATA)!=0; pPage->leaf = (flagByte & PTF_LEAF)!=0; pPage->childPtrSize = 4*(pPage->leaf==0); pBt = pPage->pBt; if( flagByte & PTF_LEAFDATA ){ pPage->leafData = 1; |
︙ | ︙ | |||
880 881 882 883 884 885 886 | int cellOffset; /* Offset from start of page to first cell pointer */ int nFree; /* Number of unused bytes on the page */ int top; /* First byte of the cell content area */ pBt = pPage->pBt; assert( pBt!=0 ); assert( pParent==0 || pParent->pBt==pBt ); | | | 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 | int cellOffset; /* Offset from start of page to first cell pointer */ int nFree; /* Number of unused bytes on the page */ int top; /* First byte of the cell content area */ pBt = pPage->pBt; assert( pBt!=0 ); assert( pParent==0 || pParent->pBt==pBt ); assert( sqlite3BtreeMutexHeld(pBt->mutex) ); assert( pPage->pgno==sqlite3PagerPagenumber(pPage->pDbPage) ); assert( pPage->aData == &((unsigned char*)pPage)[-pBt->pageSize] ); if( pPage->pParent!=pParent && (pPage->pParent!=0 || pPage->isInit) ){ /* The parent page should never change unless the file is corrupt */ return SQLITE_CORRUPT_BKPT; } if( pPage->isInit ) return SQLITE_OK; |
︙ | ︙ | |||
951 952 953 954 955 956 957 | BtShared *pBt = pPage->pBt; int hdr = pPage->hdrOffset; int first; assert( sqlite3PagerPagenumber(pPage->pDbPage)==pPage->pgno ); assert( &data[pBt->pageSize] == (unsigned char*)pPage ); assert( sqlite3PagerIswriteable(pPage->pDbPage) ); | | | 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 | BtShared *pBt = pPage->pBt; int hdr = pPage->hdrOffset; int first; assert( sqlite3PagerPagenumber(pPage->pDbPage)==pPage->pgno ); assert( &data[pBt->pageSize] == (unsigned char*)pPage ); assert( sqlite3PagerIswriteable(pPage->pDbPage) ); assert( sqlite3BtreeMutexHeld(pBt->mutex) ); memset(&data[hdr], 0, pBt->usableSize - hdr); data[hdr] = flags; first = hdr + 8 + 4*((flags&PTF_LEAF)==0); memset(&data[hdr+1], 0, 4); data[hdr+7] = 0; put2byte(&data[hdr+5], pBt->usableSize); pPage->nFree = pBt->usableSize - first; |
︙ | ︙ | |||
989 990 991 992 993 994 995 | MemPage **ppPage, /* Return the page in this parameter */ int noContent /* Do not load page content if true */ ){ int rc; MemPage *pPage; DbPage *pDbPage; | | | 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 | MemPage **ppPage, /* Return the page in this parameter */ int noContent /* Do not load page content if true */ ){ int rc; MemPage *pPage; DbPage *pDbPage; assert( sqlite3BtreeMutexHeld(pBt->mutex) ); rc = sqlite3PagerAcquire(pBt->pPager, pgno, (DbPage**)&pDbPage, noContent); if( rc ) return rc; pPage = (MemPage *)sqlite3PagerGetExtra(pDbPage); pPage->aData = sqlite3PagerGetData(pDbPage); pPage->pDbPage = pDbPage; pPage->pBt = pBt; pPage->pgno = pgno; |
︙ | ︙ | |||
1014 1015 1016 1017 1018 1019 1020 | static int getAndInitPage( BtShared *pBt, /* The database file */ Pgno pgno, /* Number of the page to get */ MemPage **ppPage, /* Write the page pointer here */ MemPage *pParent /* Parent of the page */ ){ int rc; | | | | | | 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 | static int getAndInitPage( BtShared *pBt, /* The database file */ Pgno pgno, /* Number of the page to get */ MemPage **ppPage, /* Write the page pointer here */ MemPage *pParent /* Parent of the page */ ){ int rc; assert( sqlite3BtreeMutexHeld(pBt->mutex) ); if( pgno==0 ){ return SQLITE_CORRUPT_BKPT; } rc = sqlite3BtreeGetPage(pBt, pgno, ppPage, 0); if( rc==SQLITE_OK && (*ppPage)->isInit==0 ){ rc = sqlite3BtreeInitPage(*ppPage, pParent); } return rc; } /* ** Release a MemPage. This should be called once for each prior ** call to sqlite3BtreeGetPage. */ static void releasePage(MemPage *pPage){ if( pPage ){ assert( pPage->aData ); assert( pPage->pBt ); assert( &pPage->aData[pPage->pBt->pageSize]==(unsigned char*)pPage ); assert( sqlite3BtreeMutexHeld(pPage->pBt->mutex) ); sqlite3PagerUnref(pPage->pDbPage); } } /* ** This routine is called when the reference count for a page ** reaches zero. We need to unref the pParent pointer when that ** happens. */ static void pageDestructor(DbPage *pData, int pageSize){ MemPage *pPage; assert( (pageSize & 7)==0 ); pPage = (MemPage *)sqlite3PagerGetExtra(pData); if( pPage->pParent ){ MemPage *pParent = pPage->pParent; assert( sqlite3BtreeMutexHeld(pPage->pBt->mutex) ); pPage->pParent = 0; releasePage(pParent); } pPage->isInit = 0; } /* ** During a rollback, when the pager reloads information into the cache ** so that the cache is restored to its original state at the start of ** the transaction, for each page restored this routine is called. ** ** This routine needs to reset the extra data section at the end of the ** page to agree with the restored data. */ static void pageReinit(DbPage *pData, int pageSize){ MemPage *pPage; assert( (pageSize & 7)==0 ); pPage = (MemPage *)sqlite3PagerGetExtra(pData); if( pPage->isInit ){ assert( sqlite3BtreeMutexHeld(pPage->pBt->mutex) ); pPage->isInit = 0; sqlite3BtreeInitPage(pPage, pPage->pParent); } } /* ** Open a database file. |
︙ | ︙ | |||
1103 1104 1105 1106 1107 1108 1109 | unsigned char zDbHeader[100]; if( pSqlite ){ pVfs = pSqlite->pVfs; }else{ pVfs = sqlite3_vfs_find(0); } | | | 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 | unsigned char zDbHeader[100]; if( pSqlite ){ pVfs = pSqlite->pVfs; }else{ pVfs = sqlite3_vfs_find(0); } assert( sqlite3BtreeMutexHeld(pSqlite->mutex) ); /* 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 ** into the library. */ #if !defined(SQLITE_OMIT_SHARED_CACHE) || !defined(SQLITE_OMIT_AUTOVACUUM) |
︙ | ︙ | |||
1416 1417 1418 1419 1420 1421 1422 | assert( p->sharable || (p->pNext==0 && p->pPrev==0) ); /* Check for locking consistency */ assert( !p->locked || p->wantToLock>0 ); assert( p->sharable || p->wantToLock==0 ); /* We should already hold a lock on the database connection */ | | | 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 | assert( p->sharable || (p->pNext==0 && p->pPrev==0) ); /* Check for locking consistency */ assert( !p->locked || p->wantToLock>0 ); assert( p->sharable || p->wantToLock==0 ); /* We should already hold a lock on the database connection */ assert( sqlite3BtreeMutexHeld(p->pSqlite->mutex) ); if( !p->sharable ) return; p->wantToLock++; if( p->locked ) return; /* In most cases, we should be able to acquire the lock we ** want without having to go throught the ascending lock |
︙ | ︙ | |||
1679 1680 1681 1682 1683 1684 1685 | ** SQLITE_BUSY is returned if the database is locked. SQLITE_NOMEM ** is returned if we run out of memory. */ static int lockBtree(BtShared *pBt){ int rc, pageSize; MemPage *pPage1; | | | 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 | ** SQLITE_BUSY is returned if the database is locked. SQLITE_NOMEM ** is returned if we run out of memory. */ static int lockBtree(BtShared *pBt){ int rc, pageSize; MemPage *pPage1; assert( sqlite3BtreeMutexHeld(pBt->mutex) ); if( pBt->pPage1 ) return SQLITE_OK; rc = sqlite3BtreeGetPage(pBt, 1, &pPage1, 0); if( rc!=SQLITE_OK ) return rc; /* Do some checking to help insure the file we opened really is ** a valid database file. |
︙ | ︙ | |||
1756 1757 1758 1759 1760 1761 1762 | /* ** This routine works like lockBtree() except that it also invokes the ** busy callback if there is lock contention. */ static int lockBtreeWithRetry(Btree *pRef){ int rc = SQLITE_OK; | | | | 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 | /* ** This routine works like lockBtree() except that it also invokes the ** busy callback if there is lock contention. */ static int lockBtreeWithRetry(Btree *pRef){ int rc = SQLITE_OK; assert( sqlite3BtreeMutexHeld(pRef->pSqlite->mutex) ); assert( sqlite3BtreeMutexHeld(pRef->pBt->mutex) ); if( pRef->inTrans==TRANS_NONE ){ u8 inTransaction = pRef->pBt->inTransaction; btreeIntegrity(pRef); rc = sqlite3BtreeBeginTrans(pRef, 0); pRef->pBt->inTransaction = inTransaction; pRef->inTrans = TRANS_NONE; if( rc==SQLITE_OK ){ |
︙ | ︙ | |||
1784 1785 1786 1787 1788 1789 1790 | ** has the effect of releasing the read lock. ** ** If there are any outstanding cursors, this routine is a no-op. ** ** If there is a transaction in progress, this routine is a no-op. */ static void unlockBtreeIfUnused(BtShared *pBt){ | | | 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 | ** has the effect of releasing the read lock. ** ** If there are any outstanding cursors, this routine is a no-op. ** ** If there is a transaction in progress, this routine is a no-op. */ static void unlockBtreeIfUnused(BtShared *pBt){ assert( sqlite3BtreeMutexHeld(pBt->mutex) ); if( pBt->inTransaction==TRANS_NONE && pBt->pCursor==0 && pBt->pPage1!=0 ){ if( sqlite3PagerRefcount(pBt->pPager)>=1 ){ if( pBt->pPage1->aData==0 ){ MemPage *pPage = pBt->pPage1; pPage->aData = &((u8*)pPage)[-pBt->pageSize]; pPage->pBt = pBt; pPage->pgno = 1; |
︙ | ︙ | |||
1809 1810 1811 1812 1813 1814 1815 | ** file. */ static int newDatabase(BtShared *pBt){ MemPage *pP1; unsigned char *data; int rc; | | | 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 | ** file. */ static int newDatabase(BtShared *pBt){ MemPage *pP1; unsigned char *data; int rc; assert( sqlite3BtreeMutexHeld(pBt->mutex) ); if( sqlite3PagerPagecount(pBt->pPager)>0 ) return SQLITE_OK; pP1 = pBt->pPage1; assert( pP1!=0 ); data = pP1->aData; rc = sqlite3PagerWrite(pP1->pDbPage); if( rc ) return rc; memcpy(data, zMagicHeader, sizeof(zMagicHeader)); |
︙ | ︙ | |||
1958 1959 1960 1961 1962 1963 1964 | int i; /* Counter variable */ int nCell; /* Number of cells in page pPage */ int rc; /* Return code */ BtShared *pBt = pPage->pBt; int isInitOrig = pPage->isInit; Pgno pgno = pPage->pgno; | | | 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 | int i; /* Counter variable */ int nCell; /* Number of cells in page pPage */ int rc; /* Return code */ BtShared *pBt = pPage->pBt; int isInitOrig = pPage->isInit; Pgno pgno = pPage->pgno; assert( sqlite3BtreeMutexHeld(pPage->pBt->mutex) ); rc = sqlite3BtreeInitPage(pPage, pPage->pParent); if( rc!=SQLITE_OK ){ goto set_child_ptrmaps_out; } nCell = pPage->nCell; for(i=0; i<nCell; i++){ |
︙ | ︙ | |||
2006 2007 2008 2009 2010 2011 2012 | ** PTRMAP_OVERFLOW1: pPage is a btree-page. The pointer points at an overflow ** page pointed to by one of the cells on pPage. ** ** PTRMAP_OVERFLOW2: pPage is an overflow-page. The pointer points at the next ** overflow page in the list. */ static int modifyPagePointer(MemPage *pPage, Pgno iFrom, Pgno iTo, u8 eType){ | | | 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 | ** PTRMAP_OVERFLOW1: pPage is a btree-page. The pointer points at an overflow ** page pointed to by one of the cells on pPage. ** ** PTRMAP_OVERFLOW2: pPage is an overflow-page. The pointer points at the next ** overflow page in the list. */ static int modifyPagePointer(MemPage *pPage, Pgno iFrom, Pgno iTo, u8 eType){ assert( sqlite3BtreeMutexHeld(pPage->pBt->mutex) ); if( eType==PTRMAP_OVERFLOW2 ){ /* The pointer is always the first 4 bytes of the page in this case. */ if( get4byte(pPage->aData)!=iFrom ){ return SQLITE_CORRUPT_BKPT; } put4byte(pPage->aData, iTo); }else{ |
︙ | ︙ | |||
2072 2073 2074 2075 2076 2077 2078 | MemPage *pPtrPage; /* The page that contains a pointer to pDbPage */ Pgno iDbPage = pDbPage->pgno; Pager *pPager = pBt->pPager; int rc; assert( eType==PTRMAP_OVERFLOW2 || eType==PTRMAP_OVERFLOW1 || eType==PTRMAP_BTREE || eType==PTRMAP_ROOTPAGE ); | | | 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 | MemPage *pPtrPage; /* The page that contains a pointer to pDbPage */ Pgno iDbPage = pDbPage->pgno; Pager *pPager = pBt->pPager; int rc; assert( eType==PTRMAP_OVERFLOW2 || eType==PTRMAP_OVERFLOW1 || eType==PTRMAP_BTREE || eType==PTRMAP_ROOTPAGE ); assert( sqlite3BtreeMutexHeld(pBt->mutex) ); /* Move page iDbPage from it's current location to page number iFreePage */ TRACE(("AUTOVACUUM: Moving %d to free page %d (ptr page %d type %d)\n", iDbPage, iFreePage, iPtrPage, eType)); rc = sqlite3PagerMovepage(pPager, pDbPage->pDbPage, iFreePage); if( rc!=SQLITE_OK ){ return rc; |
︙ | ︙ | |||
2151 2152 2153 2154 2155 2156 2157 | ** number of pages the database file will contain after this ** process is complete. */ static int incrVacuumStep(BtShared *pBt, Pgno nFin){ Pgno iLastPg; /* Last page in the database */ Pgno nFreeList; /* Number of pages still on the free-list */ | | | 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 | ** number of pages the database file will contain after this ** process is complete. */ static int incrVacuumStep(BtShared *pBt, Pgno nFin){ Pgno iLastPg; /* Last page in the database */ Pgno nFreeList; /* Number of pages still on the free-list */ assert( sqlite3BtreeMutexHeld(pBt->mutex) ); iLastPg = pBt->nTrunc; if( iLastPg==0 ){ iLastPg = sqlite3PagerPagecount(pBt->pPager); } if( !PTRMAP_ISPAGE(pBt, iLastPg) && iLastPg!=PENDING_BYTE_PAGE(pBt) ){ int rc; |
︙ | ︙ | |||
2277 2278 2279 2280 2281 2282 2283 | static int autoVacuumCommit(BtShared *pBt, Pgno *pnTrunc){ int rc = SQLITE_OK; Pager *pPager = pBt->pPager; #ifndef NDEBUG int nRef = sqlite3PagerRefcount(pPager); #endif | | | 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 | static int autoVacuumCommit(BtShared *pBt, Pgno *pnTrunc){ int rc = SQLITE_OK; Pager *pPager = pBt->pPager; #ifndef NDEBUG int nRef = sqlite3PagerRefcount(pPager); #endif assert( sqlite3BtreeMutexHeld(pBt->mutex) ); invalidateAllOverflowCache(pBt); assert(pBt->autoVacuum); if( !pBt->incrVacuum ){ Pgno nFin = 0; if( pBt->nTrunc==0 ){ Pgno nFree; |
︙ | ︙ | |||
2681 2682 2683 2684 2685 2686 2687 | void *pArg, /* First arg to xCompare() */ BtCursor **ppCur /* Write new cursor here */ ){ int rc; BtCursor *pCur; BtShared *pBt = p->pBt; | | | 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 | void *pArg, /* First arg to xCompare() */ BtCursor **ppCur /* Write new cursor here */ ){ int rc; BtCursor *pCur; BtShared *pBt = p->pBt; assert( sqlite3BtreeMutexHeld(pBt->mutex) ); *ppCur = 0; if( wrFlag ){ if( pBt->readOnly ){ return SQLITE_READONLY; } if( checkReadLocks(p, iTable, 0) ){ return SQLITE_LOCKED; |
︙ | ︙ | |||
2932 2933 2934 2935 2936 2937 2938 | Pgno ovfl, /* Overflow page */ MemPage **ppPage, /* OUT: MemPage handle */ Pgno *pPgnoNext /* OUT: Next overflow page number */ ){ Pgno next = 0; int rc; | | | 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 | Pgno ovfl, /* Overflow page */ MemPage **ppPage, /* OUT: MemPage handle */ Pgno *pPgnoNext /* OUT: Next overflow page number */ ){ Pgno next = 0; int rc; assert( sqlite3BtreeMutexHeld(pBt->mutex) ); /* One of these must not be NULL. Otherwise, why call this function? */ assert(ppPage || pPgnoNext); /* If pPgnoNext is NULL, then this function is being called to obtain ** a MemPage* reference only. No page-data is required in this case. */ if( !pPgnoNext ){ |
︙ | ︙ | |||
3072 3073 3074 3075 3076 3077 3078 | MemPage *pPage = pCur->pPage; /* Btree page of current cursor entry */ BtShared *pBt = pCur->pBtree->pBt; /* Btree this cursor belongs to */ assert( pPage ); assert( pCur->eState==CURSOR_VALID ); assert( pCur->idx>=0 && pCur->idx<pPage->nCell ); assert( offset>=0 ); | | | 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086 | MemPage *pPage = pCur->pPage; /* Btree page of current cursor entry */ BtShared *pBt = pCur->pBtree->pBt; /* Btree this cursor belongs to */ assert( pPage ); assert( pCur->eState==CURSOR_VALID ); assert( pCur->idx>=0 && pCur->idx<pPage->nCell ); assert( offset>=0 ); assert( sqlite3BtreeMutexHeld(pCur->pBtree->pBt->mutex) ); getCellInfo(pCur); aPayload = pCur->info.pCell + pCur->info.nHeader; nKey = (pPage->intKey ? 0 : pCur->info.nKey); if( skipKey ){ offset += nKey; |
︙ | ︙ | |||
3270 3271 3272 3273 3274 3275 3276 | unsigned char *aPayload; MemPage *pPage; u32 nKey; int nLocal; assert( pCur!=0 && pCur->pPage!=0 ); assert( pCur->eState==CURSOR_VALID ); | | | 3270 3271 3272 3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 | unsigned char *aPayload; MemPage *pPage; u32 nKey; int nLocal; assert( pCur!=0 && pCur->pPage!=0 ); assert( pCur->eState==CURSOR_VALID ); assert( sqlite3BtreeMutexHeld(pCur->pBtree->pBt->mutex) ); pPage = pCur->pPage; assert( pCur->idx>=0 && pCur->idx<pPage->nCell ); getCellInfo(pCur); aPayload = pCur->info.pCell; aPayload += pCur->info.nHeader; if( pPage->intKey ){ nKey = 0; |
︙ | ︙ | |||
3310 3311 3312 3313 3314 3315 3316 | ** Hence, a mutex on the BtShared should be held prior to calling ** this routine. ** ** These routines is used to get quick access to key and data ** in the common case where no overflow pages are used. */ const void *sqlite3BtreeKeyFetch(BtCursor *pCur, int *pAmt){ | | | | | 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 | ** Hence, a mutex on the BtShared should be held prior to calling ** this routine. ** ** These routines is used to get quick access to key and data ** in the common case where no overflow pages are used. */ const void *sqlite3BtreeKeyFetch(BtCursor *pCur, int *pAmt){ assert( sqlite3BtreeMutexHeld(pCur->pBtree->pBt->mutex) ); if( pCur->eState==CURSOR_VALID ){ return (const void*)fetchPayload(pCur, pAmt, 0); } return 0; } const void *sqlite3BtreeDataFetch(BtCursor *pCur, int *pAmt){ assert( sqlite3BtreeMutexHeld(pCur->pBtree->pBt->mutex) ); if( pCur->eState==CURSOR_VALID ){ return (const void*)fetchPayload(pCur, pAmt, 1); } return 0; } /* ** Move the cursor down to a new child page. The newPgno argument is the ** page number of the child page to move to. */ static int moveToChild(BtCursor *pCur, u32 newPgno){ int rc; MemPage *pNewPage; MemPage *pOldPage; BtShared *pBt = pCur->pBtree->pBt; assert( sqlite3BtreeMutexHeld(pBt->mutex) ); assert( pCur->eState==CURSOR_VALID ); rc = getAndInitPage(pBt, newPgno, &pNewPage, pCur->pPage); if( rc ) return rc; pNewPage->idxParent = pCur->idx; pOldPage = pCur->pPage; pOldPage->idxShift = 0; releasePage(pOldPage); |
︙ | ︙ | |||
3364 3365 3366 3367 3368 3369 3370 | ** is empty except for the right-pointer. In such cases the ** virtual root page is the page that the right-pointer of page ** 1 is pointing to. */ int sqlite3BtreeIsRootPage(MemPage *pPage){ MemPage *pParent; | | | 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 3376 3377 3378 | ** is empty except for the right-pointer. In such cases the ** virtual root page is the page that the right-pointer of page ** 1 is pointing to. */ int sqlite3BtreeIsRootPage(MemPage *pPage){ MemPage *pParent; assert( sqlite3BtreeMutexHeld(pPage->pBt->mutex) ); pParent = pPage->pParent; if( pParent==0 ) return 1; if( pParent->pgno>1 ) return 0; if( get2byte(&pParent->aData[pParent->hdrOffset+3])==0 ) return 1; return 0; } |
︙ | ︙ | |||
3411 3412 3413 3414 3415 3416 3417 | */ static int moveToRoot(BtCursor *pCur){ MemPage *pRoot; int rc = SQLITE_OK; Btree *p = pCur->pBtree; BtShared *pBt = p->pBt; | | | | 3411 3412 3413 3414 3415 3416 3417 3418 3419 3420 3421 3422 3423 3424 3425 3426 | */ static int moveToRoot(BtCursor *pCur){ MemPage *pRoot; int rc = SQLITE_OK; Btree *p = pCur->pBtree; BtShared *pBt = p->pBt; assert( sqlite3BtreeMutexHeld(p->pSqlite->mutex) ); assert( sqlite3BtreeMutexHeld(pBt->mutex) ); if( pCur->eState==CURSOR_REQUIRESEEK ){ clearCursorPosition(pCur); } pRoot = pCur->pPage; if( pRoot && pRoot->pgno==pCur->pgnoRoot ){ assert( pRoot->isInit ); }else{ |
︙ | ︙ | |||
3455 3456 3457 3458 3459 3460 3461 | ** in ascending order. */ static int moveToLeftmost(BtCursor *pCur){ Pgno pgno; int rc = SQLITE_OK; MemPage *pPage; | | | | 3455 3456 3457 3458 3459 3460 3461 3462 3463 3464 3465 3466 3467 3468 3469 3470 | ** in ascending order. */ static int moveToLeftmost(BtCursor *pCur){ Pgno pgno; int rc = SQLITE_OK; MemPage *pPage; assert( sqlite3BtreeMutexHeld(pCur->pBtree->pBt->mutex) ); assert( sqlite3BtreeMutexHeld(pCur->pBtree->pSqlite->mutex) ); assert( pCur->eState==CURSOR_VALID ); while( rc==SQLITE_OK && !(pPage = pCur->pPage)->leaf ){ assert( pCur->idx>=0 && pCur->idx<pPage->nCell ); pgno = get4byte(findCell(pPage, pCur->idx)); rc = moveToChild(pCur, pgno); } return rc; |
︙ | ︙ | |||
3481 3482 3483 3484 3485 3486 3487 | ** key in ascending order. */ static int moveToRightmost(BtCursor *pCur){ Pgno pgno; int rc = SQLITE_OK; MemPage *pPage; | | | | | | 3481 3482 3483 3484 3485 3486 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513 3514 3515 3516 3517 3518 | ** key in ascending order. */ static int moveToRightmost(BtCursor *pCur){ Pgno pgno; int rc = SQLITE_OK; MemPage *pPage; assert( sqlite3BtreeMutexHeld(pCur->pBtree->pBt->mutex) ); assert( sqlite3BtreeMutexHeld(pCur->pBtree->pSqlite->mutex) ); assert( pCur->eState==CURSOR_VALID ); while( rc==SQLITE_OK && !(pPage = pCur->pPage)->leaf ){ pgno = get4byte(&pPage->aData[pPage->hdrOffset+8]); pCur->idx = pPage->nCell; rc = moveToChild(pCur, pgno); } if( rc==SQLITE_OK ){ pCur->idx = pPage->nCell - 1; pCur->info.nSize = 0; } return SQLITE_OK; } /* Move the cursor to the first entry in the table. Return SQLITE_OK ** on success. Set *pRes to 0 if the cursor actually points to something ** or set *pRes to 1 if the table is empty. */ int sqlite3BtreeFirst(BtCursor *pCur, int *pRes){ int rc; assert( sqlite3BtreeMutexHeld(pCur->pBtree->pBt->mutex) ); assert( sqlite3BtreeMutexHeld(pCur->pBtree->pSqlite->mutex) ); rc = moveToRoot(pCur); if( rc==SQLITE_OK ){ if( pCur->eState==CURSOR_INVALID ){ assert( pCur->pPage->nCell==0 ); *pRes = 1; rc = SQLITE_OK; }else{ |
︙ | ︙ | |||
3527 3528 3529 3530 3531 3532 3533 | /* Move the cursor to the last entry in the table. Return SQLITE_OK ** on success. Set *pRes to 0 if the cursor actually points to something ** or set *pRes to 1 if the table is empty. */ int sqlite3BtreeLast(BtCursor *pCur, int *pRes){ int rc; | | | | 3527 3528 3529 3530 3531 3532 3533 3534 3535 3536 3537 3538 3539 3540 3541 3542 | /* Move the cursor to the last entry in the table. Return SQLITE_OK ** on success. Set *pRes to 0 if the cursor actually points to something ** or set *pRes to 1 if the table is empty. */ int sqlite3BtreeLast(BtCursor *pCur, int *pRes){ int rc; assert( sqlite3BtreeMutexHeld(pCur->pBtree->pBt->mutex) ); assert( sqlite3BtreeMutexHeld(pCur->pBtree->pSqlite->mutex) ); rc = moveToRoot(pCur); if( rc==SQLITE_OK ){ if( CURSOR_INVALID==pCur->eState ){ assert( pCur->pPage->nCell==0 ); *pRes = 1; }else{ assert( pCur->eState==CURSOR_VALID ); |
︙ | ︙ | |||
3580 3581 3582 3583 3584 3585 3586 | const void *pKey, /* The key content for indices. Not used by tables */ i64 nKey, /* Size of pKey. Or the key for tables */ int biasRight, /* If true, bias the search to the high end */ int *pRes /* Search result flag */ ){ int rc; | | | | 3580 3581 3582 3583 3584 3585 3586 3587 3588 3589 3590 3591 3592 3593 3594 3595 | const void *pKey, /* The key content for indices. Not used by tables */ i64 nKey, /* Size of pKey. Or the key for tables */ int biasRight, /* If true, bias the search to the high end */ int *pRes /* Search result flag */ ){ int rc; assert( sqlite3BtreeMutexHeld(pCur->pBtree->pBt->mutex) ); assert( sqlite3BtreeMutexHeld(pCur->pBtree->pSqlite->mutex) ); rc = moveToRoot(pCur); if( rc ){ return rc; } assert( pCur->pPage ); assert( pCur->pPage->isInit ); if( pCur->eState==CURSOR_INVALID ){ |
︙ | ︙ | |||
3885 3886 3887 3888 3889 3890 3891 | MemPage *pPage1; int rc; int n; /* Number of pages on the freelist */ int k; /* Number of leaves on the trunk of the freelist */ MemPage *pTrunk = 0; MemPage *pPrevTrunk = 0; | | | 3885 3886 3887 3888 3889 3890 3891 3892 3893 3894 3895 3896 3897 3898 3899 | MemPage *pPage1; int rc; int n; /* Number of pages on the freelist */ int k; /* Number of leaves on the trunk of the freelist */ MemPage *pTrunk = 0; MemPage *pPrevTrunk = 0; assert( sqlite3BtreeMutexHeld(pBt->mutex) ); pPage1 = pBt->pPage1; n = get4byte(&pPage1->aData[36]); if( n>0 ){ /* There are pages on the freelist. Reuse one of those pages. */ Pgno iTrunk; u8 searchList = 0; /* If the free-list must be searched for 'nearby' */ |
︙ | ︙ | |||
4118 4119 4120 4121 4122 4123 4124 | */ static int freePage(MemPage *pPage){ BtShared *pBt = pPage->pBt; MemPage *pPage1 = pBt->pPage1; int rc, n, k; /* Prepare the page for freeing */ | | | 4118 4119 4120 4121 4122 4123 4124 4125 4126 4127 4128 4129 4130 4131 4132 | */ static int freePage(MemPage *pPage){ BtShared *pBt = pPage->pBt; MemPage *pPage1 = pBt->pPage1; int rc, n, k; /* Prepare the page for freeing */ assert( sqlite3BtreeMutexHeld(pPage->pBt->mutex) ); assert( pPage->pgno>1 ); pPage->isInit = 0; releasePage(pPage->pParent); pPage->pParent = 0; /* Increment the free page count on pPage1 */ rc = sqlite3PagerWrite(pPage1->pDbPage); |
︙ | ︙ | |||
4201 4202 4203 4204 4205 4206 4207 | BtShared *pBt = pPage->pBt; CellInfo info; Pgno ovflPgno; int rc; int nOvfl; int ovflPageSize; | | | 4201 4202 4203 4204 4205 4206 4207 4208 4209 4210 4211 4212 4213 4214 4215 | BtShared *pBt = pPage->pBt; CellInfo info; Pgno ovflPgno; int rc; int nOvfl; int ovflPageSize; assert( sqlite3BtreeMutexHeld(pPage->pBt->mutex) ); sqlite3BtreeParseCellPtr(pPage, pCell, &info); if( info.iOverflow==0 ){ return SQLITE_OK; /* No overflow pages. Return without doing anything */ } ovflPgno = get4byte(&pCell[info.iOverflow]); ovflPageSize = pBt->usableSize - 4; nOvfl = (info.nPayload - info.nLocal + ovflPageSize - 1)/ovflPageSize; |
︙ | ︙ | |||
4258 4259 4260 4261 4262 4263 4264 | unsigned char *pPrior; unsigned char *pPayload; BtShared *pBt = pPage->pBt; Pgno pgnoOvfl = 0; int nHeader; CellInfo info; | | | 4258 4259 4260 4261 4262 4263 4264 4265 4266 4267 4268 4269 4270 4271 4272 | unsigned char *pPrior; unsigned char *pPayload; BtShared *pBt = pPage->pBt; Pgno pgnoOvfl = 0; int nHeader; CellInfo info; assert( sqlite3BtreeMutexHeld(pPage->pBt->mutex) ); /* Fill in the header. */ nHeader = 0; if( !pPage->leaf ){ nHeader += 4; } if( pPage->hasData ){ |
︙ | ︙ | |||
4372 4373 4374 4375 4376 4377 4378 | ** given in the second argument so that MemPage.pParent holds the ** pointer in the third argument. */ static int reparentPage(BtShared *pBt, Pgno pgno, MemPage *pNewParent, int idx){ MemPage *pThis; DbPage *pDbPage; | | | 4372 4373 4374 4375 4376 4377 4378 4379 4380 4381 4382 4383 4384 4385 4386 | ** given in the second argument so that MemPage.pParent holds the ** pointer in the third argument. */ static int reparentPage(BtShared *pBt, Pgno pgno, MemPage *pNewParent, int idx){ MemPage *pThis; DbPage *pDbPage; assert( sqlite3BtreeMutexHeld(pBt->mutex) ); assert( pNewParent!=0 ); if( pgno==0 ) return SQLITE_OK; assert( pBt->pPager!=0 ); pDbPage = sqlite3PagerLookup(pBt->pPager, pgno); if( pDbPage ){ pThis = (MemPage *)sqlite3PagerGetExtra(pDbPage); if( pThis->isInit ){ |
︙ | ︙ | |||
4416 4417 4418 4419 4420 4421 4422 | ** another. */ static int reparentChildPages(MemPage *pPage){ int i; BtShared *pBt = pPage->pBt; int rc = SQLITE_OK; | | | 4416 4417 4418 4419 4420 4421 4422 4423 4424 4425 4426 4427 4428 4429 4430 | ** another. */ static int reparentChildPages(MemPage *pPage){ int i; BtShared *pBt = pPage->pBt; int rc = SQLITE_OK; assert( sqlite3BtreeMutexHeld(pPage->pBt->mutex) ); if( pPage->leaf ) return SQLITE_OK; for(i=0; i<pPage->nCell; i++){ u8 *pCell = findCell(pPage, i); if( !pPage->leaf ){ rc = reparentPage(pBt, get4byte(pCell), pPage, i); if( rc!=SQLITE_OK ) return rc; |
︙ | ︙ | |||
4451 4452 4453 4454 4455 4456 4457 | int pc; /* Offset to cell content of cell being deleted */ u8 *data; /* pPage->aData */ u8 *ptr; /* Used to move bytes around within data[] */ assert( idx>=0 && idx<pPage->nCell ); assert( sz==cellSize(pPage, idx) ); assert( sqlite3PagerIswriteable(pPage->pDbPage) ); | | | 4451 4452 4453 4454 4455 4456 4457 4458 4459 4460 4461 4462 4463 4464 4465 | int pc; /* Offset to cell content of cell being deleted */ u8 *data; /* pPage->aData */ u8 *ptr; /* Used to move bytes around within data[] */ assert( idx>=0 && idx<pPage->nCell ); assert( sz==cellSize(pPage, idx) ); assert( sqlite3PagerIswriteable(pPage->pDbPage) ); assert( sqlite3BtreeMutexHeld(pPage->pBt->mutex) ); data = pPage->aData; ptr = &data[pPage->cellOffset + 2*idx]; pc = get2byte(ptr); assert( pc>10 && pc+sz<=pPage->pBt->usableSize ); freeSpace(pPage, pc, sz); for(i=idx+1; i<pPage->nCell; i++, ptr+=2){ ptr[0] = ptr[2]; |
︙ | ︙ | |||
4504 4505 4506 4507 4508 4509 4510 | int hdr; /* Offset into data[] of the page header */ int cellOffset; /* Address of first cell pointer in data[] */ u8 *data; /* The content of the whole page */ u8 *ptr; /* Used for moving information around in data[] */ assert( i>=0 && i<=pPage->nCell+pPage->nOverflow ); assert( sz==cellSizePtr(pPage, pCell) ); | | | 4504 4505 4506 4507 4508 4509 4510 4511 4512 4513 4514 4515 4516 4517 4518 | int hdr; /* Offset into data[] of the page header */ int cellOffset; /* Address of first cell pointer in data[] */ u8 *data; /* The content of the whole page */ u8 *ptr; /* Used for moving information around in data[] */ assert( i>=0 && i<=pPage->nCell+pPage->nOverflow ); assert( sz==cellSizePtr(pPage, pCell) ); assert( sqlite3BtreeMutexHeld(pPage->pBt->mutex) ); if( pPage->nOverflow || sz+2>pPage->nFree ){ if( pTemp ){ memcpy(pTemp+nSkip, pCell+nSkip, sz-nSkip); pCell = pTemp; } j = pPage->nOverflow++; assert( j<sizeof(pPage->aOvfl)/sizeof(pPage->aOvfl[0]) ); |
︙ | ︙ | |||
4584 4585 4586 4587 4588 4589 4590 | int totalSize; /* Total size of all cells */ int hdr; /* Index of page header */ int cellptr; /* Address of next cell pointer */ int cellbody; /* Address of next cell body */ u8 *data; /* Data for the page */ assert( pPage->nOverflow==0 ); | | | 4584 4585 4586 4587 4588 4589 4590 4591 4592 4593 4594 4595 4596 4597 4598 | int totalSize; /* Total size of all cells */ int hdr; /* Index of page header */ int cellptr; /* Address of next cell pointer */ int cellbody; /* Address of next cell body */ u8 *data; /* Data for the page */ assert( pPage->nOverflow==0 ); assert( sqlite3BtreeMutexHeld(pPage->pBt->mutex) ); totalSize = 0; for(i=0; i<nCell; i++){ totalSize += aSize[i]; } assert( totalSize+2*nCell<=pPage->nFree ); assert( pPage->nCell==0 ); cellptr = pPage->cellOffset; |
︙ | ︙ | |||
4659 4660 4661 4662 4663 4664 4665 | int szCell; CellInfo info; BtShared *pBt = pPage->pBt; int parentIdx = pParent->nCell; /* pParent new divider cell index */ int parentSize; /* Size of new divider cell */ u8 parentCell[64]; /* Space for the new divider cell */ | | | 4659 4660 4661 4662 4663 4664 4665 4666 4667 4668 4669 4670 4671 4672 4673 | int szCell; CellInfo info; BtShared *pBt = pPage->pBt; int parentIdx = pParent->nCell; /* pParent new divider cell index */ int parentSize; /* Size of new divider cell */ u8 parentCell[64]; /* Space for the new divider cell */ assert( sqlite3BtreeMutexHeld(pPage->pBt->mutex) ); /* Allocate a new page. Insert the overflow cell from pPage ** into it. Then remove the overflow cell from pPage. */ rc = allocateBtreePage(pBt, &pNew, &pgnoNew, 0, 0); if( rc!=SQLITE_OK ){ return rc; |
︙ | ︙ | |||
4785 4786 4787 4788 4789 4790 4791 | int *szCell; /* Local size of all cells in apCell[] */ u8 *aCopy[NB]; /* Space for holding data of apCopy[] */ u8 *aSpace; /* Space to hold copies of dividers cells */ #ifndef SQLITE_OMIT_AUTOVACUUM u8 *aFrom = 0; #endif | | | 4785 4786 4787 4788 4789 4790 4791 4792 4793 4794 4795 4796 4797 4798 4799 | int *szCell; /* Local size of all cells in apCell[] */ u8 *aCopy[NB]; /* Space for holding data of apCopy[] */ u8 *aSpace; /* Space to hold copies of dividers cells */ #ifndef SQLITE_OMIT_AUTOVACUUM u8 *aFrom = 0; #endif assert( sqlite3BtreeMutexHeld(pPage->pBt->mutex) ); /* ** Find the parent page. */ assert( pPage->isInit ); assert( sqlite3PagerIswriteable(pPage->pDbPage) || pPage->nOverflow==1 ); pBt = pPage->pBt; |
︙ | ︙ | |||
5338 5339 5340 5341 5342 5343 5344 | BtShared *pBt; /* The main BTree structure */ int mxCellPerPage; /* Maximum number of cells per page */ u8 **apCell; /* All cells from pages being balanced */ int *szCell; /* Local size of all cells */ assert( pPage->pParent==0 ); assert( pPage->nCell==0 ); | | | 5338 5339 5340 5341 5342 5343 5344 5345 5346 5347 5348 5349 5350 5351 5352 | BtShared *pBt; /* The main BTree structure */ int mxCellPerPage; /* Maximum number of cells per page */ u8 **apCell; /* All cells from pages being balanced */ int *szCell; /* Local size of all cells */ assert( pPage->pParent==0 ); assert( pPage->nCell==0 ); assert( sqlite3BtreeMutexHeld(pPage->pBt->mutex) ); pBt = pPage->pBt; mxCellPerPage = MX_CELL(pBt); apCell = sqlite3_malloc( mxCellPerPage*(sizeof(u8*)+sizeof(int)) ); if( apCell==0 ) return SQLITE_NOMEM; szCell = (int*)&apCell[mxCellPerPage]; if( pPage->leaf ){ /* The table is completely empty */ |
︙ | ︙ | |||
5443 5444 5445 5446 5447 5448 5449 | u8 *cdata; /* Content of the child page */ int hdr; /* Offset to page header in parent */ int brk; /* Offset to content of first cell in parent */ assert( pPage->pParent==0 ); assert( pPage->nOverflow>0 ); pBt = pPage->pBt; | | | 5443 5444 5445 5446 5447 5448 5449 5450 5451 5452 5453 5454 5455 5456 5457 | u8 *cdata; /* Content of the child page */ int hdr; /* Offset to page header in parent */ int brk; /* Offset to content of first cell in parent */ assert( pPage->pParent==0 ); assert( pPage->nOverflow>0 ); pBt = pPage->pBt; assert( sqlite3BtreeMutexHeld(pBt->mutex) ); rc = allocateBtreePage(pBt, &pChild, &pgnoChild, pPage->pgno, 0); if( rc ) return rc; assert( sqlite3PagerIswriteable(pChild->pDbPage) ); usableSize = pBt->usableSize; data = pPage->aData; hdr = pPage->hdrOffset; brk = get2byte(&data[hdr+5]); |
︙ | ︙ | |||
5492 5493 5494 5495 5496 5497 5498 | /* ** Decide if the page pPage needs to be balanced. If balancing is ** required, call the appropriate balancing routine. */ static int balance(MemPage *pPage, int insert){ int rc = SQLITE_OK; | | | 5492 5493 5494 5495 5496 5497 5498 5499 5500 5501 5502 5503 5504 5505 5506 | /* ** Decide if the page pPage needs to be balanced. If balancing is ** required, call the appropriate balancing routine. */ static int balance(MemPage *pPage, int insert){ int rc = SQLITE_OK; assert( sqlite3BtreeMutexHeld(pPage->pBt->mutex) ); if( pPage->pParent==0 ){ rc = sqlite3PagerWrite(pPage->pDbPage); if( rc==SQLITE_OK && pPage->nOverflow>0 ){ rc = balance_deeper(pPage); } if( rc==SQLITE_OK && pPage->nCell==0 ){ rc = balance_shallower(pPage); |
︙ | ︙ | |||
5530 5531 5532 5533 5534 5535 5536 | ** a page entirely and we do not want to leave any cursors ** pointing to non-existant pages or cells. */ static int checkReadLocks(Btree *pBtree, Pgno pgnoRoot, BtCursor *pExclude){ BtCursor *p; BtShared *pBt = pBtree->pBt; sqlite3 *db = pBtree->pSqlite; | | | | 5530 5531 5532 5533 5534 5535 5536 5537 5538 5539 5540 5541 5542 5543 5544 5545 | ** a page entirely and we do not want to leave any cursors ** pointing to non-existant pages or cells. */ static int checkReadLocks(Btree *pBtree, Pgno pgnoRoot, BtCursor *pExclude){ BtCursor *p; BtShared *pBt = pBtree->pBt; sqlite3 *db = pBtree->pSqlite; assert( sqlite3BtreeMutexHeld(pBt->mutex) ); assert( sqlite3BtreeMutexHeld(db->mutex) ); for(p=pBt->pCursor; p; p=p->pNext){ if( p==pExclude ) continue; if( p->eState!=CURSOR_VALID ) continue; if( p->pgnoRoot!=pgnoRoot ) continue; if( p->wrFlag==0 ){ sqlite3 *dbOther = p->pBtree->pSqlite; if( dbOther==0 || |
︙ | ︙ | |||
5935 5936 5937 5938 5939 5940 5941 | int freePageFlag /* Deallocate page if true */ ){ MemPage *pPage = 0; int rc; unsigned char *pCell; int i; | | | 5935 5936 5937 5938 5939 5940 5941 5942 5943 5944 5945 5946 5947 5948 5949 | int freePageFlag /* Deallocate page if true */ ){ MemPage *pPage = 0; int rc; unsigned char *pCell; int i; assert( sqlite3BtreeMutexHeld(pBt->mutex) ); if( pgno>sqlite3PagerPagecount(pBt->pPager) ){ return SQLITE_CORRUPT_BKPT; } rc = getAndInitPage(pBt, pgno, &pPage, pParent); if( rc ) goto cleardatabasepage_out; for(i=0; i<pPage->nCell; i++){ |
︙ | ︙ | |||
6017 6018 6019 6020 6021 6022 6023 | ** meta[3] is updated by this procedure. */ static int btreeDropTable(Btree *p, int iTable, int *piMoved){ int rc; MemPage *pPage = 0; BtShared *pBt = p->pBt; | | | 6017 6018 6019 6020 6021 6022 6023 6024 6025 6026 6027 6028 6029 6030 6031 | ** meta[3] is updated by this procedure. */ static int btreeDropTable(Btree *p, int iTable, int *piMoved){ int rc; MemPage *pPage = 0; BtShared *pBt = p->pBt; assert( sqlite3BtreeMutexHeld(pBt->mutex) ); if( p->inTrans!=TRANS_WRITE ){ return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR; } /* It is illegal to drop a table if any cursors are open on the ** database. This is because in auto-vacuum mode the backend may ** need to move another root-page to fill a gap left by the deleted |
︙ | ︙ | |||
6218 6219 6220 6221 6222 6223 6224 | ** is currently pointing to. */ int sqlite3BtreeFlags(BtCursor *pCur){ /* TODO: What about CURSOR_REQUIRESEEK state? Probably need to call ** restoreOrClearCursorPosition() here. */ MemPage *pPage = pCur->pPage; | | | | | 6218 6219 6220 6221 6222 6223 6224 6225 6226 6227 6228 6229 6230 6231 6232 6233 6234 6235 6236 6237 6238 6239 6240 6241 6242 6243 | ** is currently pointing to. */ int sqlite3BtreeFlags(BtCursor *pCur){ /* TODO: What about CURSOR_REQUIRESEEK state? Probably need to call ** restoreOrClearCursorPosition() here. */ MemPage *pPage = pCur->pPage; assert( sqlite3BtreeMutexHeld(pPage->pBt->mutex) ); return pPage ? pPage->aData[pPage->hdrOffset] : 0; } /* ** Return the pager associated with a BTree. This routine is used for ** testing and debugging only. */ Pager *sqlite3BtreePager(Btree *p){ assert( sqlite3BtreeMutexHeld(p->pSqlite->mutex) ); assert( sqlite3BtreeMutexHeld(p->pBt->mutex) ); return p->pBt->pPager; } #ifndef SQLITE_OMIT_INTEGRITY_CHECK /* ** Append a message to the error message string. */ |
︙ | ︙ | |||
6676 6677 6678 6679 6680 6681 6682 | #endif /* SQLITE_OMIT_INTEGRITY_CHECK */ /* ** Return the full pathname of the underlying database file. */ const char *sqlite3BtreeGetFilename(Btree *p){ assert( p->pBt->pPager!=0 ); | | | | | 6676 6677 6678 6679 6680 6681 6682 6683 6684 6685 6686 6687 6688 6689 6690 6691 6692 6693 6694 6695 6696 6697 6698 6699 6700 6701 6702 6703 6704 6705 6706 6707 6708 6709 6710 | #endif /* SQLITE_OMIT_INTEGRITY_CHECK */ /* ** Return the full pathname of the underlying database file. */ const char *sqlite3BtreeGetFilename(Btree *p){ assert( p->pBt->pPager!=0 ); assert( sqlite3BtreeMutexHeld(p->pBt->mutex) ); return sqlite3PagerFilename(p->pBt->pPager); } /* ** Return the pathname of the directory that contains the database file. */ const char *sqlite3BtreeGetDirname(Btree *p){ assert( p->pBt->pPager!=0 ); assert( sqlite3BtreeMutexHeld(p->pBt->mutex) ); return sqlite3PagerDirname(p->pBt->pPager); } /* ** Return the pathname of the journal file for this database. The return ** value of this routine is the same regardless of whether the journal file ** has been created or not. */ const char *sqlite3BtreeGetJournalname(Btree *p){ assert( p->pBt->pPager!=0 ); assert( sqlite3BtreeMutexHeld(p->pBt->mutex) ); return sqlite3PagerJournalname(p->pBt->pPager); } #ifndef SQLITE_OMIT_VACUUM /* ** Copy the complete content of pBtFrom into pBtTo. A transaction ** must be active for both files. |
︙ | ︙ | |||
6776 6777 6778 6779 6780 6781 6782 | #endif /* SQLITE_OMIT_VACUUM */ /* ** Return non-zero if a transaction is active. */ int sqlite3BtreeIsInTrans(Btree *p){ | | | | | | | | 6776 6777 6778 6779 6780 6781 6782 6783 6784 6785 6786 6787 6788 6789 6790 6791 6792 6793 6794 6795 6796 6797 6798 6799 6800 6801 6802 6803 6804 6805 6806 6807 6808 6809 | #endif /* SQLITE_OMIT_VACUUM */ /* ** Return non-zero if a transaction is active. */ int sqlite3BtreeIsInTrans(Btree *p){ assert( sqlite3BtreeMutexHeld(p->pBt->mutex) ); assert( sqlite3BtreeMutexHeld(p->pSqlite->mutex) ); return (p && (p->inTrans==TRANS_WRITE)); } /* ** Return non-zero if a statement transaction is active. */ int sqlite3BtreeIsInStmt(Btree *p){ assert( sqlite3BtreeMutexHeld(p->pBt->mutex) ); assert( sqlite3BtreeMutexHeld(p->pSqlite->mutex) ); return (p->pBt && p->pBt->inStmt); } /* ** Return non-zero if a read (or write) transaction is active. */ int sqlite3BtreeIsInReadTrans(Btree *p){ assert( sqlite3BtreeMutexHeld(p->pBt->mutex) ); assert( sqlite3BtreeMutexHeld(p->pSqlite->mutex) ); return (p && (p->inTrans!=TRANS_NONE)); } /* ** This function returns a pointer to a blob of memory associated with ** a single shared-btree. The memory is used by client code for it's own ** purposes (for example, to store a high-level schema associated with |
︙ | ︙ | |||
6817 6818 6819 6820 6821 6822 6823 | ** Just before the shared-btree is closed, the function passed as the ** xFree argument when the memory allocation was made is invoked on the ** blob of allocated memory. This function should not call sqlite3_free() ** on the memory, the btree layer does that. */ void *sqlite3BtreeSchema(Btree *p, int nBytes, void(*xFree)(void *)){ BtShared *pBt = p->pBt; | | | > > | | | > > | 6817 6818 6819 6820 6821 6822 6823 6824 6825 6826 6827 6828 6829 6830 6831 6832 6833 6834 6835 6836 6837 6838 6839 6840 6841 6842 6843 6844 6845 6846 6847 6848 6849 6850 6851 | ** Just before the shared-btree is closed, the function passed as the ** xFree argument when the memory allocation was made is invoked on the ** blob of allocated memory. This function should not call sqlite3_free() ** on the memory, the btree layer does that. */ void *sqlite3BtreeSchema(Btree *p, int nBytes, void(*xFree)(void *)){ BtShared *pBt = p->pBt; assert( sqlite3BtreeMutexHeld(p->pSqlite->mutex) ); sqlite3BtreeEnter(p); if( !pBt->pSchema ){ pBt->pSchema = sqlite3MallocZero(nBytes); pBt->xFreeSchema = xFree; } sqlite3BtreeLeave(p); return pBt->pSchema; } /* ** Return true if another user of the same shared btree as the argument ** handle holds an exclusive lock on the sqlite_master table. */ int sqlite3BtreeSchemaLocked(Btree *p){ int rc; assert( sqlite3BtreeMutexHeld(p->pSqlite->mutex) ); sqlite3BtreeEnter(p); rc = (queryTableLock(p, MASTER_ROOT, READ_LOCK)!=SQLITE_OK); sqlite3BtreeLeave(p); return rc; } #ifndef SQLITE_OMIT_SHARED_CACHE /* ** Obtain a lock on the table whose root page is iTab. The ** lock is a write lock if isWritelock is true or a read lock |
︙ | ︙ | |||
6865 6866 6867 6868 6869 6870 6871 | ** Argument pCsr must be a cursor opened for writing on an ** INTKEY table currently pointing at a valid table entry. ** This function modifies the data stored as part of that entry. ** Only the data content may only be modified, it is not possible ** to change the length of the data stored. */ int sqlite3BtreePutData(BtCursor *pCsr, u32 offset, u32 amt, void *z){ | | | | 6869 6870 6871 6872 6873 6874 6875 6876 6877 6878 6879 6880 6881 6882 6883 6884 | ** Argument pCsr must be a cursor opened for writing on an ** INTKEY table currently pointing at a valid table entry. ** This function modifies the data stored as part of that entry. ** Only the data content may only be modified, it is not possible ** to change the length of the data stored. */ int sqlite3BtreePutData(BtCursor *pCsr, u32 offset, u32 amt, void *z){ assert( sqlite3BtreeMutexHeld(pCsr->pBtree->pBt->mutex) ); assert( sqlite3BtreeMutexHeld(pCsr->pBtree->pSqlite->mutex) ); assert(pCsr->isIncrblobHandle); if( pCsr->eState==CURSOR_REQUIRESEEK ){ return SQLITE_ABORT; } /* Check some preconditions: ** (a) the cursor is open for writing, |
︙ | ︙ | |||
6903 6904 6905 6906 6907 6908 6909 | ** ** This function sets a flag only. The actual page location cache ** (stored in BtCursor.aOverflow[]) is allocated and used by function ** accessPayload() (the worker function for sqlite3BtreeData() and ** sqlite3BtreePutData()). */ void sqlite3BtreeCacheOverflow(BtCursor *pCur){ | | | | 6907 6908 6909 6910 6911 6912 6913 6914 6915 6916 6917 6918 6919 6920 | ** ** This function sets a flag only. The actual page location cache ** (stored in BtCursor.aOverflow[]) is allocated and used by function ** accessPayload() (the worker function for sqlite3BtreeData() and ** sqlite3BtreePutData()). */ void sqlite3BtreeCacheOverflow(BtCursor *pCur){ assert( sqlite3BtreeMutexHeld(pCur->pBtree->pBt->mutex) ); assert( sqlite3BtreeMutexHeld(pCur->pBtree->pSqlite->mutex) ); assert(!pCur->isIncrblobHandle); assert(!pCur->aOverflow); pCur->isIncrblobHandle = 1; } #endif |
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.86 2007/08/22 02:56:43 drh Exp $ */ #ifndef _BTREE_H_ #define _BTREE_H_ /* TODO: This definition is just included so other modules compile. It ** needs to be revisited. */ |
︙ | ︙ | |||
99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 | ** If we are not using shared cache, then there is no need to ** use mutexes to access the BtShared structures. So make the ** Enter and Leave procedures no-ops. */ #if SQLITE_THREADSAFE && !defined(SQLITE_OMIT_SHARED_CACHE) void sqlite3BtreeEnter(Btree*); void sqlite3BtreeLeave(Btree*); #else # define sqlite3BtreeEnter(X) # define sqlite3BtreeLeave(X) #endif const char *sqlite3BtreeGetFilename(Btree *); const char *sqlite3BtreeGetDirname(Btree *); const char *sqlite3BtreeGetJournalname(Btree *); int sqlite3BtreeCopyFile(Btree *, Btree *); | > > | 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 | ** If we are not using shared cache, then there is no need to ** use mutexes to access the BtShared structures. So make the ** Enter and Leave procedures no-ops. */ #if SQLITE_THREADSAFE && !defined(SQLITE_OMIT_SHARED_CACHE) void sqlite3BtreeEnter(Btree*); void sqlite3BtreeLeave(Btree*); # define sqlite3BtreeMutexHeld(X) sqlite3_mutex_held(X) #else # define sqlite3BtreeEnter(X) # define sqlite3BtreeLeave(X) # define sqlite3BtreeMutexHeld(X) 1 #endif const char *sqlite3BtreeGetFilename(Btree *); const char *sqlite3BtreeGetDirname(Btree *); const char *sqlite3BtreeGetJournalname(Btree *); int sqlite3BtreeCopyFile(Btree *, Btree *); |
︙ | ︙ |
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.395 2007/08/22 02:56:44 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> /* ** The version of the library */ |
︙ | ︙ | |||
138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 | */ sqlite3VtabRollback(db); /* If there are any outstanding VMs, return SQLITE_BUSY. */ if( db->pVdbe ){ sqlite3Error(db, SQLITE_BUSY, "Unable to close due to unfinalised statements"); return SQLITE_BUSY; } assert( !sqlite3SafetyCheck(db) ); /* FIX ME: db->magic may be set to SQLITE_MAGIC_CLOSED if the database ** cannot be opened for some reason. So this routine needs to run in ** that case. But maybe there should be an extra magic value for the ** "failed to open" state. ** ** TODO: Coverage tests do not test the case where this condition is ** true. It's hard to see how to cause it without messing with threads. */ if( db->magic!=SQLITE_MAGIC_CLOSED && sqlite3SafetyOn(db) ){ /* printf("DID NOT CLOSE\n"); fflush(stdout); */ return SQLITE_ERROR; } for(j=0; j<db->nDb; j++){ struct Db *pDb = &db->aDb[j]; if( pDb->pBt ){ sqlite3BtreeClose(pDb->pBt); | > > | 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 | */ sqlite3VtabRollback(db); /* If there are any outstanding VMs, return SQLITE_BUSY. */ if( db->pVdbe ){ sqlite3Error(db, SQLITE_BUSY, "Unable to close due to unfinalised statements"); sqlite3_mutex_leave(db->mutex); return SQLITE_BUSY; } assert( !sqlite3SafetyCheck(db) ); /* FIX ME: db->magic may be set to SQLITE_MAGIC_CLOSED if the database ** cannot be opened for some reason. So this routine needs to run in ** that case. But maybe there should be an extra magic value for the ** "failed to open" state. ** ** TODO: Coverage tests do not test the case where this condition is ** true. It's hard to see how to cause it without messing with threads. */ if( db->magic!=SQLITE_MAGIC_CLOSED && sqlite3SafetyOn(db) ){ /* printf("DID NOT CLOSE\n"); fflush(stdout); */ sqlite3_mutex_leave(db->mutex); return SQLITE_ERROR; } for(j=0; j<db->nDb; j++){ struct Db *pDb = &db->aDb[j]; if( pDb->pBt ){ sqlite3BtreeClose(pDb->pBt); |
︙ | ︙ | |||
766 767 768 769 770 771 772 | ** error. */ const char *sqlite3_errmsg(sqlite3 *db){ const char *z; if( !db ){ return sqlite3ErrStr(SQLITE_NOMEM); } | < > | 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 | ** error. */ const char *sqlite3_errmsg(sqlite3 *db){ const char *z; if( !db ){ return sqlite3ErrStr(SQLITE_NOMEM); } if( sqlite3SafetyCheck(db) || db->errCode==SQLITE_MISUSE ){ return sqlite3ErrStr(SQLITE_MISUSE); } sqlite3_mutex_enter(db->mutex); assert( !db->mallocFailed ); z = (char*)sqlite3_value_text(db->pErr); if( z==0 ){ z = sqlite3ErrStr(db->errCode); } sqlite3_mutex_leave(db->mutex); return z; |
︙ | ︙ | |||
942 943 944 945 946 947 948 949 950 951 952 953 954 955 | db = sqlite3MallocZero( sizeof(sqlite3) ); if( db==0 ) goto opendb_out; db->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_RECURSIVE); if( db->mutex==0 ){ db->mallocFailed = 1; goto opendb_out; } db->pVfs = sqlite3_vfs_find(zVfs); db->errMask = 0xff; db->priorNewRowid = 0; db->magic = SQLITE_MAGIC_BUSY; db->nDb = 2; db->aDb = db->aDbStatic; db->autoCommit = 1; | > | 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 | db = sqlite3MallocZero( sizeof(sqlite3) ); if( db==0 ) goto opendb_out; db->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_RECURSIVE); if( db->mutex==0 ){ db->mallocFailed = 1; goto opendb_out; } sqlite3_mutex_enter(db->mutex); db->pVfs = sqlite3_vfs_find(zVfs); db->errMask = 0xff; db->priorNewRowid = 0; db->magic = SQLITE_MAGIC_BUSY; db->nDb = 2; db->aDb = db->aDbStatic; db->autoCommit = 1; |
︙ | ︙ | |||
1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 | #ifdef SQLITE_DEFAULT_LOCKING_MODE db->dfltLockMode = SQLITE_DEFAULT_LOCKING_MODE; sqlite3PagerLockingMode(sqlite3BtreePager(db->aDb[0].pBt), SQLITE_DEFAULT_LOCKING_MODE); #endif opendb_out: if( SQLITE_NOMEM==(rc = sqlite3_errcode(db)) ){ sqlite3_close(db); db = 0; } *ppDb = db; return sqlite3ApiExit(0, rc); } | > | 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 | #ifdef SQLITE_DEFAULT_LOCKING_MODE db->dfltLockMode = SQLITE_DEFAULT_LOCKING_MODE; sqlite3PagerLockingMode(sqlite3BtreePager(db->aDb[0].pBt), SQLITE_DEFAULT_LOCKING_MODE); #endif opendb_out: sqlite3_mutex_leave(db->mutex); if( SQLITE_NOMEM==(rc = sqlite3_errcode(db)) ){ sqlite3_close(db); db = 0; } *ppDb = db; return sqlite3ApiExit(0, rc); } |
︙ | ︙ |
Changes to src/mutex.c.
︙ | ︙ | |||
8 9 10 11 12 13 14 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains the C functions that implement mutexes for ** use by the SQLite core. ** | | < > | 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 34 35 36 37 38 39 40 41 42 43 44 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains the C functions that implement mutexes for ** use by the SQLite core. ** ** $Id: mutex.c,v 1.8 2007/08/22 02:56:44 drh Exp $ */ /* ** If SQLITE_MUTEX_APPDEF is defined, then this whole module is ** omitted and equivalent functionality must be provided by the ** application that links against the SQLite library. */ #ifndef SQLITE_MUTEX_APPDEF /* This is the beginning of real code */ #include "sqliteInt.h" /* ** Figure out what version of the code to use */ #define SQLITE_MUTEX_NOOP 1 /* The default */ #if defined(SQLITE_DEBUG) && !SQLITE_THREADSAFE # undef SQLITE_MUTEX_NOOP # define SQLITE_MUTEX_NOOP_DEBUG #endif #if 0 #if defined(SQLITE_MUTEX_NOOP) && SQLITE_THREADSAFE && OS_UNIX # undef SQLITE_MUTEX_NOOP # define SQLITE_MUTEX_PTHREAD #endif #if defined(SQLITE_MUTEX_NOOP) && SQLITE_THREADSAFE && OS_WIN # undef SQLITE_MUTEX_NOOP # define SQLITE_MUTEX_WIN |
︙ | ︙ | |||
135 136 137 138 139 140 141 | if( pNew ){ pNew->id = id; pNew->cnt = 0; } break; } default: { | | | | | 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 | if( pNew ){ pNew->id = id; pNew->cnt = 0; } break; } default: { assert( id-2 >= 0 ); assert( id-2 < sizeof(aStatic)/sizeof(aStatic[0]) ); pNew = &aStatic[id-2]; pNew->id = id; break; } } return pNew; } |
︙ | ︙ |
Changes to src/prepare.c.
︙ | ︙ | |||
9 10 11 12 13 14 15 | ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains the implementation of the sqlite3_prepare() ** interface, and routines that contribute to loading the database schema ** from disk. ** | | | 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 file contains the implementation of the sqlite3_prepare() ** interface, and routines that contribute to loading the database schema ** from disk. ** ** $Id: prepare.c,v 1.58 2007/08/22 02:56:44 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> /* ** Fill the InitData structure with an error message that indicates ** that the database is corrupt. |
︙ | ︙ | |||
567 568 569 570 571 572 573 574 575 576 577 578 579 580 | const char *zSql, /* UTF-8 encoded SQL statement. */ int nBytes, /* Length of zSql in bytes. */ int saveSqlFlag, /* True to copy SQL text into the sqlite3_stmt */ sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */ const char **pzTail /* OUT: End of parsed string */ ){ int rc; sqlite3_mutex_enter(db->mutex); rc = sqlite3Prepare(db, zSql, nBytes, saveSqlFlag, ppStmt, pzTail); sqlite3_mutex_leave(db->mutex); return rc; } /* | > > > | 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 | const char *zSql, /* UTF-8 encoded SQL statement. */ int nBytes, /* Length of zSql in bytes. */ int saveSqlFlag, /* True to copy SQL text into the sqlite3_stmt */ sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */ const char **pzTail /* OUT: End of parsed string */ ){ int rc; if( sqlite3SafetyCheck(db) ){ return SQLITE_MISUSE; } sqlite3_mutex_enter(db->mutex); rc = sqlite3Prepare(db, zSql, nBytes, saveSqlFlag, ppStmt, pzTail); sqlite3_mutex_leave(db->mutex); return rc; } /* |
︙ | ︙ |
Changes to src/test1.c.
︙ | ︙ | |||
9 10 11 12 13 14 15 | ** May you share freely, never taking more than you give. ** ************************************************************************* ** Code for testing all sorts of SQLite interfaces. This code ** is not included in the SQLite library. It is used for automated ** testing of the SQLite library. ** | | | 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. ** ************************************************************************* ** Code for testing all sorts of SQLite interfaces. This code ** is not included in the SQLite library. It is used for automated ** testing of the SQLite library. ** ** $Id: test1.c,v 1.269 2007/08/22 02:56:44 drh Exp $ */ #include "sqliteInt.h" #include "tcl.h" #include <stdlib.h> #include <string.h> /* |
︙ | ︙ | |||
317 318 319 320 321 322 323 324 325 326 327 328 329 330 | Tcl_AppendElement(interp, zBuf); Tcl_AppendElement(interp, rc==SQLITE_OK ? Tcl_DStringValue(&str) : zErr); Tcl_DStringFree(&str); if( zErr ) sqlite3_free(zErr); if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; return TCL_OK; } /* ** Usage: sqlite3_exec DB SQL ** ** Invoke the sqlite3_exec interface using the open database DB */ static int test_exec( | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 | Tcl_AppendElement(interp, zBuf); Tcl_AppendElement(interp, rc==SQLITE_OK ? Tcl_DStringValue(&str) : zErr); Tcl_DStringFree(&str); if( zErr ) sqlite3_free(zErr); if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; return TCL_OK; } /* ** Usage: db_enter DB ** db_leave DB ** ** Enter or leave the mutex on a database connection. */ static int db_enter( void *NotUsed, Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ int argc, /* Number of arguments */ char **argv /* Text of each argument */ ){ sqlite3 *db; if( argc!=2 ){ Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " DB", 0); return TCL_ERROR; } if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; sqlite3_mutex_enter(db->mutex); return TCL_OK; } static int db_leave( void *NotUsed, Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ int argc, /* Number of arguments */ char **argv /* Text of each argument */ ){ sqlite3 *db; if( argc!=2 ){ Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " DB", 0); return TCL_ERROR; } if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; sqlite3_mutex_leave(db->mutex); return TCL_OK; } /* ** Usage: sqlite3_exec DB SQL ** ** Invoke the sqlite3_exec interface using the open database DB */ static int test_exec( |
︙ | ︙ | |||
912 913 914 915 916 917 918 | } #ifndef SQLITE_OMIT_UTF16 /* Use the sqlite3_create_function16() API here. Mainly for fun, but also ** because it is not tested anywhere else. */ if( rc==SQLITE_OK ){ sqlite3_value *pVal; | | | 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 | } #ifndef SQLITE_OMIT_UTF16 /* Use the sqlite3_create_function16() API here. Mainly for fun, but also ** because it is not tested anywhere else. */ if( rc==SQLITE_OK ){ sqlite3_value *pVal; pVal = sqlite3ValueNew(0); sqlite3ValueSetStr(pVal, -1, "x_sqlite_exec", SQLITE_UTF8, SQLITE_STATIC); rc = sqlite3_create_function16(db, sqlite3ValueText(pVal, SQLITE_UTF16NATIVE), 1, SQLITE_UTF16, db, sqlite3ExecFunc, 0, 0); sqlite3ValueFree(pVal); } #endif |
︙ | ︙ | |||
4099 4100 4101 4102 4103 4104 4105 4106 4107 4108 4109 4110 4111 4112 4113 4114 | } if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; pResult = Tcl_NewObj(); for(i=0; i<db->nDb; i++){ if( db->aDb[i].pBt==0 ){ v = -1; }else{ a = sqlite3PagerStats(sqlite3BtreePager(db->aDb[i].pBt)); v = a[0]; } Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(v)); } Tcl_SetObjResult(interp, pResult); return TCL_OK; } | > > | 4138 4139 4140 4141 4142 4143 4144 4145 4146 4147 4148 4149 4150 4151 4152 4153 4154 4155 | } if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; pResult = Tcl_NewObj(); for(i=0; i<db->nDb; i++){ if( db->aDb[i].pBt==0 ){ v = -1; }else{ sqlite3_mutex_enter(db->mutex); a = sqlite3PagerStats(sqlite3BtreePager(db->aDb[i].pBt)); v = a[0]; sqlite3_mutex_leave(db->mutex); } Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(v)); } Tcl_SetObjResult(interp, pResult); return TCL_OK; } |
︙ | ︙ | |||
4154 4155 4156 4157 4158 4159 4160 4161 4162 4163 4164 4165 4166 4167 | extern int sqlite3_max_blobsize; extern int sqlite3BtreeSharedCacheReport(void*, Tcl_Interp*,int,Tcl_Obj*CONST*); static struct { char *zName; Tcl_CmdProc *xProc; } aCmd[] = { { "sqlite3_mprintf_int", (Tcl_CmdProc*)sqlite3_mprintf_int }, { "sqlite3_mprintf_int64", (Tcl_CmdProc*)sqlite3_mprintf_int64 }, { "sqlite3_mprintf_str", (Tcl_CmdProc*)sqlite3_mprintf_str }, { "sqlite3_snprintf_str", (Tcl_CmdProc*)sqlite3_snprintf_str }, { "sqlite3_mprintf_stronly", (Tcl_CmdProc*)sqlite3_mprintf_stronly}, { "sqlite3_mprintf_double", (Tcl_CmdProc*)sqlite3_mprintf_double }, { "sqlite3_mprintf_scaled", (Tcl_CmdProc*)sqlite3_mprintf_scaled }, | > > | 4195 4196 4197 4198 4199 4200 4201 4202 4203 4204 4205 4206 4207 4208 4209 4210 | extern int sqlite3_max_blobsize; extern int sqlite3BtreeSharedCacheReport(void*, Tcl_Interp*,int,Tcl_Obj*CONST*); static struct { char *zName; Tcl_CmdProc *xProc; } aCmd[] = { { "db_enter", (Tcl_CmdProc*)db_enter }, { "db_leave", (Tcl_CmdProc*)db_leave }, { "sqlite3_mprintf_int", (Tcl_CmdProc*)sqlite3_mprintf_int }, { "sqlite3_mprintf_int64", (Tcl_CmdProc*)sqlite3_mprintf_int64 }, { "sqlite3_mprintf_str", (Tcl_CmdProc*)sqlite3_mprintf_str }, { "sqlite3_snprintf_str", (Tcl_CmdProc*)sqlite3_snprintf_str }, { "sqlite3_mprintf_stronly", (Tcl_CmdProc*)sqlite3_mprintf_stronly}, { "sqlite3_mprintf_double", (Tcl_CmdProc*)sqlite3_mprintf_double }, { "sqlite3_mprintf_scaled", (Tcl_CmdProc*)sqlite3_mprintf_scaled }, |
︙ | ︙ |
Changes to src/test3.c.
︙ | ︙ | |||
9 10 11 12 13 14 15 | ** May you share freely, never taking more than you give. ** ************************************************************************* ** Code for testing the btree.c module in SQLite. This code ** is not included in the SQLite library. It is used for automated ** testing of the SQLite library. ** | | | 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. ** ************************************************************************* ** Code for testing the btree.c module in SQLite. This code ** is not included in the SQLite library. It is used for automated ** testing of the SQLite library. ** ** $Id: test3.c,v 1.81 2007/08/22 02:56:44 drh Exp $ */ #include "sqliteInt.h" #include "tcl.h" #include <stdlib.h> #include <string.h> /* |
︙ | ︙ | |||
74 75 76 77 78 79 80 81 82 83 84 85 86 87 | } 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 = sqlite3_mutex_alloc(SQLITE_MUTEX_RECURSIVE); } rc = sqlite3BtreeOpen(argv[1], &sDb, &pBt, flags); if( rc!=SQLITE_OK ){ Tcl_AppendResult(interp, errorName(rc), 0); return TCL_ERROR; } sqlite3BtreeSetCacheSize(pBt, nCache); | > | 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 | } 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 = sqlite3_mutex_alloc(SQLITE_MUTEX_RECURSIVE); sqlite3_mutex_enter(sDb.mutex); } rc = sqlite3BtreeOpen(argv[1], &sDb, &pBt, flags); if( rc!=SQLITE_OK ){ Tcl_AppendResult(interp, errorName(rc), 0); return TCL_ERROR; } sqlite3BtreeSetCacheSize(pBt, nCache); |
︙ | ︙ | |||
112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 | rc = sqlite3BtreeClose(pBt); if( rc!=SQLITE_OK ){ Tcl_AppendResult(interp, errorName(rc), 0); return TCL_ERROR; } nRefSqlite3--; if( nRefSqlite3==0 ){ sqlite3_mutex_free(sDb.mutex); sDb.mutex = 0; sqlite3_vfs_release(sDb.pVfs); sDb.pVfs = 0; } return TCL_OK; } /* ** Usage: btree_begin_transaction ID ** ** Start a new transaction */ static int btree_begin_transaction( | > > | 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 | rc = sqlite3BtreeClose(pBt); if( rc!=SQLITE_OK ){ Tcl_AppendResult(interp, errorName(rc), 0); return TCL_ERROR; } nRefSqlite3--; if( nRefSqlite3==0 ){ sqlite3_mutex_leave(sDb.mutex); sqlite3_mutex_free(sDb.mutex); sDb.mutex = 0; sqlite3_vfs_release(sDb.pVfs); sDb.pVfs = 0; } return TCL_OK; } /* ** Usage: btree_begin_transaction ID ** ** Start a new transaction */ static int btree_begin_transaction( |
︙ | ︙ | |||
524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 | if( argc!=2 ){ Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " ID\"", 0); return TCL_ERROR; } pBt = sqlite3TextToPtr(argv[1]); a = sqlite3PagerStats(sqlite3BtreePager(pBt)); for(i=0; i<11; i++){ static char *zName[] = { "ref", "page", "max", "size", "state", "err", "hit", "miss", "ovfl", "read", "write" }; char zBuf[100]; Tcl_AppendElement(interp, zName[i]); sqlite3_snprintf(sizeof(zBuf), zBuf,"%d",a[i]); Tcl_AppendElement(interp, zBuf); } return TCL_OK; } /* ** Usage: btree_pager_ref_dump ID ** ** Print out all outstanding pages. | > > | 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 | if( argc!=2 ){ Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " ID\"", 0); return TCL_ERROR; } pBt = sqlite3TextToPtr(argv[1]); sqlite3BtreeEnter(pBt); a = sqlite3PagerStats(sqlite3BtreePager(pBt)); for(i=0; i<11; i++){ static char *zName[] = { "ref", "page", "max", "size", "state", "err", "hit", "miss", "ovfl", "read", "write" }; char zBuf[100]; Tcl_AppendElement(interp, zName[i]); sqlite3_snprintf(sizeof(zBuf), zBuf,"%d",a[i]); Tcl_AppendElement(interp, zBuf); } sqlite3BtreeLeave(pBt); return TCL_OK; } /* ** Usage: btree_pager_ref_dump ID ** ** Print out all outstanding pages. |
︙ | ︙ |
Changes to src/vdbeapi.c.
︙ | ︙ | |||
556 557 558 559 560 561 562 | pVm = (Vdbe *)pStmt; if( pVm && pVm->resOnStack && i<pVm->nResColumn && i>=0 ){ sqlite3_mutex_enter(pVm->db->mutex); vals = sqlite3_data_count(pStmt); pOut = &pVm->pTos[(1-vals)+i]; }else{ static const Mem nullMem = {{0}, 0.0, 0, "", 0, MEM_Null, SQLITE_NULL }; | > > | > | 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 | pVm = (Vdbe *)pStmt; if( pVm && pVm->resOnStack && i<pVm->nResColumn && i>=0 ){ sqlite3_mutex_enter(pVm->db->mutex); vals = sqlite3_data_count(pStmt); pOut = &pVm->pTos[(1-vals)+i]; }else{ static const Mem nullMem = {{0}, 0.0, 0, "", 0, MEM_Null, SQLITE_NULL }; if( pVm->db ){ sqlite3_mutex_enter(pVm->db->mutex); sqlite3Error(pVm->db, SQLITE_RANGE, 0); } pOut = (Mem*)&nullMem; } return pOut; } /* ** This function is called after invoking an sqlite3_value_XXX function on a |
︙ | ︙ | |||
842 843 844 845 846 847 848 | int rc; if( p==0 ){ return SQLITE_MISUSE; } sqlite3_mutex_enter(p->db->mutex); rc = vdbeUnbind(p, i); | | < < | | | | | | | > | 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 | int rc; if( p==0 ){ return SQLITE_MISUSE; } sqlite3_mutex_enter(p->db->mutex); rc = vdbeUnbind(p, i); if( rc==SQLITE_OK && zData!=0 ){ pVar = &p->aVar[i-1]; rc = sqlite3VdbeMemSetStr(pVar, zData, nData, encoding, xDel); if( rc==SQLITE_OK && encoding!=0 ){ rc = sqlite3VdbeChangeEncoding(pVar, ENC(p->db)); } sqlite3Error(p->db, rc, 0); rc = sqlite3ApiExit(p->db, rc); } sqlite3_mutex_leave(p->db->mutex); return rc; } /* ** Bind a blob value to an SQL statement variable. |
︙ | ︙ | |||
1025 1026 1027 1028 1029 1030 1031 | ** an SQLITE_ERROR is returned. */ int sqlite3_transfer_bindings(sqlite3_stmt *pFromStmt, sqlite3_stmt *pToStmt){ Vdbe *pFrom = (Vdbe*)pFromStmt; Vdbe *pTo = (Vdbe*)pToStmt; int i, rc = SQLITE_OK; if( (pFrom->magic!=VDBE_MAGIC_RUN && pFrom->magic!=VDBE_MAGIC_HALT) | | > > > | 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 | ** an SQLITE_ERROR is returned. */ int sqlite3_transfer_bindings(sqlite3_stmt *pFromStmt, sqlite3_stmt *pToStmt){ Vdbe *pFrom = (Vdbe*)pFromStmt; Vdbe *pTo = (Vdbe*)pToStmt; int i, rc = SQLITE_OK; if( (pFrom->magic!=VDBE_MAGIC_RUN && pFrom->magic!=VDBE_MAGIC_HALT) || (pTo->magic!=VDBE_MAGIC_RUN && pTo->magic!=VDBE_MAGIC_HALT) || pTo->db!=pFrom->db ){ return SQLITE_MISUSE; } if( pFrom->nVar!=pTo->nVar ){ return SQLITE_ERROR; } sqlite3_mutex_enter(pTo->db->mutex); for(i=0; rc==SQLITE_OK && i<pFrom->nVar; i++){ sqlite3MallocDisallow(); rc = sqlite3VdbeMemMove(&pTo->aVar[i], &pFrom->aVar[i]); sqlite3MallocAllow(); } sqlite3_mutex_leave(pTo->db->mutex); assert( rc==SQLITE_OK || rc==SQLITE_NOMEM ); return rc; } /* ** Return the sqlite3* database handle to which the prepared statement given ** in the argument belongs. This is the same database handle that was ** the first argument to the sqlite3_prepare() that was used to create ** the statement in the first place. */ sqlite3 *sqlite3_db_handle(sqlite3_stmt *pStmt){ return pStmt ? ((Vdbe*)pStmt)->db : 0; } |
Changes to src/vtab.c.
1 2 3 4 5 6 7 8 9 10 11 12 13 | /* ** 2006 June 10 ** ** 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 contains code used to help implement virtual tables. ** | | > > > | | > > | 1 2 3 4 5 6 7 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 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | /* ** 2006 June 10 ** ** 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 contains code used to help implement virtual tables. ** ** $Id: vtab.c,v 1.52 2007/08/22 02:56:44 drh Exp $ */ #ifndef SQLITE_OMIT_VIRTUALTABLE #include "sqliteInt.h" static int createModule( sqlite3 *db, /* Database in which module is registered */ const char *zName, /* Name assigned to this module */ const sqlite3_module *pModule, /* The definition of the module */ void *pAux, /* Context pointer for xCreate/xConnect */ void (*xDestroy)(void *) /* Module destructor function */ ) { int rc, nName; sqlite3_mutex_enter(db->mutex); nName = strlen(zName); Module *pMod = (Module *)sqlite3DbMallocRaw(db, sizeof(Module) + nName + 1); if( pMod ){ char *zCopy = (char *)(&pMod[1]); memcpy(zCopy, zName, nName+1); pMod->zName = zCopy; pMod->pModule = pModule; pMod->pAux = pAux; pMod->xDestroy = xDestroy; pMod = (Module *)sqlite3HashInsert(&db->aModule, zCopy, nName, (void*)pMod); if( pMod && pMod->xDestroy ){ pMod->xDestroy(pMod->pAux); } sqlite3_free(pMod); sqlite3ResetInternalSchema(db, 0); } rc = sqlite3ApiExit(db, SQLITE_OK); sqlite3_mutex_leave(db->mutex); return rc; } /* ** External API function used to create a new virtual-table module. */ int sqlite3_create_module( |
︙ | ︙ | |||
521 522 523 524 525 526 527 | ** valid to call this function from within the xCreate() or xConnect() of a ** virtual table module. */ int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){ Parse sParse; int rc = SQLITE_OK; | | > > > | 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 | ** valid to call this function from within the xCreate() or xConnect() of a ** virtual table module. */ int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){ Parse sParse; int rc = SQLITE_OK; Table *pTab; char *zErr = 0; sqlite3_mutex_enter(db->mutex); pTab = db->pVTab; if( !pTab ){ sqlite3Error(db, SQLITE_MISUSE, 0); sqlite3_mutex_leave(db->mutex); return SQLITE_MISUSE; } assert(pTab->isVirtual && pTab->nCol==0 && pTab->aCol==0); memset(&sParse, 0, sizeof(Parse)); sParse.declareVtab = 1; sParse.db = db; |
︙ | ︙ | |||
557 558 559 560 561 562 563 | sParse.declareVtab = 0; sqlite3_finalize((sqlite3_stmt*)sParse.pVdbe); sqlite3DeleteTable(sParse.pNewTable); sParse.pNewTable = 0; assert( (rc&0xff)==rc ); | | > > | 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 | sParse.declareVtab = 0; sqlite3_finalize((sqlite3_stmt*)sParse.pVdbe); sqlite3DeleteTable(sParse.pNewTable); sParse.pNewTable = 0; assert( (rc&0xff)==rc ); rc = sqlite3ApiExit(db, rc); sqlite3_mutex_leave(db->mutex); return rc; } /* ** This function is invoked by the vdbe to call the xDestroy method ** of the virtual table named zTab in database iDb. This occurs ** when a DROP TABLE is mentioned. ** |
︙ | ︙ |
Changes to test/cache.test.
1 2 3 4 5 6 7 8 9 10 11 | # 2007 March 24 # # 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 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | # 2007 March 24 # # 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: cache.test,v 1.4 2007/08/22 02:56:44 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl ifcapable {!pager_pragmas} { finish_test return } sqlite3_soft_heap_limit 0 proc pager_cache_size {db} { set bt [btree_from_db $db] db_enter $db array set stats [btree_pager_stats $bt] db_leave $db return $stats(page) } do_test cache-1.1 { pager_cache_size db } {0} |
︙ | ︙ |
Changes to test/capi3.test.
1 2 3 4 5 6 7 8 9 10 11 12 13 | # 2003 January 29 # # 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 regression tests for SQLite library. The # focus of this script testing the callback-free C/C++ API. # | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | # 2003 January 29 # # 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 regression tests for SQLite library. The # focus of this script testing the callback-free C/C++ API. # # $Id: capi3.test,v 1.52 2007/08/22 02:56:44 drh Exp $ # set testdir [file dirname $argv0] source $testdir/tester.tcl # Return the UTF-16 representation of the supplied UTF-8 string $str. # If $nt is true, append two 0x00 bytes as a nul terminator. |
︙ | ︙ | |||
599 600 601 602 603 604 605 | } SQLITE_OK set ::ENC [execsql {pragma encoding}] db close do_test capi3-6.0 { | < < | 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 | } SQLITE_OK set ::ENC [execsql {pragma encoding}] db close do_test capi3-6.0 { sqlite3 db test.db set DB [sqlite3_connection_pointer db] sqlite3_key $DB xyzzy set sql {SELECT a FROM t1 order by rowid} set STMT [sqlite3_prepare $DB $sql -1 TAIL] expr 0 } {0} do_test capi3-6.1 { db cache flush |
︙ | ︙ |
Changes to test/incrblob.test.
1 2 3 4 5 6 7 8 9 10 11 | # 2007 May 1 # # 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 | # 2007 May 1 # # 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: incrblob.test,v 1.14 2007/08/22 02:56:44 drh Exp $ # set testdir [file dirname $argv0] source $testdir/tester.tcl ifcapable {!autovacuum || !pragma || !incrblob} { finish_test |
︙ | ︙ | |||
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 | # # * Reading near the end of a blob, # * Writing near the end of a blob, and # * SELECT a column value that is located on an overflow page. # proc nRead {db} { set bt [btree_from_db $db] array set stats [btree_pager_stats $bt] return $stats(read) } proc nWrite {db} { set bt [btree_from_db $db] array set stats [btree_pager_stats $bt] return $stats(write) } sqlite3_soft_heap_limit 0 foreach AutoVacuumMode [list 0 1] { | > > > > | 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 | # # * Reading near the end of a blob, # * Writing near the end of a blob, and # * SELECT a column value that is located on an overflow page. # proc nRead {db} { set bt [btree_from_db $db] db_enter $db array set stats [btree_pager_stats $bt] db_leave $db return $stats(read) } proc nWrite {db} { set bt [btree_from_db $db] db_enter $db array set stats [btree_pager_stats $bt] db_leave $db return $stats(write) } sqlite3_soft_heap_limit 0 foreach AutoVacuumMode [list 0 1] { |
︙ | ︙ |
Changes to test/io.test.
︙ | ︙ | |||
9 10 11 12 13 14 15 | # #*********************************************************************** # # The focus of this file is testing some specific characteristics of the # IO traffic generated by SQLite (making sure SQLite is not writing out # more database pages than it has to, stuff like that). # | | > | | 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 | # #*********************************************************************** # # The focus of this file is testing some specific characteristics of the # IO traffic generated by SQLite (making sure SQLite is not writing out # more database pages than it has to, stuff like that). # # $Id: io.test,v 1.2 2007/08/22 02:56:44 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl set ::nWrite 0 proc nWrite {db} { set bt [btree_from_db $db] db_enter $db array set stats [btree_pager_stats $bt] db_leave $db set res [expr $stats(write) - $::nWrite] set ::nWrite $stats(write) set res } do_test io-1.1 { execsql { |
︙ | ︙ | |||
84 85 86 87 88 89 90 | execsql { INSERT INTO abc VALUES(9,randstr(230,230)); } nWrite db } {3} #db eval {select * from sqlite_master} {btree_tree_dump [btree_from_db db] 2} finish_test | < | 85 86 87 88 89 90 91 | execsql { INSERT INTO abc VALUES(9,randstr(230,230)); } nWrite db } {3} #db eval {select * from sqlite_master} {btree_tree_dump [btree_from_db db] 2} finish_test |
Changes to test/speed3.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 that the overflow-page related # enhancements added after version 3.3.17 speed things up. # | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | # 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 that the overflow-page related # enhancements added after version 3.3.17 speed things up. # # $Id: speed3.test,v 1.3 2007/08/22 02:56:44 drh Exp $ # #--------------------------------------------------------------------- # Test plan: # # If auto-vacuum is enabled for the database, the following cases # should show performance improvement with respect to 3.3.17. |
︙ | ︙ | |||
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 | } $db eval {INSERT INTO aux.t1 SELECT * FROM main.t1} } } proc io_log {db} { array set stats1 [btree_pager_stats [btree_from_db db]] array set stats2 [btree_pager_stats [btree_from_db db 2]] # puts "1: [array get stats1]" # puts "2: [array get stats2]" puts "Incrvacuum: Read $stats1(read), wrote $stats1(write)" puts "Normal : Read $stats2(read), wrote $stats2(write)" } proc overflow_report {db} { | > > | 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 | } $db eval {INSERT INTO aux.t1 SELECT * FROM main.t1} } } proc io_log {db} { db_enter db array set stats1 [btree_pager_stats [btree_from_db db]] array set stats2 [btree_pager_stats [btree_from_db db 2]] db_leave db # puts "1: [array get stats1]" # puts "2: [array get stats2]" puts "Incrvacuum: Read $stats1(read), wrote $stats1(write)" puts "Normal : Read $stats2(read), wrote $stats2(write)" } proc overflow_report {db} { |
︙ | ︙ | |||
172 173 174 175 176 177 178 | #overflow_report db reset_db speed_trial speed3-2.incrvacuum $::NROW row {SELECT c FROM main.t1} speed_trial speed3-2.normal $::NROW row {SELECT c FROM aux.t1} io_log db finish_test | < | 174 175 176 177 178 179 180 | #overflow_report db reset_db speed_trial speed3-2.incrvacuum $::NROW row {SELECT c FROM main.t1} speed_trial speed3-2.normal $::NROW row {SELECT c FROM aux.t1} io_log db finish_test |
Changes to test/vtab1.test.
1 2 3 4 5 6 7 8 9 10 11 12 13 | # 2006 June 10 # # 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 regression tests for SQLite library. The # focus of this file is creating and dropping virtual tables. # | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | # 2006 June 10 # # 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 regression tests for SQLite library. The # focus of this file is creating and dropping virtual tables. # # $Id: vtab1.test,v 1.44 2007/08/22 02:56:44 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl ifcapable !vtab||!schema_pragmas { finish_test return |
︙ | ︙ | |||
810 811 812 813 814 815 816 817 818 819 820 821 822 823 | catchsql { SELECT * FROM e2; } } {1 {vtable constructor failed: e2}} do_test vtab1.10-2 { set rc [catch { set ptr [sqlite3_connection_pointer db] sqlite3_declare_vtab $ptr {CREATE TABLE abc(a, b, c)} } msg] list $rc $msg } {1 {library routine called out of sequence}} do_test vtab1.10-3 { set ::echo_module_begin_fail r catchsql { | > | 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 | catchsql { SELECT * FROM e2; } } {1 {vtable constructor failed: e2}} do_test vtab1.10-2 { set rc [catch { set ptr [sqlite3_connection_pointer db] btree_breakpoint sqlite3_declare_vtab $ptr {CREATE TABLE abc(a, b, c)} } msg] list $rc $msg } {1 {library routine called out of sequence}} do_test vtab1.10-3 { set ::echo_module_begin_fail r catchsql { |
︙ | ︙ |