Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Refactor the sqlite3VdbeRecordUnpack() interface to better accommodate the vdbesort.c module. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
f115b2303509c678dbe83b2fa3d9c40d |
User & Date: | dan 2011-09-05 14:20:27.320 |
Context
2011-09-05
| ||
20:16 | Fix a minor performance regression in btreeMoveto(). (check-in: d0712dfb24 user: dan tags: trunk) | |
14:20 | Refactor the sqlite3VdbeRecordUnpack() interface to better accommodate the vdbesort.c module. (check-in: f115b23035 user: dan tags: trunk) | |
2011-09-04
| ||
01:27 | Fix a compiler warning about an unused parameter in the merge-sort code. (check-in: 6b657ae750 user: drh tags: trunk) | |
Changes
Changes to src/btree.c.
︙ | ︙ | |||
652 653 654 655 656 657 658 659 660 661 | i64 nKey, /* Integer key for tables. Size of pKey for indices */ int bias, /* Bias search to the high end */ int *pRes /* Write search results here */ ){ int rc; /* Status code */ UnpackedRecord *pIdxKey; /* Unpacked index key */ char aSpace[150]; /* Temp space for pIdxKey - to avoid a malloc */ if( pKey ){ assert( nKey==(i64)(int)nKey ); | > | | > > | | 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 | i64 nKey, /* Integer key for tables. Size of pKey for indices */ int bias, /* Bias search to the high end */ int *pRes /* Write search results here */ ){ int rc; /* Status code */ UnpackedRecord *pIdxKey; /* Unpacked index key */ char aSpace[150]; /* Temp space for pIdxKey - to avoid a malloc */ char *pFree = 0; if( pKey ){ assert( nKey==(i64)(int)nKey ); pIdxKey = sqlite3VdbeAllocUnpackedRecord( pCur->pKeyInfo, aSpace, sizeof(aSpace), &pFree ); if( pIdxKey==0 ) return SQLITE_NOMEM; sqlite3VdbeRecordUnpack(pCur->pKeyInfo, nKey, pKey, pIdxKey); }else{ pIdxKey = 0; } rc = sqlite3BtreeMovetoUnpacked(pCur, pIdxKey, nKey, bias, pRes); if( pKey ){ sqlite3DbFree(pCur->pKeyInfo->db, pFree); } return rc; } /* ** 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 |
︙ | ︙ |
Changes to src/vdbe.c.
︙ | ︙ | |||
3527 3528 3529 3530 3531 3532 3533 3534 3535 3536 3537 3538 3539 3540 | ** See also: Found, NotExists, IsUnique */ case OP_NotFound: /* jump, in3 */ case OP_Found: { /* jump, in3 */ int alreadyExists; VdbeCursor *pC; int res; UnpackedRecord *pIdxKey; UnpackedRecord r; char aTempRec[ROUND8(sizeof(UnpackedRecord)) + sizeof(Mem)*3 + 7]; #ifdef SQLITE_TEST sqlite3_found_count++; #endif | > | 3527 3528 3529 3530 3531 3532 3533 3534 3535 3536 3537 3538 3539 3540 3541 | ** See also: Found, NotExists, IsUnique */ case OP_NotFound: /* jump, in3 */ case OP_Found: { /* jump, in3 */ int alreadyExists; VdbeCursor *pC; int res; char *pFree; UnpackedRecord *pIdxKey; UnpackedRecord r; char aTempRec[ROUND8(sizeof(UnpackedRecord)) + sizeof(Mem)*3 + 7]; #ifdef SQLITE_TEST sqlite3_found_count++; #endif |
︙ | ︙ | |||
3554 3555 3556 3557 3558 3559 3560 3561 3562 | r.aMem = pIn3; #ifdef SQLITE_DEBUG { int i; for(i=0; i<r.nField; i++) assert( memIsValid(&r.aMem[i]) ); } #endif r.flags = UNPACKED_PREFIX_MATCH; pIdxKey = &r; }else{ assert( pIn3->flags & MEM_Blob ); assert( (pIn3->flags & MEM_Zero)==0 ); /* zeroblobs already expanded */ | > > > > | < < < < | | 3555 3556 3557 3558 3559 3560 3561 3562 3563 3564 3565 3566 3567 3568 3569 3570 3571 3572 3573 3574 3575 3576 3577 3578 3579 3580 | r.aMem = pIn3; #ifdef SQLITE_DEBUG { int i; for(i=0; i<r.nField; i++) assert( memIsValid(&r.aMem[i]) ); } #endif r.flags = UNPACKED_PREFIX_MATCH; pIdxKey = &r; }else{ pIdxKey = sqlite3VdbeAllocUnpackedRecord( pC->pKeyInfo, aTempRec, sizeof(aTempRec), &pFree ); if( pIdxKey==0 ) goto no_mem; assert( pIn3->flags & MEM_Blob ); assert( (pIn3->flags & MEM_Zero)==0 ); /* zeroblobs already expanded */ sqlite3VdbeRecordUnpack(pC->pKeyInfo, pIn3->n, pIn3->z, pIdxKey); pIdxKey->flags |= UNPACKED_PREFIX_MATCH; } rc = sqlite3BtreeMovetoUnpacked(pC->pCursor, pIdxKey, 0, 0, &res); if( pOp->p4.i==0 ){ sqlite3DbFree(db, pFree); } if( rc!=SQLITE_OK ){ break; } alreadyExists = (res==0); pC->deferredMoveto = 0; pC->cacheStatus = CACHE_STALE; |
︙ | ︙ |
Changes to src/vdbe.h.
︙ | ︙ | |||
208 209 210 211 212 213 214 | VdbeOp *sqlite3VdbeTakeOpArray(Vdbe*, int*, int*); sqlite3_value *sqlite3VdbeGetValue(Vdbe*, int, u8); void sqlite3VdbeSetVarmask(Vdbe*, int); #ifndef SQLITE_OMIT_TRACE char *sqlite3VdbeExpandSql(Vdbe*, const char*); #endif | | < > | 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 | VdbeOp *sqlite3VdbeTakeOpArray(Vdbe*, int*, int*); sqlite3_value *sqlite3VdbeGetValue(Vdbe*, int, u8); void sqlite3VdbeSetVarmask(Vdbe*, int); #ifndef SQLITE_OMIT_TRACE char *sqlite3VdbeExpandSql(Vdbe*, const char*); #endif void sqlite3VdbeRecordUnpack(KeyInfo*,int,const void*,UnpackedRecord*); int sqlite3VdbeRecordCompare(int,const void*,UnpackedRecord*); UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(KeyInfo *, char *, int, char **); #ifndef SQLITE_OMIT_TRIGGER void sqlite3VdbeLinkSubProgram(Vdbe *, SubProgram *); #endif #ifndef NDEBUG |
︙ | ︙ |
Changes to src/vdbeaux.c.
︙ | ︙ | |||
2826 2827 2828 2829 2830 2831 2832 | } return len; } } return 0; } | < < | | > | > | | | > | < | | | < < | | > < | | < < | < < < | < | > | | < > > | > | > > > > > > > > > > > > > > > > > > > > | 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 | } return len; } } return 0; } /* ** This routine is used to allocate sufficient space for an UnpackedRecord ** structure large enough to be used with sqlite3VdbeRecordUnpack() if ** the first argument is a pointer to KeyInfo structure pKeyInfo. ** ** The space is either allocated using sqlite3DbMallocRaw() or from within ** the unaligned buffer passed via the second and third arguments (presumably ** stack space). If the former, then *ppFree is set to a pointer that should ** be eventually freed by the caller using sqlite3DbFree(). Or, if the ** allocation comes from the pSpace/szSpace buffer, *ppFree is set to NULL ** before returning. ** ** If an OOM error occurs, NULL is returned. */ UnpackedRecord *sqlite3VdbeAllocUnpackedRecord( KeyInfo *pKeyInfo, /* Description of the record */ char *pSpace, /* Unaligned space available */ int szSpace, /* Size of pSpace[] in bytes */ char **ppFree /* OUT: Caller should free this pointer */ ){ UnpackedRecord *p; /* Unpacked record to return */ int nOff; /* Increment pSpace by nOff to align it */ int nByte; /* Number of bytes required for *p */ /* We want to shift the pointer pSpace up such that it is 8-byte aligned. ** Thus, we need to calculate a value, nOff, between 0 and 7, to shift ** it by. If pSpace is already 8-byte aligned, nOff should be zero. */ nOff = (8 - (SQLITE_PTR_TO_INT(pSpace) & 7)) & 7; pSpace += nOff; szSpace -= nOff; nByte = ROUND8(sizeof(UnpackedRecord)) + sizeof(Mem)*(pKeyInfo->nField+1); if( nByte>szSpace ){ p = (UnpackedRecord *)sqlite3DbMallocRaw(pKeyInfo->db, nByte); *ppFree = (char *)p; }else{ p = (UnpackedRecord*)pSpace; *ppFree = 0; } return p; } /* ** Given the nKey-byte encoding of a record in pKey[], populate the ** UnpackedRecord structure indicated by the fourth argument with the ** contents of the decoded record. */ void sqlite3VdbeRecordUnpack( KeyInfo *pKeyInfo, /* Information about the record format */ int nKey, /* Size of the binary record */ const void *pKey, /* The binary record */ UnpackedRecord *p /* Populate this structure before returning. */ ){ const unsigned char *aKey = (const unsigned char *)pKey; int d; u32 idx; /* Offset in aKey[] to read from */ u16 u; /* Unsigned loop counter */ u32 szHdr; Mem *pMem; p->flags = 0; p->pKeyInfo = pKeyInfo; p->nField = pKeyInfo->nField + 1; p->aMem = pMem = (Mem*)&((char*)p)[ROUND8(sizeof(UnpackedRecord))]; assert( EIGHT_BYTE_ALIGNMENT(pMem) ); idx = getVarint32(aKey, szHdr); d = szHdr; u = 0; |
︙ | ︙ | |||
2895 2896 2897 2898 2899 2900 2901 | pMem->zMalloc = 0; d += sqlite3VdbeSerialGet(&aKey[d], serial_type, pMem); pMem++; u++; } assert( u<=pKeyInfo->nField + 1 ); p->nField = u; | < < < < < < < < < < < < < < < < < < < < < < < < < | 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 | pMem->zMalloc = 0; d += sqlite3VdbeSerialGet(&aKey[d], serial_type, pMem); pMem++; u++; } assert( u<=pKeyInfo->nField + 1 ); p->nField = u; } /* ** This function compares the two table rows or index records ** specified by {nKey1, pKey1} and pPKey2. It returns a negative, zero ** or positive integer if key1 is less than, equal to or ** greater than key2. The {nKey1, pKey1} key must be a blob |
︙ | ︙ |
Changes to src/vdbesort.c.
︙ | ︙ | |||
100 101 102 103 104 105 106 | i64 iWriteOff; /* Current write offset within file pTemp1 */ i64 iReadOff; /* Current read offset within file pTemp1 */ sqlite3_file *pTemp1; /* PMA file 1 */ int nPMA; /* Number of PMAs stored in pTemp1 */ SorterRecord *pRecord; /* Head of in-memory record list */ int mnPmaSize; /* Minimum PMA size, in bytes */ int mxPmaSize; /* Maximum PMA size, in bytes. 0==no limit */ | | < | 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 | i64 iWriteOff; /* Current write offset within file pTemp1 */ i64 iReadOff; /* Current read offset within file pTemp1 */ sqlite3_file *pTemp1; /* PMA file 1 */ int nPMA; /* Number of PMAs stored in pTemp1 */ SorterRecord *pRecord; /* Head of in-memory record list */ int mnPmaSize; /* Minimum PMA size, in bytes */ int mxPmaSize; /* Maximum PMA size, in bytes. 0==no limit */ UnpackedRecord *pUnpacked; /* Used to unpack keys */ }; /* ** The following type is an iterator for a PMA. It caches the current key in ** variables nKey/aKey. If the iterator is at EOF, pFile==0. */ struct VdbeSorterIter { |
︙ | ︙ | |||
304 305 306 307 308 309 310 | int bOmitRowid, /* Ignore rowid field at end of keys */ void *pKey1, int nKey1, /* Left side of comparison */ void *pKey2, int nKey2, /* Right side of comparison */ int *pRes /* OUT: Result of comparison */ ){ KeyInfo *pKeyInfo = pCsr->pKeyInfo; VdbeSorter *pSorter = pCsr->pSorter; | < < | | < | > | > | < < | < < < < < | 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 | int bOmitRowid, /* Ignore rowid field at end of keys */ void *pKey1, int nKey1, /* Left side of comparison */ void *pKey2, int nKey2, /* Right side of comparison */ int *pRes /* OUT: Result of comparison */ ){ KeyInfo *pKeyInfo = pCsr->pKeyInfo; VdbeSorter *pSorter = pCsr->pSorter; UnpackedRecord *r2 = pSorter->pUnpacked; int i; if( r2==0 ){ char *pFree; r2 = sqlite3VdbeAllocUnpackedRecord(pKeyInfo, 0, 0, &pFree); if( r2==0 ) return SQLITE_NOMEM; assert( pFree==(char *)r2 ); pSorter->pUnpacked = r2; } if( pKey2 ){ sqlite3VdbeRecordUnpack(pKeyInfo, nKey2, pKey2, r2); } if( bOmitRowid ){ for(i=0; i<r2->nField-1; i++){ if( r2->aMem[i].flags & MEM_Null ){ *pRes = -1; return SQLITE_OK; |
︙ | ︙ | |||
376 377 378 379 380 381 382 | if( p1->pFile==0 ){ iRes = i2; }else if( p2->pFile==0 ){ iRes = i1; }else{ int res; int rc; | | | | 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 | if( p1->pFile==0 ){ iRes = i2; }else if( p2->pFile==0 ){ iRes = i1; }else{ int res; int rc; assert( pCsr->pSorter->pUnpacked!=0 ); /* allocated in vdbeSorterMerge() */ rc = vdbeSorterCompare( pCsr, 0, p1->aKey, p1->nKey, p2->aKey, p2->nKey, &res ); /* The vdbeSorterCompare() call cannot fail since pCsr->pSorter->pUnpacked ** has already been allocated. */ assert( rc==SQLITE_OK ); if( res<=0 ){ iRes = i1; }else{ iRes = i2; |
︙ | ︙ | |||
449 450 451 452 453 454 455 | } sqlite3DbFree(db, pSorter->aIter); } if( pSorter->pTemp1 ){ sqlite3OsCloseFree(pSorter->pTemp1); } vdbeSorterRecordFree(db, pSorter->pRecord); | | | 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 | } sqlite3DbFree(db, pSorter->aIter); } if( pSorter->pTemp1 ){ sqlite3OsCloseFree(pSorter->pTemp1); } vdbeSorterRecordFree(db, pSorter->pRecord); sqlite3DbFree(db, pSorter->pUnpacked); sqlite3DbFree(db, pSorter); pCsr->pSorter = 0; } } /* ** Allocate space for a file-handle and open a temporary file. If successful, |
︙ | ︙ |