/* Perform a full-text query; return a list of documents in [pResult]. */ static int fulltext_query(fulltext_vtab *v, const char *zQuery, DocList **pResult){ Query q; int phrase_start = -1; int i; sqlite3_stmt *pSelect = NULL; DocList *d = NULL; int rc = parse_query(v, zQuery, &q); if( rc!=SQLITE_OK ) return rc; /* Merge terms. */ for(i = 0 ; i < q.nTerms ; ++i){ /* In each merge step, we need to generate positions whenever we're * processing a phrase which hasn't ended yet. */ int need_positions = i<q.nTerms-1 && !q.pTerm[i+1].is_phrase; DocList *next = docListNew(need_positions ? DL_POSITIONS : DL_DOCIDS); if( q.pTerm[i].is_phrase ){ phrase_start = i; } rc = query_merge(v, &pSelect, q.pTerm[i].zTerm, d, i - phrase_start, next); if( rc!=SQLITE_OK ) break; if( d!=NULL ){ docListDelete(d); } d = next; } sqlite3_finalize(pSelect); query_free(&q); *pResult = d; return rc; }
/* Insert a row into the full-text index; set *piRowid to be the ID of the * new row. */ static int index_insert(fulltext_vtab *v, sqlite3_value *pRequestRowid, const char *zText, sqlite_int64 *piRowid){ Hash terms; /* maps term string -> PosList */ HashElem *e; int rc = content_insert(v, pRequestRowid, zText, -1); if( rc!=SQLITE_OK ) return rc; *piRowid = sqlite3_last_insert_rowid(v->db); if( !zText ) return SQLITE_OK; /* nothing to index */ rc = build_terms(&terms, v->pTokenizer, zText, *piRowid); if( rc!=SQLITE_OK ) return rc; for(e=HashFirst(&terms); e; e=HashNext(e)){ DocList *p = HashData(e); rc = index_insert_term(v, HashKey(e), HashKeysize(e), *piRowid, p); if( rc!=SQLITE_OK ) break; } for(e=HashFirst(&terms); e; e=HashNext(e)){ DocList *p = HashData(e); docListDelete(p); } HashClear(&terms); return rc; }
static int fulltext_query(fulltext_vtab *v, const char *zQuery, DocList **pResult){ Query q; int phrase_start = -1; int i; sqlite3_stmt *pSelect = NULL; DocList *d = NULL; int rc = parse_query(v, zQuery, &q); if( rc!=SQLITE_OK ) return rc; for(i = 0 ; i < q.nTerms ; ++i){ int need_positions = i<q.nTerms-1 && !q.pTerm[i+1].is_phrase; DocList *next = docListNew(need_positions ? DL_POSITIONS : DL_DOCIDS); if( q.pTerm[i].is_phrase ){ phrase_start = i; } rc = query_merge(v, &pSelect, q.pTerm[i].zTerm, d, i - phrase_start, next); if( rc!=SQLITE_OK ) break; if( d!=NULL ){ docListDelete(d); } d = next; } sqlite3_finalize(pSelect); query_free(&q); *pResult = d; return rc; }
static int fulltextClose(sqlite3_vtab_cursor *pCursor){ fulltext_cursor *c = (fulltext_cursor *) pCursor; sqlite3_finalize(c->pStmt); if( c->result.pDoclist!=NULL ){ docListDelete(c->result.pDoclist); } free(c); return SQLITE_OK; }
/* Delete a row from the full-text index. */ static int index_delete(fulltext_vtab *v, sqlite_int64 iRow){ char *zText; Hash terms; HashElem *e; int rc = content_select(v, iRow, &zText); if( rc!=SQLITE_OK ) return rc; rc = build_terms(&terms, v->pTokenizer, zText, iRow); free(zText); if( rc!=SQLITE_OK ) return rc; for(e=HashFirst(&terms); e; e=HashNext(e)){ rc = index_delete_term(v, HashKey(e), HashKeysize(e), iRow); if( rc!=SQLITE_OK ) break; } for(e=HashFirst(&terms); e; e=HashNext(e)){ DocList *p = HashData(e); docListDelete(p); } HashClear(&terms); return content_delete(v, iRow); }