Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Change a few selected functions to macros to speed things up. (CVS 4015) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
93f811ec747f6a42daf9ee27cd8b013f |
User & Date: | danielk1977 2007-05-16 17:28:43.000 |
Context
2007-05-16
| ||
17:50 | Avoid passing a negative value to isspace() in a couple places. (CVS 4016) (check-in: d5db8be368 user: danielk1977 tags: trunk) | |
17:28 | Change a few selected functions to macros to speed things up. (CVS 4015) (check-in: 93f811ec74 user: danielk1977 tags: trunk) | |
14:23 | Omit some extra code when OMIT_INCRBLOB is defined. (CVS 4014) (check-in: 1d89be287d user: danielk1977 tags: trunk) | |
Changes
Changes to src/btree.c.
1 2 3 4 5 6 7 8 9 10 11 | /* ** 2004 April 6 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | /* ** 2004 April 6 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** $Id: btree.c,v 1.382 2007/05/16 17:28:43 danielk1977 Exp $ ** ** This file implements a external (disk-based) database using BTrees. ** See the header comment on "btreeInt.h" for additional information. ** Including a description of file format and an overview of operation. */ #include "btreeInt.h" |
︙ | ︙ | |||
415 416 417 418 419 420 421 422 423 424 425 | /* ** Given a btree page and a cell index (0 means the first cell on ** the page, 1 means the second cell, and so forth) return a pointer ** to the cell content. ** ** This routine works only for pages that do not contain overflow cells. */ u8 *sqlite3BtreeFindCell(MemPage *pPage, int iCell){ u8 *data = pPage->aData; assert( iCell>=0 ); assert( iCell<get2byte(&data[pPage->hdrOffset+3]) ); | > > | | > > > | 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 | /* ** Given a btree page and a cell index (0 means the first cell on ** the page, 1 means the second cell, and so forth) return a pointer ** to the cell content. ** ** This routine works only for pages that do not contain overflow cells. */ #define findCell(pPage, iCell) \ ((pPage)->aData + get2byte(&(pPage)->aData[(pPage)->cellOffset+2*(iCell)])) u8 *sqlite3BtreeFindCell(MemPage *pPage, int iCell){ u8 *data = pPage->aData; assert( iCell>=0 ); assert( iCell<get2byte(&data[pPage->hdrOffset+3]) ); return findCell(pPage, iCell); } /* ** This a more complex version of sqlite3BtreeFindCell() that works for ** pages that do contain overflow cells. See insert */ static u8 *findOverflowCell(MemPage *pPage, int iCell){ int i; for(i=pPage->nOverflow-1; i>=0; i--){ int k; struct _OvflCell *pOvfl; pOvfl = &pPage->aOvfl[i]; k = pOvfl->idx; if( k<=iCell ){ if( k==iCell ){ return pOvfl->pCell; } iCell--; } } return findCell(pPage, iCell); } /* ** Parse a cell content block and fill in the CellInfo structure. There ** are two versions of this function. sqlite3BtreeParseCell() takes a ** cell index as the second argument and sqlite3BtreeParseCellPtr() ** takes a pointer to the body of the cell as its second argument. ** ** Within this file, the parseCell() macro can be called instead of ** sqlite3BtreeParseCellPtr(). Using some compilers, this will be faster. */ void sqlite3BtreeParseCellPtr( MemPage *pPage, /* Page containing the cell */ u8 *pCell, /* Pointer to the cell text. */ CellInfo *pInfo /* Fill in this structure */ ){ int n; /* Number bytes in cell content header */ |
︙ | ︙ | |||
515 516 517 518 519 520 521 522 523 524 525 526 | }else{ pInfo->nLocal = minLocal; } pInfo->iOverflow = pInfo->nLocal + n; pInfo->nSize = pInfo->iOverflow + 4; } } void sqlite3BtreeParseCell( MemPage *pPage, /* Page containing the cell */ int iCell, /* The cell index. First cell is 0 */ CellInfo *pInfo /* Fill in this structure */ ){ | > > | | 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 | }else{ pInfo->nLocal = minLocal; } pInfo->iOverflow = pInfo->nLocal + n; pInfo->nSize = pInfo->iOverflow + 4; } } #define parseCell(pPage, iCell, pInfo) \ sqlite3BtreeParseCellPtr((pPage), findCell((pPage), (iCell)), (pInfo)) void sqlite3BtreeParseCell( MemPage *pPage, /* Page containing the cell */ int iCell, /* The cell index. First cell is 0 */ CellInfo *pInfo /* Fill in this structure */ ){ parseCell(pPage, iCell, pInfo); } /* ** Compute the total number of bytes that a Cell needs in the cell ** data area of the btree-page. The return number includes the cell ** data header and the local payload, but not any overflow page or ** the space used by the cell pointer. |
︙ | ︙ | |||
1657 1658 1659 1660 1661 1662 1663 | int isInitOrig = pPage->isInit; Pgno pgno = pPage->pgno; sqlite3BtreeInitPage(pPage, 0); nCell = pPage->nCell; for(i=0; i<nCell; i++){ | | | 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 | int isInitOrig = pPage->isInit; Pgno pgno = pPage->pgno; sqlite3BtreeInitPage(pPage, 0); nCell = pPage->nCell; for(i=0; i<nCell; i++){ u8 *pCell = findCell(pPage, i); rc = ptrmapPutOvflPtr(pPage, pCell); if( rc!=SQLITE_OK ){ goto set_child_ptrmaps_out; } if( !pPage->leaf ){ |
︙ | ︙ | |||
1712 1713 1714 1715 1716 1717 1718 | int i; int nCell; sqlite3BtreeInitPage(pPage, 0); nCell = pPage->nCell; for(i=0; i<nCell; i++){ | | | 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 | int i; int nCell; sqlite3BtreeInitPage(pPage, 0); nCell = pPage->nCell; for(i=0; i<nCell; i++){ u8 *pCell = findCell(pPage, i); if( eType==PTRMAP_OVERFLOW1 ){ CellInfo info; sqlite3BtreeParseCellPtr(pPage, pCell, &info); if( info.iOverflow ){ if( iFrom==get4byte(&pCell[info.iOverflow]) ){ put4byte(&pCell[info.iOverflow], iTo); break; |
︙ | ︙ | |||
2451 2452 2453 2454 2455 2456 2457 | void sqlite3BtreeReleaseTempCursor(BtCursor *pCur){ if( pCur->pPage ){ sqlite3PagerUnref(pCur->pPage->pDbPage); } } /* | > > | | < < < < > > > > | > > > > > | | | 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 | void sqlite3BtreeReleaseTempCursor(BtCursor *pCur){ if( pCur->pPage ){ sqlite3PagerUnref(pCur->pPage->pDbPage); } } /* ** The GET_CELL_INFO() macro. Takes one argument, a pointer to a valid ** btree cursor (type BtCursor*). This macro makes sure the BtCursor.info ** field of the given cursor is valid. If it is not already valid, call ** sqlite3BtreeParseCell() to fill it in. ** ** BtCursor.info is a cache of the information in the current cell. ** Using this cache reduces the number of calls to sqlite3BtreeParseCell(). */ #ifndef NDEBUG static void assertCellInfo(BtCursor *pCur){ CellInfo info; memset(&info, 0, sizeof(info)); sqlite3BtreeParseCell(pCur->pPage, pCur->idx, &info); assert( memcmp(&info, &pCur->info, sizeof(info))==0 ); } #else #define assertCellInfo(x) #endif #define GET_CELL_INFO(pCur) \ if( pCur->info.nSize==0 ) \ sqlite3BtreeParseCell(pCur->pPage, pCur->idx, &pCur->info); \ else \ assertCellInfo(pCur); /* ** Set *pSize to the size of the buffer needed to hold the value of ** 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); if( rc==SQLITE_OK ){ assert( pCur->eState==CURSOR_INVALID || pCur->eState==CURSOR_VALID ); if( pCur->eState==CURSOR_INVALID ){ *pSize = 0; }else{ GET_CELL_INFO(pCur); *pSize = pCur->info.nKey; } } return rc; } /* |
︙ | ︙ | |||
2507 2508 2509 2510 2511 2512 2513 | int rc = restoreOrClearCursorPosition(pCur); 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{ | | | 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 | int rc = restoreOrClearCursorPosition(pCur); 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{ GET_CELL_INFO(pCur); *pSize = pCur->info.nData; } } return rc; } /* |
︙ | ︙ | |||
2680 2681 2682 2683 2684 2685 2686 | BtShared *pBt = pCur->pBtree->pBt; /* Btree this cursor belongs to */ assert( pPage ); assert( pCur->eState==CURSOR_VALID ); assert( pCur->idx>=0 && pCur->idx<pPage->nCell ); assert( offset>=0 ); | | | 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 | BtShared *pBt = pCur->pBtree->pBt; /* Btree this cursor belongs to */ assert( pPage ); assert( pCur->eState==CURSOR_VALID ); assert( pCur->idx>=0 && pCur->idx<pPage->nCell ); assert( offset>=0 ); GET_CELL_INFO(pCur); aPayload = pCur->info.pCell + pCur->info.nHeader; nKey = (pPage->intKey ? 0 : pCur->info.nKey); if( skipKey ){ offset += nKey; } if( offset+amt > nKey+pCur->info.nData ){ |
︙ | ︙ | |||
2870 2871 2872 2873 2874 2875 2876 | u32 nKey; int nLocal; assert( pCur!=0 && pCur->pPage!=0 ); assert( pCur->eState==CURSOR_VALID ); pPage = pCur->pPage; assert( pCur->idx>=0 && pCur->idx<pPage->nCell ); | | | 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 | u32 nKey; int nLocal; assert( pCur!=0 && pCur->pPage!=0 ); assert( pCur->eState==CURSOR_VALID ); pPage = pCur->pPage; assert( pCur->idx>=0 && pCur->idx<pPage->nCell ); GET_CELL_INFO(pCur); aPayload = pCur->info.pCell; aPayload += pCur->info.nHeader; if( pPage->intKey ){ nKey = 0; }else{ nKey = pCur->info.nKey; } |
︙ | ︙ | |||
3041 3042 3043 3044 3045 3046 3047 | Pgno pgno; int rc; MemPage *pPage; assert( pCur->eState==CURSOR_VALID ); while( !(pPage = pCur->pPage)->leaf ){ assert( pCur->idx>=0 && pCur->idx<pPage->nCell ); | | | 3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 | Pgno pgno; int rc; MemPage *pPage; assert( pCur->eState==CURSOR_VALID ); while( !(pPage = pCur->pPage)->leaf ){ assert( pCur->idx>=0 && pCur->idx<pPage->nCell ); pgno = get4byte(findCell(pPage, pCur->idx)); rc = moveToChild(pCur, pgno); if( rc ) return rc; } return SQLITE_OK; } /* |
︙ | ︙ | |||
3178 3179 3180 3181 3182 3183 3184 | } if( lwr<=upr ) for(;;){ void *pCellKey; i64 nCellKey; pCur->info.nSize = 0; if( pPage->intKey ){ u8 *pCell; | | | 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206 | } if( lwr<=upr ) for(;;){ void *pCellKey; i64 nCellKey; pCur->info.nSize = 0; if( pPage->intKey ){ u8 *pCell; pCell = findCell(pPage, pCur->idx) + pPage->childPtrSize; if( pPage->hasData ){ u32 dummy; pCell += getVarint32(pCell, &dummy); } getVarint(pCell, (u64 *)&nCellKey); if( nCellKey<nKey ){ c = -1; |
︙ | ︙ | |||
3233 3234 3235 3236 3237 3238 3239 | assert( lwr==upr+1 ); assert( pPage->isInit ); if( pPage->leaf ){ chldPg = 0; }else if( lwr>=pPage->nCell ){ chldPg = get4byte(&pPage->aData[pPage->hdrOffset+8]); }else{ | | | 3247 3248 3249 3250 3251 3252 3253 3254 3255 3256 3257 3258 3259 3260 3261 | assert( lwr==upr+1 ); assert( pPage->isInit ); if( pPage->leaf ){ chldPg = 0; }else if( lwr>=pPage->nCell ){ chldPg = get4byte(&pPage->aData[pPage->hdrOffset+8]); }else{ chldPg = get4byte(findCell(pPage, lwr)); } if( chldPg==0 ){ assert( pCur->idx>=0 && pCur->idx<pCur->pPage->nCell ); if( pRes ) *pRes = c; return SQLITE_OK; } pCur->idx = lwr; |
︙ | ︙ | |||
3360 3361 3362 3363 3364 3365 3366 | } pCur->skip = 0; pPage = pCur->pPage; assert( pPage->isInit ); assert( pCur->idx>=0 ); if( !pPage->leaf ){ | | | 3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 3385 3386 3387 3388 | } pCur->skip = 0; pPage = pCur->pPage; assert( pPage->isInit ); assert( pCur->idx>=0 ); if( !pPage->leaf ){ pgno = get4byte( findCell(pPage, pCur->idx) ); rc = moveToChild(pCur, pgno); if( rc ) return rc; rc = moveToRightmost(pCur); }else{ while( pCur->idx==0 ){ if( sqlite3BtreeIsRootPage(pPage) ){ pCur->eState = CURSOR_INVALID; |
︙ | ︙ | |||
3929 3930 3931 3932 3933 3934 3935 | int i; BtShared *pBt = pPage->pBt; int rc = SQLITE_OK; if( pPage->leaf ) return SQLITE_OK; for(i=0; i<pPage->nCell; i++){ | | | 3943 3944 3945 3946 3947 3948 3949 3950 3951 3952 3953 3954 3955 3956 3957 | int i; BtShared *pBt = pPage->pBt; int rc = SQLITE_OK; if( pPage->leaf ) return SQLITE_OK; for(i=0; i<pPage->nCell; i++){ u8 *pCell = findCell(pPage, i); if( !pPage->leaf ){ rc = reparentPage(pBt, get4byte(pCell), pPage, i); if( rc!=SQLITE_OK ) return rc; } } if( !pPage->leaf ){ rc = reparentPage(pBt, get4byte(&pPage->aData[pPage->hdrOffset+8]), |
︙ | ︙ | |||
4183 4184 4185 4186 4187 4188 4189 | sqlite3PagerRef(pParent->pDbPage); /* pPage is currently the right-child of pParent. Change this ** so that the right-child is the new page allocated above and ** pPage is the next-to-right child. */ assert( pPage->nCell>0 ); | | | 4197 4198 4199 4200 4201 4202 4203 4204 4205 4206 4207 4208 4209 4210 4211 | sqlite3PagerRef(pParent->pDbPage); /* pPage is currently the right-child of pParent. Change this ** so that the right-child is the new page allocated above and ** pPage is the next-to-right child. */ assert( pPage->nCell>0 ); pCell = findCell(pPage, pPage->nCell-1); sqlite3BtreeParseCellPtr(pPage, pCell, &info); rc = fillInCell(pParent, parentCell, 0, info.nKey, 0, 0, 0, &parentSize); if( rc!=SQLITE_OK ){ return rc; } assert( parentSize<64 ); rc = insertCell(pParent, parentIdx, parentCell, parentSize, 0, 4); |
︙ | ︙ | |||
4333 4334 4335 4336 4337 4338 4339 | ** is the rightmost child of pParent then set idx to pParent->nCell */ if( pParent->idxShift ){ Pgno pgno; pgno = pPage->pgno; assert( pgno==sqlite3PagerPagenumber(pPage->pDbPage) ); for(idx=0; idx<pParent->nCell; idx++){ | | | 4347 4348 4349 4350 4351 4352 4353 4354 4355 4356 4357 4358 4359 4360 4361 | ** is the rightmost child of pParent then set idx to pParent->nCell */ if( pParent->idxShift ){ Pgno pgno; pgno = pPage->pgno; assert( pgno==sqlite3PagerPagenumber(pPage->pDbPage) ); for(idx=0; idx<pParent->nCell; idx++){ if( get4byte(findCell(pParent, idx))==pgno ){ break; } } assert( idx<pParent->nCell || get4byte(&pParent->aData[pParent->hdrOffset+8])==pgno ); }else{ idx = pPage->idxParent; |
︙ | ︙ | |||
4367 4368 4369 4370 4371 4372 4373 | } if( nxDiv<0 ){ nxDiv = 0; } nDiv = 0; for(i=0, k=nxDiv; i<NB; i++, k++){ if( k<pParent->nCell ){ | | | 4381 4382 4383 4384 4385 4386 4387 4388 4389 4390 4391 4392 4393 4394 4395 | } if( nxDiv<0 ){ nxDiv = 0; } nDiv = 0; for(i=0, k=nxDiv; i<NB; i++, k++){ if( k<pParent->nCell ){ apDiv[i] = findCell(pParent, k); nDiv++; assert( !pParent->leaf ); pgnoOld[i] = get4byte(apDiv[i]); }else if( k==pParent->nCell ){ pgnoOld[i] = get4byte(&pParent->aData[pParent->hdrOffset+8]); }else{ break; |
︙ | ︙ | |||
4868 4869 4870 4871 4872 4873 4874 | assert( pChild->nOverflow==0 ); if( pChild->nFree>=100 ){ /* The child information will fit on the root page, so do the ** copy */ int i; zeroPage(pPage, pChild->aData[0]); for(i=0; i<pChild->nCell; i++){ | | | 4882 4883 4884 4885 4886 4887 4888 4889 4890 4891 4892 4893 4894 4895 4896 | assert( pChild->nOverflow==0 ); if( pChild->nFree>=100 ){ /* The child information will fit on the root page, so do the ** copy */ int i; zeroPage(pPage, pChild->aData[0]); for(i=0; i<pChild->nCell; i++){ apCell[i] = findCell(pChild,i); szCell[i] = cellSizePtr(pChild, apCell[i]); } assemblePage(pPage, pChild->nCell, apCell, szCell); /* Copy the right-pointer of the child to the parent. */ put4byte(&pPage->aData[pPage->hdrOffset+8], get4byte(&pChild->aData[pChild->hdrOffset+8])); freePage(pChild); |
︙ | ︙ | |||
5101 5102 5103 5104 5105 5106 5107 | rc = fillInCell(pPage, newCell, pKey, nKey, pData, nData, nZero, &szNew); if( rc ) goto end_insert; assert( szNew==cellSizePtr(pPage, newCell) ); assert( szNew<=MX_CELL_SIZE(pBt) ); if( loc==0 && CURSOR_VALID==pCur->eState ){ int szOld; assert( pCur->idx>=0 && pCur->idx<pPage->nCell ); | | | 5115 5116 5117 5118 5119 5120 5121 5122 5123 5124 5125 5126 5127 5128 5129 | rc = fillInCell(pPage, newCell, pKey, nKey, pData, nData, nZero, &szNew); if( rc ) goto end_insert; assert( szNew==cellSizePtr(pPage, newCell) ); assert( szNew<=MX_CELL_SIZE(pBt) ); if( loc==0 && CURSOR_VALID==pCur->eState ){ int szOld; assert( pCur->idx>=0 && pCur->idx<pPage->nCell ); oldCell = findCell(pPage, pCur->idx); if( !pPage->leaf ){ memcpy(newCell, oldCell, 4); } szOld = cellSizePtr(pPage, oldCell); rc = clearCell(pPage, oldCell); if( rc ) goto end_insert; dropCell(pPage, pCur->idx, szOld); |
︙ | ︙ | |||
5173 5174 5175 5176 5177 5178 5179 | return rc; } /* Locate the cell within it's page and leave pCell pointing to the ** data. The clearCell() call frees any overflow pages associated with the ** cell. The cell itself is still intact. */ | | | 5187 5188 5189 5190 5191 5192 5193 5194 5195 5196 5197 5198 5199 5200 5201 | return rc; } /* Locate the cell within it's page and leave pCell pointing to the ** data. The clearCell() call frees any overflow pages associated with the ** cell. The cell itself is still intact. */ pCell = findCell(pPage, pCur->idx); if( !pPage->leaf ){ pgnoChild = get4byte(pCell); } rc = clearCell(pPage, pCell); if( rc ) return rc; if( !pPage->leaf ){ |
︙ | ︙ | |||
5205 5206 5207 5208 5209 5210 5211 | if( rc==SQLITE_OK ){ rc = sqlite3PagerWrite(leafCur.pPage->pDbPage); } if( rc==SQLITE_OK ){ TRACE(("DELETE: table=%d delete internal from %d replace from leaf %d\n", pCur->pgnoRoot, pPage->pgno, leafCur.pPage->pgno)); dropCell(pPage, pCur->idx, cellSizePtr(pPage, pCell)); | | | 5219 5220 5221 5222 5223 5224 5225 5226 5227 5228 5229 5230 5231 5232 5233 | if( rc==SQLITE_OK ){ rc = sqlite3PagerWrite(leafCur.pPage->pDbPage); } if( rc==SQLITE_OK ){ TRACE(("DELETE: table=%d delete internal from %d replace from leaf %d\n", pCur->pgnoRoot, pPage->pgno, leafCur.pPage->pgno)); dropCell(pPage, pCur->idx, cellSizePtr(pPage, pCell)); pNext = findCell(leafCur.pPage, leafCur.idx); szNext = cellSizePtr(leafCur.pPage, pNext); assert( MX_CELL_SIZE(pBt)>=szNext+4 ); tempCell = sqliteMallocRaw( MX_CELL_SIZE(pBt) ); if( tempCell==0 ){ rc = SQLITE_NOMEM; } } |
︙ | ︙ | |||
5396 5397 5398 5399 5400 5401 5402 | if( pgno>sqlite3PagerPagecount(pBt->pPager) ){ return SQLITE_CORRUPT_BKPT; } rc = getAndInitPage(pBt, pgno, &pPage, pParent); if( rc ) goto cleardatabasepage_out; for(i=0; i<pPage->nCell; i++){ | | | 5410 5411 5412 5413 5414 5415 5416 5417 5418 5419 5420 5421 5422 5423 5424 | if( pgno>sqlite3PagerPagecount(pBt->pPager) ){ return SQLITE_CORRUPT_BKPT; } rc = getAndInitPage(pBt, pgno, &pPage, pParent); if( rc ) goto cleardatabasepage_out; for(i=0; i<pPage->nCell; i++){ pCell = findCell(pPage, i); if( !pPage->leaf ){ rc = clearDatabasePage(pBt, get4byte(pCell), pPage->pParent, 1); if( rc ) goto cleardatabasepage_out; } rc = clearCell(pPage, pCell); if( rc ) goto cleardatabasepage_out; } |
︙ | ︙ | |||
5883 5884 5885 5886 5887 5888 5889 | int sz; CellInfo info; /* Check payload overflow pages */ sqlite3_snprintf(sizeof(zContext), zContext, "On tree page %d cell %d: ", iPage, i); | | | 5897 5898 5899 5900 5901 5902 5903 5904 5905 5906 5907 5908 5909 5910 5911 | int sz; CellInfo info; /* Check payload overflow pages */ sqlite3_snprintf(sizeof(zContext), zContext, "On tree page %d cell %d: ", iPage, i); pCell = findCell(pPage,i); sqlite3BtreeParseCellPtr(pPage, pCell, &info); sz = info.nData; if( !pPage->intKey ) sz += info.nKey; assert( sz==info.nPayload ); if( sz>info.nLocal ){ int nPage = (sz - info.nLocal + usableSize - 5)/(usableSize - 4); Pgno pgnoOvfl = get4byte(&pCell[info.iOverflow]); |
︙ | ︙ |
Changes to src/btreeInt.h.
1 2 3 4 5 6 7 8 9 10 11 | /* ** 2004 April 6 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | /* ** 2004 April 6 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** $Id: btreeInt.h,v 1.4 2007/05/16 17:28:43 danielk1977 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. |
︙ | ︙ | |||
566 567 568 569 570 571 572 | char *zErrMsg; /* An error message. NULL if no errors seen. */ int nErr; /* Number of messages written to zErrMsg so far */ }; /* ** Read or write a two- and four-byte big-endian integer values. */ | | > < | 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 | char *zErrMsg; /* An error message. NULL if no errors seen. */ int nErr; /* Number of messages written to zErrMsg so far */ }; /* ** Read or write a two- and four-byte big-endian integer values. */ #define get2byte(x) ((x)[0]<<8 | (x)[1]) #define put2byte(p,v) ((p)[0] = (v)>>8, (p)[1] = (v)) #define get4byte sqlite3Get4byte #define put4byte sqlite3Put4byte /* ** Internal routines that should be accessed by the btree layer only. */ int sqlite3BtreeGetPage(BtShared*, Pgno, MemPage**, int); int sqlite3BtreeInitPage(MemPage *pPage, MemPage *pParent); |
︙ | ︙ |
Changes to src/malloc.c.
︙ | ︙ | |||
8 9 10 11 12 13 14 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** Memory allocation functions used throughout sqlite. ** ** | | | 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. ** ************************************************************************* ** Memory allocation functions used throughout sqlite. ** ** ** $Id: malloc.c,v 1.2 2007/05/16 17:28:43 danielk1977 Exp $ */ #include "sqliteInt.h" #include "os.h" #include <stdarg.h> #include <ctype.h> /* |
︙ | ︙ | |||
784 785 786 787 788 789 790 | ** function. However, if a malloc() failure has occured since the previous ** invocation SQLITE_NOMEM is returned instead. ** ** If the first argument, db, is not NULL and a malloc() error has occured, ** then the connection error-code (the value returned by sqlite3_errcode()) ** is set to SQLITE_NOMEM. */ | | | < < < < < < < < | | | 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 | ** function. However, if a malloc() failure has occured since the previous ** invocation SQLITE_NOMEM is returned instead. ** ** If the first argument, db, is not NULL and a malloc() error has occured, ** then the connection error-code (the value returned by sqlite3_errcode()) ** is set to SQLITE_NOMEM. */ int sqlite3_mallocHasFailed = 0; int sqlite3ApiExit(sqlite3* db, int rc){ if( sqlite3MallocFailed() ){ sqlite3_mallocHasFailed = 0; sqlite3OsLeaveMutex(); sqlite3Error(db, SQLITE_NOMEM, 0); rc = SQLITE_NOMEM; } return rc & (db ? db->errMask : 0xff); } /* ** Set the "malloc has failed" condition to true for this thread. */ void sqlite3FailedMalloc(){ if( !sqlite3MallocFailed() ){ sqlite3OsEnterMutex(); assert( sqlite3_mallocHasFailed==0 ); sqlite3_mallocHasFailed = 1; } } #ifdef SQLITE_MEMDEBUG /* ** This function sets a flag in the thread-specific-data structure that will ** cause an assert to fail if sqliteMalloc() or sqliteRealloc() is called. |
︙ | ︙ |
Changes to src/sqliteInt.h.
1 2 3 4 5 6 7 8 9 10 11 12 13 | /* ** 2001 September 15 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** Internal interface definitions for SQLite. ** | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | /* ** 2001 September 15 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** Internal interface definitions for SQLite. ** ** @(#) $Id: sqliteInt.h,v 1.569 2007/05/16 17:28:43 danielk1977 Exp $ */ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ #include "limits.h" #if defined(SQLITE_TCL) || defined(TCLSH) |
︙ | ︙ | |||
250 251 252 253 254 255 256 257 258 | #define sqliteRealloc(x,y) sqlite3Realloc(x,y) #define sqliteStrDup(x) sqlite3StrDup(x) #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) | > > > > > > > > > > < | 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 | #define sqliteRealloc(x,y) sqlite3Realloc(x,y) #define sqliteStrDup(x) sqlite3StrDup(x) #define sqliteStrNDup(x,y) sqlite3StrNDup(x,y) #define sqliteReallocOrFree(x,y) sqlite3ReallocOrFree(x,y) #endif /* Variable sqlite3_mallocHasFailed is set to true after a malloc() ** failure occurs. ** ** The sqlite3MallocFailed() macro returns true if a malloc has failed ** in this thread since the last call to sqlite3ApiExit(), or false ** otherwise. */ extern int sqlite3_mallocHasFailed; #define sqlite3MallocFailed() (sqlite3_mallocHasFailed && sqlite3OsInMutex(1)) #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. */ struct ThreadData { int dummy; /* So that this structure is never empty */ |
︙ | ︙ | |||
328 329 330 331 332 333 334 335 336 337 338 339 340 341 | typedef struct TableLock TableLock; typedef struct Token Token; typedef struct TriggerStack TriggerStack; typedef struct TriggerStep TriggerStep; typedef struct Trigger Trigger; typedef struct WhereInfo WhereInfo; typedef struct WhereLevel WhereLevel; /* ** Each database file to be accessed by the system is an instance ** of the following structure. There are normally two of these structures ** in the sqlite.aDb[] array. aDb[0] is the main database file and ** aDb[1] is the database file used to hold temporary tables. Additional ** databases may be attached. | > > | 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 | typedef struct TableLock TableLock; typedef struct Token Token; typedef struct TriggerStack TriggerStack; typedef struct TriggerStep TriggerStep; typedef struct Trigger Trigger; typedef struct WhereInfo WhereInfo; typedef struct WhereLevel WhereLevel; #include "os.h" /* ** Each database file to be accessed by the system is an instance ** of the following structure. There are normally two of these structures ** in the sqlite.aDb[] array. aDb[0] is the main database file and ** aDb[1] is the database file used to hold temporary tables. Additional ** databases may be attached. |
︙ | ︙ | |||
1874 1875 1876 1877 1878 1879 1880 | Schema *sqlite3SchemaGet(Btree *); int sqlite3SchemaToIndex(sqlite3 *db, Schema *); KeyInfo *sqlite3IndexKeyinfo(Parse *, Index *); int sqlite3CreateFunc(sqlite3 *, const char *, int, int, void *, void (*)(sqlite3_context*,int,sqlite3_value **), void (*)(sqlite3_context*,int,sqlite3_value **), void (*)(sqlite3_context*)); int sqlite3ApiExit(sqlite3 *db, int); | < | 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 | Schema *sqlite3SchemaGet(Btree *); int sqlite3SchemaToIndex(sqlite3 *db, Schema *); KeyInfo *sqlite3IndexKeyinfo(Parse *, Index *); int sqlite3CreateFunc(sqlite3 *, const char *, int, int, void *, void (*)(sqlite3_context*,int,sqlite3_value **), void (*)(sqlite3_context*,int,sqlite3_value **), void (*)(sqlite3_context*)); int sqlite3ApiExit(sqlite3 *db, int); void sqlite3FailedMalloc(void); void sqlite3AbortOtherActiveVdbes(sqlite3 *, Vdbe *); int sqlite3OpenTempDatabase(Parse *); #ifndef SQLITE_OMIT_LOAD_EXTENSION void sqlite3CloseExtensions(sqlite3*); int sqlite3AutoLoadExtensions(sqlite3*); |
︙ | ︙ |
Changes to src/util.c.
︙ | ︙ | |||
10 11 12 13 14 15 16 | ** ************************************************************************* ** Utility functions used throughout sqlite. ** ** This file contains functions for allocating memory, comparing ** strings, and stuff like that. ** | | | 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | ** ************************************************************************* ** Utility functions used throughout sqlite. ** ** This file contains functions for allocating memory, comparing ** strings, and stuff like that. ** ** $Id: util.c,v 1.204 2007/05/16 17:28:43 danielk1977 Exp $ */ #include "sqliteInt.h" #include "os.h" #include <stdarg.h> #include <ctype.h> |
︙ | ︙ | |||
533 534 535 536 537 538 539 | v >>= 7; }while( v!=0 && i<9 ); return i; } /* | | < < < < < < < | 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 | v >>= 7; }while( v!=0 && i<9 ); return i; } /* ** Read or write a four-byte big-endian integer value. */ u32 sqlite3Get4byte(const u8 *p){ return (p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3]; } void sqlite3Put4byte(unsigned char *p, u32 v){ p[0] = v>>24; p[1] = v>>16; p[2] = v>>8; p[3] = v; } |
︙ | ︙ |
Changes to src/vdbe.c.
︙ | ︙ | |||
39 40 41 42 43 44 45 | ** ** Various scripts scan this source file in order to generate HTML ** documentation, headers files, or other derived files. The formatting ** of the code in this file is, therefore, important. See other comments ** in this file for details. If in doubt, do not deviate from existing ** commenting and indentation practices when changing or adding code. ** | | | 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | ** ** Various scripts scan this source file in order to generate HTML ** documentation, headers files, or other derived files. The formatting ** of the code in this file is, therefore, important. See other comments ** in this file for details. If in doubt, do not deviate from existing ** commenting and indentation practices when changing or adding code. ** ** $Id: vdbe.c,v 1.621 2007/05/16 17:28:43 danielk1977 Exp $ */ #include "sqliteInt.h" #include "os.h" #include <ctype.h> #include <math.h> #include "vdbeInt.h" |
︙ | ︙ | |||
147 148 149 150 151 152 153 154 155 156 157 158 159 160 | ** string that the stack entry itself controls. In other words, it ** converts an MEM_Ephem string into an MEM_Dyn string. */ #define Deephemeralize(P) \ if( ((P)->flags&MEM_Ephem)!=0 \ && sqlite3VdbeMemMakeWriteable(P) ){ goto no_mem;} /* ** Argument pMem points at a memory cell that will be passed to a ** user-defined function or returned to the user as the result of a query. ** The second argument, 'db_enc' is the text encoding used by the vdbe for ** stack variables. This routine sets the pMem->enc and pMem->type ** variables used by the sqlite3_value_*() routines. */ | > > > > > > | 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 | ** string that the stack entry itself controls. In other words, it ** converts an MEM_Ephem string into an MEM_Dyn string. */ #define Deephemeralize(P) \ if( ((P)->flags&MEM_Ephem)!=0 \ && sqlite3VdbeMemMakeWriteable(P) ){ goto no_mem;} /* ** Call sqlite3VdbeMemExpandBlob() on the supplied value (type Mem*) ** P if required. */ #define ExpandBlob(P) (((P)->flags&MEM_Zero)?sqlite3VdbeMemExpandBlob(P):0) /* ** Argument pMem points at a memory cell that will be passed to a ** user-defined function or returned to the user as the result of a query. ** The second argument, 'db_enc' is the text encoding used by the vdbe for ** stack variables. This routine sets the pMem->enc and pMem->type ** variables used by the sqlite3_value_*() routines. */ |
︙ | ︙ | |||
1466 1467 1468 1469 1470 1471 1472 | */ case OP_ToText: { /* same as TK_TO_TEXT, no-push */ assert( pTos>=p->aStack ); if( pTos->flags & MEM_Null ) break; assert( MEM_Str==(MEM_Blob>>3) ); pTos->flags |= (pTos->flags&MEM_Blob)>>3; applyAffinity(pTos, SQLITE_AFF_TEXT, encoding); | | | 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 | */ case OP_ToText: { /* same as TK_TO_TEXT, no-push */ assert( pTos>=p->aStack ); if( pTos->flags & MEM_Null ) break; assert( MEM_Str==(MEM_Blob>>3) ); pTos->flags |= (pTos->flags&MEM_Blob)>>3; applyAffinity(pTos, SQLITE_AFF_TEXT, encoding); rc = ExpandBlob(pTos); assert( pTos->flags & MEM_Str ); pTos->flags &= ~(MEM_Int|MEM_Real|MEM_Blob); break; } /* Opcode: ToBlob * * * ** |
︙ | ︙ | |||
1671 1672 1673 1674 1675 1676 1677 | affinity = pOp->p1 & 0xFF; if( affinity ){ applyAffinity(pNos, affinity, encoding); applyAffinity(pTos, affinity, encoding); } assert( pOp->p3type==P3_COLLSEQ || pOp->p3==0 ); | | | | 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 | affinity = pOp->p1 & 0xFF; if( affinity ){ applyAffinity(pNos, affinity, encoding); applyAffinity(pTos, affinity, encoding); } assert( pOp->p3type==P3_COLLSEQ || pOp->p3==0 ); ExpandBlob(pNos); ExpandBlob(pTos); res = sqlite3MemCompare(pNos, pTos, (CollSeq*)pOp->p3); switch( pOp->opcode ){ case OP_Eq: res = res==0; break; case OP_Ne: res = res!=0; break; case OP_Lt: res = res<0; break; case OP_Le: res = res<=0; break; case OP_Gt: res = res>0; break; |
︙ | ︙ | |||
2271 2272 2273 2274 2275 2276 2277 | if( zAffinity ){ applyAffinity(pRec, zAffinity[pRec-pData0], encoding); } if( pRec->flags&MEM_Null ){ containsNull = 1; } if( pRec->flags&MEM_Zero && pRec->n>0 ){ | | | 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 | if( zAffinity ){ applyAffinity(pRec, zAffinity[pRec-pData0], encoding); } if( pRec->flags&MEM_Null ){ containsNull = 1; } if( pRec->flags&MEM_Zero && pRec->n>0 ){ ExpandBlob(pRec); } serial_type = sqlite3VdbeSerialType(pRec, file_format); len = sqlite3VdbeSerialTypeLen(serial_type); nData += len; nHdr += sqlite3VarintLen(serial_type); if( pRec->flags & MEM_Zero ){ /* Only pure zero-filled BLOBs can be input to this Opcode. |
︙ | ︙ | |||
2924 2925 2926 2927 2928 2929 2930 | if( rc!=SQLITE_OK ){ goto abort_due_to_error; } pC->lastRowid = pTos->u.i; pC->rowidIsValid = res==0; }else{ assert( pTos->flags & MEM_Blob ); | | | 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 | if( rc!=SQLITE_OK ){ goto abort_due_to_error; } pC->lastRowid = pTos->u.i; pC->rowidIsValid = res==0; }else{ assert( pTos->flags & MEM_Blob ); ExpandBlob(pTos); rc = sqlite3BtreeMoveto(pC->pCursor, pTos->z, pTos->n, 0, &res); if( rc!=SQLITE_OK ){ goto abort_due_to_error; } pC->rowidIsValid = 0; } pC->deferredMoveto = 0; |
︙ | ︙ | |||
3827 3828 3829 3830 3831 3832 3833 | BtCursor *pCrsr; assert( pTos>=p->aStack ); assert( i>=0 && i<p->nCursor ); assert( p->apCsr[i]!=0 ); assert( pTos->flags & MEM_Blob ); if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){ assert( pC->isTable==0 ); | | | 3833 3834 3835 3836 3837 3838 3839 3840 3841 3842 3843 3844 3845 3846 3847 | BtCursor *pCrsr; assert( pTos>=p->aStack ); assert( i>=0 && i<p->nCursor ); assert( p->apCsr[i]!=0 ); assert( pTos->flags & MEM_Blob ); if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){ assert( pC->isTable==0 ); rc = ExpandBlob(pTos); if( rc==SQLITE_OK ){ int nKey = pTos->n; const char *zKey = pTos->z; rc = sqlite3BtreeInsert(pCrsr, zKey, nKey, "", 0, 0, pOp->p2); assert( pC->deferredMoveto==0 ); pC->cacheStatus = CACHE_STALE; } |
︙ | ︙ | |||
3963 3964 3965 3966 3967 3968 3969 | assert( p->apCsr[i]!=0 ); assert( pTos>=p->aStack ); if( (pC = p->apCsr[i])->pCursor!=0 ){ int res; assert( pTos->flags & MEM_Blob ); /* Created using OP_MakeRecord */ assert( pC->deferredMoveto==0 ); | | | 3969 3970 3971 3972 3973 3974 3975 3976 3977 3978 3979 3980 3981 3982 3983 | assert( p->apCsr[i]!=0 ); assert( pTos>=p->aStack ); if( (pC = p->apCsr[i])->pCursor!=0 ){ int res; assert( pTos->flags & MEM_Blob ); /* Created using OP_MakeRecord */ assert( pC->deferredMoveto==0 ); ExpandBlob(pTos); *pC->pIncrKey = pOp->p3!=0; assert( pOp->p3==0 || pOp->opcode!=OP_IdxGT ); rc = sqlite3VdbeIdxKeyCompare(pC, pTos->n, (u8*)pTos->z, &res); *pC->pIncrKey = 0; if( rc!=SQLITE_OK ){ break; } |
︙ | ︙ |
Changes to src/vdbemem.c.
︙ | ︙ | |||
17 18 19 20 21 22 23 24 25 26 27 28 29 30 | */ #include "sqliteInt.h" #include "os.h" #include <math.h> #include <ctype.h> #include "vdbeInt.h" /* ** If pMem is an object with a valid string representation, this routine ** ensures the internal encoding for the string representation is ** 'desiredEnc', one of SQLITE_UTF8, SQLITE_UTF16LE or SQLITE_UTF16BE. ** ** If pMem is not a string object, or the encoding of the string ** representation is already stored using the requested encoding, then this | > > > > > > | 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | */ #include "sqliteInt.h" #include "os.h" #include <math.h> #include <ctype.h> #include "vdbeInt.h" /* ** Call sqlite3VdbeMemExpandBlob() on the supplied value (type Mem*) ** P if required. */ #define expandBlob(P) (((P)->flags&MEM_Zero)?sqlite3VdbeMemExpandBlob(P):0) /* ** If pMem is an object with a valid string representation, this routine ** ensures the internal encoding for the string representation is ** 'desiredEnc', one of SQLITE_UTF8, SQLITE_UTF16LE or SQLITE_UTF16BE. ** ** If pMem is not a string object, or the encoding of the string ** representation is already stored using the requested encoding, then this |
︙ | ︙ | |||
59 60 61 62 63 64 65 | ** Make the given Mem object MEM_Dyn. ** ** Return SQLITE_OK on success or SQLITE_NOMEM if malloc fails. */ int sqlite3VdbeMemDynamicify(Mem *pMem){ int n; u8 *z; | | | 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 | ** Make the given Mem object MEM_Dyn. ** ** Return SQLITE_OK on success or SQLITE_NOMEM if malloc fails. */ int sqlite3VdbeMemDynamicify(Mem *pMem){ int n; u8 *z; expandBlob(pMem); if( (pMem->flags & (MEM_Ephem|MEM_Static|MEM_Short))==0 ){ return SQLITE_OK; } assert( (pMem->flags & MEM_Dyn)==0 ); n = pMem->n; assert( pMem->flags & (MEM_Str|MEM_Blob) ); z = sqliteMallocRaw( n+2 ); |
︙ | ︙ | |||
116 117 118 119 120 121 122 | ** of the Mem.z[] array can be modified. ** ** Return SQLITE_OK on success or SQLITE_NOMEM if malloc fails. */ int sqlite3VdbeMemMakeWriteable(Mem *pMem){ int n; u8 *z; | | | 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 | ** of the Mem.z[] array can be modified. ** ** Return SQLITE_OK on success or SQLITE_NOMEM if malloc fails. */ int sqlite3VdbeMemMakeWriteable(Mem *pMem){ int n; u8 *z; expandBlob(pMem); if( (pMem->flags & (MEM_Ephem|MEM_Static))==0 ){ return SQLITE_OK; } assert( (pMem->flags & MEM_Dyn)==0 ); assert( pMem->flags & (MEM_Str|MEM_Blob) ); if( (n = pMem->n)+2<sizeof(pMem->zShort) ){ z = (u8*)pMem->zShort; |
︙ | ︙ | |||
832 833 834 835 836 837 838 | assert( (enc&3)==(enc&~SQLITE_UTF16_ALIGNED) ); if( pVal->flags&MEM_Null ){ return 0; } assert( (MEM_Blob>>3) == MEM_Str ); pVal->flags |= (pVal->flags & MEM_Blob)>>3; | | | 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 | assert( (enc&3)==(enc&~SQLITE_UTF16_ALIGNED) ); if( pVal->flags&MEM_Null ){ return 0; } assert( (MEM_Blob>>3) == MEM_Str ); pVal->flags |= (pVal->flags & MEM_Blob)>>3; expandBlob(pVal); if( pVal->flags&MEM_Str ){ sqlite3VdbeChangeEncoding(pVal, enc & ~SQLITE_UTF16_ALIGNED); if( (enc & SQLITE_UTF16_ALIGNED)!=0 && 1==(1&(int)pVal->z) ){ assert( (pVal->flags & (MEM_Ephem|MEM_Static))!=0 ); if( sqlite3VdbeMemMakeWriteable(pVal)!=SQLITE_OK ){ return 0; } |
︙ | ︙ |