From: dan Date: Mon, 5 Sep 2011 14:20:27 +0000 (+0000) Subject: Refactor the sqlite3VdbeRecordUnpack() interface to better accommodate the vdbesort... X-Git-Tag: version-3.7.8~19 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=03e9cfc2231c3ac9a7b458e1a2a48df3e177afb8;p=thirdparty%2Fsqlite.git Refactor the sqlite3VdbeRecordUnpack() interface to better accommodate the vdbesort.c module. FossilOrigin-Name: f115b2303509c678dbe83b2fa3d9c40d82882813 --- diff --git a/manifest b/manifest index cdcd0fb2ff..6146f80f7a 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\scompiler\swarning\sabout\san\sunused\sparameter\sin\sthe\smerge-sort\scode. -D 2011-09-04T01:27:00.510 +C Refactor\sthe\ssqlite3VdbeRecordUnpack()\sinterface\sto\sbetter\saccommodate\sthe\svdbesort.c\smodule. +D 2011-09-05T14:20:27.320 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in d314143fa6be24828021d3f583ad37d9afdce505 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -124,7 +124,7 @@ F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34 F src/backup.c 28a4fe55327ff708bfaf9d4326d02686f7a553c3 F src/bitvec.c af50f1c8c0ff54d6bdb7a80e2fceca5a93670bef F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7 -F src/btree.c 4d46fe30b8bc920f68b7d58a5f45316fa5d023ec +F src/btree.c 958f26c8f5ff001791ba1ba3825e69d1a383c2fd F src/btree.h f5d775cd6cfc7ac32a2535b70e8d2af48ef5f2ce F src/btreeInt.h 67978c014fa4f7cc874032dd3aacadd8db656bc3 F src/build.c 851e81f26a75abbb98bd99a7c5f10e8670d867bb @@ -238,14 +238,14 @@ F src/update.c 74a6cfb34e9732c1e2a86278b229913b4b51eeec F src/utf.c c53eb7404b3eb5c1cbb5655c6a7a0e0ce6bd50f0 F src/util.c 06302ffd2b80408d4f6c7af71f7090e0cf8d8ff7 F src/vacuum.c 05513dca036a1e7848fe18d5ed1265ac0b32365e -F src/vdbe.c d4c8224cc931c6082557501d7f822fb12f273922 -F src/vdbe.h c1eeedacab6bcf1e7c2cf8203ba9763a616f9a86 +F src/vdbe.c 7008edbf8f608d82c035dcb1c56367ad85e68aaa +F src/vdbe.h a10b360bf69474babc8aba8fcc64b824c5e97d38 F src/vdbeInt.h 693d6ac6810298fc6b4c503cfbe3f99a240f40af F src/vdbeapi.c 11dc47987abacb76ad016dcf5abc0dc422482a98 -F src/vdbeaux.c e58acbc5ea3823922a0cd8fa21f94f39af51ee88 +F src/vdbeaux.c 8546b9481d8c642f2403ae8ebf20823b54e00606 F src/vdbeblob.c f024f0bf420f36b070143c32b15cc7287341ffd3 F src/vdbemem.c 5e6effb96dd53d233361cbfaa3f0a43b9af689e9 -F src/vdbesort.c 14d127565bab1032a20558e6c9ae5f2ec0499111 +F src/vdbesort.c 4f3265707c3277011fbb0c09d3d8e6461152f639 F src/vdbetrace.c 5d0dc3d5fd54878cc8d6d28eb41deb8d5885b114 F src/vtab.c 901791a47318c0562cd0c676a2c6ff1bc530e582 F src/wal.c 3154756177d6219e233d84291d5b05f4e06ff5e9 @@ -961,7 +961,7 @@ F tool/symbols.sh caaf6ccc7300fd43353318b44524853e222557d5 F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f F tool/warnings.sh b7fdb2cc525f5ef4fa43c80e771636dd3690f9d2 -P b5179baf87aa00ed5cecbdcaa65bee10e112a9e9 -R 19f8e6b3aaa4f6faa3ce68485711b8fa -U drh -Z c68d8b01f68570c73b0670afe2bb6a90 +P 6b657ae75035eb10b0ad640998d3c9eadfdffa6e +R 17c6c62caa602109512a646943ac3f7f +U dan +Z 1812248ebcb21a3973c4b6e0222ea90b diff --git a/manifest.uuid b/manifest.uuid index 80fcf402aa..ecb95ed250 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -6b657ae75035eb10b0ad640998d3c9eadfdffa6e \ No newline at end of file +f115b2303509c678dbe83b2fa3d9c40d82882813 \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index f0eb376dec..014267cc84 100644 --- a/src/btree.c +++ b/src/btree.c @@ -656,18 +656,21 @@ static int btreeMoveto( 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 = sqlite3VdbeRecordUnpack(pCur->pKeyInfo, (int)nKey, pKey, - aSpace, sizeof(aSpace)); + 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 ){ - sqlite3VdbeDeleteUnpackedRecord(pIdxKey); + sqlite3DbFree(pCur->pKeyInfo->db, pFree); } return rc; } diff --git a/src/vdbe.c b/src/vdbe.c index acf113515f..906058c1f8 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -3531,6 +3531,7 @@ 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]; @@ -3558,18 +3559,18 @@ case OP_Found: { /* jump, in3 */ 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 */ - pIdxKey = sqlite3VdbeRecordUnpack(pC->pKeyInfo, pIn3->n, pIn3->z, - aTempRec, sizeof(aTempRec)); - if( pIdxKey==0 ){ - goto no_mem; - } + 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 ){ - sqlite3VdbeDeleteUnpackedRecord(pIdxKey); + sqlite3DbFree(db, pFree); } if( rc!=SQLITE_OK ){ break; diff --git a/src/vdbe.h b/src/vdbe.h index 9728548517..f4691c0e8f 100644 --- a/src/vdbe.h +++ b/src/vdbe.h @@ -212,9 +212,9 @@ void sqlite3VdbeSetVarmask(Vdbe*, int); char *sqlite3VdbeExpandSql(Vdbe*, const char*); #endif -UnpackedRecord *sqlite3VdbeRecordUnpack(KeyInfo*,int,const void*,char*,int); -void sqlite3VdbeDeleteUnpackedRecord(UnpackedRecord*); +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 *); diff --git a/src/vdbeaux.c b/src/vdbeaux.c index f622e8d09a..06ed06dfcb 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -2830,54 +2830,69 @@ u32 sqlite3VdbeSerialGet( return 0; } - /* -** Given the nKey-byte encoding of a record in pKey[], parse the -** record into a UnpackedRecord structure. Return a pointer to -** that structure. +** 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 calling function might provide szSpace bytes of memory -** space at pSpace. This space can be used to hold the returned -** VDbeParsedRecord structure if it is large enough. If it is -** not big enough, space is obtained from sqlite3_malloc(). +** 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. ** -** The returned structure should be closed by a call to -** sqlite3VdbeDeleteUnpackedRecord(). -*/ -UnpackedRecord *sqlite3VdbeRecordUnpack( - KeyInfo *pKeyInfo, /* Information about the record format */ - int nKey, /* Size of the binary record */ - const void *pKey, /* The binary record */ - char *pSpace, /* Unaligned space available to hold the object */ - int szSpace /* Size of pSpace[] in bytes */ +** 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 */ ){ - const unsigned char *aKey = (const unsigned char *)pKey; - UnpackedRecord *p; /* The unpacked record that we will return */ - int nByte; /* Memory space needed to hold p, in bytes */ - int d; - u32 idx; - u16 u; /* Unsigned loop counter */ - u32 szHdr; - Mem *pMem; - int nOff; /* Increase pSpace by this much to 8-byte align it */ - - /* - ** We want to shift the pointer pSpace up such that it is 8-byte aligned. + 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 = sqlite3DbMallocRaw(pKeyInfo->db, nByte); - if( p==0 ) return 0; - p->flags = UNPACKED_NEED_FREE | UNPACKED_NEED_DESTROY; + p = (UnpackedRecord *)sqlite3DbMallocRaw(pKeyInfo->db, nByte); + *ppFree = (char *)p; }else{ p = (UnpackedRecord*)pSpace; - p->flags = UNPACKED_NEED_DESTROY; + *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))]; @@ -2899,31 +2914,6 @@ UnpackedRecord *sqlite3VdbeRecordUnpack( } assert( u<=pKeyInfo->nField + 1 ); p->nField = u; - return (void*)p; -} - -/* -** This routine destroys a UnpackedRecord object. -*/ -void sqlite3VdbeDeleteUnpackedRecord(UnpackedRecord *p){ -#ifdef SQLITE_DEBUG - int i; - Mem *pMem; - - assert( p!=0 ); - assert( p->flags & UNPACKED_NEED_DESTROY ); - for(i=0, pMem=p->aMem; inField; i++, pMem++){ - /* The unpacked record is always constructed by the - ** sqlite3VdbeUnpackRecord() function above, which makes all - ** strings and blobs static. And none of the elements are - ** ever transformed, so there is never anything to delete. - */ - if( NEVER(pMem->zMalloc) ) sqlite3VdbeMemRelease(pMem); - } -#endif - if( p->flags & UNPACKED_NEED_FREE ){ - sqlite3DbFree(p->pKeyInfo->db, p); - } } /* diff --git a/src/vdbesort.c b/src/vdbesort.c index 2acba8778d..79f17dcbc9 100644 --- a/src/vdbesort.c +++ b/src/vdbesort.c @@ -104,8 +104,7 @@ struct VdbeSorter { 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 */ - char *aSpace; /* Space for UnpackRecord() */ - int nSpace; /* Size of aSpace in bytes */ + UnpackedRecord *pUnpacked; /* Used to unpack keys */ }; /* @@ -308,27 +307,19 @@ static int vdbeSorterCompare( ){ KeyInfo *pKeyInfo = pCsr->pKeyInfo; VdbeSorter *pSorter = pCsr->pSorter; - char *aSpace = pSorter->aSpace; - int nSpace = pSorter->nSpace; - UnpackedRecord *r2; + UnpackedRecord *r2 = pSorter->pUnpacked; int i; - if( aSpace==0 ){ - nSpace = ROUND8(sizeof(UnpackedRecord))+(pKeyInfo->nField+1)*sizeof(Mem); - aSpace = (char *)sqlite3Malloc(nSpace); - if( aSpace==0 ) return SQLITE_NOMEM; - pSorter->aSpace = aSpace; - pSorter->nSpace = nSpace; + 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 ){ - /* This call cannot fail. As the memory is already allocated. */ - r2 = sqlite3VdbeRecordUnpack(pKeyInfo, nKey2, pKey2, aSpace, nSpace); - assert( r2 && (r2->flags & UNPACKED_NEED_FREE)==0 ); - assert( r2==(UnpackedRecord*)aSpace ); - }else{ - r2 = (UnpackedRecord *)aSpace; - assert( !bOmitRowid ); + sqlite3VdbeRecordUnpack(pKeyInfo, nKey2, pKey2, r2); } if( bOmitRowid ){ @@ -380,11 +371,11 @@ static int vdbeSorterDoCompare(VdbeCursor *pCsr, int iOut){ }else{ int res; int rc; - assert( pCsr->pSorter->aSpace!=0 ); /* allocated in vdbeSorterMerge() */ + 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->aSpace + /* The vdbeSorterCompare() call cannot fail since pCsr->pSorter->pUnpacked ** has already been allocated. */ assert( rc==SQLITE_OK ); @@ -453,7 +444,7 @@ void sqlite3VdbeSorterClose(sqlite3 *db, VdbeCursor *pCsr){ sqlite3OsCloseFree(pSorter->pTemp1); } vdbeSorterRecordFree(db, pSorter->pRecord); - sqlite3_free(pSorter->aSpace); + sqlite3DbFree(db, pSorter->pUnpacked); sqlite3DbFree(db, pSorter); pCsr->pSorter = 0; }