Change FTS4 so that if both the content=xxx option and column names are specified, the virtual table assumes that the named columns correspond to columns of table xxx.

FossilOrigin-Name: 289ee43179369fce2fde50870d72c445e184e896
This commit is contained in:
dan
2011-10-05 15:11:30 +00:00
parent 8361b189c9
commit deb9473250
5 changed files with 121 additions and 64 deletions
+64 -41
View File
@@ -1182,20 +1182,19 @@ static int fts3InitVtab(
**
** 1. Ignore any compress= and uncompress= options.
**
** 2. Ignore any column names that were specified as part of the
** the CREATE VIRTUAL TABLE statement.
**
** 3. Determine the actual column names to use for the FTS table
** based on the columns of the content= table.
** 2. If no column names were specified as part of the CREATE VIRTUAL
** TABLE statement, use all columns from the content table.
*/
if( rc==SQLITE_OK && zContent ){
sqlite3_free(aCol);
sqlite3_free(zCompress);
sqlite3_free(zUncompress);
zCompress = 0;
zUncompress = 0;
aCol = 0;
rc = fts3ContentColumns(db, argv[1], zContent, &aCol, &nCol, &nString);
if( nCol==0 ){
sqlite3_free(aCol);
aCol = 0;
rc = fts3ContentColumns(db, argv[1], zContent, &aCol, &nCol, &nString);
}
assert( rc!=SQLITE_OK || nCol>0 );
}
if( rc!=SQLITE_OK ) goto fts3_init_out;
@@ -1457,40 +1456,64 @@ static int fts3CloseMethod(sqlite3_vtab_cursor *pCursor){
return SQLITE_OK;
}
/*
** If pCsr->pStmt has not been prepared (i.e. if pCsr->pStmt==0), then
** compose and prepare an SQL statement of the form:
**
** "SELECT <columns> FROM %_content WHERE rowid = ?"
**
** (or the equivalent for a content=xxx table) and set pCsr->pStmt to
** it. If an error occurs, return an SQLite error code.
**
** Otherwise, set *ppStmt to point to pCsr->pStmt and return SQLITE_OK.
*/
static int fts3CursorSeekStmt(Fts3Cursor *pCsr, sqlite3_stmt **ppStmt){
int rc = SQLITE_OK;
if( pCsr->pStmt==0 ){
Fts3Table *p = (Fts3Table *)pCsr->base.pVtab;
char *zSql;
zSql = sqlite3_mprintf("SELECT %s WHERE rowid = ?", p->zReadExprlist);
if( !zSql ) return SQLITE_NOMEM;
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pCsr->pStmt, 0);
sqlite3_free(zSql);
}
*ppStmt = pCsr->pStmt;
return rc;
}
/*
** Position the pCsr->pStmt statement so that it is on the row
** of the %_content table that contains the last match. Return
** SQLITE_OK on success.
*/
static int fts3CursorSeek(sqlite3_context *pContext, Fts3Cursor *pCsr){
int rc = SQLITE_OK;
if( pCsr->isRequireSeek ){
sqlite3_bind_int64(pCsr->pStmt, 1, pCsr->iPrevId);
pCsr->isRequireSeek = 0;
if( SQLITE_ROW==sqlite3_step(pCsr->pStmt) ){
return SQLITE_OK;
}else{
int rc = sqlite3_reset(pCsr->pStmt);
if( rc==SQLITE_OK ){
Fts3Table *p = (Fts3Table *)pCsr->base.pVtab;
if( p->zContentTbl==0 ){
sqlite3_stmt *pStmt = 0;
rc = fts3CursorSeekStmt(pCsr, &pStmt);
if( rc==SQLITE_OK ){
sqlite3_bind_int64(pCsr->pStmt, 1, pCsr->iPrevId);
pCsr->isRequireSeek = 0;
if( SQLITE_ROW==sqlite3_step(pCsr->pStmt) ){
return SQLITE_OK;
}else{
rc = sqlite3_reset(pCsr->pStmt);
if( rc==SQLITE_OK && ((Fts3Table *)pCsr->base.pVtab)->zContentTbl==0 ){
/* If no row was found and no error has occured, then the %_content
** table is missing a row that is present in the full-text index.
** The data structures are corrupt.
*/
** The data structures are corrupt. */
rc = SQLITE_CORRUPT_VTAB;
}else{
return SQLITE_OK;
pCsr->isEof = 1;
}
}
pCsr->isEof = 1;
if( pContext ){
sqlite3_result_error_code(pContext, rc);
}
return rc;
}
}else{
return SQLITE_OK;
}
if( rc!=SQLITE_OK && pContext ){
sqlite3_result_error_code(pContext, rc);
}
return rc;
}
/*
@@ -2848,24 +2871,24 @@ static int fts3FilterMethod(
** row by docid.
*/
if( idxNum==FTS3_FULLSCAN_SEARCH ){
const char *zTmpl = "SELECT %s ORDER BY rowid %s";
zSql = sqlite3_mprintf(zTmpl,
zSql = sqlite3_mprintf(
"SELECT %s ORDER BY rowid %s",
p->zReadExprlist, (pCsr->bDesc ? "DESC" : "ASC")
);
}else{
const char *zTmpl = "SELECT %s WHERE rowid = ?";
zSql = sqlite3_mprintf(zTmpl, p->zReadExprlist);
if( zSql ){
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pCsr->pStmt, 0);
sqlite3_free(zSql);
}else{
rc = SQLITE_NOMEM;
}
}else if( idxNum==FTS3_DOCID_SEARCH ){
rc = fts3CursorSeekStmt(pCsr, &pCsr->pStmt);
if( rc==SQLITE_OK ){
rc = sqlite3_bind_value(pCsr->pStmt, 1, apVal[0]);
}
}
if( !zSql ) return SQLITE_NOMEM;
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pCsr->pStmt, 0);
sqlite3_free(zSql);
if( rc!=SQLITE_OK ) return rc;
if( idxNum==FTS3_DOCID_SEARCH ){
rc = sqlite3_bind_value(pCsr->pStmt, 1, apVal[0]);
if( rc!=SQLITE_OK ) return rc;
}
return fts3NextMethod(pCursor);
}