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:
dan 2017-04-15 14:16:04 +00:00
parent 0824ccf29b
commit 79610f5d09
4 changed files with 48 additions and 136 deletions

View File

@ -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);
}
}

View File

@ -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

View File

@ -1 +1 @@
3bb6585004090dbf92dd5e9abdf0fd2c921e64b5b3121c4fb7446db764ab59e5
0cd75a872c89958a7f418720a0e8c6f638f8284c488f666015c19136feae6be8

View File

@ -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;