Fix memory leaks in the code on this branch. Make use of the
sqlite3_index_constraint.usage field. Do not try to handle ORDER BY terms with explicit COLLATE clauses - they don't get passed to the vtab layer anyway. FossilOrigin-Name: 0cd75a872c89958a7f418720a0e8c6f638f8284c488f666015c19136feae6be8
This commit is contained in:
parent
0824ccf29b
commit
79610f5d09
@ -39,7 +39,6 @@ struct IdxConstraint {
|
||||
char *zColl; /* Collation sequence */
|
||||
int bRange; /* True for range, false for eq */
|
||||
int iCol; /* Constrained table column */
|
||||
i64 depmask; /* Dependency mask */
|
||||
int bFlag; /* Used by idxFindCompatible() */
|
||||
int bDesc; /* True if ORDER BY <expr> DESC */
|
||||
IdxConstraint *pNext; /* Next constraint in pEq or pRange list */
|
||||
@ -111,25 +110,6 @@ struct IdxHash {
|
||||
IdxHashEntry *aHash[IDX_HASH_SIZE];
|
||||
};
|
||||
|
||||
/*
|
||||
** A hash table for storing a set of 64-bit values. Methods are:
|
||||
**
|
||||
** idxHash64Init()
|
||||
** idxHash64Clear()
|
||||
** idxHash64Add()
|
||||
*/
|
||||
typedef struct IdxHash64Entry IdxHash64Entry;
|
||||
typedef struct IdxHash64 IdxHash64;
|
||||
struct IdxHash64Entry {
|
||||
u64 iVal;
|
||||
IdxHash64Entry *pNext; /* Next entry in hash table */
|
||||
IdxHash64Entry *pHashNext; /* Next entry in same hash bucket */
|
||||
};
|
||||
struct IdxHash64 {
|
||||
IdxHash64Entry *pFirst; /* Most recently added entry in hash table */
|
||||
IdxHash64Entry *aHash[IDX_HASH_SIZE];
|
||||
};
|
||||
|
||||
/*
|
||||
** sqlite3expert object.
|
||||
*/
|
||||
@ -166,48 +146,6 @@ static void *idxMalloc(int *pRc, int nByte){
|
||||
return pRet;
|
||||
}
|
||||
|
||||
/*
|
||||
** Initialize an IdxHash64 hash table.
|
||||
*/
|
||||
static void idxHash64Init(IdxHash64 *pHash){
|
||||
memset(pHash, 0, sizeof(IdxHash64));
|
||||
}
|
||||
|
||||
/*
|
||||
** Reset an IdxHash64 hash table.
|
||||
*/
|
||||
static void idxHash64Clear(IdxHash64 *pHash){
|
||||
IdxHash64Entry *pEntry;
|
||||
IdxHash64Entry *pNext;
|
||||
for(pEntry=pHash->pFirst; pEntry; pEntry=pNext){
|
||||
pNext = pEntry->pNext;
|
||||
sqlite3_free(pEntry);
|
||||
}
|
||||
memset(pHash, 0, sizeof(IdxHash64));
|
||||
}
|
||||
|
||||
/*
|
||||
** Add iVal to the IdxHash64 hash table passed as the second argument. This
|
||||
** function is a no-op if iVal is already present in the hash table.
|
||||
*/
|
||||
static void idxHash64Add(int *pRc, IdxHash64 *pHash, u64 iVal){
|
||||
int iHash = (int)((iVal*7) % IDX_HASH_SIZE);
|
||||
IdxHash64Entry *pEntry;
|
||||
assert( iHash>=0 );
|
||||
|
||||
for(pEntry=pHash->aHash[iHash]; pEntry; pEntry=pEntry->pHashNext){
|
||||
if( pEntry->iVal==iVal ) return;
|
||||
}
|
||||
pEntry = idxMalloc(pRc, sizeof(IdxHash64Entry));
|
||||
if( pEntry ){
|
||||
pEntry->iVal = iVal;
|
||||
pEntry->pHashNext = pHash->aHash[iHash];
|
||||
pHash->aHash[iHash] = pEntry;
|
||||
pEntry->pNext = pHash->pFirst;
|
||||
pHash->pFirst = pEntry;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Initialize an IdxHash hash table.
|
||||
*/
|
||||
@ -426,14 +364,14 @@ static int expertBestIndex(sqlite3_vtab *pVtab, sqlite3_index_info *pIdxInfo){
|
||||
|
||||
/* Add the constraints to the IdxScan object */
|
||||
for(i=0; i<pIdxInfo->nConstraint; i++){
|
||||
int op = pIdxInfo->aConstraint[i].op;
|
||||
if( op&opmask ){
|
||||
struct sqlite3_index_constraint *pCons = &pIdxInfo->aConstraint[i];
|
||||
if( pCons->usable && (pCons->op & opmask) ){
|
||||
IdxConstraint *pNew;
|
||||
const char *zColl = sqlite3_vtab_collation(dbv, i);
|
||||
pNew = idxNewConstraint(&rc, zColl);
|
||||
if( pNew ){
|
||||
pNew->iCol = pIdxInfo->aConstraint[i].iColumn;
|
||||
if( op==SQLITE_INDEX_CONSTRAINT_EQ ){
|
||||
pNew->iCol = pCons->iColumn;
|
||||
if( pCons->op==SQLITE_INDEX_CONSTRAINT_EQ ){
|
||||
pNew->pNext = pScan->pEq;
|
||||
pScan->pEq = pNew;
|
||||
}else{
|
||||
@ -442,20 +380,17 @@ static int expertBestIndex(sqlite3_vtab *pVtab, sqlite3_index_info *pIdxInfo){
|
||||
pScan->pRange = pNew;
|
||||
}
|
||||
}
|
||||
if( pIdxInfo->aConstraint[i].usable ){
|
||||
n++;
|
||||
pIdxInfo->aConstraintUsage[i].argvIndex = n;
|
||||
}
|
||||
n++;
|
||||
pIdxInfo->aConstraintUsage[i].argvIndex = n;
|
||||
}
|
||||
}
|
||||
|
||||
/* Add the ORDER BY to the IdxScan object */
|
||||
for(i=pIdxInfo->nOrderBy-1; i>=0; i--){
|
||||
IdxConstraint *pNew;
|
||||
const char *zColl = sqlite3_vtab_collation(dbv, i+pIdxInfo->nConstraint);
|
||||
pNew = idxNewConstraint(&rc, zColl);
|
||||
int iCol = pIdxInfo->aOrderBy[i].iColumn;
|
||||
IdxConstraint *pNew = idxNewConstraint(&rc, p->pTab->aCol[iCol].zColl);
|
||||
if( pNew ){
|
||||
pNew->iCol = pIdxInfo->aOrderBy[i].iColumn;
|
||||
pNew->iCol = iCol;
|
||||
pNew->bDesc = pIdxInfo->aOrderBy[i].desc;
|
||||
pNew->pNext = pScan->pOrder;
|
||||
pNew->pLink = pScan->pOrder;
|
||||
@ -813,7 +748,6 @@ static int idxFindCompatible(
|
||||
|
||||
static int idxCreateFromCons(
|
||||
sqlite3expert *p,
|
||||
IdxTable *pTab,
|
||||
IdxScan *pScan,
|
||||
IdxConstraint *pEq,
|
||||
IdxConstraint *pTail
|
||||
@ -821,6 +755,7 @@ static int idxCreateFromCons(
|
||||
sqlite3 *dbm = p->dbm;
|
||||
int rc = SQLITE_OK;
|
||||
if( (pEq || pTail) && 0==idxFindCompatible(&rc, dbm, pScan, pEq, pTail) ){
|
||||
IdxTable *pTab = pScan->pTab;
|
||||
char *zCols = 0;
|
||||
char *zIdx = 0;
|
||||
IdxConstraint *pCons;
|
||||
@ -882,22 +817,16 @@ static int idxFindConstraint(IdxConstraint *pList, IdxConstraint *p){
|
||||
|
||||
static int idxCreateFromWhere(
|
||||
sqlite3expert *p,
|
||||
IdxTable *pTab,
|
||||
i64 mask, /* Consider only these constraints */
|
||||
IdxScan *pScan, /* Create indexes for this scan */
|
||||
IdxConstraint *pEq, /* == constraints for inclusion */
|
||||
IdxConstraint *pTail /* range/ORDER BY constraints for inclusion */
|
||||
){
|
||||
IdxConstraint *p1 = pEq;
|
||||
IdxConstraint *p1 = 0;
|
||||
IdxConstraint *pCon;
|
||||
int rc;
|
||||
|
||||
/* Gather up all the == constraints that match the mask. */
|
||||
/* Gather up all the == constraints. */
|
||||
for(pCon=pScan->pEq; pCon; pCon=pCon->pNext){
|
||||
if( (mask & pCon->depmask)==pCon->depmask
|
||||
&& idxFindConstraint(p1, pCon)==0
|
||||
&& idxFindConstraint(pTail, pCon)==0
|
||||
){
|
||||
if( !idxFindConstraint(p1, pCon) && !idxFindConstraint(pTail, pCon) ){
|
||||
pCon->pLink = p1;
|
||||
p1 = pCon;
|
||||
}
|
||||
@ -905,18 +834,15 @@ static int idxCreateFromWhere(
|
||||
|
||||
/* Create an index using the == constraints collected above. And the
|
||||
** range constraint/ORDER BY terms passed in by the caller, if any. */
|
||||
rc = idxCreateFromCons(p, pTab, pScan, p1, pTail);
|
||||
rc = idxCreateFromCons(p, pScan, p1, pTail);
|
||||
|
||||
/* If no range/ORDER BY passed by the caller, create a version of the
|
||||
** index for each range constraint that matches the mask. */
|
||||
** index for each range constraint. */
|
||||
if( pTail==0 ){
|
||||
for(pCon=pScan->pRange; rc==SQLITE_OK && pCon; pCon=pCon->pNext){
|
||||
assert( pCon->pLink==0 );
|
||||
if( (mask & pCon->depmask)==pCon->depmask
|
||||
&& idxFindConstraint(pEq, pCon)==0
|
||||
&& idxFindConstraint(pTail, pCon)==0
|
||||
){
|
||||
rc = idxCreateFromCons(p, pTab, pScan, p1, pCon);
|
||||
if( !idxFindConstraint(p1, pCon) && !idxFindConstraint(pTail, pCon) ){
|
||||
rc = idxCreateFromCons(p, pScan, p1, pCon);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -931,30 +857,12 @@ static int idxCreateFromWhere(
|
||||
static int idxCreateCandidates(sqlite3expert *p, char **pzErr){
|
||||
int rc = SQLITE_OK;
|
||||
IdxScan *pIter;
|
||||
IdxHash64 hMask;
|
||||
idxHash64Init(&hMask);
|
||||
|
||||
for(pIter=p->pScan; pIter && rc==SQLITE_OK; pIter=pIter->pNextScan){
|
||||
IdxHash64Entry *pEntry;
|
||||
IdxConstraint *pCons;
|
||||
IdxTable *pTab = pIter->pTab;
|
||||
|
||||
idxHash64Add(&rc, &hMask, 0);
|
||||
for(pCons=pIter->pEq; pCons; pCons=pCons->pNext){
|
||||
for(pEntry=hMask.pFirst; pEntry; pEntry=pEntry->pNext){
|
||||
idxHash64Add(&rc, &hMask, pEntry->iVal | (u64)pCons->depmask);
|
||||
}
|
||||
rc = idxCreateFromWhere(p, pIter, 0);
|
||||
if( rc==SQLITE_OK && pIter->pOrder ){
|
||||
rc = idxCreateFromWhere(p, pIter, pIter->pOrder);
|
||||
}
|
||||
|
||||
for(pEntry=hMask.pFirst; rc==SQLITE_OK && pEntry; pEntry=pEntry->pNext){
|
||||
i64 mask = (i64)pEntry->iVal;
|
||||
rc = idxCreateFromWhere(p, pTab, mask, pIter, 0, 0);
|
||||
if( rc==SQLITE_OK && pIter->pOrder ){
|
||||
rc = idxCreateFromWhere(p, pTab, mask, pIter, 0, pIter->pOrder);
|
||||
}
|
||||
}
|
||||
|
||||
idxHash64Clear(&hMask);
|
||||
}
|
||||
|
||||
return rc;
|
||||
@ -1004,6 +912,18 @@ static void idxStatementFree(IdxStatement *pStatement, IdxStatement *pLast){
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Free the linked list of IdxTable objects starting at pTab.
|
||||
*/
|
||||
static void idxTableFree(IdxTable *pTab){
|
||||
IdxTable *pIter;
|
||||
IdxTable *pNext;
|
||||
for(pIter=pTab; pIter; pIter=pNext){
|
||||
pNext = pIter->pNext;
|
||||
sqlite3_free(pIter);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** This function is called after candidate indexes have been created. It
|
||||
@ -1126,6 +1046,7 @@ static int idxCreateVtabSchema(sqlite3expert *p, char **pzErrmsg){
|
||||
}
|
||||
}
|
||||
}
|
||||
idxFinalize(&rc, pSchema);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -1296,7 +1217,9 @@ void sqlite3_expert_destroy(sqlite3expert *p){
|
||||
sqlite3_close(p->dbv);
|
||||
idxScanFree(p->pScan, 0);
|
||||
idxStatementFree(p->pStatement, 0);
|
||||
idxTableFree(p->pTable);
|
||||
idxHashClear(&p->hIdx);
|
||||
sqlite3_free(p->zCandidates);
|
||||
sqlite3_free(p);
|
||||
}
|
||||
}
|
||||
|
14
manifest
14
manifest
@ -1,5 +1,5 @@
|
||||
C Modify\sthe\scode\sin\sext/expert/\sto\suse\sthe\svtab\sinterface\sinstead\sof\nsqlite3_whereinfo_hook().\sRemove\ssqlite3_whereinfo_hook().
|
||||
D 2017-04-14T19:41:37.126
|
||||
C Fix\smemory\sleaks\sin\sthe\scode\son\sthis\sbranch.\sMake\suse\sof\sthe\nsqlite3_index_constraint.usage\sfield.\sDo\snot\stry\sto\shandle\sORDER\sBY\sterms\swith\nexplicit\sCOLLATE\sclauses\s-\sthey\sdon't\sget\spassed\sto\sthe\svtab\slayer\sanyway.
|
||||
D 2017-04-15T14:16:04.093
|
||||
F Makefile.in 1cc758ce3374a32425e4d130c2fe7b026b20de5b8843243de75f087c0a2661fb
|
||||
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
|
||||
F Makefile.msc a4c0613a18663bda56d8cf76079ab6590a7c3602e54befb4bbdef76bcaa38b6a
|
||||
@ -43,7 +43,7 @@ F ext/async/sqlite3async.h f489b080af7e72aec0e1ee6f1d98ab6cf2e4dcef
|
||||
F ext/expert/README.md 9f15075ec5ad772808eff55ef044c31140fd1146aa0a3c47eafd155e71851b01
|
||||
F ext/expert/expert.c 6349cf8d26c847f5f0fa7e25772b614c67f60f3c850dca0d75d55eb27cf3f69b
|
||||
F ext/expert/expert1.test cd630eda18a2508eade4c39a1eafe32e7437a33973391e5dddfc7fd0f3163684
|
||||
F ext/expert/sqlite3expert.c 9473b011d7e0be5b52157f3b1fc153d7e5f7d2b43af110180843e7a03972439f
|
||||
F ext/expert/sqlite3expert.c d4a0a45be58874b4cf54316e5d776726489967140399b1e77a17dbb66558cb38
|
||||
F ext/expert/sqlite3expert.h b1c9eedeb647fd734c4206ae6851635284cfbfa5fb688eff74c3265c9f949b4d
|
||||
F ext/expert/test_expert.c bad0611732d07180d586bd589cbb7713dc3ab0338c52bff29680eb2007678c05
|
||||
F ext/fts1/README.txt 20ac73b006a70bcfd80069bdaf59214b6cf1db5e
|
||||
@ -488,7 +488,7 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
|
||||
F src/wal.c 40c543f0a2195d1b0dc88ef12142bea690009344
|
||||
F src/wal.h 06b2a0b599cc0f53ea97f497cf8c6b758c999f71
|
||||
F src/walker.c b71a992b413b3a022572eccf29ef4b4890223791
|
||||
F src/where.c 64f2c18c72e06bc935c64a53fd5cea6446ffedeba87c45905408bea124c201b6
|
||||
F src/where.c 7b4d39ffdb82a6c5abd8678c66a4cd16d8bdba3bbe158a9e2f181a78e05b07ef
|
||||
F src/whereInt.h 7a21ef633e26acbf46df04add2eba6e0a2100c78dc5879049e93f981fc3344df
|
||||
F src/wherecode.c 943e32e9dccd0af802e0683ae11071c8bd808364e5908a5fb66758bd404c8681
|
||||
F src/whereexpr.c e913aaa7b73ffcce66abcea5f197e2c538d48b5df78d0b7bba8ff4d73cc2e745
|
||||
@ -1578,7 +1578,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
|
||||
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
||||
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
||||
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
||||
P 5fcd840cf9b6a5c3ee4ef1e8f92f6c30f96a7899a3d774ee9be8a816916f2c3b
|
||||
R 754b00e271f01cdc7a8ee810736e1b12
|
||||
P 3bb6585004090dbf92dd5e9abdf0fd2c921e64b5b3121c4fb7446db764ab59e5
|
||||
R 039cfbfa3ee0c0fcda94663d31b151d9
|
||||
U dan
|
||||
Z bc14af8147812d1c0312a546deaaf0cc
|
||||
Z 80d209b7df04543ba8ed8a1a58dd2c4a
|
||||
|
@ -1 +1 @@
|
||||
3bb6585004090dbf92dd5e9abdf0fd2c921e64b5b3121c4fb7446db764ab59e5
|
||||
0cd75a872c89958a7f418720a0e8c6f638f8284c488f666015c19136feae6be8
|
21
src/where.c
21
src/where.c
@ -3120,27 +3120,17 @@ static int whereLoopAddVirtualOne(
|
||||
struct BestIndexCtx {
|
||||
WhereClause *pWC;
|
||||
sqlite3_index_info *pIdxInfo;
|
||||
ExprList *pOrderBy;
|
||||
Parse *pParse;
|
||||
};
|
||||
|
||||
const char *sqlite3_vtab_collation(sqlite3 *db, int iCons){
|
||||
struct BestIndexCtx *p = (struct BestIndexCtx*)db->pVtabWC;
|
||||
const char *zRet = 0;
|
||||
if( p && iCons>=0 ){
|
||||
if( iCons<p->pIdxInfo->nConstraint ){
|
||||
int iTerm = p->pIdxInfo->aConstraint[iCons].iTermOffset;
|
||||
Expr *pX = p->pWC->a[iTerm].pExpr;
|
||||
CollSeq *pC = sqlite3BinaryCompareCollSeq(p->pParse,pX->pLeft,pX->pRight);
|
||||
zRet = (pC ? pC->zName : "BINARY");
|
||||
}else{
|
||||
iCons -= p->pIdxInfo->nConstraint;
|
||||
if( iCons<p->pIdxInfo->nOrderBy ){
|
||||
Expr *pX = p->pOrderBy->a[iCons].pExpr;
|
||||
CollSeq *pC = sqlite3ExprCollSeq(p->pParse, pX);
|
||||
zRet = (pC ? pC->zName : "BINARY");
|
||||
}
|
||||
}
|
||||
if( p && iCons>=0 && iCons<p->pIdxInfo->nConstraint ){
|
||||
int iTerm = p->pIdxInfo->aConstraint[iCons].iTermOffset;
|
||||
Expr *pX = p->pWC->a[iTerm].pExpr;
|
||||
CollSeq *pC = sqlite3BinaryCompareCollSeq(p->pParse,pX->pLeft,pX->pRight);
|
||||
zRet = (pC ? pC->zName : "BINARY");
|
||||
}
|
||||
return zRet;
|
||||
}
|
||||
@ -3212,7 +3202,6 @@ static int whereLoopAddVirtual(
|
||||
bic.pWC = pWC;
|
||||
bic.pIdxInfo = p;
|
||||
bic.pParse = pParse;
|
||||
bic.pOrderBy = pBuilder->pOrderBy;
|
||||
pSaved = pParse->db->pVtabWC;
|
||||
pParse->db->pVtabWC = (void*)&bic;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user