/* end utility functions */
-#define QUERY_GENERIC 0
-#define QUERY_FULLTEXT 1
+typedef enum QueryType {
+ QUERY_GENERIC, /* table scan */
+ QUERY_ROWID, /* lookup by rowid */
+ QUERY_FULLTEXT /* full-text search */
+} QueryType;
/* TODO(shess) CHUNK_MAX controls how much data we allow in segment 0
** before we start aggregating into larger segments. Lower CHUNK_MAX
typedef struct fulltext_cursor {
sqlite3_vtab_cursor base;
- int iCursorType; /* QUERY_GENERIC or QUERY_FULLTEXT */
+ QueryType iCursorType;
sqlite3_stmt *pStmt;
-
int eof;
- /* The following is used only when iCursorType == QUERY_FULLTEXT. */
- DocListReader result;
+ DocListReader result; /* used when iCursorType == QUERY_FULLTEXT */
} fulltext_cursor;
static struct fulltext_vtab *cursor_vtab(fulltext_cursor *c){
for(i=0; i<pInfo->nConstraint; ++i){
const struct sqlite3_index_constraint *pConstraint;
pConstraint = &pInfo->aConstraint[i];
- if( pConstraint->iColumn==0 &&
- pConstraint->op==SQLITE_INDEX_CONSTRAINT_MATCH &&
- pConstraint->usable ){ /* a full-text search */
+ if( pConstraint->usable ) {
+ if( pConstraint->iColumn==-1 &&
+ pConstraint->op==SQLITE_INDEX_CONSTRAINT_EQ ){
+ pInfo->idxNum = QUERY_ROWID; /* lookup by rowid */
+ } else if( pConstraint->iColumn==0 &&
+ pConstraint->op==SQLITE_INDEX_CONSTRAINT_MATCH ){
+ pInfo->idxNum = QUERY_FULLTEXT; /* full-text search */
+ } else continue;
+
pInfo->aConstraintUsage[i].argvIndex = 1;
pInfo->aConstraintUsage[i].omit = 1;
- pInfo->idxNum = QUERY_FULLTEXT;
- pInfo->estimatedCost = 1.0; /* an arbitrary value for now */
+
+ /* An arbitrary value for now.
+ * TODO: Perhaps rowid matches should be considered cheaper than
+ * full-text searches. */
+ pInfo->estimatedCost = 1.0;
+
return SQLITE_OK;
}
}
int rc;
TRACE(("FTS1 Next %p\n", pCursor));
- switch( c->iCursorType ){
- case QUERY_GENERIC:
- /* TODO(shess) Handle SQLITE_SCHEMA AND SQLITE_BUSY. */
- rc = sqlite3_step(c->pStmt);
- switch( rc ){
- case SQLITE_ROW:
- c->eof = 0;
- return SQLITE_OK;
- case SQLITE_DONE:
- c->eof = 1;
- return SQLITE_OK;
- default:
- c->eof = 1;
- return rc;
- }
- case QUERY_FULLTEXT:
- rc = sqlite3_reset(c->pStmt);
- if( rc!=SQLITE_OK ) return rc;
-
- iDocid = nextValidDocid(&c->result);
- if( iDocid==0 ){
- c->eof = 1;
- return SQLITE_OK;
- }
- rc = sqlite3_bind_int64(c->pStmt, 1, iDocid);
- if( rc!=SQLITE_OK ) return rc;
- /* TODO(shess) Handle SQLITE_SCHEMA AND SQLITE_BUSY. */
- rc = sqlite3_step(c->pStmt);
- if( rc==SQLITE_ROW ){ /* the case we expect */
+ if( c->iCursorType != QUERY_FULLTEXT ){
+ /* TODO(shess) Handle SQLITE_SCHEMA AND SQLITE_BUSY. */
+ rc = sqlite3_step(c->pStmt);
+ switch( rc ){
+ case SQLITE_ROW:
c->eof = 0;
return SQLITE_OK;
- }
- /* an error occurred; abort */
- return rc==SQLITE_DONE ? SQLITE_ERROR : rc;
- default:
- assert( 0 );
- return SQLITE_ERROR; /* not reached */
+ case SQLITE_DONE:
+ c->eof = 1;
+ return SQLITE_OK;
+ default:
+ c->eof = 1;
+ return rc;
+ }
+ } else { /* full-text query */
+ rc = sqlite3_reset(c->pStmt);
+ if( rc!=SQLITE_OK ) return rc;
+
+ iDocid = nextValidDocid(&c->result);
+ if( iDocid==0 ){
+ c->eof = 1;
+ return SQLITE_OK;
+ }
+ rc = sqlite3_bind_int64(c->pStmt, 1, iDocid);
+ if( rc!=SQLITE_OK ) return rc;
+ /* TODO(shess) Handle SQLITE_SCHEMA AND SQLITE_BUSY. */
+ rc = sqlite3_step(c->pStmt);
+ if( rc==SQLITE_ROW ){ /* the case we expect */
+ c->eof = 0;
+ return SQLITE_OK;
+ }
+ /* an error occurred; abort */
+ return rc==SQLITE_DONE ? SQLITE_ERROR : rc;
}
}
fulltext_cursor *c = (fulltext_cursor *) pCursor;
fulltext_vtab *v = cursor_vtab(c);
int rc;
- const char *zStatement;
TRACE(("FTS1 Filter %p\n",pCursor));
c->iCursorType = idxNum;
switch( idxNum ){
case QUERY_GENERIC:
- zStatement = "select rowid, content from %_content";
+ rc = sql_prepare(v->db, v->zName, &c->pStmt,
+ "select rowid, content from %_content");
+ break;
+
+ case QUERY_ROWID:
+ rc = sql_prepare(v->db, v->zName, &c->pStmt,
+ "select rowid, content from %_content where rowid = ?");
+ if( rc!=SQLITE_OK ) return rc;
+
+ rc = sqlite3_bind_int64(c->pStmt, 1, sqlite3_value_int64(argv[0]));
break;
case QUERY_FULLTEXT: /* full-text search */
rc = fulltextQuery(v, zQuery, -1, &pResult);
if( rc!=SQLITE_OK ) return rc;
readerInit(&c->result, pResult);
- zStatement = "select rowid, content from %_content where rowid = ?";
+ rc = sql_prepare(v->db, v->zName, &c->pStmt,
+ "select rowid, content from %_content where rowid = ?");
break;
}
assert( 0 );
}
- rc = sql_prepare(v->db, v->zName, &c->pStmt, zStatement);
if( rc!=SQLITE_OK ) return rc;
return fulltextNext(pCursor);
-C Add\ssupport\sfor\sIF\sEXISTS\son\sCREATE/DROP\sTRIGGER/VIEW.\s\sTicket\s#1899.\s(CVS\s3406)
-D 2006-09-11T23:45:49
+C Answer\squeries\sfor\sa\sparticular\srowid\sin\sa\sfull-text\stable\sby\slooking\sup\nthat\srowid\sdirectly\srather\sthan\sby\sperforming\sa\stable\sscan.\s(CVS\s3407)
+D 2006-09-12T23:36:45
F Makefile.in cabd42d34340f49260bc2a7668c38eba8d4cfd99
F Makefile.linux-gcc 2d8574d1ba75f129aba2019f0b959db380a90935
F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028
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 5c5e362ec08487a0bdcf58b7467a28321eed8025
+F ext/fts1/fts1.c 9ba2598d8f7fe6a774282150602b4dcf8d08981d
F ext/fts1/fts1.h fe8e8f38dd6d2d2645b9b0d6972e80985249575f
F ext/fts1/fts1_hash.c 3196cee866edbebb1c0521e21672e6d599965114
F ext/fts1/fts1_hash.h 957d378355ed29f672cd5add012ce8b088a5e089
F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
F www/whentouse.tcl 97e2b5cd296f7d8057e11f44427dea8a4c2db513
-P 2f5f6290c9ef99c7b060aecc4d996c976c50c9d7
-R d17bd6ef8648d9d2f3852e6272db6a75
-U drh
-Z 86240886575897a77ef3f7d53b2d3c49
+P e4fe736cfbbdc081581911a01690576034877b72
+R cd04ef21e43abddd90a3615c7fb02f51
+U adamd
+Z 7cc52eecbd18356560e00617aa5563fc