Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Minor optimizations to fts3 code. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
b456eacbbb16513d1b27e90015ea58a6 |
User & Date: | dan 2009-11-20 02:24:15.000 |
Context
2009-11-20
| ||
05:05 | Improve comments and other things in fts3_write.c. (check-in: 1cf0e3cc14 user: dan tags: trunk) | |
02:24 | Minor optimizations to fts3 code. (check-in: b456eacbbb user: dan tags: trunk) | |
2009-11-19
| ||
18:30 | Merge leaves [7cd178a72a] and [598727e6da]. (check-in: 4115c0c286 user: dan tags: trunk) | |
Changes
Changes to ext/fts3/fts3.c.
︙ | ︙ | |||
494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 | assert( p->nPendingData==0 ); /* Free any prepared statements held */ for(i=0; i<SizeofArray(p->aStmt); i++){ sqlite3_finalize(p->aStmt[i]); } sqlite3_free(p->zSelectLeaves); /* Invoke the tokenizer destructor to free the tokenizer. */ p->pTokenizer->pModule->xDestroy(p->pTokenizer); sqlite3_free(p); return SQLITE_OK; } | > > > > | 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 | assert( p->nPendingData==0 ); /* Free any prepared statements held */ for(i=0; i<SizeofArray(p->aStmt); i++){ sqlite3_finalize(p->aStmt[i]); } for(i=0; i<p->nLeavesStmt; i++){ sqlite3_finalize(p->aLeavesStmt[i]); } sqlite3_free(p->zSelectLeaves); sqlite3_free(p->aLeavesStmt); /* Invoke the tokenizer destructor to free the tokenizer. */ p->pTokenizer->pModule->xDestroy(p->pTokenizer); sqlite3_free(p); return SQLITE_OK; } |
︙ | ︙ | |||
859 860 861 862 863 864 865 866 867 | Fts3Cursor *pCsr = (Fts3Cursor *)pCursor; sqlite3_finalize(pCsr->pStmt); sqlite3Fts3ExprFree(pCsr->pExpr); sqlite3_free(pCsr->aDoclist); sqlite3_free(pCsr); return SQLITE_OK; } static int fts3NextMethod(sqlite3_vtab_cursor *pCursor){ | > > > > > > > > > > > > > > > > > > > | | < < < < < < < | < < < < | 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 | Fts3Cursor *pCsr = (Fts3Cursor *)pCursor; sqlite3_finalize(pCsr->pStmt); sqlite3Fts3ExprFree(pCsr->pExpr); sqlite3_free(pCsr->aDoclist); sqlite3_free(pCsr); return SQLITE_OK; } static int fts3CursorSeek(Fts3Cursor *pCsr){ if( pCsr->isRequireSeek ){ pCsr->isRequireSeek = 0; sqlite3_bind_int64(pCsr->pStmt, 1, pCsr->iPrevId); if( SQLITE_ROW==sqlite3_step(pCsr->pStmt) ){ return SQLITE_OK; }else{ int rc; pCsr->isEof = 1; if( SQLITE_OK==(rc = sqlite3_reset(pCsr->pStmt)) ){ rc = SQLITE_ERROR; } return rc; } }else{ return SQLITE_OK; } } static int fts3NextMethod(sqlite3_vtab_cursor *pCursor){ int rc = SQLITE_OK; /* Return code */ Fts3Cursor *pCsr = (Fts3Cursor *)pCursor; if( pCsr->aDoclist==0 ){ if( SQLITE_ROW!=sqlite3_step(pCsr->pStmt) ){ pCsr->isEof = 1; rc = sqlite3_reset(pCsr->pStmt); } }else if( pCsr->pNextId>=&pCsr->aDoclist[pCsr->nDoclist] ){ pCsr->isEof = 1; }else{ sqlite3_reset(pCsr->pStmt); fts3GetDeltaVarint(&pCsr->pNextId, &pCsr->iPrevId); pCsr->isRequireSeek = 1; } return rc; } /* ** The buffer pointed to by argument zNode (size nNode bytes) contains the |
︙ | ︙ | |||
1520 1521 1522 1523 1524 1525 1526 | if( pNew ){ if( nSegment==nAlloc ){ nAlloc += 16; Fts3SegReader **pArray = (Fts3SegReader **)sqlite3_realloc( apSegment, nAlloc*sizeof(Fts3SegReader *) ); if( !pArray ){ | | | 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 | if( pNew ){ if( nSegment==nAlloc ){ nAlloc += 16; Fts3SegReader **pArray = (Fts3SegReader **)sqlite3_realloc( apSegment, nAlloc*sizeof(Fts3SegReader *) ); if( !pArray ){ sqlite3Fts3SegReaderFree(p, pNew); rc = SQLITE_NOMEM; goto finished; } apSegment = pArray; } apSegment[nSegment++] = pNew; } |
︙ | ︙ | |||
1559 1560 1561 1562 1563 1564 1565 | }else{ sqlite3_free(tsc.aOutput); } finished: sqlite3_reset(pStmt); for(i=0; i<nSegment; i++){ | | | 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 | }else{ sqlite3_free(tsc.aOutput); } finished: sqlite3_reset(pStmt); for(i=0; i<nSegment; i++){ sqlite3Fts3SegReaderFree(p, apSegment[i]); } sqlite3_free(apSegment); return rc; } /* |
︙ | ︙ | |||
1825 1826 1827 1828 1829 1830 1831 | /* This is the xColumn method of the virtual table. The SQLite ** core calls this method during a query when it needs the value ** of a column from the virtual table. This method needs to use ** one of the sqlite3_result_*() routines to store the requested ** value back in the pContext. */ | | > > > > | 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 | /* This is the xColumn method of the virtual table. The SQLite ** core calls this method during a query when it needs the value ** of a column from the virtual table. This method needs to use ** one of the sqlite3_result_*() routines to store the requested ** value back in the pContext. */ static int fts3ColumnMethod(sqlite3_vtab_cursor *pCursor, sqlite3_context *pContext, int idxCol){ Fts3Cursor *c = (Fts3Cursor *) pCursor; Fts3Table *v = cursor_vtab(c); int rc = fts3CursorSeek(c); if( rc!=SQLITE_OK ){ return rc; } if( idxCol<v->nColumn ){ sqlite3_value *pVal = sqlite3_column_value(c->pStmt, idxCol+1); sqlite3_result_value(pContext, pVal); }else if( idxCol==v->nColumn ){ /* The extra column whose name is the same as the table. ** Return a blob which is a pointer to the cursor |
︙ | ︙ | |||
1854 1855 1856 1857 1858 1859 1860 | ** This is the xRowid method. The SQLite core calls this routine to ** retrieve the rowid for the current row of the result set. fts3 ** exposes %_content.docid as the rowid for the virtual table. The ** rowid should be written to *pRowid. */ static int fts3RowidMethod(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){ Fts3Cursor *pCsr = (Fts3Cursor *) pCursor; | > > > | > | 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 | ** This is the xRowid method. The SQLite core calls this routine to ** retrieve the rowid for the current row of the result set. fts3 ** exposes %_content.docid as the rowid for the virtual table. The ** rowid should be written to *pRowid. */ static int fts3RowidMethod(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){ Fts3Cursor *pCsr = (Fts3Cursor *) pCursor; if( pCsr->aDoclist ){ *pRowid = pCsr->iPrevId; }else{ *pRowid = sqlite3_column_int64(pCsr->pStmt, 0); } return SQLITE_OK; } /* ** This function is the implementation of the xUpdate callback used by ** FTS3 virtual tables. It is invoked by SQLite each time a row is to be ** inserted, updated or deleted. |
︙ | ︙ | |||
2085 2086 2087 2088 2089 2090 2091 | /* xDisconnect */ fts3DisconnectMethod, /* xDestroy */ fts3DestroyMethod, /* xOpen */ fts3OpenMethod, /* xClose */ fulltextClose, /* xFilter */ fts3FilterMethod, /* xNext */ fts3NextMethod, /* xEof */ fts3EofMethod, | | | 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 | /* xDisconnect */ fts3DisconnectMethod, /* xDestroy */ fts3DestroyMethod, /* xOpen */ fts3OpenMethod, /* xClose */ fulltextClose, /* xFilter */ fts3FilterMethod, /* xNext */ fts3NextMethod, /* xEof */ fts3EofMethod, /* xColumn */ fts3ColumnMethod, /* xRowid */ fts3RowidMethod, /* xUpdate */ fts3UpdateMethod, /* xBegin */ fts3BeginMethod, /* xSync */ fts3SyncMethod, /* xCommit */ fts3CommitMethod, /* xRollback */ fts3RollbackMethod, /* xFindFunction */ fts3FindFunctionMethod, |
︙ | ︙ |
Changes to ext/fts3/fts3Int.h.
︙ | ︙ | |||
64 65 66 67 68 69 70 | ** A connection to a fulltext index is an instance of the following ** structure. The xCreate and xConnect methods create an instance ** of this structure and xDestroy and xDisconnect free that instance. ** All other methods receive a pointer to the structure as one of their ** arguments. */ struct Fts3Table { | | | | | | | | > > > > | 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 | ** A connection to a fulltext index is an instance of the following ** structure. The xCreate and xConnect methods create an instance ** of this structure and xDestroy and xDisconnect free that instance. ** All other methods receive a pointer to the structure as one of their ** arguments. */ struct Fts3Table { sqlite3_vtab base; /* Base class used by SQLite core */ sqlite3 *db; /* The database connection */ const char *zDb; /* logical database name */ const char *zName; /* virtual table name */ int nColumn; /* number of columns in virtual table */ char **azColumn; /* column names. malloced */ sqlite3_tokenizer *pTokenizer; /* tokenizer for inserts and queries */ /* Precompiled statements used by the implementation. Each of these ** statements is run and reset within a single virtual table API call. */ sqlite3_stmt *aStmt[18]; /* Pointer to string containing the SQL: ** ** "SELECT block FROM %_segments WHERE blockid BETWEEN ? AND ? ** ORDER BY blockid" */ char *zSelectLeaves; int nLeavesStmt; /* Valid statements in aLeavesStmt */ int nLeavesTotal; /* Total number of prepared leaves stmts */ int nLeavesAlloc; /* Allocated size of aLeavesStmt */ sqlite3_stmt **aLeavesStmt; /* Array of prepared zSelectLeaves stmts */ /* The following hash table is used to buffer pending index updates during ** transactions. Variable nPendingData estimates the memory size of the ** pending data, including hash table overhead, but not malloc overhead. ** When nPendingData exceeds FTS3_MAX_PENDING_DATA, the buffer is flushed ** automatically. Variable iPrevDocid is the docid of the most recently ** inserted record. |
︙ | ︙ | |||
106 107 108 109 110 111 112 113 114 115 116 117 118 119 | ** the xOpen method. Cursors are destroyed using the xClose method. */ struct Fts3Cursor { sqlite3_vtab_cursor base; /* Base class used by SQLite core */ int eType; /* Search strategy (see below) */ sqlite3_stmt *pStmt; /* Prepared statement in use by the cursor */ int isEof; /* True if at End Of Results */ Fts3Expr *pExpr; /* Parsed MATCH query string */ sqlite3_int64 iPrevId; /* Previous id read from aDoclist */ char *pNextId; /* Pointer into the body of aDoclist */ char *aDoclist; /* List of docids for full-text queries */ int nDoclist; /* Size of buffer at aDoclist */ }; | > | 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 | ** the xOpen method. Cursors are destroyed using the xClose method. */ struct Fts3Cursor { sqlite3_vtab_cursor base; /* Base class used by SQLite core */ int eType; /* Search strategy (see below) */ sqlite3_stmt *pStmt; /* Prepared statement in use by the cursor */ int isEof; /* True if at End Of Results */ int isRequireSeek; /* True if must seek pStmt to %_content row */ Fts3Expr *pExpr; /* Parsed MATCH query string */ sqlite3_int64 iPrevId; /* Previous id read from aDoclist */ char *pNextId; /* Pointer into the body of aDoclist */ char *aDoclist; /* List of docids for full-text queries */ int nDoclist; /* Size of buffer at aDoclist */ }; |
︙ | ︙ | |||
172 173 174 175 176 177 178 | /* fts3_write.c */ int sqlite3Fts3UpdateMethod(sqlite3_vtab*,int,sqlite3_value**,sqlite3_int64*); int sqlite3Fts3PendingTermsFlush(Fts3Table *); void sqlite3Fts3PendingTermsClear(Fts3Table *); int sqlite3Fts3Optimize(Fts3Table *); int sqlite3Fts3SegReaderNew(Fts3Table *,int, sqlite3_int64, sqlite3_int64, sqlite3_int64, const char *, int, Fts3SegReader**); | | | 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 | /* fts3_write.c */ int sqlite3Fts3UpdateMethod(sqlite3_vtab*,int,sqlite3_value**,sqlite3_int64*); int sqlite3Fts3PendingTermsFlush(Fts3Table *); void sqlite3Fts3PendingTermsClear(Fts3Table *); int sqlite3Fts3Optimize(Fts3Table *); int sqlite3Fts3SegReaderNew(Fts3Table *,int, sqlite3_int64, sqlite3_int64, sqlite3_int64, const char *, int, Fts3SegReader**); void sqlite3Fts3SegReaderFree(Fts3Table *, Fts3SegReader *); int sqlite3Fts3SegReaderIterate( Fts3Table *, Fts3SegReader **, int, Fts3SegFilter *, int (*)(Fts3Table *, void *, char *, int, char *, int), void * ); int sqlite3Fts3ReadBlock(Fts3Table*, sqlite3_int64, char const**, int*); int sqlite3Fts3AllSegdirs(Fts3Table*, sqlite3_stmt **); |
︙ | ︙ |
Changes to ext/fts3/fts3_write.c.
︙ | ︙ | |||
775 776 777 778 779 780 781 | } } /* ** Free all allocations associated with the iterator passed as the first ** argument. */ | | > > | > > | 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 | } } /* ** Free all allocations associated with the iterator passed as the first ** argument. */ void sqlite3Fts3SegReaderFree(Fts3Table *p, Fts3SegReader *pReader){ if( pReader ){ if( pReader->pStmt ){ assert( p->nLeavesStmt<p->nLeavesTotal ); sqlite3_reset(pReader->pStmt); p->aLeavesStmt[p->nLeavesStmt++] = pReader->pStmt; } sqlite3_free(pReader->zTerm); sqlite3_free(pReader); } } int sqlite3Fts3SegReaderNew( Fts3Table *p, /* Virtual table handle */ |
︙ | ︙ | |||
816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 | if( nExtra ){ /* The entire segment is stored in the root node. */ pReader->aNode = (char *)&pReader[1]; pReader->nNode = nRoot; memcpy(pReader->aNode, zRoot, nRoot); }else{ if( !p->zSelectLeaves ){ p->zSelectLeaves = sqlite3_mprintf( "SELECT block FROM %Q.'%q_segments' WHERE blockid BETWEEN ? AND ? " "ORDER BY blockid", p->zDb, p->zName ); if( !p->zSelectLeaves ){ rc = SQLITE_NOMEM; goto finished; } } | > > > > > > > > > > > > > > | | | > > > > | | 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 | if( nExtra ){ /* The entire segment is stored in the root node. */ pReader->aNode = (char *)&pReader[1]; pReader->nNode = nRoot; memcpy(pReader->aNode, zRoot, nRoot); }else{ sqlite3_stmt *pStmt; if( !p->zSelectLeaves ){ p->zSelectLeaves = sqlite3_mprintf( "SELECT block FROM %Q.'%q_segments' WHERE blockid BETWEEN ? AND ? " "ORDER BY blockid", p->zDb, p->zName ); if( !p->zSelectLeaves ){ rc = SQLITE_NOMEM; goto finished; } } if( p->nLeavesStmt==0 ){ if( p->nLeavesTotal==p->nLeavesAlloc ){ int nNew = p->nLeavesAlloc + 16; sqlite3_stmt **aNew = (sqlite3_stmt **)sqlite3_realloc( p->aLeavesStmt, nNew*sizeof(sqlite3_stmt *) ); if( !aNew ){ rc = SQLITE_NOMEM; goto finished; } p->nLeavesAlloc = nNew; p->aLeavesStmt = aNew; } rc = sqlite3_prepare_v2(p->db, p->zSelectLeaves, -1, &pReader->pStmt, 0); if( rc!=SQLITE_OK ){ goto finished; } p->nLeavesTotal++; }else{ pReader->pStmt = p->aLeavesStmt[--p->nLeavesStmt]; } sqlite3_bind_int64(pReader->pStmt, 1, iStartLeaf); sqlite3_bind_int64(pReader->pStmt, 2, iEndLeaf); } rc = fts3SegReaderNext(pReader); finished: if( rc==SQLITE_OK ){ *ppReader = pReader; }else{ sqlite3Fts3SegReaderFree(p, pReader); } return rc; } /* ** The second argument to this function is expected to be a statement of |
︙ | ︙ | |||
1787 1788 1789 1790 1791 1792 1793 | rc = fts3SegWriterFlush(p, pWriter, iNewLevel, iIdx); } finished: fts3SegWriterFree(pWriter); if( apSegment ){ for(i=0; i<nSegment; i++){ | | | 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 | rc = fts3SegWriterFlush(p, pWriter, iNewLevel, iIdx); } finished: fts3SegWriterFree(pWriter); if( apSegment ){ for(i=0; i<nSegment; i++){ sqlite3Fts3SegReaderFree(p, apSegment[i]); } sqlite3_free(apSegment); } sqlite3_reset(pStmt); return rc; } |
︙ | ︙ |