]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
http://www.sqlite.org/cvstrac/tktview?tn=2046
authorshess <shess@noemail.net>
Wed, 29 Nov 2006 05:17:28 +0000 (05:17 +0000)
committershess <shess@noemail.net>
Wed, 29 Nov 2006 05:17:28 +0000 (05:17 +0000)
The virtual table interface allows for a cursor to field multiple
xFilter() calls.  For instance, if a join is done with a virtual
table, there could be a call for each row which potentially matches.
Unfortunately, fulltextFilter() assumes that it has a fresh cursor,
and overwrites a prepared statement and a malloc'ed pointer, resulting
in unfinalized statements and a memory leak.

This change hacks the code to manually clean up offending items in
fulltextFilter(), emphasis on "hacks", since it's a fragile fix
insofar as future additions to fulltext_cursor could continue to have
the problem. (CVS 3521)

FossilOrigin-Name: 18142fdb6d1f5bfdbb1155274502b9a602885fcb

ext/fts1/fts1.c
ext/fts2/fts2.c
manifest
manifest.uuid

index 480fc4b9b0914644af7e7e48792870b781042214..e0e2560ee55df5ad41d53a78c811f52b5b73ae15 100644 (file)
@@ -2040,6 +2040,7 @@ out:
 /* Decide how to handle an SQL query. */
 static int fulltextBestIndex(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
   int i;
+  TRACE(("FTS1 BestIndex\n"));
 
   for(i=0; i<pInfo->nConstraint; ++i){
     const struct sqlite3_index_constraint *pConstraint;
@@ -2048,10 +2049,12 @@ static int fulltextBestIndex(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
       if( pConstraint->iColumn==-1 &&
           pConstraint->op==SQLITE_INDEX_CONSTRAINT_EQ ){
         pInfo->idxNum = QUERY_ROWID;      /* lookup by rowid */
+        TRACE(("FTS1 QUERY_ROWID\n"));
       } else if( pConstraint->iColumn>=0 &&
                  pConstraint->op==SQLITE_INDEX_CONSTRAINT_MATCH ){
         /* full-text search */
         pInfo->idxNum = QUERY_FULLTEXT + pConstraint->iColumn;
+        TRACE(("FTS1 QUERY_FULLTEXT %d\n", pConstraint->iColumn));
       } else continue;
 
       pInfo->aConstraintUsage[i].argvIndex = 1;
@@ -2066,7 +2069,6 @@ static int fulltextBestIndex(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
     }
   }
   pInfo->idxNum = QUERY_GENERIC;
-  TRACE(("FTS1 BestIndex\n"));
   return SQLITE_OK;
 }
 
@@ -2818,6 +2820,11 @@ static int fulltextQuery(
 ** number idxNum-QUERY_FULLTEXT, 0 indexed.  argv[0] is the right-hand
 ** side of the MATCH operator.
 */
+/* TODO(shess) Upgrade the cursor initialization and destruction to
+** account for fulltextFilter() being called multiple times on the
+** same cursor.  The current solution is very fragile.  Apply fix to
+** fts2 as appropriate.
+*/
 static int fulltextFilter(
   sqlite3_vtab_cursor *pCursor,     /* The cursor used for this query */
   int idxNum, const char *idxStr,   /* Which indexing scheme to use */
@@ -2832,9 +2839,10 @@ static int fulltextFilter(
 
   zSql = sqlite3_mprintf("select rowid, * from %%_content %s",
                           idxNum==QUERY_GENERIC ? "" : "where rowid=?");
+  sqlite3_finalize(c->pStmt);
   rc = sql_prepare(v->db, v->zName, &c->pStmt, zSql);
   sqlite3_free(zSql);
-  if( rc!=SQLITE_OK ) goto out;
+  if( rc!=SQLITE_OK ) return rc;
 
   c->iCursorType = idxNum;
   switch( idxNum ){
@@ -2843,7 +2851,7 @@ static int fulltextFilter(
 
     case QUERY_ROWID:
       rc = sqlite3_bind_int64(c->pStmt, 1, sqlite3_value_int64(argv[0]));
-      if( rc!=SQLITE_OK ) goto out;
+      if( rc!=SQLITE_OK ) return rc;
       break;
 
     default:   /* full-text search */
@@ -2854,16 +2862,14 @@ static int fulltextFilter(
       assert( argc==1 );
       queryClear(&c->q);
       rc = fulltextQuery(v, idxNum-QUERY_FULLTEXT, zQuery, -1, &pResult, &c->q);
-      if( rc!=SQLITE_OK ) goto out;
+      if( rc!=SQLITE_OK ) return rc;
+      if( c->result.pDoclist!=NULL ) docListDelete(c->result.pDoclist);
       readerInit(&c->result, pResult);
       break;
     }
   }
 
-  rc = fulltextNext(pCursor);
-
-out:
-  return rc;
+  return fulltextNext(pCursor);
 }
 
 /* This is the xEof method of the virtual table.  The SQLite core
index 8e906f7db0f7914de9cb9d4ae55503a783a6c0a7..070089bdaa94413747049155b442acdc2fc388a3 100644 (file)
@@ -2613,6 +2613,7 @@ out:
 /* Decide how to handle an SQL query. */
 static int fulltextBestIndex(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
   int i;
+  TRACE(("FTS2 BestIndex\n"));
 
   for(i=0; i<pInfo->nConstraint; ++i){
     const struct sqlite3_index_constraint *pConstraint;
@@ -2621,10 +2622,12 @@ static int fulltextBestIndex(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
       if( pConstraint->iColumn==-1 &&
           pConstraint->op==SQLITE_INDEX_CONSTRAINT_EQ ){
         pInfo->idxNum = QUERY_ROWID;      /* lookup by rowid */
+        TRACE(("FTS2 QUERY_ROWID\n"));
       } else if( pConstraint->iColumn>=0 &&
                  pConstraint->op==SQLITE_INDEX_CONSTRAINT_MATCH ){
         /* full-text search */
         pInfo->idxNum = QUERY_FULLTEXT + pConstraint->iColumn;
+        TRACE(("FTS2 QUERY_FULLTEXT %d\n", pConstraint->iColumn));
       } else continue;
 
       pInfo->aConstraintUsage[i].argvIndex = 1;
@@ -2639,7 +2642,6 @@ static int fulltextBestIndex(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
     }
   }
   pInfo->idxNum = QUERY_GENERIC;
-  TRACE(("FTS2 BestIndex\n"));
   return SQLITE_OK;
 }
 
@@ -3034,10 +3036,8 @@ static int fulltextClose(sqlite3_vtab_cursor *pCursor){
   sqlite3_finalize(c->pStmt);
   queryClear(&c->q);
   snippetClear(&c->snippet);
-  if( c->result.nData!=0 ){
-    dlrDestroy(&c->reader);
-    dataBufferDestroy(&c->result);
-  }
+  if( c->result.nData!=0 ) dlrDestroy(&c->reader);
+  dataBufferDestroy(&c->result);
   free(c);
   return SQLITE_OK;
 }
@@ -3400,6 +3400,11 @@ static int fulltextQuery(
 ** number idxNum-QUERY_FULLTEXT, 0 indexed.  argv[0] is the right-hand
 ** side of the MATCH operator.
 */
+/* TODO(shess) Upgrade the cursor initialization and destruction to
+** account for fulltextFilter() being called multiple times on the
+** same cursor.  The current solution is very fragile.  Apply fix to
+** fts2 as appropriate.
+*/
 static int fulltextFilter(
   sqlite3_vtab_cursor *pCursor,     /* The cursor used for this query */
   int idxNum, const char *idxStr,   /* Which indexing scheme to use */
@@ -3414,9 +3419,10 @@ static int fulltextFilter(
 
   zSql = sqlite3_mprintf("select rowid, * from %%_content %s",
                           idxNum==QUERY_GENERIC ? "" : "where rowid=?");
+  sqlite3_finalize(c->pStmt);
   rc = sql_prepare(v->db, v->zName, &c->pStmt, zSql);
   sqlite3_free(zSql);
-  if( rc!=SQLITE_OK ) goto out;
+  if( rc!=SQLITE_OK ) return rc;
 
   c->iCursorType = idxNum;
   switch( idxNum ){
@@ -3425,7 +3431,7 @@ static int fulltextFilter(
 
     case QUERY_ROWID:
       rc = sqlite3_bind_int64(c->pStmt, 1, sqlite3_value_int64(argv[0]));
-      if( rc!=SQLITE_OK ) goto out;
+      if( rc!=SQLITE_OK ) return rc;
       break;
 
     default:   /* full-text search */
@@ -3434,7 +3440,13 @@ static int fulltextFilter(
       assert( idxNum<=QUERY_FULLTEXT+v->nColumn);
       assert( argc==1 );
       queryClear(&c->q);
-      dataBufferInit(&c->result, 0);
+      if( c->result.nData!=0 ){
+        /* This case happens if the same cursor is used repeatedly. */
+        dlrDestroy(&c->reader);
+        dataBufferReset(&c->result);
+      }else{
+        dataBufferInit(&c->result, 0);
+      }
       rc = fulltextQuery(v, idxNum-QUERY_FULLTEXT, zQuery, -1, &c->result, &c->q);
       if( rc!=SQLITE_OK ) return rc;
       if( c->result.nData!=0 ){
@@ -3444,10 +3456,7 @@ static int fulltextFilter(
     }
   }
 
-  rc = fulltextNext(pCursor);
-
-out:
-  return rc;
+  return fulltextNext(pCursor);
 }
 
 /* This is the xEof method of the virtual table.  The SQLite core
index 4306c87da16381a944eb523da5683857ef6b7309..4c8bb77f9637f154ebb364e7d7a1234c41280658 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Delta-encode\sterms\sin\sinterior\snodes.\s\sWhile\sexperiments\shave\sshown\nthat\sthis\sis\sof\smarginal\sutility\swhen\sencoding\sterms\sresulting\sfrom\nregular\sEnglish\stext,\sit\sturns\sout\sto\sbe\svery\suseful\swhen\sencoding\ninputs\swith\svery\slarge\sterms.\s(CVS\s3520)
-D 2006-11-29T01:02:03
+C http://www.sqlite.org/cvstrac/tktview?tn=2046\n\nThe\svirtual\stable\sinterface\sallows\sfor\sa\scursor\sto\sfield\smultiple\nxFilter()\scalls.\s\sFor\sinstance,\sif\sa\sjoin\sis\sdone\swith\sa\svirtual\ntable,\sthere\scould\sbe\sa\scall\sfor\seach\srow\swhich\spotentially\smatches.\nUnfortunately,\sfulltextFilter()\sassumes\sthat\sit\shas\sa\sfresh\scursor,\nand\soverwrites\sa\sprepared\sstatement\sand\sa\smalloc'ed\spointer,\sresulting\nin\sunfinalized\sstatements\sand\sa\smemory\sleak.\n\nThis\schange\shacks\sthe\scode\sto\smanually\sclean\sup\soffending\sitems\sin\nfulltextFilter(),\semphasis\son\s"hacks",\ssince\sit's\sa\sfragile\sfix\ninsofar\sas\sfuture\sadditions\sto\sfulltext_cursor\scould\scontinue\sto\shave\nthe\sproblem.\s(CVS\s3521)
+D 2006-11-29T05:17:28
 F Makefile.in 8e14898d41a53033ecb687d93c9cd5d109fb9ae3
 F Makefile.linux-gcc 2d8574d1ba75f129aba2019f0b959db380a90935
 F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028
@@ -21,7 +21,7 @@ F ext/README.txt 913a7bd3f4837ab14d7e063304181787658b14e1
 F ext/fts1/README.txt 20ac73b006a70bcfd80069bdaf59214b6cf1db5e
 F ext/fts1/ft_hash.c 3927bd880e65329bdc6f506555b228b28924921b
 F ext/fts1/ft_hash.h 1a35e654a235c2c662d3ca0dfc3138ad60b8b7d5
-F ext/fts1/fts1.c 78218fb06050899508387de38ce2769f5e57ed8e
+F ext/fts1/fts1.c a6b6a7b5ebc3f2fd8b1a8d65e8e7334c03b522d4
 F ext/fts1/fts1.h 6060b8f62c1d925ea8356cb1a6598073eb9159a6
 F ext/fts1/fts1_hash.c 3196cee866edbebb1c0521e21672e6d599965114
 F ext/fts1/fts1_hash.h 957d378355ed29f672cd5add012ce8b088a5e089
@@ -33,7 +33,7 @@ F ext/fts1/fulltext.h 08525a47852d1d62a0be81d3fc3fe2d23b094efd
 F ext/fts1/simple_tokenizer.c 1844d72f7194c3fd3d7e4173053911bf0661b70d
 F ext/fts1/tokenizer.h 0c53421b832366d20d720d21ea3e1f6e66a36ef9
 F ext/fts2/README.txt 8c18f41574404623b76917b9da66fcb0ab38328d
-F ext/fts2/fts2.c 6065a73ad89e7fb0dcfc41d1b110f856dea98dc8
+F ext/fts2/fts2.c 94b438480762ba2a2cb5e5d66b80290e93c50960
 F ext/fts2/fts2.h bbdab26d34f91974d5b9ade8b7836c140a7c4ce1
 F ext/fts2/fts2_hash.c b3f22116d4ef0bc8f2da6e3fdc435c86d0951a9b
 F ext/fts2/fts2_hash.h e283308156018329f042816eb09334df714e105e
@@ -421,7 +421,7 @@ F www/tclsqlite.tcl bb0d1357328a42b1993d78573e587c6dcbc964b9
 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
 F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
 F www/whentouse.tcl 97e2b5cd296f7d8057e11f44427dea8a4c2db513
-P 272c1a6e61d053121b5412564948dad4366b5727
-R 64f64a706f1c764008e348249e53ac19
+P c8151a998ec2423b417566823dc9957c7d5d782c
+R f017f7c21acd0dc81410dabbd79839d6
 U shess
-Z 613a143cab46a942074b48bd6bce5a4c
+Z 7ba30b5c9f8e043c81e82dcfd18e4b5c
index 33103b55f70ead9d85b4d2d41d2381a78cb41fe6..955563d166564392f53e92256a352ee1afea422e 100644 (file)
@@ -1 +1 @@
-c8151a998ec2423b417566823dc9957c7d5d782c
\ No newline at end of file
+18142fdb6d1f5bfdbb1155274502b9a602885fcb
\ No newline at end of file