Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Answer queries for a particular rowid in a full-text table by looking up that rowid directly rather than by performing a table scan. (CVS 3407) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
877d5558b1a6f65201b1825336935b14 |
User & Date: | adamd 2006-09-12 23:36:45.000 |
Context
2006-09-13
| ||
02:18 |
Allow virtual tables to contain multiple full-text-indexed columns. Added a magic column "_all" which can be used for querying all columns in a table at once.
For now, each posting list stores position/offset information for multiple columns. We may implement separate posting lists for separate columns at some future point. (CVS 3408) (check-in: 366a70b086 user: adamd tags: trunk) | |
2006-09-12
| ||
23:36 | Answer queries for a particular rowid in a full-text table by looking up that rowid directly rather than by performing a table scan. (CVS 3407) (check-in: 877d5558b1 user: adamd tags: trunk) | |
2006-09-11
| ||
23:45 | Add support for IF EXISTS on CREATE/DROP TRIGGER/VIEW. Ticket #1899. (CVS 3406) (check-in: e4fe736cfb user: drh tags: trunk) | |
Changes
Changes to ext/fts1/fts1.c.
︙ | ︙ | |||
746 747 748 749 750 751 752 | rc = sqlite3_prepare(db, zCommand, -1, ppStmt, NULL); free(zCommand); return rc; } /* end utility functions */ | > | > | > | 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 | rc = sqlite3_prepare(db, zCommand, -1, ppStmt, NULL); free(zCommand); return rc; } /* end utility functions */ 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 ** means that for a given input we have more individual segments per ** term, which means more rows in the table and a bigger index (due to ** both more rows and bigger rowids). But it also reduces the average ** cost of adding new elements to the segment 0 doclist, and it seems |
︙ | ︙ | |||
813 814 815 816 817 818 819 | ** open. */ sqlite3_stmt *pFulltextStatements[MAX_STMT]; } fulltext_vtab; typedef struct fulltext_cursor { sqlite3_vtab_cursor base; | | < < | | 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 | ** open. */ sqlite3_stmt *pFulltextStatements[MAX_STMT]; } fulltext_vtab; typedef struct fulltext_cursor { sqlite3_vtab_cursor base; QueryType iCursorType; sqlite3_stmt *pStmt; int eof; DocListReader result; /* used when iCursorType == QUERY_FULLTEXT */ } fulltext_cursor; static struct fulltext_vtab *cursor_vtab(fulltext_cursor *c){ return (fulltext_vtab *) c->base.pVtab; } static const sqlite3_module fulltextModule; /* forward declaration */ |
︙ | ︙ | |||
1452 1453 1454 1455 1456 1457 1458 | * haven't implemented phrase searches or OR yet. */ static int fulltextBestIndex(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){ int i; for(i=0; i<pInfo->nConstraint; ++i){ const struct sqlite3_index_constraint *pConstraint; pConstraint = &pInfo->aConstraint[i]; | > | > > > | | > > | > > > | > | 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 | * haven't implemented phrase searches or OR yet. */ static int fulltextBestIndex(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){ int i; for(i=0; i<pInfo->nConstraint; ++i){ const struct sqlite3_index_constraint *pConstraint; pConstraint = &pInfo->aConstraint[i]; 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; /* An arbitrary value for now. * TODO: Perhaps rowid matches should be considered cheaper than * full-text searches. */ pInfo->estimatedCost = 1.0; return SQLITE_OK; } } pInfo->idxNum = QUERY_GENERIC; TRACE(("FTS1 BestIndex\n")); return SQLITE_OK; } |
︙ | ︙ | |||
1514 1515 1516 1517 1518 1519 1520 | static int fulltextNext(sqlite3_vtab_cursor *pCursor){ fulltext_cursor *c = (fulltext_cursor *) pCursor; sqlite_int64 iDocid; int rc; TRACE(("FTS1 Next %p\n", pCursor)); | | < | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < < < | 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 | static int fulltextNext(sqlite3_vtab_cursor *pCursor){ fulltext_cursor *c = (fulltext_cursor *) pCursor; sqlite_int64 iDocid; int rc; TRACE(("FTS1 Next %p\n", pCursor)); 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; 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; } } /* A single term in a query is represented by an instances of ** the following structure. */ typedef struct QueryTerm { |
︙ | ︙ | |||
1826 1827 1828 1829 1830 1831 1832 | static int fulltextFilter(sqlite3_vtab_cursor *pCursor, int idxNum, const char *idxStr, int argc, sqlite3_value **argv){ fulltext_cursor *c = (fulltext_cursor *) pCursor; fulltext_vtab *v = cursor_vtab(c); int rc; | < > | > > > > > > > > > | < | 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 | static int fulltextFilter(sqlite3_vtab_cursor *pCursor, int idxNum, const char *idxStr, int argc, sqlite3_value **argv){ fulltext_cursor *c = (fulltext_cursor *) pCursor; fulltext_vtab *v = cursor_vtab(c); int rc; TRACE(("FTS1 Filter %p\n",pCursor)); c->iCursorType = idxNum; switch( idxNum ){ case QUERY_GENERIC: 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 */ { const char *zQuery = (const char *)sqlite3_value_text(argv[0]); DocList *pResult; assert( argc==1 ); rc = fulltextQuery(v, zQuery, -1, &pResult); if( rc!=SQLITE_OK ) return rc; readerInit(&c->result, pResult); rc = sql_prepare(v->db, v->zName, &c->pStmt, "select rowid, content from %_content where rowid = ?"); break; } default: assert( 0 ); } if( rc!=SQLITE_OK ) return rc; return fulltextNext(pCursor); } static int fulltextEof(sqlite3_vtab_cursor *pCursor){ fulltext_cursor *c = (fulltext_cursor *) pCursor; |
︙ | ︙ |