Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Comment: | 3.3.1 alpha |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | sourceforge |
Files: | files | file ages | folders |
SHA1: |
2e8d224477a79f75e2e55e9482548dfc |
User & Date: | rmsimpson 2006-01-16 15:51:47 |
2006-01-20
| ||
15:50 | 1.0.24.5 check-in: ab457a3ee7 user: rmsimpson tags: sourceforge | |
2006-01-16
| ||
15:51 | 3.3.1 alpha check-in: 2e8d224477 user: rmsimpson tags: sourceforge | |
15:49 | 1.0.24.4 check-in: aa2d5e4dc5 user: rmsimpson tags: sourceforge | |
Changes to SQLite.Interop/src/alter.c.
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains C code routines that used to generate VDBE code ** that implements the ALTER TABLE command. ** ** $Id: alter.c,v 1.14 2006/01/12 20:54:07 rmsimpson Exp $ */ #include "sqliteInt.h" #include <ctype.h> /* ** The code in this file only exists if we are not omitting the ** ALTER TABLE logic from the build. |
| |
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains C code routines that used to generate VDBE code ** that implements the ALTER TABLE command. ** ** $Id: alter.c,v 1.15 2006/01/16 15:51:47 rmsimpson Exp $ */ #include "sqliteInt.h" #include <ctype.h> /* ** The code in this file only exists if we are not omitting the ** ALTER TABLE logic from the build. |
Changes to SQLite.Interop/src/analyze.c.
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
** 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 associated with the ANALYZE command. ** ** @(#) $Id: analyze.c,v 1.8 2006/01/12 20:54:07 rmsimpson Exp $ */ #ifndef SQLITE_OMIT_ANALYZE #include "sqliteInt.h" /* ** This routine generates code that opens the sqlite_stat1 table on cursor ** iStatCur. |
| |
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
** 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 associated with the ANALYZE command. ** ** @(#) $Id: analyze.c,v 1.9 2006/01/16 15:51:47 rmsimpson Exp $ */ #ifndef SQLITE_OMIT_ANALYZE #include "sqliteInt.h" /* ** This routine generates code that opens the sqlite_stat1 table on cursor ** iStatCur. |
Changes to SQLite.Interop/src/attach.c.
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
** 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 implement the ATTACH and DETACH commands. ** ** $Id: attach.c,v 1.14 2006/01/12 20:54:07 rmsimpson Exp $ */ #include "sqliteInt.h" /* ** Resolve an expression that was part of an ATTACH or DETACH statement. This ** is slightly different from resolving a normal SQL expression, because simple ** identifiers are treated as strings, not possible column names or aliases. |
| |
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
** 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 implement the ATTACH and DETACH commands. ** ** $Id: attach.c,v 1.15 2006/01/16 15:51:47 rmsimpson Exp $ */ #include "sqliteInt.h" /* ** Resolve an expression that was part of an ATTACH or DETACH statement. This ** is slightly different from resolving a normal SQL expression, because simple ** identifiers are treated as strings, not possible column names or aliases. |
Changes to SQLite.Interop/src/auth.c.
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 ... 114 115 116 117 118 119 120 121 122 123 124 125 126 127 ... 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 |
** ************************************************************************* ** This file contains code used to implement the sqlite3_set_authorizer() ** API. This facility is an optional feature of the library. Embedded ** systems that do not need this facility may omit it by recompiling ** the library with -DSQLITE_OMIT_AUTHORIZATION=1 ** ** $Id: auth.c,v 1.14 2006/01/12 20:54:07 rmsimpson Exp $ */ #include "sqliteInt.h" /* ** All of the code in this file may be omitted by defining a single ** macro. */ ................................................................................ TriggerStack *pStack; /* The stack of current triggers */ int iDb; /* The index of the database the expression refers to */ if( db->xAuth==0 ) return; if( pExpr->op==TK_AS ) return; assert( pExpr->op==TK_COLUMN ); iDb = sqlite3SchemaToIndex(pParse->db, pExpr->pSchema); for(iSrc=0; pTabList && iSrc<pTabList->nSrc; iSrc++){ if( pExpr->iTable==pTabList->a[iSrc].iCursor ) break; } if( iSrc>=0 && pTabList && iSrc<pTabList->nSrc ){ pTab = pTabList->a[iSrc].pTab; }else if( (pStack = pParse->trigStack)!=0 ){ /* This must be an attempt to read the NEW or OLD pseudo-tables ................................................................................ zCol = pTab->aCol[pExpr->iColumn].zName; }else if( pTab->iPKey>=0 ){ assert( pTab->iPKey<pTab->nCol ); zCol = pTab->aCol[pTab->iPKey].zName; }else{ zCol = "ROWID"; } assert( iDb<db->nDb ); zDBase = db->aDb[iDb].zName; rc = db->xAuth(db->pAuthArg, SQLITE_READ, pTab->zName, zCol, zDBase, pParse->zAuthContext); if( rc==SQLITE_IGNORE ){ pExpr->op = TK_NULL; }else if( rc==SQLITE_DENY ){ if( db->nDb>2 || iDb!=0 ){ |
| > > > > > | |
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 ... 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 ... 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 |
** ************************************************************************* ** This file contains code used to implement the sqlite3_set_authorizer() ** API. This facility is an optional feature of the library. Embedded ** systems that do not need this facility may omit it by recompiling ** the library with -DSQLITE_OMIT_AUTHORIZATION=1 ** ** $Id: auth.c,v 1.15 2006/01/16 15:51:47 rmsimpson Exp $ */ #include "sqliteInt.h" /* ** All of the code in this file may be omitted by defining a single ** macro. */ ................................................................................ TriggerStack *pStack; /* The stack of current triggers */ int iDb; /* The index of the database the expression refers to */ if( db->xAuth==0 ) return; if( pExpr->op==TK_AS ) return; assert( pExpr->op==TK_COLUMN ); iDb = sqlite3SchemaToIndex(pParse->db, pExpr->pSchema); if( iDb<0 ){ /* An attempt to read a column out of a subquery or other ** temporary table. */ return; } for(iSrc=0; pTabList && iSrc<pTabList->nSrc; iSrc++){ if( pExpr->iTable==pTabList->a[iSrc].iCursor ) break; } if( iSrc>=0 && pTabList && iSrc<pTabList->nSrc ){ pTab = pTabList->a[iSrc].pTab; }else if( (pStack = pParse->trigStack)!=0 ){ /* This must be an attempt to read the NEW or OLD pseudo-tables ................................................................................ zCol = pTab->aCol[pExpr->iColumn].zName; }else if( pTab->iPKey>=0 ){ assert( pTab->iPKey<pTab->nCol ); zCol = pTab->aCol[pTab->iPKey].zName; }else{ zCol = "ROWID"; } assert( iDb>=0 && iDb<db->nDb ); zDBase = db->aDb[iDb].zName; rc = db->xAuth(db->pAuthArg, SQLITE_READ, pTab->zName, zCol, zDBase, pParse->zAuthContext); if( rc==SQLITE_IGNORE ){ pExpr->op = TK_NULL; }else if( rc==SQLITE_DENY ){ if( db->nDb>2 || iDb!=0 ){ |
Changes to SQLite.Interop/src/btree.c.
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ... 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 ... 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 ... 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 .... 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 .... 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 .... 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 .... 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 .... 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 .... 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 .... 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 .... 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 .... 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 .... 3161 3162 3163 3164 3165 3166 3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 3186 3187 .... 3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 3203 3204 .... 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222 3223 3224 3225 3226 .... 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 .... 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 3350 3351 3352 3353 3354 3355 3356 .... 3420 3421 3422 3423 3424 3425 3426 3427 3428 3429 3430 3431 3432 3433 3434 .... 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 3497 3498 3499 3500 3501 .... 5157 5158 5159 5160 5161 5162 5163 5164 5165 5166 5167 5168 5169 5170 5171 5172 .... 5244 5245 5246 5247 5248 5249 5250 5251 5252 5253 5254 5255 5256 5257 5258 .... 5726 5727 5728 5729 5730 5731 5732 5733 5734 5735 5736 5737 5738 5739 5740 .... 5861 5862 5863 5864 5865 5866 5867 5868 5869 5870 5871 5872 5873 5874 5875 |
** 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.16 2006/01/12 20:54:07 rmsimpson Exp $ ** ** This file implements a external (disk-based) database using BTrees. ** For a detailed discussion of BTrees, refer to ** ** Donald E. Knuth, THE ART OF COMPUTER PROGRAMMING, Volume 3: ** "Sorting And Searching", pages 473-480. Addison-Wesley ** Publishing Company, Reading, Massachusetts. ................................................................................ ** because the table is empty or because BtreeCursorFirst() has not been ** called. ** ** CURSOR_REQUIRESEEK: ** The table that this cursor was opened on still exists, but has been ** modified since the cursor was last used. The cursor position is saved ** in variables BtCursor.pKey and BtCursor.nKey. When a cursor is in ** this state, restoreCursorPosition() can be called to attempt to seek ** the cursor to the saved position. */ #define CURSOR_INVALID 0 #define CURSOR_VALID 1 #define CURSOR_REQUIRESEEK 2 /* ................................................................................ ** shared-cache feature disabled, then there is only ever one user ** of each BtShared structure and so this locking is not necessary. ** So define the lock related functions as no-ops. */ #define queryTableLock(a,b,c) SQLITE_OK #define lockTable(a,b,c) SQLITE_OK #define unlockAllTables(a) #define restoreCursorPosition(a,b) SQLITE_OK #define saveAllCursors(a,b,c) SQLITE_OK #else /* ** Save the current cursor position in the variables BtCursor.nKey ** and BtCursor.pKey. The cursor's state is set to CURSOR_REQUIRESEEK. ................................................................................ return SQLITE_OK; } /* ** Restore the cursor to the position it was in (or as close to as possible) ** when saveCursorPosition() was called. Note that this call deletes the ** saved position info stored by saveCursorPosition(), so there can be ** at most one effective restoreCursorPosition() call after each ** saveCursorPosition(). ** ** If the second argument argument - doSeek - is false, then instead of ** returning the cursor to it's saved position, any saved position is deleted ** and the cursor state set to CURSOR_INVALID. */ static int restoreCursorPosition(BtCursor *pCur, int doSeek){ int rc = SQLITE_OK; if( pCur->eState==CURSOR_REQUIRESEEK ){ assert( sqlite3ThreadDataReadOnly()->useSharedData ); if( doSeek ){ rc = sqlite3BtreeMoveto(pCur, pCur->pKey, pCur->nKey, &pCur->skip); }else{ pCur->eState = CURSOR_INVALID; } if( rc==SQLITE_OK ){ sqliteFree(pCur->pKey); pCur->pKey = 0; assert( CURSOR_VALID==pCur->eState || CURSOR_INVALID==pCur->eState ); } } return rc; } /* ** Query to see if btree handle p may obtain a lock of type eLock ** (READ_LOCK or WRITE_LOCK) on the table with root-page iTab. Return ** 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){ ................................................................................ BtCursor *pTmp = pCur; pCur = pCur->pNext; if( pTmp->pBtree==p ){ sqlite3BtreeCloseCursor(pTmp); } } sqliteFree(p); #ifndef SQLITE_OMIT_SHARED_CACHE /* If there are still other outstanding references to the shared-btree ** structure, return now. The remainder of this procedure cleans ** up the shared-btree. */ ................................................................................ } pCur = sqliteMalloc( sizeof(*pCur) ); if( pCur==0 ){ rc = SQLITE_NOMEM; goto create_cursor_exception; } pCur->pgnoRoot = (Pgno)iTable; pCur->pPage = 0; /* For exit-handler, in case getAndInitPage() fails. */ if( iTable==1 && sqlite3pager_pagecount(pBt->pPager)==0 ){ rc = SQLITE_EMPTY; goto create_cursor_exception; } rc = getAndInitPage(pBt, pCur->pgnoRoot, &pCur->pPage, 0); if( rc!=SQLITE_OK ){ goto create_cursor_exception; ................................................................................ ** variables, link the cursor into the BtShared list and set *ppCur (the ** output argument to this function). */ pCur->xCompare = xCmp ? xCmp : dfltCompare; pCur->pArg = pArg; pCur->pBtree = p; pCur->wrFlag = wrFlag; pCur->idx = 0; memset(&pCur->info, 0, sizeof(pCur->info)); pCur->pNext = pBt->pCursor; if( pCur->pNext ){ pCur->pNext->pPrev = pCur; } pCur->pPrev = 0; pBt->pCursor = pCur; pCur->eState = CURSOR_INVALID; *ppCur = pCur; return SQLITE_OK; create_cursor_exception: if( pCur ){ ................................................................................ /* ** Close a cursor. The read lock on the database file is released ** when the last cursor is closed. */ int sqlite3BtreeCloseCursor(BtCursor *pCur){ BtShared *pBt = pCur->pBtree->pBt; restoreCursorPosition(pCur, 0); if( pCur->pPrev ){ pCur->pPrev->pNext = pCur->pNext; }else{ pBt->pCursor = pCur->pNext; } if( pCur->pNext ){ pCur->pNext->pPrev = pCur->pPrev; ................................................................................ ** the key for the current entry. If the cursor is not pointing ** to a valid entry, *pSize is set to 0. ** ** For a table with the INTKEY flag set, this routine returns the key ** itself, not the number of bytes in the key. */ int sqlite3BtreeKeySize(BtCursor *pCur, i64 *pSize){ int rc = restoreCursorPosition(pCur, 1); if( rc==SQLITE_OK ){ assert( pCur->eState==CURSOR_INVALID || pCur->eState==CURSOR_VALID ); if( pCur->eState==CURSOR_INVALID ){ *pSize = 0; }else{ getCellInfo(pCur); *pSize = pCur->info.nKey; ................................................................................ ** Set *pSize to the number of bytes of data in the entry the ** cursor currently points to. Always return SQLITE_OK. ** Failure is not possible. If the cursor is not currently ** pointing to an entry (which can happen, for example, if ** the database is empty) then *pSize is set to 0. */ int sqlite3BtreeDataSize(BtCursor *pCur, u32 *pSize){ int rc = restoreCursorPosition(pCur, 1); if( rc==SQLITE_OK ){ assert( pCur->eState==CURSOR_INVALID || pCur->eState==CURSOR_VALID ); if( pCur->eState==CURSOR_INVALID ){ /* Not pointing at a valid entry - set *pSize to 0. */ *pSize = 0; }else{ getCellInfo(pCur); ................................................................................ assert( pCur!=0 && pCur->pPage!=0 ); assert( pCur->eState==CURSOR_VALID ); pBt = pCur->pBtree->pBt; pPage = pCur->pPage; pageIntegrity(pPage); assert( pCur->idx>=0 && pCur->idx<pPage->nCell ); getCellInfo(pCur); aPayload = pCur->info.pCell; aPayload += pCur->info.nHeader; if( pPage->intKey ){ nKey = 0; }else{ nKey = pCur->info.nKey; } assert( offset>=0 ); if( skipKey ){ ................................................................................ ** begins at "offset". ** ** Return SQLITE_OK on success or an error code if anything goes ** wrong. An error is returned if "offset+amt" is larger than ** the available payload. */ int sqlite3BtreeKey(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){ int rc = restoreCursorPosition(pCur, 1); if( rc==SQLITE_OK ){ assert( pCur->eState==CURSOR_VALID ); assert( pCur->pPage!=0 ); if( pCur->pPage->intKey ){ return SQLITE_CORRUPT_BKPT; } assert( pCur->pPage->intKey==0 ); ................................................................................ ** begins at "offset". ** ** Return SQLITE_OK on success or an error code if anything goes ** wrong. An error is returned if "offset+amt" is larger than ** the available payload. */ int sqlite3BtreeData(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){ int rc = restoreCursorPosition(pCur, 1); if( rc==SQLITE_OK ){ assert( pCur->eState==CURSOR_VALID ); assert( pCur->pPage!=0 ); assert( pCur->idx>=0 && pCur->idx<pCur->pPage->nCell ); rc = getPayload(pCur, offset, amt, pBuf, 1); } return rc; ................................................................................ } /* ** Move the cursor to the root page */ static int moveToRoot(BtCursor *pCur){ MemPage *pRoot; int rc; BtShared *pBt = pCur->pBtree->pBt; if( SQLITE_OK!=(rc = restoreCursorPosition(pCur, 0)) || SQLITE_OK!=(rc = getAndInitPage(pBt, pCur->pgnoRoot, &pRoot, 0)) ){ pCur->eState = CURSOR_INVALID; return rc; } releasePage(pCur->pPage); pageIntegrity(pRoot); pCur->pPage = pRoot; pCur->idx = 0; pCur->info.nSize = 0; if( pRoot->nCell==0 && !pRoot->leaf ){ Pgno subpage; assert( pRoot->pgno==1 ); subpage = get4byte(&pRoot->aData[pRoot->hdrOffset+8]); assert( subpage>0 ); ................................................................................ pCur->eState = ((pCur->pPage->nCell>0)?CURSOR_VALID:CURSOR_INVALID); return rc; } /* ** Move the cursor down to the left-most leaf entry beneath the ** entry to which it is currently pointing. */ static int moveToLeftmost(BtCursor *pCur){ Pgno pgno; int rc; MemPage *pPage; assert( pCur->eState==CURSOR_VALID ); ................................................................................ /* ** Move the cursor down to the right-most leaf entry beneath the ** page to which it is currently pointing. Notice the difference ** between moveToLeftmost() and moveToRightmost(). moveToLeftmost() ** finds the left-most entry beneath the *entry* whereas moveToRightmost() ** finds the right-most entry beneath the *page*. */ static int moveToRightmost(BtCursor *pCur){ Pgno pgno; int rc; MemPage *pPage; assert( pCur->eState==CURSOR_VALID ); ................................................................................ ** exactly matches pKey. ** ** *pRes>0 The cursor is left pointing at an entry that ** is larger than pKey. */ int sqlite3BtreeMoveto(BtCursor *pCur, const void *pKey, i64 nKey, int *pRes){ int rc; rc = moveToRoot(pCur); if( rc ) return rc; assert( pCur->pPage ); assert( pCur->pPage->isInit ); if( pCur->eState==CURSOR_INVALID ){ *pRes = -1; assert( pCur->pPage->nCell==0 ); return SQLITE_OK; } for(;;){ int lwr, upr; ................................................................................ return SQLITE_CORRUPT_BKPT; } pageIntegrity(pPage); while( lwr<=upr ){ void *pCellKey; i64 nCellKey; pCur->idx = (lwr+upr)/2; if( pPage->intKey ){ u8 *pCell = findCell(pPage, pCur->idx); pCell += pPage->childPtrSize; if( pPage->hasData ){ int dummy; pCell += getVarint32(pCell, &dummy); } getVarint(pCell, &nCellKey); pCur->info.nSize = 0; if( nCellKey<nKey ){ c = -1; }else if( nCellKey>nKey ){ c = +1; }else{ c = 0; } }else{ int available; parseCell(pPage, pCur->idx, &pCur->info); nCellKey = pCur->info.nKey; pCellKey = (void *)fetchPayload(pCur, &available, 0); if( available>=nCellKey ){ c = pCur->xCompare(pCur->pArg, nCellKey, pCellKey, nKey, pKey); }else{ pCellKey = sqliteMallocRaw( nCellKey ); if( pCellKey==0 ) return SQLITE_NOMEM; rc = sqlite3BtreeKey(pCur, 0, nCellKey, (void *)pCellKey); c = pCur->xCompare(pCur->pArg, nCellKey, pCellKey, nKey, pKey); ................................................................................ ** this routine was called, then set *pRes=1. */ int sqlite3BtreeNext(BtCursor *pCur, int *pRes){ int rc; MemPage *pPage = pCur->pPage; #ifndef SQLITE_OMIT_SHARED_CACHE rc = restoreCursorPosition(pCur, 1); if( rc!=SQLITE_OK ){ return rc; } if( pCur->skip>0 ){ pCur->skip = 0; *pRes = 0; return SQLITE_OK; ................................................................................ */ int sqlite3BtreePrevious(BtCursor *pCur, int *pRes){ int rc; Pgno pgno; MemPage *pPage; #ifndef SQLITE_OMIT_SHARED_CACHE rc = restoreCursorPosition(pCur, 1); if( rc!=SQLITE_OK ){ return rc; } if( pCur->skip<0 ){ pCur->skip = 0; *pRes = 0; return SQLITE_OK; ................................................................................ return SQLITE_PERM; /* Cursor not open for writing */ } if( checkReadLocks(pBt, pCur->pgnoRoot, pCur) ){ return SQLITE_LOCKED; /* The table pCur points to has a read lock */ } /* Save the positions of any other cursors open on this table */ if( SQLITE_OK!=(rc = restoreCursorPosition(pCur, 0)) || SQLITE_OK!=(rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur)) || SQLITE_OK!=(rc = sqlite3BtreeMoveto(pCur, pKey, nKey, &loc)) ){ return rc; } pPage = pCur->pPage; ................................................................................ /* Restore the current cursor position (a no-op if the cursor is not in ** CURSOR_REQUIRESEEK state) and save the positions of any other cursors ** open on the same table. Then call sqlite3pager_write() on the page ** that the entry will be deleted from. */ if( (rc = restoreCursorPosition(pCur, 1)) || (rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur)) || (rc = sqlite3pager_write(pPage->aData)) ){ return rc; } /* Locate the cell within it's page and leave pCell pointing to the ................................................................................ /* ** Return the flag byte at the beginning of the page that the cursor ** is currently pointing to. */ int sqlite3BtreeFlags(BtCursor *pCur){ /* TODO: What about CURSOR_REQUIRESEEK state? Probably need to call ** restoreCursorPosition() here. */ MemPage *pPage = pCur->pPage; return pPage ? pPage->aData[pPage->hdrOffset] : 0; } #ifdef SQLITE_DEBUG /* ................................................................................ ** This routine is used for testing and debugging only. */ int sqlite3BtreeCursorInfo(BtCursor *pCur, int *aResult, int upCnt){ int cnt, idx; MemPage *pPage = pCur->pPage; BtCursor tmpCur; int rc = restoreCursorPosition(pCur, 1); if( rc!=SQLITE_OK ){ return rc; } pageIntegrity(pPage); assert( pPage->isInit ); getTempCursor(pCur, &tmpCur); |
| | | | | < | > < > > > > > < < < < | | | | < | | | > > > > > > | < > > > > > > > > > > > > > > | < < > | < | | > < | | | |
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ... 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 ... 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 ... 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 .... 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 .... 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 .... 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 .... 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 .... 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 .... 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 .... 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 .... 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 .... 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 .... 3160 3161 3162 3163 3164 3165 3166 3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 3186 3187 3188 3189 3190 3191 3192 .... 3196 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 .... 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 3232 3233 3234 3235 3236 3237 .... 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 .... 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 3372 .... 3436 3437 3438 3439 3440 3441 3442 3443 3444 3445 3446 3447 3448 3449 3450 .... 3503 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513 3514 3515 3516 3517 .... 5173 5174 5175 5176 5177 5178 5179 5180 5181 5182 5183 5184 5185 5186 5187 5188 .... 5260 5261 5262 5263 5264 5265 5266 5267 5268 5269 5270 5271 5272 5273 5274 .... 5742 5743 5744 5745 5746 5747 5748 5749 5750 5751 5752 5753 5754 5755 5756 .... 5877 5878 5879 5880 5881 5882 5883 5884 5885 5886 5887 5888 5889 5890 5891 |
** 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.17 2006/01/16 15:51:47 rmsimpson Exp $ ** ** This file implements a external (disk-based) database using BTrees. ** For a detailed discussion of BTrees, refer to ** ** Donald E. Knuth, THE ART OF COMPUTER PROGRAMMING, Volume 3: ** "Sorting And Searching", pages 473-480. Addison-Wesley ** Publishing Company, Reading, Massachusetts. ................................................................................ ** because the table is empty or because BtreeCursorFirst() has not been ** called. ** ** CURSOR_REQUIRESEEK: ** The table that this cursor was opened on still exists, but has been ** modified since the cursor was last used. The cursor position is saved ** in variables BtCursor.pKey and BtCursor.nKey. When a cursor is in ** this state, restoreOrClearCursorPosition() can be called to attempt to seek ** the cursor to the saved position. */ #define CURSOR_INVALID 0 #define CURSOR_VALID 1 #define CURSOR_REQUIRESEEK 2 /* ................................................................................ ** shared-cache feature disabled, then there is only ever one user ** of each BtShared structure and so this locking is not necessary. ** So define the lock related functions as no-ops. */ #define queryTableLock(a,b,c) SQLITE_OK #define lockTable(a,b,c) SQLITE_OK #define unlockAllTables(a) #define restoreOrClearCursorPosition(a,b) SQLITE_OK #define saveAllCursors(a,b,c) SQLITE_OK #else /* ** Save the current cursor position in the variables BtCursor.nKey ** and BtCursor.pKey. The cursor's state is set to CURSOR_REQUIRESEEK. ................................................................................ return SQLITE_OK; } /* ** Restore the cursor to the position it was in (or as close to as possible) ** when saveCursorPosition() was called. Note that this call deletes the ** saved position info stored by saveCursorPosition(), so there can be ** at most one effective restoreOrClearCursorPosition() call after each ** saveCursorPosition(). ** ** If the second argument argument - doSeek - is false, then instead of ** returning the cursor to it's saved position, any saved position is deleted ** and the cursor state set to CURSOR_INVALID. */ static int restoreOrClearCursorPositionX(BtCursor *pCur, int doSeek){ int rc = SQLITE_OK; assert( sqlite3ThreadDataReadOnly()->useSharedData ); assert( pCur->eState==CURSOR_REQUIRESEEK ); if( doSeek ){ rc = sqlite3BtreeMoveto(pCur, pCur->pKey, pCur->nKey, &pCur->skip); }else{ pCur->eState = CURSOR_INVALID; } if( rc==SQLITE_OK ){ sqliteFree(pCur->pKey); pCur->pKey = 0; assert( CURSOR_VALID==pCur->eState || CURSOR_INVALID==pCur->eState ); } return rc; } #define restoreOrClearCursorPosition(p,x) \ (p->eState==CURSOR_REQUIRESEEK?restoreOrClearCursorPositionX(p,x):SQLITE_OK) /* ** Query to see if btree handle p may obtain a lock of type eLock ** (READ_LOCK or WRITE_LOCK) on the table with root-page iTab. Return ** 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){ ................................................................................ BtCursor *pTmp = pCur; pCur = pCur->pNext; if( pTmp->pBtree==p ){ sqlite3BtreeCloseCursor(pTmp); } } /* Rollback any active transaction and free the handle structure */ sqlite3BtreeRollback(p); sqliteFree(p); #ifndef SQLITE_OMIT_SHARED_CACHE /* If there are still other outstanding references to the shared-btree ** structure, return now. The remainder of this procedure cleans ** up the shared-btree. */ ................................................................................ } pCur = sqliteMalloc( sizeof(*pCur) ); if( pCur==0 ){ rc = SQLITE_NOMEM; goto create_cursor_exception; } pCur->pgnoRoot = (Pgno)iTable; if( iTable==1 && sqlite3pager_pagecount(pBt->pPager)==0 ){ rc = SQLITE_EMPTY; goto create_cursor_exception; } rc = getAndInitPage(pBt, pCur->pgnoRoot, &pCur->pPage, 0); if( rc!=SQLITE_OK ){ goto create_cursor_exception; ................................................................................ ** variables, link the cursor into the BtShared list and set *ppCur (the ** output argument to this function). */ pCur->xCompare = xCmp ? xCmp : dfltCompare; pCur->pArg = pArg; pCur->pBtree = p; pCur->wrFlag = wrFlag; pCur->pNext = pBt->pCursor; if( pCur->pNext ){ pCur->pNext->pPrev = pCur; } pBt->pCursor = pCur; pCur->eState = CURSOR_INVALID; *ppCur = pCur; return SQLITE_OK; create_cursor_exception: if( pCur ){ ................................................................................ /* ** Close a cursor. The read lock on the database file is released ** when the last cursor is closed. */ int sqlite3BtreeCloseCursor(BtCursor *pCur){ BtShared *pBt = pCur->pBtree->pBt; restoreOrClearCursorPosition(pCur, 0); if( pCur->pPrev ){ pCur->pPrev->pNext = pCur->pNext; }else{ pBt->pCursor = pCur->pNext; } if( pCur->pNext ){ pCur->pNext->pPrev = pCur->pPrev; ................................................................................ ** the key for the current entry. If the cursor is not pointing ** to a valid entry, *pSize is set to 0. ** ** For a table with the INTKEY flag set, this routine returns the key ** itself, not the number of bytes in the key. */ int sqlite3BtreeKeySize(BtCursor *pCur, i64 *pSize){ int rc = restoreOrClearCursorPosition(pCur, 1); if( rc==SQLITE_OK ){ assert( pCur->eState==CURSOR_INVALID || pCur->eState==CURSOR_VALID ); if( pCur->eState==CURSOR_INVALID ){ *pSize = 0; }else{ getCellInfo(pCur); *pSize = pCur->info.nKey; ................................................................................ ** Set *pSize to the number of bytes of data in the entry the ** cursor currently points to. Always return SQLITE_OK. ** Failure is not possible. If the cursor is not currently ** pointing to an entry (which can happen, for example, if ** the database is empty) then *pSize is set to 0. */ int sqlite3BtreeDataSize(BtCursor *pCur, u32 *pSize){ int rc = restoreOrClearCursorPosition(pCur, 1); if( rc==SQLITE_OK ){ assert( pCur->eState==CURSOR_INVALID || pCur->eState==CURSOR_VALID ); if( pCur->eState==CURSOR_INVALID ){ /* Not pointing at a valid entry - set *pSize to 0. */ *pSize = 0; }else{ getCellInfo(pCur); ................................................................................ assert( pCur!=0 && pCur->pPage!=0 ); assert( pCur->eState==CURSOR_VALID ); pBt = pCur->pBtree->pBt; pPage = pCur->pPage; pageIntegrity(pPage); assert( pCur->idx>=0 && pCur->idx<pPage->nCell ); getCellInfo(pCur); aPayload = pCur->info.pCell + pCur->info.nHeader; if( pPage->intKey ){ nKey = 0; }else{ nKey = pCur->info.nKey; } assert( offset>=0 ); if( skipKey ){ ................................................................................ ** begins at "offset". ** ** Return SQLITE_OK on success or an error code if anything goes ** wrong. An error is returned if "offset+amt" is larger than ** the available payload. */ int sqlite3BtreeKey(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){ int rc = restoreOrClearCursorPosition(pCur, 1); if( rc==SQLITE_OK ){ assert( pCur->eState==CURSOR_VALID ); assert( pCur->pPage!=0 ); if( pCur->pPage->intKey ){ return SQLITE_CORRUPT_BKPT; } assert( pCur->pPage->intKey==0 ); ................................................................................ ** begins at "offset". ** ** Return SQLITE_OK on success or an error code if anything goes ** wrong. An error is returned if "offset+amt" is larger than ** the available payload. */ int sqlite3BtreeData(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){ int rc = restoreOrClearCursorPosition(pCur, 1); if( rc==SQLITE_OK ){ assert( pCur->eState==CURSOR_VALID ); assert( pCur->pPage!=0 ); assert( pCur->idx>=0 && pCur->idx<pCur->pPage->nCell ); rc = getPayload(pCur, offset, amt, pBuf, 1); } return rc; ................................................................................ } /* ** Move the cursor to the root page */ static int moveToRoot(BtCursor *pCur){ MemPage *pRoot; int rc = SQLITE_OK; BtShared *pBt = pCur->pBtree->pBt; restoreOrClearCursorPosition(pCur, 0); assert( pCur->pPage ); pRoot = pCur->pPage; if( pRoot->pgno==pCur->pgnoRoot ){ assert( pRoot->isInit ); }else{ if( SQLITE_OK!=(rc = getAndInitPage(pBt, pCur->pgnoRoot, &pRoot, 0)) ){ pCur->eState = CURSOR_INVALID; return rc; } releasePage(pCur->pPage); pageIntegrity(pRoot); pCur->pPage = pRoot; } pCur->idx = 0; pCur->info.nSize = 0; if( pRoot->nCell==0 && !pRoot->leaf ){ Pgno subpage; assert( pRoot->pgno==1 ); subpage = get4byte(&pRoot->aData[pRoot->hdrOffset+8]); assert( subpage>0 ); ................................................................................ pCur->eState = ((pCur->pPage->nCell>0)?CURSOR_VALID:CURSOR_INVALID); return rc; } /* ** Move the cursor down to the left-most leaf entry beneath the ** entry to which it is currently pointing. ** ** The left-most leaf is the one with the smallest key - the first ** in ascending order. */ static int moveToLeftmost(BtCursor *pCur){ Pgno pgno; int rc; MemPage *pPage; assert( pCur->eState==CURSOR_VALID ); ................................................................................ /* ** Move the cursor down to the right-most leaf entry beneath the ** page to which it is currently pointing. Notice the difference ** between moveToLeftmost() and moveToRightmost(). moveToLeftmost() ** finds the left-most entry beneath the *entry* whereas moveToRightmost() ** finds the right-most entry beneath the *page*. ** ** The right-most entry is the one with the largest key - the last ** key in ascending order. */ static int moveToRightmost(BtCursor *pCur){ Pgno pgno; int rc; MemPage *pPage; assert( pCur->eState==CURSOR_VALID ); ................................................................................ ** exactly matches pKey. ** ** *pRes>0 The cursor is left pointing at an entry that ** is larger than pKey. */ int sqlite3BtreeMoveto(BtCursor *pCur, const void *pKey, i64 nKey, int *pRes){ int rc; int tryRightmost; rc = moveToRoot(pCur); if( rc ) return rc; assert( pCur->pPage ); assert( pCur->pPage->isInit ); tryRightmost = pCur->pPage->intKey; if( pCur->eState==CURSOR_INVALID ){ *pRes = -1; assert( pCur->pPage->nCell==0 ); return SQLITE_OK; } for(;;){ int lwr, upr; ................................................................................ return SQLITE_CORRUPT_BKPT; } pageIntegrity(pPage); while( lwr<=upr ){ void *pCellKey; i64 nCellKey; pCur->idx = (lwr+upr)/2; pCur->info.nSize = 0; if( pPage->intKey ){ u8 *pCell; if( tryRightmost ){ pCur->idx = upr; } pCell = findCell(pPage, pCur->idx) + pPage->childPtrSize; if( pPage->hasData ){ int dummy; pCell += getVarint32(pCell, &dummy); } getVarint(pCell, &nCellKey); if( nCellKey<nKey ){ c = -1; }else if( nCellKey>nKey ){ c = +1; tryRightmost = 0; }else{ c = 0; } }else{ int available; pCellKey = (void *)fetchPayload(pCur, &available, 0); nCellKey = pCur->info.nKey; if( available>=nCellKey ){ c = pCur->xCompare(pCur->pArg, nCellKey, pCellKey, nKey, pKey); }else{ pCellKey = sqliteMallocRaw( nCellKey ); if( pCellKey==0 ) return SQLITE_NOMEM; rc = sqlite3BtreeKey(pCur, 0, nCellKey, (void *)pCellKey); c = pCur->xCompare(pCur->pArg, nCellKey, pCellKey, nKey, pKey); ................................................................................ ** this routine was called, then set *pRes=1. */ int sqlite3BtreeNext(BtCursor *pCur, int *pRes){ int rc; MemPage *pPage = pCur->pPage; #ifndef SQLITE_OMIT_SHARED_CACHE rc = restoreOrClearCursorPosition(pCur, 1); if( rc!=SQLITE_OK ){ return rc; } if( pCur->skip>0 ){ pCur->skip = 0; *pRes = 0; return SQLITE_OK; ................................................................................ */ int sqlite3BtreePrevious(BtCursor *pCur, int *pRes){ int rc; Pgno pgno; MemPage *pPage; #ifndef SQLITE_OMIT_SHARED_CACHE rc = restoreOrClearCursorPosition(pCur, 1); if( rc!=SQLITE_OK ){ return rc; } if( pCur->skip<0 ){ pCur->skip = 0; *pRes = 0; return SQLITE_OK; ................................................................................ return SQLITE_PERM; /* Cursor not open for writing */ } if( checkReadLocks(pBt, pCur->pgnoRoot, pCur) ){ return SQLITE_LOCKED; /* The table pCur points to has a read lock */ } /* Save the positions of any other cursors open on this table */ restoreOrClearCursorPosition(pCur, 0); if( SQLITE_OK!=(rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur)) || SQLITE_OK!=(rc = sqlite3BtreeMoveto(pCur, pKey, nKey, &loc)) ){ return rc; } pPage = pCur->pPage; ................................................................................ /* Restore the current cursor position (a no-op if the cursor is not in ** CURSOR_REQUIRESEEK state) and save the positions of any other cursors ** open on the same table. Then call sqlite3pager_write() on the page ** that the entry will be deleted from. */ if( (rc = restoreOrClearCursorPosition(pCur, 1)) || (rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur)) || (rc = sqlite3pager_write(pPage->aData)) ){ return rc; } /* Locate the cell within it's page and leave pCell pointing to the ................................................................................ /* ** Return the flag byte at the beginning of the page that the cursor ** is currently pointing to. */ int sqlite3BtreeFlags(BtCursor *pCur){ /* TODO: What about CURSOR_REQUIRESEEK state? Probably need to call ** restoreOrClearCursorPosition() here. */ MemPage *pPage = pCur->pPage; return pPage ? pPage->aData[pPage->hdrOffset] : 0; } #ifdef SQLITE_DEBUG /* ................................................................................ ** This routine is used for testing and debugging only. */ int sqlite3BtreeCursorInfo(BtCursor *pCur, int *aResult, int upCnt){ int cnt, idx; MemPage *pPage = pCur->pPage; BtCursor tmpCur; int rc = restoreOrClearCursorPosition(pCur, 1); if( rc!=SQLITE_OK ){ return rc; } pageIntegrity(pPage); assert( pPage->isInit ); getTempCursor(pCur, &tmpCur); |
Changes to SQLite.Interop/src/btree.h.
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.15 2006/01/12 20:54:07 rmsimpson Exp $ */ #ifndef _BTREE_H_ #define _BTREE_H_ /* TODO: This definition is just included so other modules compile. It ** needs to be revisited. */ |
| |
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.16 2006/01/16 15:51:47 rmsimpson Exp $ */ #ifndef _BTREE_H_ #define _BTREE_H_ /* TODO: This definition is just included so other modules compile. It ** needs to be revisited. */ |
Changes to SQLite.Interop/src/build.c.
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 .... 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 .... 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 .... 3149 3150 3151 3152 3153 3154 3155 3156 3157 3158 3159 3160 3161 3162 3163 |
** CREATE INDEX ** DROP INDEX ** creating ID lists ** BEGIN TRANSACTION ** COMMIT ** ROLLBACK ** ** $Id: build.c,v 1.14 2006/01/12 20:54:07 rmsimpson Exp $ */ #include "sqliteInt.h" #include <ctype.h> /* ** This routine is called when a new SQL statement is beginning to ** be parsed. Initialize the pParse structure as needed. ................................................................................ int i; if( (p = pParse->pNewTable)==0 ) return; i = p->nCol-1; if( sqlite3LocateCollSeq(pParse, zType, nType) ){ Index *pIdx; p->aCol[i].zColl = sqlite3StrNDup(zType, nType); /* If the column is declared as "<name> PRIMARY KEY COLLATE <type>", ** then an index may have been created on this column before the ** collation type was added. Correct this if it is the case. */ for(pIdx=p->pIndex; pIdx; pIdx=pIdx->pNext){ assert( pIdx->nColumn==1 ); ................................................................................ #endif pParse->pNewTable = 0; db->nTable++; db->flags |= SQLITE_InternChanges; #ifndef SQLITE_OMIT_ALTERTABLE if( !p->pSelect ){ assert( !pSelect && pCons && pEnd ); if( pCons->z==0 ) pCons = pEnd; p->addColOffset = 13 + (pCons->z - pParse->sNameToken.z); } #endif } } #ifndef SQLITE_OMIT_VIEW /* ................................................................................ if( pName1==0 || pName1->z==0 ){ reindexDatabases(pParse, 0); return; }else if( pName2==0 || pName2->z==0 ){ assert( pName1->z ); pColl = sqlite3FindCollSeq(db, ENC(db), (char*)pName1->z, pName1->n, 0); if( pColl ){ char *z = sqlite3StrNDup(pName1->z, pName1->n); if( z ){ reindexDatabases(pParse, z); sqliteFree(z); } return; } } |
| | > | | |
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 .... 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 .... 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 .... 3150 3151 3152 3153 3154 3155 3156 3157 3158 3159 3160 3161 3162 3163 3164 |
** CREATE INDEX ** DROP INDEX ** creating ID lists ** BEGIN TRANSACTION ** COMMIT ** ROLLBACK ** ** $Id: build.c,v 1.15 2006/01/16 15:51:47 rmsimpson Exp $ */ #include "sqliteInt.h" #include <ctype.h> /* ** This routine is called when a new SQL statement is beginning to ** be parsed. Initialize the pParse structure as needed. ................................................................................ int i; if( (p = pParse->pNewTable)==0 ) return; i = p->nCol-1; if( sqlite3LocateCollSeq(pParse, zType, nType) ){ Index *pIdx; p->aCol[i].zColl = sqliteStrNDup(zType, nType); /* If the column is declared as "<name> PRIMARY KEY COLLATE <type>", ** then an index may have been created on this column before the ** collation type was added. Correct this if it is the case. */ for(pIdx=p->pIndex; pIdx; pIdx=pIdx->pNext){ assert( pIdx->nColumn==1 ); ................................................................................ #endif pParse->pNewTable = 0; db->nTable++; db->flags |= SQLITE_InternChanges; #ifndef SQLITE_OMIT_ALTERTABLE if( !p->pSelect ){ const unsigned char *zName = pParse->sNameToken.z; assert( !pSelect && pCons && pEnd ); if( pCons->z==0 ) pCons = pEnd; p->addColOffset = 13 + sqlite3utf8CharLen(zName, pCons->z - zName); } #endif } } #ifndef SQLITE_OMIT_VIEW /* ................................................................................ if( pName1==0 || pName1->z==0 ){ reindexDatabases(pParse, 0); return; }else if( pName2==0 || pName2->z==0 ){ assert( pName1->z ); pColl = sqlite3FindCollSeq(db, ENC(db), (char*)pName1->z, pName1->n, 0); if( pColl ){ char *z = sqliteStrNDup(pName1->z, pName1->n); if( z ){ reindexDatabases(pParse, z); sqliteFree(z); } return; } } |
Changes to SQLite.Interop/src/callback.c.
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 functions used to access the internal hash tables ** of user defined functions and collation sequences. ** ** $Id: callback.c,v 1.10 2006/01/12 20:54:07 rmsimpson Exp $ */ #include "sqliteInt.h" /* ** Invoke the 'collation needed' callback to request a collation sequence ** in the database text encoding of name zName, length nName. |
| |
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 functions used to access the internal hash tables ** of user defined functions and collation sequences. ** ** $Id: callback.c,v 1.11 2006/01/16 15:51:47 rmsimpson Exp $ */ #include "sqliteInt.h" /* ** Invoke the 'collation needed' callback to request a collation sequence ** in the database text encoding of name zName, length nName. |
Changes to SQLite.Interop/src/complete.c.
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
** An tokenizer for SQL ** ** This file contains C code that implements the sqlite3_complete() API. ** This code used to be part of the tokenizer.c source file. But by ** separating it out, the code will be automatically omitted from ** static links that do not use it. ** ** $Id: complete.c,v 1.8 2006/01/12 20:54:07 rmsimpson Exp $ */ #include "sqliteInt.h" #ifndef SQLITE_OMIT_COMPLETE /* ** This is defined in tokenize.c. We just have to import the definition. */ |
| |
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
** An tokenizer for SQL ** ** This file contains C code that implements the sqlite3_complete() API. ** This code used to be part of the tokenizer.c source file. But by ** separating it out, the code will be automatically omitted from ** static links that do not use it. ** ** $Id: complete.c,v 1.9 2006/01/16 15:51:47 rmsimpson Exp $ */ #include "sqliteInt.h" #ifndef SQLITE_OMIT_COMPLETE /* ** This is defined in tokenize.c. We just have to import the definition. */ |
Changes to SQLite.Interop/src/date.c.
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
...
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
|
** This file contains the C functions that implement date and time ** functions for SQLite. ** ** There is only one exported symbol in this file - the function ** sqlite3RegisterDateTimeFunctions() found at the bottom of the file. ** All other code has file scope. ** ** $Id: date.c,v 1.15 2006/01/13 03:36:39 rmsimpson Exp $ ** ** NOTES: ** ** SQLite processes all times and dates as Julian Day numbers. The ** dates and times are stored as the number of days since noon ** in Greenwich on November 24, 4714 B.C. according to the Gregorian ** calendar system. ................................................................................ min = va_arg(ap, int); max = va_arg(ap, int); nextC = va_arg(ap, int); pVal = va_arg(ap, int*); val = 0; while( N-- ){ if( !isdigit(*(u8*)zDate) ){ return cnt; } val = val*10 + *zDate - '0'; zDate++; } if( val<min || val>max || (nextC!=0 && nextC!=*zDate) ){ return cnt; } *pVal = val; zDate++; cnt++; }while( nextC ); va_end(ap); return cnt; } /* ** Read text from z[] and convert into a floating point number. Return ** the number of digits converted. */ |
|
|
|
>
|
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
...
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
|
** This file contains the C functions that implement date and time ** functions for SQLite. ** ** There is only one exported symbol in this file - the function ** sqlite3RegisterDateTimeFunctions() found at the bottom of the file. ** All other code has file scope. ** ** $Id: date.c,v 1.16 2006/01/16 15:51:47 rmsimpson Exp $ ** ** NOTES: ** ** SQLite processes all times and dates as Julian Day numbers. The ** dates and times are stored as the number of days since noon ** in Greenwich on November 24, 4714 B.C. according to the Gregorian ** calendar system. ................................................................................ min = va_arg(ap, int); max = va_arg(ap, int); nextC = va_arg(ap, int); pVal = va_arg(ap, int*); val = 0; while( N-- ){ if( !isdigit(*(u8*)zDate) ){ goto end_getDigits; } val = val*10 + *zDate - '0'; zDate++; } if( val<min || val>max || (nextC!=0 && nextC!=*zDate) ){ goto end_getDigits; } *pVal = val; zDate++; cnt++; }while( nextC ); va_end(ap); end_getDigits: return cnt; } /* ** Read text from z[] and convert into a floating point number. Return ** the number of digits converted. */ |
Changes to SQLite.Interop/src/delete.c.
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains C code routines that are called by the parser ** in order to generate code for DELETE FROM statements. ** ** $Id: delete.c,v 1.14 2006/01/12 20:54:07 rmsimpson Exp $ */ #include "sqliteInt.h" /* ** Look up every table that is named in pSrc. If any table is not found, ** add an error message to pParse->zErrMsg and return NULL. If all tables ** are found, return a pointer to the last table. |
| |
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains C code routines that are called by the parser ** in order to generate code for DELETE FROM statements. ** ** $Id: delete.c,v 1.15 2006/01/16 15:51:47 rmsimpson Exp $ */ #include "sqliteInt.h" /* ** Look up every table that is named in pSrc. If any table is not found, ** add an error message to pParse->zErrMsg and return NULL. If all tables ** are found, return a pointer to the last table. |
Changes to SQLite.Interop/src/experimental.c.
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains C code routines that are not a part of the official ** SQLite API. These routines are unsupported. ** ** $Id: experimental.c,v 1.4 2006/01/12 20:54:07 rmsimpson Exp $ */ #include "sqliteInt.h" /* ** Set all the parameters in the compiled SQL statement to NULL. */ int sqlite3_clear_bindings(sqlite3_stmt *pStmt){ |
| |
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains C code routines that are not a part of the official ** SQLite API. These routines are unsupported. ** ** $Id: experimental.c,v 1.5 2006/01/16 15:51:47 rmsimpson Exp $ */ #include "sqliteInt.h" /* ** Set all the parameters in the compiled SQL statement to NULL. */ int sqlite3_clear_bindings(sqlite3_stmt *pStmt){ |
Changes to SQLite.Interop/src/expr.c.
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
|
** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains routines used for analyzing expressions and ** for generating VDBE code that evaluates expressions in SQLite. ** ** $Id: expr.c,v 1.21 2006/01/12 20:54:07 rmsimpson Exp $ */ #include "sqliteInt.h" #include <ctype.h> /* ** Return the 'affinity' of the expression pExpr if any. ** ................................................................................ break; } } if( i>=pParse->nVarExpr ){ pExpr->iTable = ++pParse->nVar; if( pParse->nVarExpr>=pParse->nVarExprAlloc-1 ){ pParse->nVarExprAlloc += pParse->nVarExprAlloc + 10; sqlite3ReallocOrFree((void**)&pParse->apVarExpr, pParse->nVarExprAlloc*sizeof(pParse->apVarExpr[0]) ); } if( !sqlite3ThreadDataReadOnly()->mallocFailed ){ assert( pParse->apVarExpr!=0 ); pParse->apVarExpr[pParse->nVarExpr++] = pExpr; } } |
|
|
|
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
|
** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains routines used for analyzing expressions and ** for generating VDBE code that evaluates expressions in SQLite. ** ** $Id: expr.c,v 1.22 2006/01/16 15:51:47 rmsimpson Exp $ */ #include "sqliteInt.h" #include <ctype.h> /* ** Return the 'affinity' of the expression pExpr if any. ** ................................................................................ break; } } if( i>=pParse->nVarExpr ){ pExpr->iTable = ++pParse->nVar; if( pParse->nVarExpr>=pParse->nVarExprAlloc-1 ){ pParse->nVarExprAlloc += pParse->nVarExprAlloc + 10; sqliteReallocOrFree((void**)&pParse->apVarExpr, pParse->nVarExprAlloc*sizeof(pParse->apVarExpr[0]) ); } if( !sqlite3ThreadDataReadOnly()->mallocFailed ){ assert( pParse->apVarExpr!=0 ); pParse->apVarExpr[pParse->nVarExpr++] = pExpr; } } |
Changes to SQLite.Interop/src/func.c.
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
** This file contains the C functions that implement various SQL ** functions of SQLite. ** ** There is only one exported symbol in this file - the function ** sqliteRegisterBuildinFunctions() found at the bottom of the file. ** All other code has file scope. ** ** $Id: func.c,v 1.16 2006/01/13 03:36:39 rmsimpson Exp $ */ #include "sqliteInt.h" #include <ctype.h> /* #include <math.h> */ #include <stdlib.h> #include <assert.h> #include "vdbeInt.h" |
| |
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
** This file contains the C functions that implement various SQL ** functions of SQLite. ** ** There is only one exported symbol in this file - the function ** sqliteRegisterBuildinFunctions() found at the bottom of the file. ** All other code has file scope. ** ** $Id: func.c,v 1.17 2006/01/16 15:51:47 rmsimpson Exp $ */ #include "sqliteInt.h" #include <ctype.h> /* #include <math.h> */ #include <stdlib.h> #include <assert.h> #include "vdbeInt.h" |
Changes to SQLite.Interop/src/hash.c.
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This is the implementation of generic hash-tables ** used in SQLite. ** ** $Id: hash.c,v 1.14 2006/01/12 20:54:07 rmsimpson Exp $ */ #include "sqliteInt.h" #include <assert.h> /* Turn bulk memory into a hash table object by initializing the ** fields of the Hash structure. ** |
| |
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This is the implementation of generic hash-tables ** used in SQLite. ** ** $Id: hash.c,v 1.15 2006/01/16 15:51:47 rmsimpson Exp $ */ #include "sqliteInt.h" #include <assert.h> /* Turn bulk memory into a hash table object by initializing the ** fields of the Hash structure. ** |
Changes to SQLite.Interop/src/hash.h.
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This is the header file for the generic hash-table implemenation ** used in SQLite. ** ** $Id: hash.h,v 1.14 2006/01/12 20:54:07 rmsimpson Exp $ */ #ifndef _SQLITE_HASH_H_ #define _SQLITE_HASH_H_ /* Forward declarations of structures. */ typedef struct Hash Hash; typedef struct HashElem HashElem; |
| |
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This is the header file for the generic hash-table implemenation ** used in SQLite. ** ** $Id: hash.h,v 1.15 2006/01/16 15:51:47 rmsimpson Exp $ */ #ifndef _SQLITE_HASH_H_ #define _SQLITE_HASH_H_ /* Forward declarations of structures. */ typedef struct Hash Hash; typedef struct HashElem HashElem; |
Changes to SQLite.Interop/src/insert.c.
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains C code routines that are called by the parser ** to handle INSERT statements in SQLite. ** ** $Id: insert.c,v 1.14 2006/01/12 20:54:07 rmsimpson Exp $ */ #include "sqliteInt.h" /* ** Set P3 of the most recently inserted opcode to a column affinity ** string for index pIdx. A column affinity string has one character ** for each column in the table, according to the affinity of the column: |
| |
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains C code routines that are called by the parser ** to handle INSERT statements in SQLite. ** ** $Id: insert.c,v 1.15 2006/01/16 15:51:47 rmsimpson Exp $ */ #include "sqliteInt.h" /* ** Set P3 of the most recently inserted opcode to a column affinity ** string for index pIdx. A column affinity string has one character ** for each column in the table, according to the affinity of the column: |
Changes to SQLite.Interop/src/legacy.c.
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: legacy.c,v 1.14 2006/01/12 20:54:07 rmsimpson Exp $ */ #include "sqliteInt.h" #include "os.h" #include <ctype.h> /* |
| |
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: legacy.c,v 1.15 2006/01/16 15:51:47 rmsimpson Exp $ */ #include "sqliteInt.h" #include "os.h" #include <ctype.h> /* |
Changes to SQLite.Interop/src/main.c.
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.14 2006/01/12 20:54:07 rmsimpson Exp $ */ #include "sqliteInt.h" #include "os.h" #include <ctype.h> /* ** The following constant value is used by the SQLITE_BIGENDIAN and |
| |
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.15 2006/01/16 15:51:47 rmsimpson Exp $ */ #include "sqliteInt.h" #include "os.h" #include <ctype.h> /* ** The following constant value is used by the SQLITE_BIGENDIAN and |
Changes to SQLite.Interop/src/os_common.h.
128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 |
** sqlite3GenericRealloc ** sqlite3GenericOsFree ** sqlite3GenericAllocationSize ** ** Implementation of the os level dynamic memory allocation interface in terms ** of the standard malloc(), realloc() and free() found in many operating ** systems. No rocket science here. */ void *sqlite3GenericMalloc(int n){ char *p = (char *)malloc(n+8); assert(n>0); assert(sizeof(int)<=8); if( p ){ *(int *)p = n; } return (void *)(p + 8); } void *sqlite3GenericRealloc(void *p, int n){ char *p2 = ((char *)p - 8); assert(n>0); p2 = realloc(p2, n+8); if( p2 ){ *(int *)p2 = n; } return (void *)((char *)p2 + 8); } void sqlite3GenericFree(void *p){ assert(p); free((void *)((char *)p - 8)); } int sqlite3GenericAllocationSize(void *p){ return p ? *(int *)((char *)p - 8) : 0; } |
> > > > > > > > > > | > | > > > > > > > > > > > > > > > > > > > > |
128 129 130 131 132 133 134 135 136 137 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 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 |
** sqlite3GenericRealloc ** sqlite3GenericOsFree ** sqlite3GenericAllocationSize ** ** Implementation of the os level dynamic memory allocation interface in terms ** of the standard malloc(), realloc() and free() found in many operating ** systems. No rocket science here. ** ** There are two versions of these four functions here. The version ** implemented here is only used if memory-management or memory-debugging is ** enabled. This version allocates an extra 8-bytes at the beginning of each ** block and stores the size of the allocation there. ** ** If neither memory-management or debugging is enabled, the second ** set of implementations is used instead. */ #if defined(SQLITE_ENABLE_MEMORY_MANAGEMENT) || defined (SQLITE_MEMDEBUG) void *sqlite3GenericMalloc(int n){ char *p = (char *)malloc(n+8); assert(n>0); assert(sizeof(int)<=8); if( p ){ *(int *)p = n; p += 8; } return (void *)p; } void *sqlite3GenericRealloc(void *p, int n){ char *p2 = ((char *)p - 8); assert(n>0); p2 = realloc(p2, n+8); if( p2 ){ *(int *)p2 = n; p2 += 8; } return (void *)p2; } void sqlite3GenericFree(void *p){ assert(p); free((void *)((char *)p - 8)); } int sqlite3GenericAllocationSize(void *p){ return p ? *(int *)((char *)p - 8) : 0; } #else void *sqlite3GenericMalloc(int n){ char *p = (char *)malloc(n); return (void *)p; } void *sqlite3GenericRealloc(void *p, int n){ assert(n>0); p = realloc(p, n); return p; } void sqlite3GenericFree(void *p){ assert(p); free(p); } #if 0 /* Never actually invoked */ int sqlite3GenericAllocationSize(void *p){ assert(0); } #endif #endif |
Changes to SQLite.Interop/src/os_unix.c.
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 .. 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 .. 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 ... 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 ... 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 ... 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 ... 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 ... 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 ... 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 ... 501 502 503 504 505 506 507 508 509 510 511 512 513 514 ... 536 537 538 539 540 541 542 543 544 545 546 547 548 549 ... 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 ... 758 759 760 761 762 763 764 765 766 767 768 769 770 771 .... 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 .... 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 .... 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 .... 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 .... 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 .... 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 .... 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 .... 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 .... 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 .... 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 .... 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 .... 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 .... 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 |
#include "sqliteInt.h" #include "os.h" #if OS_UNIX /* This file is used on unix only */ /* ** These #defines should enable >2GB file support on Posix if the ** underlying operating system supports it. If the OS lacks ** large file support, or if the OS is windows, these should be no-ops. ** ** Large file support can be disabled using the -DSQLITE_DISABLE_LFS switch ** on the compiler command line. This is necessary if you are compiling ** on a recent machine (ex: RedHat 7.2) but you want your code to work ** on an older machine (ex: RedHat 6.0). If you compile on RedHat 7.2 ** without this option, LFS is enable. But LFS does not exist in the kernel ** in RedHat 6.0, so the code won't work. Hence, for maximum binary ** portability you should omit LFS. ** ** Similar is true for MacOS. LFS is only supported on MacOS 9 and later. */ #ifndef SQLITE_DISABLE_LFS # define _LARGE_FILE 1 # ifndef _FILE_OFFSET_BITS # define _FILE_OFFSET_BITS 64 # endif # define _LARGEFILE_SOURCE 1 ................................................................................ #include <fcntl.h> #include <unistd.h> #include <time.h> #include <sys/time.h> #include <errno.h> /* ** Macros used to determine whether or not to use threads. The ** SQLITE_UNIX_THREADS macro is defined if we are synchronizing for ** Posix threads and SQLITE_W32_THREADS is defined if we are ** synchronizing using Win32 threads. */ #if defined(THREADSAFE) && THREADSAFE # include <pthread.h> # define SQLITE_UNIX_THREADS 1 #endif /* ................................................................................ struct lockInfo *pLock; /* Info about locks on this inode */ int h; /* The file descriptor */ unsigned char locktype; /* The type of lock held on this fd */ unsigned char isOpen; /* True if needs to be closed */ unsigned char fullSync; /* Use F_FULLSYNC if available */ int dirfd; /* File descriptor for the directory */ #ifdef SQLITE_UNIX_THREADS pthread_t tid; /* The thread authorized to use this OsFile */ #endif }; /* ** Provide the ability to override some OS-layer functions during ** testing. This is used to simulate OS crashes to verify that ** commits are atomic even in the event of an OS crash. ................................................................................ /* ** Include code that is common to all os_*.c files */ #include "os_common.h" /* ** Do not include any of the File I/O interface procedures if the ** SQLITE_OMIT_DISKIO macro is defined (indicating that there database ** will be in-memory only) */ #ifndef SQLITE_OMIT_DISKIO /* ** Define various macros that are missing from some systems. ................................................................................ ** Set or check the OsFile.tid field. This field is set when an OsFile ** is first opened. All subsequent uses of the OsFile verify that the ** same thread is operating on the OsFile. Some operating systems do ** not allow locks to be overridden by other threads and that restriction ** means that sqlite3* database handles cannot be moved from one thread ** to another. This logic makes sure a user does not try to do that ** by mistake. */ #if defined(SQLITE_UNIX_THREADS) && !defined(SQLITE_ALLOW_XTHREAD_CONNECTIONS) # define SET_THREADID(X) (X)->tid = pthread_self() # define CHECK_THREADID(X) (!pthread_equal((X)->tid, pthread_self())) #else # define SET_THREADID(X) # define CHECK_THREADID(X) 0 #endif /* ** Here is the dirt on POSIX advisory locks: ANSI STD 1003.1 (1996) ................................................................................ /* ** An instance of the following structure serves as the key used ** to locate a particular lockInfo structure given its inode. ** ** If threads cannot override each others locks, then we set the ** lockKey.tid field to the thread ID. If threads can override ** each others locks then tid is always set to zero. tid is also ** set to zero if we compile without threading support. */ struct lockKey { dev_t dev; /* Device number */ ino_t ino; /* Inode number */ #ifdef SQLITE_UNIX_THREADS pthread_t tid; /* Thread ID or zero if threads can override each other */ #endif ................................................................................ int nRef; /* Number of pointers to this structure */ int nLock; /* Number of outstanding locks */ int nPending; /* Number of pending close() operations */ int *aPending; /* Malloced space holding fd's awaiting a close() */ }; /* ** These hash table maps inodes and process IDs into lockInfo and openCnt ** structures. Access to these hash tables must be protected by a mutex. */ static Hash lockHash = { SQLITE_HASH_BINARY, 0, 0, 0, 0, 0 }; static Hash openHash = { SQLITE_HASH_BINARY, 0, 0, 0, 0, 0 }; #ifdef SQLITE_UNIX_THREADS /* ** This variable records whether or not threads can override each others ** locks. ** ** 0: No. Threads cannot override each others locks. ** 1: Yes. Threads can override each others locks. ** -1: We don't know yet. */ static int threadsOverrideEachOthersLocks = -1; /* ** This structure holds information passed into individual test ** threads by the testThreadLockingBehavior() routine. */ struct threadTestData { int fd; /* File to be locked */ ................................................................................ #ifdef SQLITE_LOCK_TRACE /* ** Print out information about all locking operations. ** ** This routine is used for troubleshooting locks on multithreaded ** platforms. Enable by compiling with the -DSQLITE_LOCK_TRACE ** command-line option on the compiler. This code is normally ** turnned off. */ static int lockTrace(int fd, int op, struct flock *p){ char *zOpName, *zType; int s; int savedErrno; if( op==F_GETLK ){ zOpName = "GETLK"; ................................................................................ } #endif /* SQLITE_UNIX_THREADS */ /* ** Release a lockInfo structure previously allocated by findLockInfo(). */ static void releaseLockInfo(struct lockInfo *pLock){ pLock->nRef--; if( pLock->nRef==0 ){ sqlite3HashInsert(&lockHash, &pLock->key, sizeof(pLock->key), 0); sqliteFree(pLock); } } /* ** Release a openCnt structure previously allocated by findLockInfo(). */ static void releaseOpenCnt(struct openCnt *pOpen){ pOpen->nRef--; if( pOpen->nRef==0 ){ sqlite3HashInsert(&openHash, &pOpen->key, sizeof(pOpen->key), 0); sqliteFree(pOpen->aPending); sqliteFree(pOpen); } } /* ** Given a file descriptor, locate lockInfo and openCnt structures that ** describes that file descriptor. Create a new ones if necessary. The ** return values might be unset if an error occurs. ** ** Return the number of errors. */ static int findLockInfo( int fd, /* The file descriptor used in the key */ struct lockInfo **ppLock, /* Return the lockInfo structure here */ struct openCnt **ppOpen /* Return the openCnt structure here */ ................................................................................ struct openKey key2; struct stat statbuf; struct lockInfo *pLock; struct openCnt *pOpen; rc = fstat(fd, &statbuf); if( rc!=0 ) return 1; memset(&key1, 0, sizeof(key1)); key1.dev = statbuf.st_dev; key1.ino = statbuf.st_ino; #ifdef SQLITE_UNIX_THREADS if( threadsOverrideEachOthersLocks<0 ){ testThreadLockingBehavior(fd); } ................................................................................ rc = 1; goto exit_findlockinfo; } }else{ pLock->nRef++; } *ppLock = pLock; pOpen = (struct openCnt*)sqlite3HashFind(&openHash, &key2, sizeof(key2)); if( pOpen==0 ){ struct openCnt *pOld; pOpen = sqliteMallocRaw( sizeof(*pOpen) ); if( pOpen==0 ){ releaseLockInfo(pLock); rc = 1; ................................................................................ rc = 1; goto exit_findlockinfo; } }else{ pOpen->nRef++; } *ppOpen = pOpen; exit_findlockinfo: return rc; } /* ** Delete the named file */ int sqlite3UnixDelete(const char *zFilename){ unlink(zFilename); return SQLITE_OK; ................................................................................ return SQLITE_OK; } /* ** If the following global variable points to a string which is the ** name of a directory, then that directory will be used to store ** temporary files. */ char *sqlite3_temp_directory = 0; /* ** Create a temporary file name in zBuf. zBuf must be big enough to ** hold at least SQLITE_TEMPNAME_SIZE characters. */ ................................................................................ ** return zero. */ static int unixCheckReservedLock(OsFile *id){ int r = 0; unixFile *pFile = (unixFile*)id; assert( pFile ); if( CHECK_THREADID(pFile) ) return SQLITE_MISUSE; sqlite3OsEnterMutex(); /* Because pFile->pLock is shared across threads */ /* Check if a thread in this process holds such a lock */ if( pFile->pLock->locktype>SHARED_LOCK ){ r = 1; } ................................................................................ sqlite3OsLeaveMutex(); TRACE3("TEST WR-LOCK %d %d\n", pFile->h, r); return r; } #ifdef SQLITE_DEBUG /* ** Helper function for printing out trace information from debugging ** binaries. This returns the string represetation of the supplied ** integer lock-type. */ static const char *locktypeName(int locktype){ switch( locktype ){ case NO_LOCK: return "NONE"; case SHARED_LOCK: return "SHARED"; case RESERVED_LOCK: return "RESERVED"; case PENDING_LOCK: return "PENDING"; case EXCLUSIVE_LOCK: return "EXCLUSIVE"; } return "ERROR"; } #endif /* ** Lock the file with the lock specified by parameter locktype - one ** of the following: ** ** (1) SHARED_LOCK ** (2) RESERVED_LOCK ** (3) PENDING_LOCK ................................................................................ struct flock lock; int s; assert( pFile ); TRACE7("LOCK %d %s was %s(%s,%d) pid=%d\n", pFile->h, locktypeName(locktype), locktypeName(pFile->locktype), locktypeName(pLock->locktype), pLock->cnt , getpid()); if( CHECK_THREADID(pFile) ) return SQLITE_MISUSE; /* If there is already a lock of this type or more restrictive on the ** OsFile, do nothing. Don't use the end_lock: exit path, as ** sqlite3OsEnterMutex() hasn't been called yet. */ if( pFile->locktype>=locktype ){ TRACE3("LOCK %d %s ok (already held)\n", pFile->h, ................................................................................ assert( pFile->locktype!=NO_LOCK || locktype==SHARED_LOCK ); assert( locktype!=PENDING_LOCK ); assert( locktype!=RESERVED_LOCK || pFile->locktype==SHARED_LOCK ); /* This mutex is needed because pFile->pLock is shared across threads */ sqlite3OsEnterMutex(); /* If some thread using this PID has a lock via a different OsFile* ** handle that precludes the requested lock, return BUSY. */ if( (pFile->locktype!=pLock->locktype && (pLock->locktype>=PENDING_LOCK || locktype>SHARED_LOCK)) ){ ................................................................................ /* ** Lower the locking level on file descriptor pFile to locktype. locktype ** must be either NO_LOCK or SHARED_LOCK. ** ** If the locking level of the file descriptor is already at or below ** the requested locking level, this routine is a no-op. ** ** It is not possible for this routine to fail if the second argument ** is NO_LOCK. If the second argument is SHARED_LOCK, this routine ** might return SQLITE_IOERR instead of SQLITE_OK. */ static int unixUnlock(OsFile *id, int locktype){ struct lockInfo *pLock; struct flock lock; int rc = SQLITE_OK; unixFile *pFile = (unixFile*)id; assert( pFile ); TRACE7("UNLOCK %d %d was %d(%d,%d) pid=%d\n", pFile->h, locktype, pFile->locktype, pFile->pLock->locktype, pFile->pLock->cnt, getpid()); if( CHECK_THREADID(pFile) ) return SQLITE_MISUSE; assert( locktype<=SHARED_LOCK ); if( pFile->locktype<=locktype ){ return SQLITE_OK; } sqlite3OsEnterMutex(); pLock = pFile->pLock; assert( pLock->cnt!=0 ); if( pFile->locktype>SHARED_LOCK ){ assert( pLock->locktype==pFile->locktype ); if( locktype==SHARED_LOCK ){ ................................................................................ pOpen->nLock--; assert( pOpen->nLock>=0 ); if( pOpen->nLock==0 && pOpen->nPending>0 ){ int i; for(i=0; i<pOpen->nPending; i++){ close(pOpen->aPending[i]); } sqliteFree(pOpen->aPending); pOpen->nPending = 0; pOpen->aPending = 0; } } sqlite3OsLeaveMutex(); pFile->locktype = locktype; return rc; ................................................................................ } /* ** Close a file. */ static int unixClose(OsFile **pId){ unixFile *id = (unixFile*)*pId; if( !id ) return SQLITE_OK; if( CHECK_THREADID(id) ) return SQLITE_MISUSE; unixUnlock(*pId, NO_LOCK); if( id->dirfd>=0 ) close(id->dirfd); id->dirfd = -1; sqlite3OsEnterMutex(); if( id->pOpen->nLock ){ /* If there are outstanding locks, do not actually close the file just ** yet because that would clear those locks. Instead, add the file ** descriptor to pOpen->aPending. It will be automatically closed when ** the last lock is cleared. */ int *aNew; struct openCnt *pOpen = id->pOpen; aNew = sqliteRealloc( pOpen->aPending, (pOpen->nPending+1)*sizeof(int) ); if( aNew==0 ){ /* If a malloc fails, just leak the file descriptor */ }else{ pOpen->aPending = aNew; pOpen->aPending[pOpen->nPending] = id->h; pOpen->nPending++; } ................................................................................ sqlite3OsLeaveMutex(); id->isOpen = 0; TRACE2("CLOSE %-3d\n", id->h); OpenCounter(-1); sqliteFree(id); *pId = 0; return SQLITE_OK; } /* ** Turn a relative pathname into a full pathname. Return a pointer ** to the full pathname stored in space obtained from sqliteMalloc(). ** The calling function is responsible for freeing this space once it ** is no longer needed. ................................................................................ ** OsFile. If we run out of memory, close the file and return NULL. */ static int allocateUnixFile(unixFile *pInit, OsFile **pId){ unixFile *pNew; pNew = sqliteMalloc( sizeof(unixFile) ); if( pNew==0 ){ close(pInit->h); releaseLockInfo(pInit->pLock); releaseOpenCnt(pInit->pOpen); *pId = 0; return SQLITE_NOMEM; }else{ *pNew = *pInit; pNew->pMethod = &sqlite3UnixIoMethod; *pId = (OsFile*)pNew; OpenCounter(+1); ................................................................................ ** prefer that the randomness be increased by making use of the ** uninitialized space in zBuf - but valgrind errors tend to worry ** some users. Rather than argue, it seems easier just to initialize ** the whole array and silence valgrind, even if that means less randomness ** in the random seed. ** ** When testing, initializing zBuf[] to zero is all we do. That means ** that we always use the same random number sequence.* This makes the ** tests repeatable. */ memset(zBuf, 0, 256); #if !defined(SQLITE_TEST) { int pid, fd; fd = open("/dev/urandom", O_RDONLY); ................................................................................ } #endif return SQLITE_OK; } /* ** Sleep for a little while. Return the amount of time slept. */ int sqlite3UnixSleep(int ms){ #if defined(HAVE_USLEEP) && HAVE_USLEEP usleep(ms*1000); return ms; #else sleep((ms+999)/1000); ................................................................................ /* ** The following pair of routine implement mutual exclusion for ** multi-threaded processes. Only a single thread is allowed to ** executed code that is surrounded by EnterMutex() and LeaveMutex(). ** ** SQLite uses only a single Mutex. There is not much critical ** code and what little there is executes quickly and without blocking. */ void sqlite3UnixEnterMutex(){ #ifdef SQLITE_UNIX_THREADS pthread_mutex_lock(&mutex); #endif assert( !inMutex ); inMutex = 1; ................................................................................ # endif #else # define TSD_COUNTER(N) /* no-op */ #endif /* ** If called with allocateFlag>1, then return a pointer to thread ** specific data for the current thread. Allocate and zero the ** thread-specific data if it does not already exist necessary. ** ** If called with allocateFlag==0, then check the current thread ** specific data. Return it if it exists. If it does not exist, ** then return NULL. ** ** If called with allocateFlag<0, check to see if the thread specific ** data is allocated and is all zero. If it is then deallocate it. |
| < < | | < < | | > > > > > > > | > | | | | > | > > > > > > > > | > > | | | > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > < < < < < < < < < < < < < < < < < < < < > > > > > > > > > < < < < < > > > | > > < | | > > | > > > | | |
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 .. 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 .. 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 ... 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 ... 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 ... 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 ... 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 370 371 ... 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 ... 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 ... 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 ... 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 ... 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 ... 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 .... 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 .... 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 .... 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 .... 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 .... 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 .... 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 .... 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 .... 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 .... 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 .... 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 .... 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 .... 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 .... 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 |
#include "sqliteInt.h" #include "os.h" #if OS_UNIX /* This file is used on unix only */ /* ** These #defines should enable >2GB file support on Posix if the ** underlying operating system supports it. If the OS lacks ** large file support, these should be no-ops. ** ** Large file support can be disabled using the -DSQLITE_DISABLE_LFS switch ** on the compiler command line. This is necessary if you are compiling ** on a recent machine (ex: RedHat 7.2) but you want your code to work ** on an older machine (ex: RedHat 6.0). If you compile on RedHat 7.2 ** without this option, LFS is enable. But LFS does not exist in the kernel ** in RedHat 6.0, so the code won't work. Hence, for maximum binary ** portability you should omit LFS. */ #ifndef SQLITE_DISABLE_LFS # define _LARGE_FILE 1 # ifndef _FILE_OFFSET_BITS # define _FILE_OFFSET_BITS 64 # endif # define _LARGEFILE_SOURCE 1 ................................................................................ #include <fcntl.h> #include <unistd.h> #include <time.h> #include <sys/time.h> #include <errno.h> /* ** If we are to be thread-safe, include the pthreads header and define ** the SQLITE_UNIX_THREADS macro. */ #if defined(THREADSAFE) && THREADSAFE # include <pthread.h> # define SQLITE_UNIX_THREADS 1 #endif /* ................................................................................ struct lockInfo *pLock; /* Info about locks on this inode */ int h; /* The file descriptor */ unsigned char locktype; /* The type of lock held on this fd */ unsigned char isOpen; /* True if needs to be closed */ unsigned char fullSync; /* Use F_FULLSYNC if available */ int dirfd; /* File descriptor for the directory */ #ifdef SQLITE_UNIX_THREADS pthread_t tid; /* The thread that "owns" this OsFile */ #endif }; /* ** Provide the ability to override some OS-layer functions during ** testing. This is used to simulate OS crashes to verify that ** commits are atomic even in the event of an OS crash. ................................................................................ /* ** Include code that is common to all os_*.c files */ #include "os_common.h" /* ** Do not include any of the File I/O interface procedures if the ** SQLITE_OMIT_DISKIO macro is defined (indicating that the database ** will be in-memory only) */ #ifndef SQLITE_OMIT_DISKIO /* ** Define various macros that are missing from some systems. ................................................................................ ** Set or check the OsFile.tid field. This field is set when an OsFile ** is first opened. All subsequent uses of the OsFile verify that the ** same thread is operating on the OsFile. Some operating systems do ** not allow locks to be overridden by other threads and that restriction ** means that sqlite3* database handles cannot be moved from one thread ** to another. This logic makes sure a user does not try to do that ** by mistake. ** ** Version 3.3.1 (2006-01-15): OsFiles can be moved from one thread to ** another as long as we are running on a system that supports threads ** overriding each others locks (which now the most common behavior) ** or if no locks are held. But the OsFile.pLock field needs to be ** recomputed because its key includes the thread-id. See the ** transferOwnership() function below for additional information */ #if defined(SQLITE_UNIX_THREADS) # define SET_THREADID(X) (X)->tid = pthread_self() # define CHECK_THREADID(X) (threadsOverrideEachOthersLocks==0 && \ !pthread_equal((X)->tid, pthread_self())) #else # define SET_THREADID(X) # define CHECK_THREADID(X) 0 #endif /* ** Here is the dirt on POSIX advisory locks: ANSI STD 1003.1 (1996) ................................................................................ /* ** An instance of the following structure serves as the key used ** to locate a particular lockInfo structure given its inode. ** ** If threads cannot override each others locks, then we set the ** lockKey.tid field to the thread ID. If threads can override ** each others locks then tid is always set to zero. tid is omitted ** if we compile without threading support. */ struct lockKey { dev_t dev; /* Device number */ ino_t ino; /* Inode number */ #ifdef SQLITE_UNIX_THREADS pthread_t tid; /* Thread ID or zero if threads can override each other */ #endif ................................................................................ int nRef; /* Number of pointers to this structure */ int nLock; /* Number of outstanding locks */ int nPending; /* Number of pending close() operations */ int *aPending; /* Malloced space holding fd's awaiting a close() */ }; /* ** These hash tables map inodes and file descriptors (really, lockKey and ** openKey structures) into lockInfo and openCnt structures. Access to ** these hash tables must be protected by a mutex. */ static Hash lockHash = { SQLITE_HASH_BINARY, 0, 0, 0, 0, 0 }; static Hash openHash = { SQLITE_HASH_BINARY, 0, 0, 0, 0, 0 }; #ifdef SQLITE_UNIX_THREADS /* ** This variable records whether or not threads can override each others ** locks. ** ** 0: No. Threads cannot override each others locks. ** 1: Yes. Threads can override each others locks. ** -1: We don't know yet. ** ** This variable normally has file scope only. But during testing, we make ** it a global so that the test code can change its value in order to verify ** that the right stuff happens in either case. */ #ifdef SQLITE_TEST int threadsOverrideEachOthersLocks = -1; #else static int threadsOverrideEachOthersLocks = -1; #endif /* ** This structure holds information passed into individual test ** threads by the testThreadLockingBehavior() routine. */ struct threadTestData { int fd; /* File to be locked */ ................................................................................ #ifdef SQLITE_LOCK_TRACE /* ** Print out information about all locking operations. ** ** This routine is used for troubleshooting locks on multithreaded ** platforms. Enable by compiling with the -DSQLITE_LOCK_TRACE ** command-line option on the compiler. This code is normally ** turned off. */ static int lockTrace(int fd, int op, struct flock *p){ char *zOpName, *zType; int s; int savedErrno; if( op==F_GETLK ){ zOpName = "GETLK"; ................................................................................ } #endif /* SQLITE_UNIX_THREADS */ /* ** Release a lockInfo structure previously allocated by findLockInfo(). */ static void releaseLockInfo(struct lockInfo *pLock){ assert( sqlite3OsInMutex() ); pLock->nRef--; if( pLock->nRef==0 ){ sqlite3HashInsert(&lockHash, &pLock->key, sizeof(pLock->key), 0); sqliteFree(pLock); } } /* ** Release a openCnt structure previously allocated by findLockInfo(). */ static void releaseOpenCnt(struct openCnt *pOpen){ assert( sqlite3OsInMutex() ); pOpen->nRef--; if( pOpen->nRef==0 ){ sqlite3HashInsert(&openHash, &pOpen->key, sizeof(pOpen->key), 0); free(pOpen->aPending); sqliteFree(pOpen); } } /* ** Given a file descriptor, locate lockInfo and openCnt structures that ** describes that file descriptor. Create new ones if necessary. The ** return values might be uninitialized if an error occurs. ** ** Return the number of errors. */ static int findLockInfo( int fd, /* The file descriptor used in the key */ struct lockInfo **ppLock, /* Return the lockInfo structure here */ struct openCnt **ppOpen /* Return the openCnt structure here */ ................................................................................ struct openKey key2; struct stat statbuf; struct lockInfo *pLock; struct openCnt *pOpen; rc = fstat(fd, &statbuf); if( rc!=0 ) return 1; assert( sqlite3OsInMutex() ); memset(&key1, 0, sizeof(key1)); key1.dev = statbuf.st_dev; key1.ino = statbuf.st_ino; #ifdef SQLITE_UNIX_THREADS if( threadsOverrideEachOthersLocks<0 ){ testThreadLockingBehavior(fd); } ................................................................................ rc = 1; goto exit_findlockinfo; } }else{ pLock->nRef++; } *ppLock = pLock; if( ppOpen!=0 ){ pOpen = (struct openCnt*)sqlite3HashFind(&openHash, &key2, sizeof(key2)); if( pOpen==0 ){ struct openCnt *pOld; pOpen = sqliteMallocRaw( sizeof(*pOpen) ); if( pOpen==0 ){ releaseLockInfo(pLock); rc = 1; ................................................................................ rc = 1; goto exit_findlockinfo; } }else{ pOpen->nRef++; } *ppOpen = pOpen; } exit_findlockinfo: return rc; } #ifdef SQLITE_DEBUG /* ** Helper function for printing out trace information from debugging ** binaries. This returns the string represetation of the supplied ** integer lock-type. */ static const char *locktypeName(int locktype){ switch( locktype ){ case NO_LOCK: return "NONE"; case SHARED_LOCK: return "SHARED"; case RESERVED_LOCK: return "RESERVED"; case PENDING_LOCK: return "PENDING"; case EXCLUSIVE_LOCK: return "EXCLUSIVE"; } return "ERROR"; } #endif /* ** If we are currently in a different thread than the thread that the ** unixFile argument belongs to, then transfer ownership of the unixFile ** over to the current thread. ** ** A unixFile is only owned by a thread on systems where one thread is ** unable to override locks created by a different thread. RedHat9 is ** an example of such a system. ** ** Ownership transfer is only allowed if the unixFile is currently unlocked. ** If the unixFile is locked and an ownership is wrong, then return ** SQLITE_MISUSE. SQLITE_OK is returned if everything works. */ #ifdef SQLITE_UNIX_THREADS static int transferOwnership(unixFile *pFile){ int rc; pthread_t hSelf; if( threadsOverrideEachOthersLocks ){ /* Ownership transfers not needed on this system */ return SQLITE_OK; } hSelf = pthread_self(); if( pthread_equal(pFile->tid, hSelf) ){ /* We are still in the same thread */ TRACE1("No-transfer, same thread\n"); return SQLITE_OK; } if( pFile->locktype!=NO_LOCK ){ /* We cannot change ownership while we are holding a lock! */ return SQLITE_MISUSE; } TRACE4("Transfer ownership of %d from %d to %d\n", pFile->h,pFile->tid,hSelf); pFile->tid = hSelf; releaseLockInfo(pFile->pLock); rc = findLockInfo(pFile->h, &pFile->pLock, 0); TRACE5("LOCK %d is now %s(%s,%d)\n", pFile->h, locktypeName(pFile->locktype), locktypeName(pFile->pLock->locktype), pFile->pLock->cnt); return rc; } #else /* On single-threaded builds, ownership transfer is a no-op */ # define transferOwnership(X) SQLITE_OK #endif /* ** Delete the named file */ int sqlite3UnixDelete(const char *zFilename){ unlink(zFilename); return SQLITE_OK; ................................................................................ return SQLITE_OK; } /* ** If the following global variable points to a string which is the ** name of a directory, then that directory will be used to store ** temporary files. ** ** See also the "PRAGMA temp_store_directory" SQL command. */ char *sqlite3_temp_directory = 0; /* ** Create a temporary file name in zBuf. zBuf must be big enough to ** hold at least SQLITE_TEMPNAME_SIZE characters. */ ................................................................................ ** return zero. */ static int unixCheckReservedLock(OsFile *id){ int r = 0; unixFile *pFile = (unixFile*)id; assert( pFile ); sqlite3OsEnterMutex(); /* Because pFile->pLock is shared across threads */ /* Check if a thread in this process holds such a lock */ if( pFile->pLock->locktype>SHARED_LOCK ){ r = 1; } ................................................................................ sqlite3OsLeaveMutex(); TRACE3("TEST WR-LOCK %d %d\n", pFile->h, r); return r; } /* ** Lock the file with the lock specified by parameter locktype - one ** of the following: ** ** (1) SHARED_LOCK ** (2) RESERVED_LOCK ** (3) PENDING_LOCK ................................................................................ struct flock lock; int s; assert( pFile ); TRACE7("LOCK %d %s was %s(%s,%d) pid=%d\n", pFile->h, locktypeName(locktype), locktypeName(pFile->locktype), locktypeName(pLock->locktype), pLock->cnt , getpid()); /* If there is already a lock of this type or more restrictive on the ** OsFile, do nothing. Don't use the end_lock: exit path, as ** sqlite3OsEnterMutex() hasn't been called yet. */ if( pFile->locktype>=locktype ){ TRACE3("LOCK %d %s ok (already held)\n", pFile->h, ................................................................................ assert( pFile->locktype!=NO_LOCK || locktype==SHARED_LOCK ); assert( locktype!=PENDING_LOCK ); assert( locktype!=RESERVED_LOCK || pFile->locktype==SHARED_LOCK ); /* This mutex is needed because pFile->pLock is shared across threads */ sqlite3OsEnterMutex(); /* Make sure the current thread owns the pFile. */ rc = transferOwnership(pFile); if( rc!=SQLITE_OK ){ sqlite3OsLeaveMutex(); return rc; } pLock = pFile->pLock; /* If some thread using this PID has a lock via a different OsFile* ** handle that precludes the requested lock, return BUSY. */ if( (pFile->locktype!=pLock->locktype && (pLock->locktype>=PENDING_LOCK || locktype>SHARED_LOCK)) ){ ................................................................................ /* ** Lower the locking level on file descriptor pFile to locktype. locktype ** must be either NO_LOCK or SHARED_LOCK. ** ** If the locking level of the file descriptor is already at or below ** the requested locking level, this routine is a no-op. */ static int unixUnlock(OsFile *id, int locktype){ struct lockInfo *pLock; struct flock lock; int rc = SQLITE_OK; unixFile *pFile = (unixFile*)id; assert( pFile ); TRACE7("UNLOCK %d %d was %d(%d,%d) pid=%d\n", pFile->h, locktype, pFile->locktype, pFile->pLock->locktype, pFile->pLock->cnt, getpid()); assert( locktype<=SHARED_LOCK ); if( pFile->locktype<=locktype ){ return SQLITE_OK; } if( CHECK_THREADID(pFile) ){ return SQLITE_MISUSE; } sqlite3OsEnterMutex(); pLock = pFile->pLock; assert( pLock->cnt!=0 ); if( pFile->locktype>SHARED_LOCK ){ assert( pLock->locktype==pFile->locktype ); if( locktype==SHARED_LOCK ){ ................................................................................ pOpen->nLock--; assert( pOpen->nLock>=0 ); if( pOpen->nLock==0 && pOpen->nPending>0 ){ int i; for(i=0; i<pOpen->nPending; i++){ close(pOpen->aPending[i]); } free(pOpen->aPending); pOpen->nPending = 0; pOpen->aPending = 0; } } sqlite3OsLeaveMutex(); pFile->locktype = locktype; return rc; ................................................................................ } /* ** Close a file. */ static int unixClose(OsFile **pId){ unixFile *id = (unixFile*)*pId; int rc; if( !id ) return SQLITE_OK; unixUnlock(*pId, NO_LOCK); if( id->dirfd>=0 ) close(id->dirfd); id->dirfd = -1; sqlite3OsEnterMutex(); if( id->pOpen->nLock ){ /* If there are outstanding locks, do not actually close the file just ** yet because that would clear those locks. Instead, add the file ** descriptor to pOpen->aPending. It will be automatically closed when ** the last lock is cleared. */ int *aNew; struct openCnt *pOpen = id->pOpen; aNew = realloc( pOpen->aPending, (pOpen->nPending+1)*sizeof(int) ); if( aNew==0 ){ /* If a malloc fails, just leak the file descriptor */ }else{ pOpen->aPending = aNew; pOpen->aPending[pOpen->nPending] = id->h; pOpen->nPending++; } ................................................................................ sqlite3OsLeaveMutex(); id->isOpen = 0; TRACE2("CLOSE %-3d\n", id->h); OpenCounter(-1); sqliteFree(id); *pId = 0; return rc; } /* ** Turn a relative pathname into a full pathname. Return a pointer ** to the full pathname stored in space obtained from sqliteMalloc(). ** The calling function is responsible for freeing this space once it ** is no longer needed. ................................................................................ ** OsFile. If we run out of memory, close the file and return NULL. */ static int allocateUnixFile(unixFile *pInit, OsFile **pId){ unixFile *pNew; pNew = sqliteMalloc( sizeof(unixFile) ); if( pNew==0 ){ close(pInit->h); sqlite3OsEnterMutex(); releaseLockInfo(pInit->pLock); releaseOpenCnt(pInit->pOpen); sqlite3OsLeaveMutex(); *pId = 0; return SQLITE_NOMEM; }else{ *pNew = *pInit; pNew->pMethod = &sqlite3UnixIoMethod; *pId = (OsFile*)pNew; OpenCounter(+1); ................................................................................ ** prefer that the randomness be increased by making use of the ** uninitialized space in zBuf - but valgrind errors tend to worry ** some users. Rather than argue, it seems easier just to initialize ** the whole array and silence valgrind, even if that means less randomness ** in the random seed. ** ** When testing, initializing zBuf[] to zero is all we do. That means ** that we always use the same random number sequence. This makes the ** tests repeatable. */ memset(zBuf, 0, 256); #if !defined(SQLITE_TEST) { int pid, fd; fd = open("/dev/urandom", O_RDONLY); ................................................................................ } #endif return SQLITE_OK; } /* ** Sleep for a little while. Return the amount of time slept. ** The argument is the number of milliseconds we want to sleep. */ int sqlite3UnixSleep(int ms){ #if defined(HAVE_USLEEP) && HAVE_USLEEP usleep(ms*1000); return ms; #else sleep((ms+999)/1000); ................................................................................ /* ** The following pair of routine implement mutual exclusion for ** multi-threaded processes. Only a single thread is allowed to ** executed code that is surrounded by EnterMutex() and LeaveMutex(). ** ** SQLite uses only a single Mutex. There is not much critical ** code and what little there is executes quickly and without blocking. ** ** This mutex is not recursive. */ void sqlite3UnixEnterMutex(){ #ifdef SQLITE_UNIX_THREADS pthread_mutex_lock(&mutex); #endif assert( !inMutex ); inMutex = 1; ................................................................................ # endif #else # define TSD_COUNTER(N) /* no-op */ #endif /* ** If called with allocateFlag>0, then return a pointer to thread ** specific data for the current thread. Allocate and zero the ** thread-specific data if it does not already exist. ** ** If called with allocateFlag==0, then check the current thread ** specific data. Return it if it exists. If it does not exist, ** then return NULL. ** ** If called with allocateFlag<0, check to see if the thread specific ** data is allocated and is all zero. If it is then deallocate it. |
Changes to SQLite.Interop/src/os_win.c.
1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 |
int nByte;
nByte = strlen(zRelative) + MAX_PATH + 1001;
zFull = sqliteMalloc( nByte );
if( zFull==0 ) return 0;
if( cygwin_conv_to_full_win32_path(zRelative, zFull) ) return 0;
#elif OS_WINCE
/* WinCE has no concept of a relative pathname, or so I am told. */
zFull = sqlite3StrDup(zRelative);
#else
char *zNotUsed;
WCHAR *zWide;
int nByte;
zWide = utf8ToUnicode(zRelative);
if( zWide ){
WCHAR *zTemp, *zNotUsedW;
|
| |
1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 |
int nByte; nByte = strlen(zRelative) + MAX_PATH + 1001; zFull = sqliteMalloc( nByte ); if( zFull==0 ) return 0; if( cygwin_conv_to_full_win32_path(zRelative, zFull) ) return 0; #elif OS_WINCE /* WinCE has no concept of a relative pathname, or so I am told. */ zFull = sqliteStrDup(zRelative); #else char *zNotUsed; WCHAR *zWide; int nByte; zWide = utf8ToUnicode(zRelative); if( zWide ){ WCHAR *zTemp, *zNotUsedW; |
Changes to SQLite.Interop/src/pager.c.
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 ... 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 ... 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 ... 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 ... 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 ... 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 ... 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 .... 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 .... 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 .... 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 .... 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 .... 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 .... 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 .... 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 .... 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 .... 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 .... 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 .... 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 .... 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 .... 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 .... 3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 .... 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 .... 3262 3263 3264 3265 3266 3267 3268 3269 3270 3271 3272 3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 .... 3381 3382 3383 3384 3385 3386 3387 3388 3389 3390 3391 3392 3393 3394 3395 3396 3397 3398 3399 3400 3401 3402 3403 3404 3405 3406 3407 3408 3409 3410 3411 3412 3413 .... 3423 3424 3425 3426 3427 3428 3429 3430 3431 3432 3433 3434 3435 3436 3437 |
** The pager is used to access a database disk file. It implements ** atomic commit and rollback through the use of a journal file that ** is separate from the database file. The pager also implements file ** locking to prevent two processes from writing the same database ** file simultaneously, or one process from reading the database while ** another is writing. ** ** @(#) $Id: pager.c,v 1.16 2006/01/13 03:36:39 rmsimpson Exp $ */ #ifndef SQLITE_OMIT_DISKIO #include "sqliteInt.h" #include "os.h" #include "pager.h" #include <assert.h> #include <string.h> ................................................................................ /* ** Hash a page number */ #define pager_hash(PN) ((PN)&(N_PG_HASH-1)) /* ** A open page cache is an instance of the following structure. */ struct Pager { u8 journalOpen; /* True if journal file descriptors is valid */ u8 journalStarted; /* True if header of journal is synced */ u8 useJournal; /* Use a rollback journal on this file */ u8 noReadlock; /* Do not bother to obtain readlocks */ u8 stmtOpen; /* True if the statement subjournal is open */ u8 stmtInUse; /* True we are in a statement subtransaction */ u8 stmtAutoopen; /* Open stmt journal when main journal is opened*/ u8 noSync; /* Do not sync the journal if true */ u8 fullSync; /* Do extra syncs of the journal for robustness */ u8 state; /* PAGER_UNLOCK, _SHARED, _RESERVED, etc. */ u8 errMask; /* One of several kinds of errors */ u8 tempFile; /* zFilename is a temporary file */ u8 readOnly; /* True for a read-only database */ u8 needSync; /* True if an fsync() is needed on the journal */ u8 dirtyCache; /* True if cached pages have changed */ u8 alwaysRollback; /* Disable dont_rollback() for all pages */ u8 memDb; /* True to inhibit all file I/O */ u8 setMaster; /* True if a m-j name has been written to jrnl */ ................................................................................ */ #ifdef SQLITE_TEST # define TEST_INCR(x) x++ #else # define TEST_INCR(x) #endif /* ** These are bits that can be set in Pager.errMask. ** ** TODO: Maybe we just want a variable - Pager.errCode. Can we really ** have two simultaneous error conditions? ** ** Recovering from an SQLITE_FULL, SQLITE_LOCK, SQLITE_CORRUPT or ** SQLITE_IOERR error is not a simple matter, particularly if the pager ** cache is shared between multiple connections. ** ** SQLITE_FULL (PAGER_ERR_FULL): ** Cleared when the transaction is rolled back. ** ** SQLITE_CORRUPT (PAGER_ERR_CORRUPT): ** Cannot be cleared. The upper layer must close the current pager ** and open a new one on the same file to continue. ** ** SQLITE_PROTOCOL (PAGER_ERR_LOCK): ** This error only occurs if an internal error occurs or another process ** is not following the sqlite locking protocol (i.e. someone is ** manipulating the database file using something other than sqlite). ** This is handled in the same way as database corruption - the error ** cannot be cleared except by closing the current pager and opening ** a brand new one on the same file. ** ** SQLITE_IOERR (PAGER_ERR_DISK): ** Cleared when the transaction is rolled back. */ #define PAGER_ERR_FULL 0x01 /* a write() failed */ #define PAGER_ERR_LOCK 0x02 /* error in the locking protocol */ #define PAGER_ERR_CORRUPT 0x04 /* database or journal corruption */ #define PAGER_ERR_DISK 0x08 /* general disk I/O error - bad hard drive? */ /* ** Journal files begin with the following magic string. The data ** was obtained from /dev/random. It is used only as a sanity check. ** ** Since version 2.8.0, the journal format contains additional sanity ** checking information. If the power fails while the journal is begin ** written, semi-random garbage data might appear in the journal ................................................................................ ** Read a 32-bit integer from the given file descriptor. Store the integer ** that is read in *pRes. Return SQLITE_OK if everything worked, or an ** error code is something goes wrong. ** ** All values are stored on disk as big-endian. */ static int read32bits(OsFile *fd, u32 *pRes){ u32 res; int rc; rc = sqlite3OsRead(fd, &res, sizeof(res)); if( rc==SQLITE_OK ){ unsigned char ac[4]; memcpy(ac, &res, 4); res = (ac[0]<<24) | (ac[1]<<16) | (ac[2]<<8) | ac[3]; } *pRes = res; return rc; } /* ** Write a 32-bit integer into a string buffer in big-endian byte order. */ static void put32bits(char *ac, u32 val){ ................................................................................ static u32 retrieve32bits(PgHdr *p, int offset){ unsigned char *ac; ac = &((unsigned char*)PGHDR_TO_DATA(p))[offset]; return (ac[0]<<24) | (ac[1]<<16) | (ac[2]<<8) | ac[3]; } /* ** Convert the bits in the pPager->errMask into an approprate ** return code. */ static int pager_errcode(Pager *pPager){ int rc = SQLITE_OK; if( pPager->errMask & PAGER_ERR_LOCK ) rc = SQLITE_PROTOCOL; if( pPager->errMask & PAGER_ERR_DISK ) rc = SQLITE_IOERR; if( pPager->errMask & PAGER_ERR_FULL ) rc = SQLITE_FULL; if( pPager->errMask & PAGER_ERR_CORRUPT ) rc = SQLITE_CORRUPT; return rc; } /* ** This function should be called when an error occurs within the pager ** code to set the appropriate bits in Pager.errMask. */ static int pager_error(Pager *pPager, int rc){ switch( rc ){ case SQLITE_PROTOCOL: pPager->errMask |= PAGER_ERR_LOCK; break; case SQLITE_IOERR: pPager->errMask |= PAGER_ERR_DISK; break; case SQLITE_FULL: pPager->errMask |= PAGER_ERR_FULL; break; case SQLITE_CORRUPT: pPager->errMask |= PAGER_ERR_CORRUPT; break; } return rc; } #ifdef SQLITE_CHECK_PAGES /* ** Return a 32-bit hash of the page data for pPage. ................................................................................ ** The CHECK_PAGE macro takes a PgHdr* as an argument. If SQLITE_CHECK_PAGES ** is defined, and NDEBUG is not defined, an assert() statement checks ** that the page is either dirty or still matches the calculated page-hash. */ #define CHECK_PAGE(x) checkPage(x) static void checkPage(PgHdr *pPg){ Pager *pPager = pPg->pPager; assert( !pPg->pageHash || pPager->errMask || MEMDB || pPg->dirty || pPg->pageHash==pager_pagehash(pPg) ); } #else #define CHECK_PAGE(x) #endif ................................................................................ ** Unlock the database and clear the in-memory cache. This routine ** sets the state of the pager back to what it was when it was first ** opened. Any outstanding pages are invalidated and subsequent attempts ** to access those pages will likely result in a coredump. */ static void pager_reset(Pager *pPager){ PgHdr *pPg, *pNext; if( pPager->errMask ) return; for(pPg=pPager->pAll; pPg; pPg=pNext){ pNext = pPg->pNextAll; sqliteFree(pPg); } pPager->pFirst = 0; pPager->pFirstSynced = 0; pPager->pLast = 0; ................................................................................ } } pPager->journalOff = szJ; end_stmt_playback: if( rc!=SQLITE_OK ){ pPager->errMask |= PAGER_ERR_CORRUPT; rc = SQLITE_CORRUPT; }else{ pPager->journalOff = szJ; /* pager_reload_cache(pPager); */ } return rc; } ................................................................................ for(i=nameLen; i>0 && pPager->zDirectory[i-1]!='/'; i--){} if( i>0 ) pPager->zDirectory[i-1] = 0; strcpy(pPager->zJournal, zFullPathname); sqliteFree(zFullPathname); strcpy(&pPager->zJournal[nameLen], "-journal"); pPager->fd = fd; pPager->journalOpen = 0; pPager->useJournal = useJournal && !memDb; pPager->noReadlock = noReadlock && readOnly; pPager->stmtOpen = 0; pPager->stmtInUse = 0; pPager->nRef = 0; pPager->dbSize = memDb-1; pPager->pageSize = SQLITE_DEFAULT_PAGE_SIZE; pPager->stmtSize = 0; pPager->stmtJSize = 0; pPager->nPage = 0; pPager->nMaxPage = 0; pPager->mxPage = 100; pPager->state = PAGER_UNLOCK; pPager->errMask = 0; pPager->tempFile = tempFile; pPager->memDb = memDb; pPager->readOnly = readOnly; pPager->needSync = 0; pPager->noSync = pPager->tempFile || !useJournal; pPager->fullSync = (pPager->noSync?0:1); pPager->pFirst = 0; pPager->pFirstSynced = 0; pPager->pLast = 0; pPager->nExtra = FORCE_ALIGNMENT(nExtra); pPager->sectorSize = PAGER_SECTOR_SIZE; pPager->pBusyHandler = 0; memset(pPager->aHash, 0, sizeof(pPager->aHash)); *ppPager = pPager; #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT if( pTsdro->useMemoryManagement ){ ThreadData *pTsd = sqlite3ThreadData(); pPager->pNext = pTsd->pPager; pTsd->pPager = pPager; } ................................................................................ int sqlite3pager_pagecount(Pager *pPager){ i64 n; assert( pPager!=0 ); if( pPager->dbSize>=0 ){ n = pPager->dbSize; } else { if( sqlite3OsFileSize(pPager->fd, &n)!=SQLITE_OK ){ pPager->errMask |= PAGER_ERR_DISK; return 0; } if( n>0 && n<pPager->pageSize ){ n = 1; }else{ n /= pPager->pageSize; } ................................................................................ /* ** Truncate the file to the number of pages specified. */ int sqlite3pager_truncate(Pager *pPager, Pgno nPage){ int rc; sqlite3pager_pagecount(pPager); if( pPager->errMask!=0 ){ rc = pager_errcode(pPager); return rc; } if( nPage>=(unsigned)pPager->dbSize ){ return SQLITE_OK; } if( MEMDB ){ pPager->dbSize = nPage; ................................................................................ */ disable_simulated_io_errors(); sqlite3pager_rollback(pPager); enable_simulated_io_errors(); if( !MEMDB ){ sqlite3OsUnlock(pPager->fd, NO_LOCK); } assert( pPager->errMask || pPager->journalOpen==0 ); break; } case PAGER_SHARED: { if( !MEMDB ){ sqlite3OsUnlock(pPager->fd, NO_LOCK); } break; ................................................................................ assert( !pHist->pStmt ); } #endif pNext = pPg->pNextAll; sqliteFree(pPg); } TRACE2("CLOSE %d\n", PAGERID(pPager)); assert( pPager->errMask || (pPager->journalOpen==0 && pPager->stmtOpen==0) ); if( pPager->journalOpen ){ sqlite3OsClose(&pPager->jfd); } sqliteFree(pPager->aInJournal); if( pPager->stmtOpen ){ sqlite3OsClose(&pPager->stfd); } ................................................................................ } } /* ** Try to find a page in the cache that can be recycled. ** ** This routine may return SQLITE_IOERR, SQLITE_FULL or SQLITE_OK. It ** does not set the pPager->errMask variable. */ static int pager_recycle(Pager *pPager, int syncOk, PgHdr **ppPg){ PgHdr *pPg; *ppPg = 0; /* Find a page to recycle. Try to locate a page that does not ** require us to do an fsync() on the journal. ................................................................................ nReleased += sqliteAllocSize(pPg); sqliteFree(pPg); } if( rc!=SQLITE_OK ){ /* An error occured whilst writing to the database file or ** journal in pager_recycle(). The error is not returned to the ** caller of this function. Instead, set the Pager.errMask variable. ** The error will be returned to the user (or users, in the case ** of a shared pager cache) of the pager for which the error occured. */ assert( rc==SQLITE_IOERR || rc==SQLITE_FULL ); assert( p->state>=PAGER_RESERVED ); pager_error(p, rc); } ................................................................................ return SQLITE_CORRUPT_BKPT; } /* Make sure we have not hit any critical errors. */ assert( pPager!=0 ); *ppPage = 0; if( pPager->errMask & ~(PAGER_ERR_FULL) ){ return pager_errcode(pPager); } /* If this is the first page accessed, then get a SHARED lock ** on the database file. */ if( pPager->nRef==0 && !MEMDB ){ if( !pPager->noReadlock ){ ................................................................................ if( pPg->pNextHash ){ assert( pPg->pNextHash->pPrevHash==0 ); pPg->pNextHash->pPrevHash = pPg; } if( pPager->nExtra>0 ){ memset(PGHDR_TO_EXTRA(pPg, pPager), 0, pPager->nExtra); } if( pPager->errMask!=0 ){ sqlite3pager_unref(PGHDR_TO_DATA(pPg)); rc = pager_errcode(pPager); return rc; } if( sqlite3pager_pagecount(pPager)<(int)pgno ){ memset(PGHDR_TO_DATA(pPg), 0, pPager->pageSize); }else{ int rc; assert( MEMDB==0 ); ................................................................................ ** has ever happened. */ void *sqlite3pager_lookup(Pager *pPager, Pgno pgno){ PgHdr *pPg; assert( pPager!=0 ); assert( pgno!=0 ); if( pPager->errMask & ~(PAGER_ERR_FULL) ){ return 0; } pPg = pager_lookup(pPager, pgno); if( pPg==0 ) return 0; page_ref(pPg); return PGHDR_TO_DATA(pPg); } ................................................................................ sqlite3OsSetFullSync(pPager->fd, pPager->fullSync); sqlite3OsOpenDirectory(pPager->jfd, pPager->zDirectory); pPager->journalOpen = 1; pPager->journalStarted = 0; pPager->needSync = 0; pPager->alwaysRollback = 0; pPager->nRec = 0; if( pPager->errMask!=0 ){ rc = pager_errcode(pPager); goto failed_to_open_journal; } pPager->origDbSize = pPager->dbSize; rc = writeJournalHdr(pPager); if( pPager->stmtAutoopen && rc==SQLITE_OK ){ ................................................................................ int sqlite3pager_write(void *pData){ PgHdr *pPg = DATA_TO_PGHDR(pData); Pager *pPager = pPg->pPager; int rc = SQLITE_OK; /* Check for errors */ if( pPager->errMask ){ return pager_errcode(pPager); } if( pPager->readOnly ){ return SQLITE_PERM; } assert( !pPager->setMaster ); ................................................................................ pPager->journalOff += szPg; TRACE4("JOURNAL %d page %d needSync=%d\n", PAGERID(pPager), pPg->pgno, pPg->needSync); CODEC(pPager, pData, pPg->pgno, 0); *(u32*)PGHDR_TO_EXTRA(pPg, pPager) = saved; if( rc!=SQLITE_OK ){ sqlite3pager_rollback(pPager); pPager->errMask |= PAGER_ERR_FULL; return rc; } pPager->nRec++; assert( pPager->aInJournal!=0 ); pPager->aInJournal[pPg->pgno/8] |= 1<<(pPg->pgno&7); pPg->needSync = !pPager->noSync; if( pPager->stmtInUse ){ ................................................................................ CODEC(pPager, pData, pPg->pgno, 7); rc = sqlite3OsWrite(pPager->stfd,((char*)pData)-4, pPager->pageSize+4); TRACE3("STMT-JOURNAL %d page %d\n", PAGERID(pPager), pPg->pgno); CODEC(pPager, pData, pPg->pgno, 0); if( rc!=SQLITE_OK ){ sqlite3pager_rollback(pPager); pPager->errMask |= PAGER_ERR_FULL; return rc; } pPager->stmtNRec++; assert( pPager->aInStmt!=0 ); pPager->aInStmt[pPg->pgno/8] |= 1<<(pPg->pgno&7); } page_add_to_stmt_list(pPg); ................................................................................ ** and an error code is returned. If the commit worked, SQLITE_OK ** is returned. */ int sqlite3pager_commit(Pager *pPager){ int rc; PgHdr *pPg; if( pPager->errMask==PAGER_ERR_FULL ){ rc = sqlite3pager_rollback(pPager); if( rc==SQLITE_OK ){ rc = SQLITE_FULL; } return rc; } if( pPager->errMask!=0 ){ rc = pager_errcode(pPager); return rc; } if( pPager->state<PAGER_RESERVED ){ return SQLITE_ERROR; } TRACE2("COMMIT %d\n", PAGERID(pPager)); if( MEMDB ){ ................................................................................ if( !pPager->dirtyCache || !pPager->journalOpen ){ rc = pager_unwritelock(pPager); pPager->dbSize = -1; return rc; } if( pPager->errMask!=0 && pPager->errMask!=PAGER_ERR_FULL ){ if( pPager->state>=PAGER_EXCLUSIVE ){ pager_playback(pPager); } return pager_errcode(pPager); } if( pPager->state==PAGER_RESERVED ){ int rc2; rc = pager_reload_cache(pPager); rc2 = pager_unwritelock(pPager); if( rc==SQLITE_OK ){ rc = rc2; } }else{ rc = pager_playback(pPager); } if( rc!=SQLITE_OK ){ rc = SQLITE_CORRUPT_BKPT; pPager->errMask |= PAGER_ERR_CORRUPT; } pPager->dbSize = -1; return rc; } /* ** Return TRUE if the database file is opened read-only. Return FALSE ................................................................................ int *sqlite3pager_stats(Pager *pPager){ static int a[11]; a[0] = pPager->nRef; a[1] = pPager->nPage; a[2] = pPager->mxPage; a[3] = pPager->dbSize; a[4] = pPager->state; a[5] = pPager->errMask; #ifdef SQLITE_TEST a[6] = pPager->nHit; a[7] = pPager->nMiss; a[8] = pPager->nOvfl; a[9] = pPager->nRead; a[10] = pPager->nWrite; #endif |
| > > > > > > > > | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | < | < < | < | | | | | | | | | | | | | | | | | | | < < < < < < < < < < < < | | < | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | > > | > > | | | | | | | |
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 ... 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 ... 303 304 305 306 307 308 309 310 311 312 313 314 315 316 ... 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 ... 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 ... 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 ... 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 .... 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 .... 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 .... 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 .... 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 .... 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 .... 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 .... 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 .... 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 .... 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 .... 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 .... 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 .... 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 .... 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 .... 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 .... 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 .... 3225 3226 3227 3228 3229 3230 3231 3232 3233 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 .... 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 3376 .... 3386 3387 3388 3389 3390 3391 3392 3393 3394 3395 3396 3397 3398 3399 3400 |
** The pager is used to access a database disk file. It implements ** atomic commit and rollback through the use of a journal file that ** is separate from the database file. The pager also implements file ** locking to prevent two processes from writing the same database ** file simultaneously, or one process from reading the database while ** another is writing. ** ** @(#) $Id: pager.c,v 1.17 2006/01/16 15:51:47 rmsimpson Exp $ */ #ifndef SQLITE_OMIT_DISKIO #include "sqliteInt.h" #include "os.h" #include "pager.h" #include <assert.h> #include <string.h> ................................................................................ /* ** Hash a page number */ #define pager_hash(PN) ((PN)&(N_PG_HASH-1)) /* ** A open page cache is an instance of the following structure. ** ** Pager.errCode may be set to SQLITE_IOERR, SQLITE_CORRUPT, SQLITE_PROTOCOL ** or SQLITE_FULL. Once one of the first three errors occurs, it persists ** and is returned as the result of every major pager API call. The ** SQLITE_FULL return code is slightly different. It persists only until the ** next successful rollback is performed on the pager cache. Also, ** SQLITE_FULL does not affect the sqlite3pager_get() and sqlite3pager_lookup() ** APIs, they may still be used successfully. */ struct Pager { u8 journalOpen; /* True if journal file descriptors is valid */ u8 journalStarted; /* True if header of journal is synced */ u8 useJournal; /* Use a rollback journal on this file */ u8 noReadlock; /* Do not bother to obtain readlocks */ u8 stmtOpen; /* True if the statement subjournal is open */ u8 stmtInUse; /* True we are in a statement subtransaction */ u8 stmtAutoopen; /* Open stmt journal when main journal is opened*/ u8 noSync; /* Do not sync the journal if true */ u8 fullSync; /* Do extra syncs of the journal for robustness */ u8 state; /* PAGER_UNLOCK, _SHARED, _RESERVED, etc. */ u8 errCode; /* One of several kinds of errors */ u8 tempFile; /* zFilename is a temporary file */ u8 readOnly; /* True for a read-only database */ u8 needSync; /* True if an fsync() is needed on the journal */ u8 dirtyCache; /* True if cached pages have changed */ u8 alwaysRollback; /* Disable dont_rollback() for all pages */ u8 memDb; /* True to inhibit all file I/O */ u8 setMaster; /* True if a m-j name has been written to jrnl */ ................................................................................ */ #ifdef SQLITE_TEST # define TEST_INCR(x) x++ #else # define TEST_INCR(x) #endif /* ** Journal files begin with the following magic string. The data ** was obtained from /dev/random. It is used only as a sanity check. ** ** Since version 2.8.0, the journal format contains additional sanity ** checking information. If the power fails while the journal is begin ** written, semi-random garbage data might appear in the journal ................................................................................ ** Read a 32-bit integer from the given file descriptor. Store the integer ** that is read in *pRes. Return SQLITE_OK if everything worked, or an ** error code is something goes wrong. ** ** All values are stored on disk as big-endian. */ static int read32bits(OsFile *fd, u32 *pRes){ unsigned char ac[4]; int rc = sqlite3OsRead(fd, ac, sizeof(ac)); if( rc==SQLITE_OK ){ *pRes = (ac[0]<<24) | (ac[1]<<16) | (ac[2]<<8) | ac[3]; } return rc; } /* ** Write a 32-bit integer into a string buffer in big-endian byte order. */ static void put32bits(char *ac, u32 val){ ................................................................................ static u32 retrieve32bits(PgHdr *p, int offset){ unsigned char *ac; ac = &((unsigned char*)PGHDR_TO_DATA(p))[offset]; return (ac[0]<<24) | (ac[1]<<16) | (ac[2]<<8) | ac[3]; } /* ** This function should be called when an error occurs within the pager ** code. The first argument is a pointer to the pager structure, the ** second the error-code about to be returned by a pager API function. ** The value returned is a copy of the second argument to this function. ** ** If the second argument is SQLITE_IOERR, SQLITE_CORRUPT or SQLITE_PROTOCOL, ** the error becomes persistent. All subsequent API calls on this Pager ** will immediately return the same error code. */ static int pager_error(Pager *pPager, int rc){ assert( pPager->errCode==SQLITE_FULL || pPager->errCode==SQLITE_OK ); if( rc==SQLITE_FULL || rc==SQLITE_IOERR || rc==SQLITE_CORRUPT || rc==SQLITE_PROTOCOL ){ pPager->errCode = rc; } return rc; } #ifdef SQLITE_CHECK_PAGES /* ** Return a 32-bit hash of the page data for pPage. ................................................................................ ** The CHECK_PAGE macro takes a PgHdr* as an argument. If SQLITE_CHECK_PAGES ** is defined, and NDEBUG is not defined, an assert() statement checks ** that the page is either dirty or still matches the calculated page-hash. */ #define CHECK_PAGE(x) checkPage(x) static void checkPage(PgHdr *pPg){ Pager *pPager = pPg->pPager; assert( !pPg->pageHash || pPager->errCode || MEMDB || pPg->dirty || pPg->pageHash==pager_pagehash(pPg) ); } #else #define CHECK_PAGE(x) #endif ................................................................................ ** Unlock the database and clear the in-memory cache. This routine ** sets the state of the pager back to what it was when it was first ** opened. Any outstanding pages are invalidated and subsequent attempts ** to access those pages will likely result in a coredump. */ static void pager_reset(Pager *pPager){ PgHdr *pPg, *pNext; if( pPager->errCode ) return; for(pPg=pPager->pAll; pPg; pPg=pNext){ pNext = pPg->pNextAll; sqliteFree(pPg); } pPager->pFirst = 0; pPager->pFirstSynced = 0; pPager->pLast = 0; ................................................................................ } } pPager->journalOff = szJ; end_stmt_playback: if( rc!=SQLITE_OK ){ rc = pager_error(pPager, SQLITE_CORRUPT); }else{ pPager->journalOff = szJ; /* pager_reload_cache(pPager); */ } return rc; } ................................................................................ for(i=nameLen; i>0 && pPager->zDirectory[i-1]!='/'; i--){} if( i>0 ) pPager->zDirectory[i-1] = 0; strcpy(pPager->zJournal, zFullPathname); sqliteFree(zFullPathname); strcpy(&pPager->zJournal[nameLen], "-journal"); pPager->fd = fd; /* pPager->journalOpen = 0; */ pPager->useJournal = useJournal && !memDb; pPager->noReadlock = noReadlock && readOnly; /* pPager->stmtOpen = 0; */ /* pPager->stmtInUse = 0; */ /* pPager->nRef = 0; */ pPager->dbSize = memDb-1; pPager->pageSize = SQLITE_DEFAULT_PAGE_SIZE; /* pPager->stmtSize = 0; */ /* pPager->stmtJSize = 0; */ /* pPager->nPage = 0; */ /* pPager->nMaxPage = 0; */ pPager->mxPage = 100; assert( PAGER_UNLOCK==0 ); /* pPager->state = PAGER_UNLOCK; */ /* pPager->errMask = 0; */ pPager->tempFile = tempFile; pPager->memDb = memDb; pPager->readOnly = readOnly; /* pPager->needSync = 0; */ pPager->noSync = pPager->tempFile || !useJournal; pPager->fullSync = (pPager->noSync?0:1); /* pPager->pFirst = 0; */ /* pPager->pFirstSynced = 0; */ /* pPager->pLast = 0; */ pPager->nExtra = FORCE_ALIGNMENT(nExtra); pPager->sectorSize = PAGER_SECTOR_SIZE; /* pPager->pBusyHandler = 0; */ /* memset(pPager->aHash, 0, sizeof(pPager->aHash)); */ *ppPager = pPager; #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT if( pTsdro->useMemoryManagement ){ ThreadData *pTsd = sqlite3ThreadData(); pPager->pNext = pTsd->pPager; pTsd->pPager = pPager; } ................................................................................ int sqlite3pager_pagecount(Pager *pPager){ i64 n; assert( pPager!=0 ); if( pPager->dbSize>=0 ){ n = pPager->dbSize; } else { if( sqlite3OsFileSize(pPager->fd, &n)!=SQLITE_OK ){ pager_error(pPager, SQLITE_IOERR); return 0; } if( n>0 && n<pPager->pageSize ){ n = 1; }else{ n /= pPager->pageSize; } ................................................................................ /* ** Truncate the file to the number of pages specified. */ int sqlite3pager_truncate(Pager *pPager, Pgno nPage){ int rc; sqlite3pager_pagecount(pPager); if( pPager->errCode ){ rc = pPager->errCode; return rc; } if( nPage>=(unsigned)pPager->dbSize ){ return SQLITE_OK; } if( MEMDB ){ pPager->dbSize = nPage; ................................................................................ */ disable_simulated_io_errors(); sqlite3pager_rollback(pPager); enable_simulated_io_errors(); if( !MEMDB ){ sqlite3OsUnlock(pPager->fd, NO_LOCK); } assert( pPager->errCode || pPager->journalOpen==0 ); break; } case PAGER_SHARED: { if( !MEMDB ){ sqlite3OsUnlock(pPager->fd, NO_LOCK); } break; ................................................................................ assert( !pHist->pStmt ); } #endif pNext = pPg->pNextAll; sqliteFree(pPg); } TRACE2("CLOSE %d\n", PAGERID(pPager)); assert( pPager->errCode || (pPager->journalOpen==0 && pPager->stmtOpen==0) ); if( pPager->journalOpen ){ sqlite3OsClose(&pPager->jfd); } sqliteFree(pPager->aInJournal); if( pPager->stmtOpen ){ sqlite3OsClose(&pPager->stfd); } ................................................................................ } } /* ** Try to find a page in the cache that can be recycled. ** ** This routine may return SQLITE_IOERR, SQLITE_FULL or SQLITE_OK. It ** does not set the pPager->errCode variable. */ static int pager_recycle(Pager *pPager, int syncOk, PgHdr **ppPg){ PgHdr *pPg; *ppPg = 0; /* Find a page to recycle. Try to locate a page that does not ** require us to do an fsync() on the journal. ................................................................................ nReleased += sqliteAllocSize(pPg); sqliteFree(pPg); } if( rc!=SQLITE_OK ){ /* An error occured whilst writing to the database file or ** journal in pager_recycle(). The error is not returned to the ** caller of this function. Instead, set the Pager.errCode variable. ** The error will be returned to the user (or users, in the case ** of a shared pager cache) of the pager for which the error occured. */ assert( rc==SQLITE_IOERR || rc==SQLITE_FULL ); assert( p->state>=PAGER_RESERVED ); pager_error(p, rc); } ................................................................................ return SQLITE_CORRUPT_BKPT; } /* Make sure we have not hit any critical errors. */ assert( pPager!=0 ); *ppPage = 0; if( pPager->errCode && pPager->errCode!=SQLITE_FULL ){ return pPager->errCode; } /* If this is the first page accessed, then get a SHARED lock ** on the database file. */ if( pPager->nRef==0 && !MEMDB ){ if( !pPager->noReadlock ){ ................................................................................ if( pPg->pNextHash ){ assert( pPg->pNextHash->pPrevHash==0 ); pPg->pNextHash->pPrevHash = pPg; } if( pPager->nExtra>0 ){ memset(PGHDR_TO_EXTRA(pPg, pPager), 0, pPager->nExtra); } if( pPager->errCode ){ sqlite3pager_unref(PGHDR_TO_DATA(pPg)); rc = pPager->errCode; return rc; } if( sqlite3pager_pagecount(pPager)<(int)pgno ){ memset(PGHDR_TO_DATA(pPg), 0, pPager->pageSize); }else{ int rc; assert( MEMDB==0 ); ................................................................................ ** has ever happened. */ void *sqlite3pager_lookup(Pager *pPager, Pgno pgno){ PgHdr *pPg; assert( pPager!=0 ); assert( pgno!=0 ); if( pPager->errCode && pPager->errCode!=SQLITE_FULL ){ return 0; } pPg = pager_lookup(pPager, pgno); if( pPg==0 ) return 0; page_ref(pPg); return PGHDR_TO_DATA(pPg); } ................................................................................ sqlite3OsSetFullSync(pPager->fd, pPager->fullSync); sqlite3OsOpenDirectory(pPager->jfd, pPager->zDirectory); pPager->journalOpen = 1; pPager->journalStarted = 0; pPager->needSync = 0; pPager->alwaysRollback = 0; pPager->nRec = 0; if( pPager->errCode ){ rc = pPager->errCode; goto failed_to_open_journal; } pPager->origDbSize = pPager->dbSize; rc = writeJournalHdr(pPager); if( pPager->stmtAutoopen && rc==SQLITE_OK ){ ................................................................................ int sqlite3pager_write(void *pData){ PgHdr *pPg = DATA_TO_PGHDR(pData); Pager *pPager = pPg->pPager; int rc = SQLITE_OK; /* Check for errors */ if( pPager->errCode ){ return pPager->errCode; } if( pPager->readOnly ){ return SQLITE_PERM; } assert( !pPager->setMaster ); ................................................................................ pPager->journalOff += szPg; TRACE4("JOURNAL %d page %d needSync=%d\n", PAGERID(pPager), pPg->pgno, pPg->needSync); CODEC(pPager, pData, pPg->pgno, 0); *(u32*)PGHDR_TO_EXTRA(pPg, pPager) = saved; if( rc!=SQLITE_OK ){ sqlite3pager_rollback(pPager); if( !pPager->errCode ){ pager_error(pPager, SQLITE_FULL); } return rc; } pPager->nRec++; assert( pPager->aInJournal!=0 ); pPager->aInJournal[pPg->pgno/8] |= 1<<(pPg->pgno&7); pPg->needSync = !pPager->noSync; if( pPager->stmtInUse ){ ................................................................................ CODEC(pPager, pData, pPg->pgno, 7); rc = sqlite3OsWrite(pPager->stfd,((char*)pData)-4, pPager->pageSize+4); TRACE3("STMT-JOURNAL %d page %d\n", PAGERID(pPager), pPg->pgno); CODEC(pPager, pData, pPg->pgno, 0); if( rc!=SQLITE_OK ){ sqlite3pager_rollback(pPager); if( !pPager->errCode ){ pager_error(pPager, SQLITE_FULL); } return rc; } pPager->stmtNRec++; assert( pPager->aInStmt!=0 ); pPager->aInStmt[pPg->pgno/8] |= 1<<(pPg->pgno&7); } page_add_to_stmt_list(pPg); ................................................................................ ** and an error code is returned. If the commit worked, SQLITE_OK ** is returned. */ int sqlite3pager_commit(Pager *pPager){ int rc; PgHdr *pPg; if( pPager->errCode==SQLITE_FULL ){ rc = sqlite3pager_rollback(pPager); if( rc==SQLITE_OK ){ rc = SQLITE_FULL; } return rc; } if( pPager->errCode ){ rc = pPager->errCode; return rc; } if( pPager->state<PAGER_RESERVED ){ return SQLITE_ERROR; } TRACE2("COMMIT %d\n", PAGERID(pPager)); if( MEMDB ){ ................................................................................ if( !pPager->dirtyCache || !pPager->journalOpen ){ rc = pager_unwritelock(pPager); pPager->dbSize = -1; return rc; } if( pPager->errCode && pPager->errCode!=SQLITE_FULL ){ if( pPager->state>=PAGER_EXCLUSIVE ){ pager_playback(pPager); } return pPager->errCode; } if( pPager->state==PAGER_RESERVED ){ int rc2; rc = pager_reload_cache(pPager); rc2 = pager_unwritelock(pPager); if( rc==SQLITE_OK ){ rc = rc2; } }else{ rc = pager_playback(pPager); } if( rc!=SQLITE_OK ){ rc = SQLITE_CORRUPT_BKPT; pager_error(pPager, SQLITE_CORRUPT); } pPager->dbSize = -1; return rc; } /* ** Return TRUE if the database file is opened read-only. Return FALSE ................................................................................ int *sqlite3pager_stats(Pager *pPager){ static int a[11]; a[0] = pPager->nRef; a[1] = pPager->nPage; a[2] = pPager->mxPage; a[3] = pPager->dbSize; a[4] = pPager->state; a[5] = pPager->errCode; #ifdef SQLITE_TEST a[6] = pPager->nHit; a[7] = pPager->nMiss; a[8] = pPager->nOvfl; a[9] = pPager->nRead; a[10] = pPager->nWrite; #endif |
Changes to SQLite.Interop/src/pager.h.
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 page cache ** subsystem. The page cache subsystem reads and writes a file a page ** at a time and provides a journal for rollback. ** ** @(#) $Id: pager.h,v 1.15 2006/01/12 20:54:07 rmsimpson Exp $ */ #ifndef _PAGER_H_ #define _PAGER_H_ /* ** The default size of a database page. |
| |
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 page cache ** subsystem. The page cache subsystem reads and writes a file a page ** at a time and provides a journal for rollback. ** ** @(#) $Id: pager.h,v 1.16 2006/01/16 15:51:47 rmsimpson Exp $ */ #ifndef _PAGER_H_ #define _PAGER_H_ /* ** The default size of a database page. |
Changes to SQLite.Interop/src/pragma.c.
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
** 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 implement the PRAGMA command. ** ** $Id: pragma.c,v 1.14 2006/01/12 20:54:07 rmsimpson Exp $ */ #include "sqliteInt.h" #include "os.h" #include <ctype.h> /* Ignore this whole file if pragmas are disabled */ |
| |
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
** 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 implement the PRAGMA command. ** ** $Id: pragma.c,v 1.15 2006/01/16 15:51:47 rmsimpson Exp $ */ #include "sqliteInt.h" #include "os.h" #include <ctype.h> /* Ignore this whole file if pragmas are disabled */ |
Changes to SQLite.Interop/src/prepare.c.
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 ... 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 ... 490 491 492 493 494 495 496 497 498 499 500 501 502 503 |
** 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.10 2006/01/12 20:54:07 rmsimpson Exp $ */ #include "sqliteInt.h" #include "os.h" #include <ctype.h> /* ** Fill the InitData structure with an error message that indicates ................................................................................ /* ** Initialize all database files - the main database file, the file ** used to store temporary tables, and any additional database files ** created using ATTACH statements. Return a success code. If an ** error occurs, write an error message into *pzErrMsg. ** ** After the database is initialized, the SQLITE_Initialized ** bit is set in the flags field of the sqlite structure. */ int sqlite3Init(sqlite3 *db, char **pzErrMsg){ int i, rc; int called_initone = 0; if( db->init.busy ) return SQLITE_OK; rc = SQLITE_OK; ................................................................................ const char** pzTail /* OUT: End of parsed string */ ){ Parse sParse; char *zErrMsg = 0; int rc = SQLITE_OK; int i; assert( !sqlite3ThreadDataReadOnly()->mallocFailed ); assert( ppStmt ); *ppStmt = 0; if( sqlite3SafetyOn(db) ){ return SQLITE_MISUSE; } |
| | | > > |
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 ... 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 ... 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 |
** 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.11 2006/01/16 15:51:47 rmsimpson Exp $ */ #include "sqliteInt.h" #include "os.h" #include <ctype.h> /* ** Fill the InitData structure with an error message that indicates ................................................................................ /* ** Initialize all database files - the main database file, the file ** used to store temporary tables, and any additional database files ** created using ATTACH statements. Return a success code. If an ** error occurs, write an error message into *pzErrMsg. ** ** After a database is initialized, the DB_SchemaLoaded bit is set ** bit is set in the flags field of the Db structure. If the database ** file was of zero-length, then the DB_Empty flag is also set. */ int sqlite3Init(sqlite3 *db, char **pzErrMsg){ int i, rc; int called_initone = 0; if( db->init.busy ) return SQLITE_OK; rc = SQLITE_OK; ................................................................................ const char** pzTail /* OUT: End of parsed string */ ){ Parse sParse; char *zErrMsg = 0; int rc = SQLITE_OK; int i; /* Assert that malloc() has not failed */ assert( !sqlite3ThreadDataReadOnly()->mallocFailed ); assert( ppStmt ); *ppStmt = 0; if( sqlite3SafetyOn(db) ){ return SQLITE_MISUSE; } |
Changes to SQLite.Interop/src/random.c.
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
************************************************************************* ** This file contains code to implement a pseudo-random number ** generator (PRNG) for SQLite. ** ** Random numbers are used by some of the database backends in order ** to generate random integer keys for tables or random filenames. ** ** $Id: random.c,v 1.14 2006/01/12 20:54:07 rmsimpson Exp $ */ #include "sqliteInt.h" #include "os.h" /* ** Get a single 8-bit random value from the RC4 PRNG. The Mutex |
| |
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
************************************************************************* ** This file contains code to implement a pseudo-random number ** generator (PRNG) for SQLite. ** ** Random numbers are used by some of the database backends in order ** to generate random integer keys for tables or random filenames. ** ** $Id: random.c,v 1.15 2006/01/16 15:51:47 rmsimpson Exp $ */ #include "sqliteInt.h" #include "os.h" /* ** Get a single 8-bit random value from the RC4 PRNG. The Mutex |
Changes to SQLite.Interop/src/select.c.
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
....
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
|
** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains C code routines that are called by the parser ** to handle SELECT statements in SQLite. ** ** $Id: select.c,v 1.15 2006/01/13 03:36:39 rmsimpson Exp $ */ #include "sqliteInt.h" /* ** Allocate a new Select structure and return a pointer to that ** structure. ................................................................................ memset(&sNC, 0, sizeof(sNC)); sNC.pSrcList = pSelect->pSrc; zType = sqliteStrDup(columnType(&sNC, p)); pCol->zType = zType; pCol->affinity = sqlite3ExprAffinity(p); pColl = sqlite3ExprCollSeq(pParse, p); if( pColl ){ pCol->zColl = sqlite3StrDup(pColl->zName); } } pTab->iPKey = -1; return pTab; } /* |
|
|
|
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
....
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
|
** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains C code routines that are called by the parser ** to handle SELECT statements in SQLite. ** ** $Id: select.c,v 1.16 2006/01/16 15:51:47 rmsimpson Exp $ */ #include "sqliteInt.h" /* ** Allocate a new Select structure and return a pointer to that ** structure. ................................................................................ memset(&sNC, 0, sizeof(sNC)); sNC.pSrcList = pSelect->pSrc; zType = sqliteStrDup(columnType(&sNC, p)); pCol->zType = zType; pCol->affinity = sqlite3ExprAffinity(p); pColl = sqlite3ExprCollSeq(pParse, p); if( pColl ){ pCol->zColl = sqliteStrDup(pColl->zName); } } pTab->iPKey = -1; return pTab; } /* |
Changes to SQLite.Interop/src/server.c.
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 .. 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 .. 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 |
** or linked into the SQLite library unless you use a non-standard option: ** ** -DSQLITE_SERVER=1 ** ** The configure script will never generate a Makefile with the option ** above. You will need to manually modify the Makefile if you want to ** include any of the code from this file in your project. Or, at your ** option, you may want to copy and paste the code from this file and ** thereby avoiding a recompile of SQLite. ** ** ** This source file demonstrates how to use SQLite to create an SQL database ** server thread in a multiple-threaded program. One or more client threads ** send messages to the server thread and the server thread processes those ** messages in the order received and returns the results to the client. ................................................................................ ** a thread different from the one where they were created. With ** the client/server approach, all database connections are created ** and used within the server thread. Client calls to the database ** can be made from multiple threads (though not at the same time!) ** ** (2) Beginning with SQLite version 3.3.0, when two or more ** connections to the same database occur within the same thread, ** they will share their database cache. This reduces I/O ** and memory requirements. ** ** (3) Database connections on a shared cache use table-level locking ** instead of file-level locking for improved concurrency. ** ** (4) Database connections on a shared cache can by optionally ** set to READ UNCOMMITTED isolation. (The default isolation for ** SQLite is SERIALIZABLE.) When this occurs, readers will ................................................................................ ** sqlite3_client_reset ** sqlite3_client_finalize ** sqlite3_client_close ** ** These interfaces work exactly like the standard core SQLite interfaces ** having the same names without the "_client_" infix. Many other SQLite ** interfaces can be used directly without having to send messages to the ** server. The following interfaces fall into this second category: ** ** sqlite3_bind_* ** sqlite3_changes ** sqlite3_clear_bindings ** sqlite3_column_* ** sqlite3_complete ** sqlite3_create_collation ** sqlite3_create_function ** sqlite3_data_count ** sqlite3_db_handle ** sqlite3_errcode ** sqlite3_errmsg ** sqlite3_last_insert_rowid ** sqlite3_libversion ** sqlite3_mprintf ** sqlite3_total_changes ** sqlite3_transfer_bindings ** sqlite3_vmprintf ** ** A single SQLite connection (an sqlite3* object) or an SQLite statement ** (an sqlite3_stmt* object) should only be passed to a single interface ** function at a time. The connections and statements can be freely used ** by any thread as long as only one thread is using them at a time. ** ** The busy handler for all database connections should remain turned ** off. That means that any lock contention will cause the associated ** sqlite3_client_step() call to return immediately with an SQLITE_BUSY ** error code. If a busy handler is enabled and lock contention occurs, ** then the entire server thread will block. This will cause not only ** the requesting client to block but every other database client as ** well. It is possible to enhance the code below so that lock ** contention will cause the message to be placed back on the top of ** the queue to be tried again later. But such enhanced processing is ** not included here, in order to keep the example simple. ** ** This code assumes the use of pthreads. Pthreads implementations ** are available for windows. (See, for example ** http://sourceware.org/pthreads-win32/announcement.html.) Or, you ** can translate the locking and thread synchronization code to use ** windows primitives easily enough. The details are left as an ** exercise to the reader. */ /* ** Only compile the code in this file on UNIX with a THREADSAFE build ** and only if the SQLITE_SERVER macro is defined. */ #ifdef SQLITE_SERVER |
| | | > > | < < < | | > > > > | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > |
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 .. 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 .. 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 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 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 |
** or linked into the SQLite library unless you use a non-standard option: ** ** -DSQLITE_SERVER=1 ** ** The configure script will never generate a Makefile with the option ** above. You will need to manually modify the Makefile if you want to ** include any of the code from this file in your project. Or, at your ** option, you may copy and paste the code from this file and ** thereby avoiding a recompile of SQLite. ** ** ** This source file demonstrates how to use SQLite to create an SQL database ** server thread in a multiple-threaded program. One or more client threads ** send messages to the server thread and the server thread processes those ** messages in the order received and returns the results to the client. ................................................................................ ** a thread different from the one where they were created. With ** the client/server approach, all database connections are created ** and used within the server thread. Client calls to the database ** can be made from multiple threads (though not at the same time!) ** ** (2) Beginning with SQLite version 3.3.0, when two or more ** connections to the same database occur within the same thread, ** they can optionally share their database cache. This reduces ** I/O and memory requirements. Cache shared is controlled using ** the sqlite3_enable_shared_cache() API. ** ** (3) Database connections on a shared cache use table-level locking ** instead of file-level locking for improved concurrency. ** ** (4) Database connections on a shared cache can by optionally ** set to READ UNCOMMITTED isolation. (The default isolation for ** SQLite is SERIALIZABLE.) When this occurs, readers will ................................................................................ ** sqlite3_client_reset ** sqlite3_client_finalize ** sqlite3_client_close ** ** These interfaces work exactly like the standard core SQLite interfaces ** having the same names without the "_client_" infix. Many other SQLite ** interfaces can be used directly without having to send messages to the ** server as long as SQLITE_ENABLE_MEMORY_MANAGEMENT is not defined. ** The following interfaces fall into this second category: ** ** sqlite3_bind_* ** sqlite3_changes ** sqlite3_clear_bindings ** sqlite3_column_* ** sqlite3_complete ** sqlite3_create_collation ** sqlite3_create_function ** sqlite3_data_count ** sqlite3_db_handle ** sqlite3_errcode ** sqlite3_errmsg ** sqlite3_last_insert_rowid ** sqlite3_total_changes ** sqlite3_transfer_bindings ** ** A single SQLite connection (an sqlite3* object) or an SQLite statement ** (an sqlite3_stmt* object) should only be passed to a single interface ** function at a time. The connections and statements can be passed from ** any thread to any of the functions listed in the second group above as ** long as the same connection is not in use by two threads at once and ** as long as SQLITE_ENABLE_MEMORY_MANAGEMENT is not defined. Additional ** information about the SQLITE_ENABLE_MEMORY_MANAGEMENT constraint is ** below. ** ** The busy handler for all database connections should remain turned ** off. That means that any lock contention will cause the associated ** sqlite3_client_step() call to return immediately with an SQLITE_BUSY ** error code. If a busy handler is enabled and lock contention occurs, ** then the entire server thread will block. This will cause not only ** the requesting client to block but every other database client as ** well. It is possible to enhance the code below so that lock ** contention will cause the message to be placed back on the top of ** the queue to be tried again later. But such enhanced processing is ** not included here, in order to keep the example simple. ** ** This example code assumes the use of pthreads. Pthreads ** implementations are available for windows. (See, for example ** http://sourceware.org/pthreads-win32/announcement.html.) Or, you ** can translate the locking and thread synchronization code to use ** windows primitives easily enough. The details are left as an ** exercise to the reader. ** **** Restrictions Associated With SQLITE_ENABLE_MEMORY_MANAGEMENT **** ** ** If you compile with SQLITE_ENABLE_MEMORY_MANAGEMENT defined, then ** SQLite includes code that tracks how much memory is being used by ** each thread. These memory counts can become confused if memory ** is allocated by one thread and then freed by another. For that ** reason, when SQLITE_ENABLE_MEMORY_MANAGEMENT is used, all operations ** that might allocate or free memory should be performanced in the same ** thread that originally created the database connection. In that case, ** many of the operations that are listed above as safe to be performed ** in separate threads would need to be sent over to the server to be ** done there. If SQLITE_ENABLE_MEMORY_MANAGEMENT is defined, then ** the following functions can be used safely from different threads ** without messing up the allocation counts: ** ** sqlite3_bind_parameter_name ** sqlite3_bind_parameter_index ** sqlite3_changes ** sqlite3_column_blob ** sqlite3_column_count ** sqlite3_complete ** sqlite3_data_count ** sqlite3_db_handle ** sqlite3_errcode ** sqlite3_errmsg ** sqlite3_last_insert_rowid ** sqlite3_total_changes ** ** The remaining functions are not thread-safe when memory management ** is enabled. So one would have to define some new interface routines ** along the following lines: ** ** sqlite3_client_bind_* ** sqlite3_client_clear_bindings ** sqlite3_client_column_* ** sqlite3_client_create_collation ** sqlite3_client_create_function ** sqlite3_client_transfer_bindings ** ** The example code in this file is intended for use with memory ** management turned off. So the implementation of these additional ** client interfaces is left as an exercise to the reader. ** ** It may seem surprising to the reader that the list of safe functions ** above does not include things like sqlite3_bind_int() or ** sqlite3_column_int(). But those routines might, in fact, allocate ** or deallocate memory. In the case of sqlite3_bind_int(), if the ** parameter was previously bound to a string that string might need ** to be deallocated before the new integer value is inserted. In ** the case of sqlite3_column_int(), the value of the column might be ** a UTF-16 string which will need to be converted to UTF-8 then into ** an integer. */ /* ** Only compile the code in this file on UNIX with a THREADSAFE build ** and only if the SQLITE_SERVER macro is defined. */ #ifdef SQLITE_SERVER |
Changes to SQLite.Interop/src/shell.c.
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains code to implement the "sqlite" command line ** utility for accessing SQLite databases. ** ** $Id: shell.c,v 1.14 2006/01/12 20:54:07 rmsimpson Exp $ */ #include <stdlib.h> #include <string.h> #include <stdio.h> #include <assert.h> #include "sqlite3.h" #include <ctype.h> |
| |
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains code to implement the "sqlite" command line ** utility for accessing SQLite databases. ** ** $Id: shell.c,v 1.15 2006/01/16 15:51:47 rmsimpson Exp $ */ #include <stdlib.h> #include <string.h> #include <stdio.h> #include <assert.h> #include "sqlite3.h" #include <ctype.h> |
Changes to SQLite.Interop/src/sqlite3.h.
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 .. 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 .. 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This header file defines the interface that the SQLite library ** presents to client programs. ** ** @(#) $Id: sqlite3.h,v 1.15 2006/01/12 20:54:07 rmsimpson Exp $ */ #ifndef _SQLITE3_H_ #define _SQLITE3_H_ #include <stdarg.h> /* Needed for the definition of va_list */ /* ** Make sure we can call this stuff from C++. ................................................................................ /* ** The version of the SQLite library. */ #ifdef SQLITE_VERSION # undef SQLITE_VERSION #endif #define SQLITE_VERSION "3.3.0" /* ** The format of the version string is "X.Y.Z<trailing string>", where ** X is the major version number, Y is the minor version number and Z ** is the release number. The trailing string is often "alpha" or "beta". ** For example "3.1.1beta". ** ................................................................................ ** SQLITE_VERSION_NUMBER is set to 3001001. To detect if they are using ** version 3.1.1 or greater at compile time, programs may use the test ** (SQLITE_VERSION_NUMBER>=3001001). */ #ifdef SQLITE_VERSION_NUMBER # undef SQLITE_VERSION_NUMBER #endif #define SQLITE_VERSION_NUMBER 3003000 /* ** The version string is also compiled into the library so that a program ** can check to make sure that the lib*.a file and the *.h file are from ** the same version. The sqlite3_libversion() function returns a pointer ** to the sqlite3_version variable - useful in DLLs which cannot access ** global variables. |
| | | |
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 .. 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 .. 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This header file defines the interface that the SQLite library ** presents to client programs. ** ** @(#) $Id: sqlite3.h,v 1.16 2006/01/16 15:51:47 rmsimpson Exp $ */ #ifndef _SQLITE3_H_ #define _SQLITE3_H_ #include <stdarg.h> /* Needed for the definition of va_list */ /* ** Make sure we can call this stuff from C++. ................................................................................ /* ** The version of the SQLite library. */ #ifdef SQLITE_VERSION # undef SQLITE_VERSION #endif #define SQLITE_VERSION "3.3.1" /* ** The format of the version string is "X.Y.Z<trailing string>", where ** X is the major version number, Y is the minor version number and Z ** is the release number. The trailing string is often "alpha" or "beta". ** For example "3.1.1beta". ** ................................................................................ ** SQLITE_VERSION_NUMBER is set to 3001001. To detect if they are using ** version 3.1.1 or greater at compile time, programs may use the test ** (SQLITE_VERSION_NUMBER>=3001001). */ #ifdef SQLITE_VERSION_NUMBER # undef SQLITE_VERSION_NUMBER #endif #define SQLITE_VERSION_NUMBER 3003001 /* ** The version string is also compiled into the library so that a program ** can check to make sure that the lib*.a file and the *.h file are from ** the same version. The sqlite3_libversion() function returns a pointer ** to the sqlite3_version variable - useful in DLLs which cannot access ** global variables. |
Changes to SQLite.Interop/src/sqliteInt.h.
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 ... 280 281 282 283 284 285 286 287 288 289 290 291 292 293 .... 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 |
** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** Internal interface definitions for SQLite. ** ** @(#) $Id: sqliteInt.h,v 1.14 2006/01/12 20:54:07 rmsimpson Exp $ */ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ /* ** Extra interface definitions for those who need them */ ................................................................................ #define sqliteStrNDup(x,y) sqlite3StrNDup(x,y) #define sqliteReallocOrFree(x,y) sqlite3ReallocOrFree(x,y) #endif #define sqliteFree(x) sqlite3FreeX(x) #define sqliteAllocSize(x) sqlite3AllocSize(x) /* ** An instance of this structure might be allocated to store information ** specific to a single thread. ** ** To avoid a memory leak on windows, the content of this structure is ** checked at the conclusion of each API call. If it is all zero, it ................................................................................ #ifndef SQLITE_OMIT_SHARED_CACHE void sqlite3TableLock(Parse *, int, int, u8, const char *); #else #define sqlite3TableLock(v,w,x,y,z) #endif void sqlite3MallocClearFailed(); #ifdef NDEBUG #define sqlite3MallocDisallow() #define sqlite3MallocAllow() #else void sqlite3MallocDisallow(); void sqlite3MallocAllow(); #endif #ifdef SQLITE_SSE #include "sseInt.h" #endif #endif |
| > | |
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 ... 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 .... 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 |
** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** Internal interface definitions for SQLite. ** ** @(#) $Id: sqliteInt.h,v 1.15 2006/01/16 15:51:47 rmsimpson Exp $ */ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ /* ** Extra interface definitions for those who need them */ ................................................................................ #define sqliteStrNDup(x,y) sqlite3StrNDup(x,y) #define sqliteReallocOrFree(x,y) sqlite3ReallocOrFree(x,y) #endif #define sqliteFree(x) sqlite3FreeX(x) #define sqliteAllocSize(x) sqlite3AllocSize(x) /* ** An instance of this structure might be allocated to store information ** specific to a single thread. ** ** To avoid a memory leak on windows, the content of this structure is ** checked at the conclusion of each API call. If it is all zero, it ................................................................................ #ifndef SQLITE_OMIT_SHARED_CACHE void sqlite3TableLock(Parse *, int, int, u8, const char *); #else #define sqlite3TableLock(v,w,x,y,z) #endif void sqlite3MallocClearFailed(); #ifndef SQLITE_MEMDEBUG #define sqlite3MallocDisallow() #define sqlite3MallocAllow() #else void sqlite3MallocDisallow(); void sqlite3MallocAllow(); #endif #ifdef SQLITE_SSE #include "sseInt.h" #endif #endif |
Changes to SQLite.Interop/src/tclsqlite.c.
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
** 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. ** ************************************************************************* ** A TCL Interface to SQLite ** ** $Id: tclsqlite.c,v 1.14 2006/01/12 20:54:08 rmsimpson Exp $ */ #ifndef NO_TCL /* Omit this whole file if TCL is unavailable */ #include "sqliteInt.h" #include "hash.h" #include "tcl.h" #include <stdlib.h> |
| |
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
** 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. ** ************************************************************************* ** A TCL Interface to SQLite ** ** $Id: tclsqlite.c,v 1.15 2006/01/16 15:51:47 rmsimpson Exp $ */ #ifndef NO_TCL /* Omit this whole file if TCL is unavailable */ #include "sqliteInt.h" #include "hash.h" #include "tcl.h" #include <stdlib.h> |
Changes to SQLite.Interop/src/tokenize.c.
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
************************************************************************* ** An tokenizer for SQL ** ** This file contains C code that splits an SQL input string up into ** individual tokens and sends those tokens one-by-one over to the ** parser for analysis. ** ** $Id: tokenize.c,v 1.18 2006/01/13 03:36:39 rmsimpson Exp $ */ #include "sqliteInt.h" #include "os.h" #include <ctype.h> #include <stdlib.h> /* |
| |
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
************************************************************************* ** An tokenizer for SQL ** ** This file contains C code that splits an SQL input string up into ** individual tokens and sends those tokens one-by-one over to the ** parser for analysis. ** ** $Id: tokenize.c,v 1.19 2006/01/16 15:51:47 rmsimpson Exp $ */ #include "sqliteInt.h" #include "os.h" #include <ctype.h> #include <stdlib.h> /* |
Changes to SQLite.Interop/src/update.c.
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains C code routines that are called by the parser ** to handle UPDATE statements. ** ** $Id: update.c,v 1.14 2006/01/12 20:54:08 rmsimpson Exp $ */ #include "sqliteInt.h" /* ** The most recently coded instruction was an OP_Column to retrieve the ** i-th column of table pTab. This routine sets the P3 parameter of the ** OP_Column to the default value, if any. |
| |
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains C code routines that are called by the parser ** to handle UPDATE statements. ** ** $Id: update.c,v 1.15 2006/01/16 15:51:47 rmsimpson Exp $ */ #include "sqliteInt.h" /* ** The most recently coded instruction was an OP_Column to retrieve the ** i-th column of table pTab. This routine sets the P3 parameter of the ** OP_Column to the default value, if any. |
Changes to SQLite.Interop/src/utf.c.
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
|
** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains routines used to translate between UTF-8, ** UTF-16, UTF-16BE, and UTF-16LE. ** ** $Id: utf.c,v 1.14 2006/01/12 20:54:08 rmsimpson Exp $ ** ** Notes on UTF-8: ** ** Byte-0 Byte-1 Byte-2 Byte-3 Value ** 0xxxxxxx 00000000 00000000 0xxxxxxx ** 110yyyyy 10xxxxxx 00000000 00000yyy yyxxxxxx ** 1110zzzz 10yyyyyy 10xxxxxx 00000000 zzzzyyyy yyxxxxxx ................................................................................ char *sqlite3utf16to8(const void *z, int nByte){ Mem m; memset(&m, 0, sizeof(m)); sqlite3VdbeMemSetStr(&m, z, nByte, SQLITE_UTF16NATIVE, SQLITE_STATIC); sqlite3VdbeChangeEncoding(&m, SQLITE_UTF8); assert( m.flags & MEM_Term ); assert( m.flags & MEM_Str ); return (m.flags & MEM_Dyn)!=0 ? m.z : sqlite3StrDup(m.z); } /* ** pZ is a UTF-16 encoded unicode string. If nChar is less than zero, ** return the number of bytes up to (but not including), the first pair ** of consecutive 0x00 bytes in pZ. If nChar is not less than zero, ** then return the number of bytes in the first nChar unicode characters |
|
|
|
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
|
** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains routines used to translate between UTF-8, ** UTF-16, UTF-16BE, and UTF-16LE. ** ** $Id: utf.c,v 1.15 2006/01/16 15:51:47 rmsimpson Exp $ ** ** Notes on UTF-8: ** ** Byte-0 Byte-1 Byte-2 Byte-3 Value ** 0xxxxxxx 00000000 00000000 0xxxxxxx ** 110yyyyy 10xxxxxx 00000000 00000yyy yyxxxxxx ** 1110zzzz 10yyyyyy 10xxxxxx 00000000 zzzzyyyy yyxxxxxx ................................................................................ char *sqlite3utf16to8(const void *z, int nByte){ Mem m; memset(&m, 0, sizeof(m)); sqlite3VdbeMemSetStr(&m, z, nByte, SQLITE_UTF16NATIVE, SQLITE_STATIC); sqlite3VdbeChangeEncoding(&m, SQLITE_UTF8); assert( m.flags & MEM_Term ); assert( m.flags & MEM_Str ); return (m.flags & MEM_Dyn)!=0 ? m.z : sqliteStrDup(m.z); } /* ** pZ is a UTF-16 encoded unicode string. If nChar is less than zero, ** return the number of bytes up to (but not including), the first pair ** of consecutive 0x00 bytes in pZ. If nChar is not less than zero, ** then return the number of bytes in the first nChar unicode characters |
Changes to SQLite.Interop/src/util.c.
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 ... 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 .... 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 |
** ************************************************************************* ** Utility functions used throughout sqlite. ** ** This file contains functions for allocating memory, comparing ** strings, and stuff like that. ** ** $Id: util.c,v 1.15 2006/01/12 20:54:08 rmsimpson Exp $ */ #include "sqliteInt.h" #include "os.h" #include <stdarg.h> #include <ctype.h> /* ................................................................................ ** sqlite3Malloc(), sqlite3Realloc() or sqlite3ReallocOrFree(). ** ** The number of bytes allocated does not include any overhead inserted by ** any malloc() wrapper functions that may be called. So the value returned ** is the number of bytes that were available to SQLite using pointer p, ** regardless of how much memory was actually allocated. */ int sqlite3AllocSize(void *p){ return OSSIZEOF(p); } /* ** Make a copy of a string in memory obtained from sqliteMalloc(). These ** functions call sqlite3MallocRaw() directly instead of sqliteMalloc(). This ** is because when memory debugging is turned on, these two functions are ** called via macros that record the current file and line number in the ** ThreadData structure. ................................................................................ #ifndef NDEBUG /* ** This function sets a flag in the thread-specific-data structure that will ** cause an assert to fail if sqliteMalloc() or sqliteRealloc() is called. */ void sqlite3MallocDisallow(){ assert(!sqlite3ThreadData()->mallocDisallowed); sqlite3ThreadData()->mallocDisallowed = 1; } /* ** This function clears the flag set in the thread-specific-data structure set ** by sqlite3MallocDisallow(). */ void sqlite3MallocAllow(){ assert(sqlite3ThreadData()->mallocDisallowed); sqlite3ThreadData()->mallocDisallowed = 0; } #endif |
| > > | | | | |
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 ... 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 .... 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 |
** ************************************************************************* ** Utility functions used throughout sqlite. ** ** This file contains functions for allocating memory, comparing ** strings, and stuff like that. ** ** $Id: util.c,v 1.16 2006/01/16 15:51:47 rmsimpson Exp $ */ #include "sqliteInt.h" #include "os.h" #include <stdarg.h> #include <ctype.h> /* ................................................................................ ** sqlite3Malloc(), sqlite3Realloc() or sqlite3ReallocOrFree(). ** ** The number of bytes allocated does not include any overhead inserted by ** any malloc() wrapper functions that may be called. So the value returned ** is the number of bytes that were available to SQLite using pointer p, ** regardless of how much memory was actually allocated. */ #if 0 /* This is never actually used */ int sqlite3AllocSize(void *p){ return OSSIZEOF(p); } #endif /* ** Make a copy of a string in memory obtained from sqliteMalloc(). These ** functions call sqlite3MallocRaw() directly instead of sqliteMalloc(). This ** is because when memory debugging is turned on, these two functions are ** called via macros that record the current file and line number in the ** ThreadData structure. ................................................................................ #ifndef NDEBUG /* ** This function sets a flag in the thread-specific-data structure that will ** cause an assert to fail if sqliteMalloc() or sqliteRealloc() is called. */ void sqlite3MallocDisallow(){ assert( sqlite3ThreadData()->mallocDisallowed>=0 ); sqlite3ThreadData()->mallocDisallowed++; } /* ** This function clears the flag set in the thread-specific-data structure set ** by sqlite3MallocDisallow(). */ void sqlite3MallocAllow(){ assert( sqlite3ThreadData()->mallocDisallowed>0 ); sqlite3ThreadData()->mallocDisallowed--; } #endif |
Changes to SQLite.Interop/src/vacuum.c.
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
** ************************************************************************* ** This file contains code used to implement the VACUUM command. ** ** Most of the code in this file may be omitted by defining the ** SQLITE_OMIT_VACUUM macro. ** ** $Id: vacuum.c,v 1.15 2006/01/13 03:36:39 rmsimpson Exp $ */ #include "sqliteInt.h" #include "vdbeInt.h" #include "os.h" #ifndef SQLITE_OMIT_VACUUM /* |
| |
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
** ************************************************************************* ** This file contains code used to implement the VACUUM command. ** ** Most of the code in this file may be omitted by defining the ** SQLITE_OMIT_VACUUM macro. ** ** $Id: vacuum.c,v 1.16 2006/01/16 15:51:47 rmsimpson Exp $ */ #include "sqliteInt.h" #include "vdbeInt.h" #include "os.h" #ifndef SQLITE_OMIT_VACUUM /* |
Changes to SQLite.Interop/src/vdbe.c.
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 ... 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 ... 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 .... 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 .... 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 .... 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 .... 4206 4207 4208 4209 4210 4211 4212 4213 4214 4215 4216 4217 4218 4219 4220 |
** ** Various scripts scan this source file in order to generate HTML ** documentation, headers files, or other derived files. The formatting ** of the code in this file is, therefore, important. See other comments ** in this file for details. If in doubt, do not deviate from existing ** commenting and indentation practices when changing or adding code. ** ** $Id: vdbe.c,v 1.15 2006/01/13 03:36:39 rmsimpson Exp $ */ #include "sqliteInt.h" #include "os.h" #include <ctype.h> #include "vdbeInt.h" /* ................................................................................ pTos->flags |= MEM_Real; sqlite3VdbeChangeEncoding(pTos, encoding); break; } /* Opcode: String8 * * P3 ** ** P3 points to a nul terminated UTF-8 string that is P1 character long ** (not counting the nul terminator). This opcode is transformed ** into an OP_String before it is executed for the first time. */ case OP_String8: { /* same as TK_STRING */ assert( pOp->p3!=0 ); pOp->opcode = OP_String; pOp->p1 = strlen(pOp->p3); ................................................................................ pTos->flags &= ~(MEM_Dyn); pTos->flags |= MEM_Static; if( pOp->p3type==P3_DYNAMIC ){ sqliteFree(pOp->p3); } pOp->p3type = P3_DYNAMIC; pOp->p3 = pTos->z; pOp->p1 *= 2; break; } #endif /* Otherwise fall through to the next case, OP_String */ } /* Opcode: String P1 * P3 ** ** The string value P3 of length P1 is pushed onto the stack. */ case OP_String: { pTos++; assert( pOp->p3!=0 ); pTos->flags = MEM_Str|MEM_Static|MEM_Term; pTos->z = pOp->p3; pTos->n = pOp->p1; ................................................................................ int p2 = pOp->p2; /* column number to retrieve */ Cursor *pC = 0; /* The VDBE cursor */ char *zRec; /* Pointer to complete record-data */ BtCursor *pCrsr; /* The BTree cursor */ u32 *aType; /* aType[i] holds the numeric type of the i-th column */ u32 *aOffset; /* aOffset[i] is offset to start of data for i-th column */ u32 nField; /* number of fields in the record */ u32 szHdr; /* Number of bytes in the record header */ int len; /* The length of the serialized data for the column */ int offset = 0; /* Offset into the data */ int idx; /* Index into the header */ int i; /* Loop counter */ char *zData; /* Part of the record being decoded */ Mem sMem; /* For storing the record being decoded */ sMem.flags = 0; assert( p1<p->nCursor ); pTos++; ................................................................................ payloadSize = 0; pCrsr = 0; nField = 0; } /* If payloadSize is 0, then just push a NULL onto the stack. */ if( payloadSize==0 ){ pTos->flags = MEM_Null; break; } assert( p2<nField ); /* Read and parse the table header. Store the results of the parse ** into the record header cache fields of the cursor. */ if( pC && pC->cacheStatus==p->cacheCtr ){ aType = pC->aType; aOffset = pC->aOffset; }else{ int avail; /* Number of bytes of available data */ if( pC && pC->aType ){ aType = pC->aType; }else{ aType = sqliteMallocRaw( 2*nField*sizeof(aType) ); } aOffset = &aType[nField]; ................................................................................ if( avail>=payloadSize ){ zRec = zData; pC->aRow = (u8*)zData; }else{ pC->aRow = 0; } } idx = GetVarint((u8*)zData, szHdr); /* The KeyFetch() or DataFetch() above are fast and will get the entire ** record header in most cases. But they will fail to get the complete ** record header if the record header does not fit on a single page ** in the B-Tree. When that happens, use sqlite3VdbeMemFromBtree() to ** acquire the complete header text. */ if( !zRec && avail<szHdr ){ rc = sqlite3VdbeMemFromBtree(pCrsr, 0, szHdr, pC->isIndex, &sMem); if( rc!=SQLITE_OK ){ goto op_column_out; } zData = sMem.z; } /* Scan the header and use it to fill in the aType[] and aOffset[] ** arrays. aType[i] will contain the type integer for the i-th ** column and aOffset[i] will contain the offset from the beginning ** of the record to the start of the data for the i-th column */ offset = szHdr; assert( offset>0 ); i = 0; while( idx<szHdr && i<nField && offset<=payloadSize ){ aOffset[i] = offset; idx += GetVarint((u8*)&zData[idx], aType[i]); offset += sqlite3VdbeSerialTypeLen(aType[i]); i++; } Release(&sMem); sMem.flags = MEM_Null; /* If i is less that nField, then there are less fields in this ** record than SetNumColumns indicated there are columns in the ** table. Set the offset for any extra columns not present in ** the record to 0. This tells code below to push a NULL onto the ** stack instead of deserializing a value from the record. */ while( i<nField ){ aOffset[i++] = 0; } /* The header should end at the start of data and the data should ** end at last byte of the record. If this is not the case then ** we are dealing with a malformed record. */ if( idx!=szHdr || offset!=payloadSize ){ rc = SQLITE_CORRUPT_BKPT; goto op_column_out; } /* Remember all aType and aColumn information if we have a cursor ** to remember it in. */ if( pC ){ ................................................................................ int i = p->contextStackTop++; Context *pContext; assert( i>=0 ); /* FIX ME: This should be allocated as part of the vdbe at compile-time */ if( i>=p->contextStackDepth ){ p->contextStackDepth = i+1; sqlite3ReallocOrFree((void**)&p->contextStack, sizeof(Context)*(i+1)); if( p->contextStack==0 ) goto no_mem; } pContext = &p->contextStack[i]; pContext->lastRowid = db->lastRowid; pContext->nChange = p->nChange; pContext->sFifo = p->sFifo; sqlite3VdbeFifoInit(&p->sFifo); |
| | < | | < < < | > > > | < | | > > | | < < | | | < < < < < > | | | | | | | | | > > | |
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 ... 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 ... 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 .... 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 .... 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 .... 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 .... 4202 4203 4204 4205 4206 4207 4208 4209 4210 4211 4212 4213 4214 4215 4216 |
** ** Various scripts scan this source file in order to generate HTML ** documentation, headers files, or other derived files. The formatting ** of the code in this file is, therefore, important. See other comments ** in this file for details. If in doubt, do not deviate from existing ** commenting and indentation practices when changing or adding code. ** ** $Id: vdbe.c,v 1.16 2006/01/16 15:51:47 rmsimpson Exp $ */ #include "sqliteInt.h" #include "os.h" #include <ctype.h> #include "vdbeInt.h" /* ................................................................................ pTos->flags |= MEM_Real; sqlite3VdbeChangeEncoding(pTos, encoding); break; } /* Opcode: String8 * * P3 ** ** P3 points to a nul terminated UTF-8 string. This opcode is transformed ** into an OP_String before it is executed for the first time. */ case OP_String8: { /* same as TK_STRING */ assert( pOp->p3!=0 ); pOp->opcode = OP_String; pOp->p1 = strlen(pOp->p3); ................................................................................ pTos->flags &= ~(MEM_Dyn); pTos->flags |= MEM_Static; if( pOp->p3type==P3_DYNAMIC ){ sqliteFree(pOp->p3); } pOp->p3type = P3_DYNAMIC; pOp->p3 = pTos->z; pOp->p1 = pTos->n; break; } #endif /* Otherwise fall through to the next case, OP_String */ } /* Opcode: String P1 * P3 ** ** The string value P3 of length P1 (bytes) is pushed onto the stack. */ case OP_String: { pTos++; assert( pOp->p3!=0 ); pTos->flags = MEM_Str|MEM_Static|MEM_Term; pTos->z = pOp->p3; pTos->n = pOp->p1; ................................................................................ int p2 = pOp->p2; /* column number to retrieve */ Cursor *pC = 0; /* The VDBE cursor */ char *zRec; /* Pointer to complete record-data */ BtCursor *pCrsr; /* The BTree cursor */ u32 *aType; /* aType[i] holds the numeric type of the i-th column */ u32 *aOffset; /* aOffset[i] is offset to start of data for i-th column */ u32 nField; /* number of fields in the record */ int len; /* The length of the serialized data for the column */ int i; /* Loop counter */ char *zData; /* Part of the record being decoded */ Mem sMem; /* For storing the record being decoded */ sMem.flags = 0; assert( p1<p->nCursor ); pTos++; ................................................................................ payloadSize = 0; pCrsr = 0; nField = 0; } /* If payloadSize is 0, then just push a NULL onto the stack. */ if( payloadSize==0 ){ assert( pTos->flags==MEM_Null ); break; } assert( p2<nField ); /* Read and parse the table header. Store the results of the parse ** into the record header cache fields of the cursor. */ if( pC && pC->cacheStatus==p->cacheCtr ){ aType = pC->aType; aOffset = pC->aOffset; }else{ u8 *zIdx; /* Index into header */ u8 *zEndHdr; /* Pointer to first byte after the header */ u32 offset; /* Offset into the data */ int avail; /* Number of bytes of available data */ if( pC && pC->aType ){ aType = pC->aType; }else{ aType = sqliteMallocRaw( 2*nField*sizeof(aType) ); } aOffset = &aType[nField]; ................................................................................ if( avail>=payloadSize ){ zRec = zData; pC->aRow = (u8*)zData; }else{ pC->aRow = 0; } } zIdx = (u8 *)GetVarint((u8*)zData, offset); /* The KeyFetch() or DataFetch() above are fast and will get the entire ** record header in most cases. But they will fail to get the complete ** record header if the record header does not fit on a single page ** in the B-Tree. When that happens, use sqlite3VdbeMemFromBtree() to ** acquire the complete header text. */ if( !zRec && avail<offset ){ rc = sqlite3VdbeMemFromBtree(pCrsr, 0, offset, pC->isIndex, &sMem); if( rc!=SQLITE_OK ){ goto op_column_out; } zData = sMem.z; } zEndHdr = (u8 *)zData + offset; zIdx = zData + (int)zIdx; /* Scan the header and use it to fill in the aType[] and aOffset[] ** arrays. aType[i] will contain the type integer for the i-th ** column and aOffset[i] will contain the offset from the beginning ** of the record to the start of the data for the i-th column */ for(i=0; i<nField; i++){ if( zIdx<zEndHdr ){ aOffset[i] = offset; zIdx += GetVarint(zIdx, aType[i]); offset += sqlite3VdbeSerialTypeLen(aType[i]); }else{ /* If i is less that nField, then there are less fields in this ** record than SetNumColumns indicated there are columns in the ** table. Set the offset for any extra columns not present in ** the record to 0. This tells code below to push a NULL onto the ** stack instead of deserializing a value from the record. */ aOffset[i] = 0; } } Release(&sMem); sMem.flags = MEM_Null; /* If we have read more header data than was contained in the header, ** or if the end of the last field appears to be past the end of the ** record, then we must be dealing with a corrupt database. */ if( zIdx>zEndHdr || offset>payloadSize ){ rc = SQLITE_CORRUPT_BKPT; goto op_column_out; } /* Remember all aType and aColumn information if we have a cursor ** to remember it in. */ if( pC ){ ................................................................................ int i = p->contextStackTop++; Context *pContext; assert( i>=0 ); /* FIX ME: This should be allocated as part of the vdbe at compile-time */ if( i>=p->contextStackDepth ){ p->contextStackDepth = i+1; sqliteReallocOrFree((void**)&p->contextStack, sizeof(Context)*(i+1)); if( p->contextStack==0 ) goto no_mem; } pContext = &p->contextStack[i]; pContext->lastRowid = db->lastRowid; pContext->nChange = p->nChange; pContext->sFifo = p->sFifo; sqlite3VdbeFifoInit(&p->sFifo); |
Changes to SQLite.Interop/src/vdbe.h.
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
************************************************************************* ** Header file for the Virtual DataBase Engine (VDBE) ** ** This header defines the interface to the virtual database engine ** or VDBE. The VDBE implements an abstract machine that runs a ** simple program to access and modify the underlying database. ** ** $Id: vdbe.h,v 1.14 2006/01/12 20:54:08 rmsimpson Exp $ */ #ifndef _SQLITE_VDBE_H_ #define _SQLITE_VDBE_H_ #include <stdio.h> /* ** A single VDBE is an opaque structure named "Vdbe". Only routines |
| |
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
************************************************************************* ** Header file for the Virtual DataBase Engine (VDBE) ** ** This header defines the interface to the virtual database engine ** or VDBE. The VDBE implements an abstract machine that runs a ** simple program to access and modify the underlying database. ** ** $Id: vdbe.h,v 1.15 2006/01/16 15:51:47 rmsimpson Exp $ */ #ifndef _SQLITE_VDBE_H_ #define _SQLITE_VDBE_H_ #include <stdio.h> /* ** A single VDBE is an opaque structure named "Vdbe". Only routines |
Changes to SQLite.Interop/src/vdbeapi.c.
152 153 154 155 156 157 158 159 160 161 162 163 164 165 |
** statement is completely executed or an error occurs. */ int sqlite3_step(sqlite3_stmt *pStmt){ Vdbe *p = (Vdbe*)pStmt; sqlite3 *db; int rc; assert(!sqlite3ThreadDataReadOnly()->mallocFailed); if( p==0 || p->magic!=VDBE_MAGIC_RUN ){ return SQLITE_MISUSE; } if( p->aborted ){ return SQLITE_ABORT; |
> |
152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 |
** statement is completely executed or an error occurs.
*/
int sqlite3_step(sqlite3_stmt *pStmt){
Vdbe *p = (Vdbe*)pStmt;
sqlite3 *db;
int rc;
/* Assert that malloc() has not failed */
assert( !sqlite3ThreadDataReadOnly()->mallocFailed );
if( p==0 || p->magic!=VDBE_MAGIC_RUN ){
return SQLITE_MISUSE;
}
if( p->aborted ){
return SQLITE_ABORT;
|
Changes to SQLite.Interop/src/vdbeaux.c.
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
...
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
|
int i; VdbeOp *pOp; i = p->nOp; p->nOp++; assert( p->magic==VDBE_MAGIC_INIT ); resizeOpArray(p, i+1); if( p->aOp==0 || p->nOp<=i ){ return 0; } pOp = &p->aOp[i]; pOp->opcode = op; pOp->p1 = p1; pOp->p2 = p2; pOp->p3 = 0; ................................................................................ */ int sqlite3VdbeMakeLabel(Vdbe *p){ int i; i = p->nLabel++; assert( p->magic==VDBE_MAGIC_INIT ); if( i>=p->nLabelAlloc ){ p->nLabelAlloc = p->nLabelAlloc*2 + 10; sqlite3ReallocOrFree((void**)&p->aLabel, p->nLabelAlloc*sizeof(p->aLabel[0])); } if( p->aLabel ){ p->aLabel[i] = -1; } return -1-i; } |
|
|
|
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
...
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
|
int i; VdbeOp *pOp; i = p->nOp; p->nOp++; assert( p->magic==VDBE_MAGIC_INIT ); resizeOpArray(p, i+1); if( p->aOp==0 || p->nOpAlloc<=i ){ return 0; } pOp = &p->aOp[i]; pOp->opcode = op; pOp->p1 = p1; pOp->p2 = p2; pOp->p3 = 0; ................................................................................ */ int sqlite3VdbeMakeLabel(Vdbe *p){ int i; i = p->nLabel++; assert( p->magic==VDBE_MAGIC_INIT ); if( i>=p->nLabelAlloc ){ p->nLabelAlloc = p->nLabelAlloc*2 + 10; sqliteReallocOrFree((void**)&p->aLabel, p->nLabelAlloc*sizeof(p->aLabel[0])); } if( p->aLabel ){ p->aLabel[i] = -1; } return -1-i; } |
Changes to SQLite.Interop/src/where.c.
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 ... 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 .... 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 .... 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 .... 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 .... 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 .... 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 .... 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 |
** This module contains C code that generates VDBE code used to process ** the WHERE clause of SQL statements. This module is reponsible for ** generating the code that loops through a table looking for applicable ** rows. Indices are selected and used to speed the search when doing ** so is applicable. Because this module is responsible for selecting ** indices, you might also think of this module as the "query optimizer". ** ** $Id: where.c,v 1.16 2006/01/12 20:54:08 rmsimpson Exp $ */ #include "sqliteInt.h" /* ** The number of bits in a Bitmask. "BMS" means "BitMask Size". */ #define BMS (sizeof(Bitmask)*8) ................................................................................ pTerm = &pWC->a[idxTerm]; pWC->a[idxNew].iParent = idxTerm; } pTerm->nChild = 2; } #endif /* SQLITE_OMIT_BETWEEN_OPTIMIZATION */ #ifndef SQLITE_OMIT_OR_OPTIMIZATION /* Attempt to convert OR-connected terms into an IN operator so that ** they can make use of indices. Example: ** ** x = expr1 OR expr2 = x OR x = expr3 ** ** is converted into ** ** x IN (expr1,expr2,expr3) */ else if( pExpr->op==TK_OR ){ int ok; int i, j; int iColumn, iCursor; WhereClause sOr; WhereTerm *pOrTerm; ................................................................................ /* ** Generate code that builds a probe for an index. Details: ** ** * Check the top nColumn entries on the stack. If any ** of those entries are NULL, jump immediately to brk, ** which is the loop exit, since no index entry will match ** if any part of the key is NULL. ** ** * Construct a probe entry from the top nColumn entries in ** the stack with affinities appropriate for index pIdx. */ static void buildIndexProbe(Vdbe *v, int nColumn, int brk, Index *pIdx){ sqlite3VdbeAddOp(v, OP_NotNull, -nColumn, sqlite3VdbeCurrentAddr(v)+3); sqlite3VdbeAddOp(v, OP_Pop, nColumn, 0); sqlite3VdbeAddOp(v, OP_Goto, 0, brk); sqlite3VdbeAddOp(v, OP_MakeRecord, nColumn, 0); sqlite3IndexAffinityStr(v, pIdx); } /* ................................................................................ Vdbe *v = pParse->pVdbe; sqlite3CodeSubselect(pParse, pX); iTab = pX->iTable; sqlite3VdbeAddOp(v, OP_Rewind, iTab, brk); VdbeComment((v, "# %.*s", pX->span.n, pX->span.z)); pLevel->nIn++; sqlite3ReallocOrFree((void**)&pLevel->aInLoop, sizeof(pLevel->aInLoop[0])*3*pLevel->nIn); aIn = pLevel->aInLoop; if( aIn ){ aIn += pLevel->nIn*3 - 3; aIn[0] = OP_Next; aIn[1] = iTab; aIn[2] = sqlite3VdbeAddOp(v, OP_Column, iTab, 0); ................................................................................ #endif /* SQLITE_OMIT_EXPLAIN */ pTabItem = &pTabList->a[pLevel->iFrom]; pTab = pTabItem->pTab; iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); if( pTab->isTransient || pTab->pSelect ) continue; if( (pLevel->flags & WHERE_IDX_ONLY)==0 ){ sqlite3OpenTable(pParse, pTabItem->iCursor, iDb, pTab, OP_OpenRead); }else{ sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName); } pLevel->iTabCur = pTabItem->iCursor; if( (pIx = pLevel->pIdx)!=0 ){ KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIx); assert( pIx->pSchema==pTab->pSchema ); ................................................................................ }else{ testOp = nEq>0 ? OP_IdxGE : OP_Noop; topEq = 1; } if( testOp!=OP_Noop ){ int nCol = nEq + topLimit; pLevel->iMem = pParse->nMem++; buildIndexProbe(v, nCol, brk, pIdx); if( bRev ){ int op = topEq ? OP_MoveLe : OP_MoveLt; sqlite3VdbeAddOp(v, op, iIdxCur, brk); }else{ sqlite3VdbeAddOp(v, OP_MemStore, pLevel->iMem, 1); } }else if( bRev ){ ................................................................................ btmEq = pTerm->operator & (WO_LE|WO_GE); disableTerm(pLevel, pTerm); }else{ btmEq = 1; } if( nEq>0 || btmLimit ){ int nCol = nEq + btmLimit; buildIndexProbe(v, nCol, brk, pIdx); if( bRev ){ pLevel->iMem = pParse->nMem++; sqlite3VdbeAddOp(v, OP_MemStore, pLevel->iMem, 1); testOp = OP_IdxLT; }else{ int op = btmEq ? OP_MoveGe : OP_MoveGt; sqlite3VdbeAddOp(v, op, iIdxCur, brk); ................................................................................ ** and leave the values of those terms on the stack. */ codeAllEqualityTerms(pParse, pLevel, &wc, notReady, brk); /* Generate a single key that will be used to both start and terminate ** the search */ buildIndexProbe(v, nEq, brk, pIdx); sqlite3VdbeAddOp(v, OP_MemStore, pLevel->iMem, 0); /* Generate code (1) to move to the first matching element of the table. ** Then generate code (2) that jumps to "brk" after the cursor is past ** the last matching element of the table. The code (1) is executed ** once to initialize the search, the code (2) is executed before each ** iteration of the scan to see if the scan has finished. */ |
| | > > > | > > > > | > > > > > > | | > > > > > > > | | | |
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 ... 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 .... 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 .... 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 .... 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 .... 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 .... 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 .... 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 |
** This module contains C code that generates VDBE code used to process ** the WHERE clause of SQL statements. This module is reponsible for ** generating the code that loops through a table looking for applicable ** rows. Indices are selected and used to speed the search when doing ** so is applicable. Because this module is responsible for selecting ** indices, you might also think of this module as the "query optimizer". ** ** $Id: where.c,v 1.17 2006/01/16 15:51:47 rmsimpson Exp $ */ #include "sqliteInt.h" /* ** The number of bits in a Bitmask. "BMS" means "BitMask Size". */ #define BMS (sizeof(Bitmask)*8) ................................................................................ pTerm = &pWC->a[idxTerm]; pWC->a[idxNew].iParent = idxTerm; } pTerm->nChild = 2; } #endif /* SQLITE_OMIT_BETWEEN_OPTIMIZATION */ #if !defined(SQLITE_OMIT_OR_OPTIMIZATION) && !defined(SQLITE_OMIT_SUBQUERY) /* Attempt to convert OR-connected terms into an IN operator so that ** they can make use of indices. Example: ** ** x = expr1 OR expr2 = x OR x = expr3 ** ** is converted into ** ** x IN (expr1,expr2,expr3) ** ** This optimization must be omitted if OMIT_SUBQUERY is defined because ** the compiler for the the IN operator is part of sub-queries. */ else if( pExpr->op==TK_OR ){ int ok; int i, j; int iColumn, iCursor; WhereClause sOr; WhereTerm *pOrTerm; ................................................................................ /* ** Generate code that builds a probe for an index. Details: ** ** * Check the top nColumn entries on the stack. If any ** of those entries are NULL, jump immediately to brk, ** which is the loop exit, since no index entry will match ** if any part of the key is NULL. Pop (nColumn+nExtra) ** elements from the stack. ** ** * Construct a probe entry from the top nColumn entries in ** the stack with affinities appropriate for index pIdx. ** Only nColumn elements are popped from the stack in this case ** (by OP_MakeRecord). ** */ static void buildIndexProbe( Vdbe *v, int nColumn, int nExtra, int brk, Index *pIdx ){ sqlite3VdbeAddOp(v, OP_NotNull, -nColumn, sqlite3VdbeCurrentAddr(v)+3); sqlite3VdbeAddOp(v, OP_Pop, nColumn+nExtra, 0); sqlite3VdbeAddOp(v, OP_Goto, 0, brk); sqlite3VdbeAddOp(v, OP_MakeRecord, nColumn, 0); sqlite3IndexAffinityStr(v, pIdx); } /* ................................................................................ Vdbe *v = pParse->pVdbe; sqlite3CodeSubselect(pParse, pX); iTab = pX->iTable; sqlite3VdbeAddOp(v, OP_Rewind, iTab, brk); VdbeComment((v, "# %.*s", pX->span.n, pX->span.z)); pLevel->nIn++; sqliteReallocOrFree((void**)&pLevel->aInLoop, sizeof(pLevel->aInLoop[0])*3*pLevel->nIn); aIn = pLevel->aInLoop; if( aIn ){ aIn += pLevel->nIn*3 - 3; aIn[0] = OP_Next; aIn[1] = iTab; aIn[2] = sqlite3VdbeAddOp(v, OP_Column, iTab, 0); ................................................................................ #endif /* SQLITE_OMIT_EXPLAIN */ pTabItem = &pTabList->a[pLevel->iFrom]; pTab = pTabItem->pTab; iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); if( pTab->isTransient || pTab->pSelect ) continue; if( (pLevel->flags & WHERE_IDX_ONLY)==0 ){ sqlite3OpenTable(pParse, pTabItem->iCursor, iDb, pTab, OP_OpenRead); if( pTab->nCol<(sizeof(Bitmask)*8) ){ Bitmask b = pTabItem->colUsed; int n = 0; for(; b; b=b>>1, n++); sqlite3VdbeChangeP2(v, sqlite3VdbeCurrentAddr(v)-1, n); assert( n<=pTab->nCol ); } }else{ sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName); } pLevel->iTabCur = pTabItem->iCursor; if( (pIx = pLevel->pIdx)!=0 ){ KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIx); assert( pIx->pSchema==pTab->pSchema ); ................................................................................ }else{ testOp = nEq>0 ? OP_IdxGE : OP_Noop; topEq = 1; } if( testOp!=OP_Noop ){ int nCol = nEq + topLimit; pLevel->iMem = pParse->nMem++; buildIndexProbe(v, nCol, nEq, brk, pIdx); if( bRev ){ int op = topEq ? OP_MoveLe : OP_MoveLt; sqlite3VdbeAddOp(v, op, iIdxCur, brk); }else{ sqlite3VdbeAddOp(v, OP_MemStore, pLevel->iMem, 1); } }else if( bRev ){ ................................................................................ btmEq = pTerm->operator & (WO_LE|WO_GE); disableTerm(pLevel, pTerm); }else{ btmEq = 1; } if( nEq>0 || btmLimit ){ int nCol = nEq + btmLimit; buildIndexProbe(v, nCol, 0, brk, pIdx); if( bRev ){ pLevel->iMem = pParse->nMem++; sqlite3VdbeAddOp(v, OP_MemStore, pLevel->iMem, 1); testOp = OP_IdxLT; }else{ int op = btmEq ? OP_MoveGe : OP_MoveGt; sqlite3VdbeAddOp(v, op, iIdxCur, brk); ................................................................................ ** and leave the values of those terms on the stack. */ codeAllEqualityTerms(pParse, pLevel, &wc, notReady, brk); /* Generate a single key that will be used to both start and terminate ** the search */ buildIndexProbe(v, nEq, 0, brk, pIdx); sqlite3VdbeAddOp(v, OP_MemStore, pLevel->iMem, 0); /* Generate code (1) to move to the first matching element of the table. ** Then generate code (2) that jumps to "brk" after the cursor is past ** the last matching element of the table. The code (1) is executed ** once to initialize the search, the code (2) is executed before each ** iteration of the scan to see if the scan has finished. */ |