Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Make comments and variable naming more consistent WRT rowid versus docid/blockid. This should have no code impact. (CVS 4281) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
76f1e18ebc25d692f122784e87d20299 |
User & Date: | shess 2007-08-23 20:28:49.000 |
Context
2007-08-24
| ||
03:51 | The win32 driver compiles but does not yet work well. Many bugs fixed. (CVS 4282) (check-in: 3a68fcddfa user: drh tags: trunk) | |
2007-08-23
| ||
20:28 | Make comments and variable naming more consistent WRT rowid versus docid/blockid. This should have no code impact. (CVS 4281) (check-in: 76f1e18ebc user: shess tags: trunk) | |
20:23 | Fix fts3 to not have the VACUUM bug from fts2. %_content.docid is an alias to fix the rowid for documents, %_segments.blockid is an alias to fix the rowid for segment blocks. Unit test for the problem. (CVS 4280) (check-in: 6eb2d74a8c user: shess tags: trunk) | |
Changes
Changes to ext/fts3/fts3.c.
︙ | ︙ | |||
1737 1738 1739 1740 1741 1742 1743 | char *zSnippet; /* Snippet text */ int nSnippet; /* strlen(zSnippet) */ } Snippet; typedef enum QueryType { QUERY_GENERIC, /* table scan */ | | | 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 | char *zSnippet; /* Snippet text */ int nSnippet; /* strlen(zSnippet) */ } Snippet; typedef enum QueryType { QUERY_GENERIC, /* table scan */ QUERY_DOCID, /* lookup by docid */ QUERY_FULLTEXT /* QUERY_FULLTEXT + [i] is a full-text search for column i*/ } QueryType; typedef enum fulltext_statement { CONTENT_INSERT_STMT, CONTENT_SELECT_STMT, CONTENT_UPDATE_STMT, |
︙ | ︙ | |||
1973 1974 1975 1976 1977 1978 1979 | if( rc!=SQLITE_OK ) return rc; } *ppStmt = v->pLeafSelectStmts[idx]; return SQLITE_OK; } | | > > > | | | | | | | | | 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 | if( rc!=SQLITE_OK ) return rc; } *ppStmt = v->pLeafSelectStmts[idx]; return SQLITE_OK; } /* insert into %_content (docid, ...) values ([docid], [pValues]) ** If the docid contains SQL NULL, then a unique docid will be ** generated. */ static int content_insert(fulltext_vtab *v, sqlite3_value *docid, sqlite3_value **pValues){ sqlite3_stmt *s; int i; int rc = sql_get_statement(v, CONTENT_INSERT_STMT, &s); if( rc!=SQLITE_OK ) return rc; rc = sqlite3_bind_value(s, 1, docid); if( rc!=SQLITE_OK ) return rc; for(i=0; i<v->nColumn; ++i){ rc = sqlite3_bind_value(s, 2+i, pValues[i]); if( rc!=SQLITE_OK ) return rc; } return sql_single_step(s); } /* update %_content set col0 = pValues[0], col1 = pValues[1], ... * where docid = [iDocid] */ static int content_update(fulltext_vtab *v, sqlite3_value **pValues, sqlite_int64 iDocid){ sqlite3_stmt *s; int i; int rc = sql_get_statement(v, CONTENT_UPDATE_STMT, &s); if( rc!=SQLITE_OK ) return rc; for(i=0; i<v->nColumn; ++i){ rc = sqlite3_bind_value(s, 1+i, pValues[i]); if( rc!=SQLITE_OK ) return rc; } rc = sqlite3_bind_int64(s, 1+v->nColumn, iDocid); if( rc!=SQLITE_OK ) return rc; return sql_single_step(s); } static void freeStringArray(int nString, const char **pString){ int i; for (i=0 ; i < nString ; ++i) { if( pString[i]!=NULL ) free((void *) pString[i]); } free((void *) pString); } /* select * from %_content where docid = [iDocid] * The caller must delete the returned array and all strings in it. * null fields will be NULL in the returned array. * * TODO: Perhaps we should return pointer/length strings here for consistency * with other code which uses pointer/length. */ static int content_select(fulltext_vtab *v, sqlite_int64 iDocid, const char ***pValues){ sqlite3_stmt *s; const char **values; int i; int rc; *pValues = NULL; rc = sql_get_statement(v, CONTENT_SELECT_STMT, &s); if( rc!=SQLITE_OK ) return rc; rc = sqlite3_bind_int64(s, 1, iDocid); if( rc!=SQLITE_OK ) return rc; rc = sqlite3_step(s); if( rc!=SQLITE_ROW ) return rc; values = (const char **) malloc(v->nColumn * sizeof(const char *)); for(i=0; i<v->nColumn; ++i){ |
︙ | ︙ | |||
2066 2067 2068 2069 2070 2071 2072 | return SQLITE_OK; } freeStringArray(v->nColumn, values); return rc; } | | | | | > | | 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 | return SQLITE_OK; } freeStringArray(v->nColumn, values); return rc; } /* delete from %_content where docid = [iDocid ] */ static int content_delete(fulltext_vtab *v, sqlite_int64 iDocid){ sqlite3_stmt *s; int rc = sql_get_statement(v, CONTENT_DELETE_STMT, &s); if( rc!=SQLITE_OK ) return rc; rc = sqlite3_bind_int64(s, 1, iDocid); if( rc!=SQLITE_OK ) return rc; return sql_single_step(s); } /* insert into %_segments values ([pData]) ** returns assigned blockid in *piBlockid */ static int block_insert(fulltext_vtab *v, const char *pData, int nData, sqlite_int64 *piBlockid){ sqlite3_stmt *s; int rc = sql_get_statement(v, BLOCK_INSERT_STMT, &s); if( rc!=SQLITE_OK ) return rc; rc = sqlite3_bind_blob(s, 1, pData, nData, SQLITE_STATIC); if( rc!=SQLITE_OK ) return rc; rc = sqlite3_step(s); if( rc==SQLITE_ROW ) return SQLITE_ERROR; if( rc!=SQLITE_DONE ) return rc; /* blockid column is an alias for rowid. */ *piBlockid = sqlite3_last_insert_rowid(v->db); return SQLITE_OK; } /* delete from %_segments ** where blockid between [iStartBlockid] and [iEndBlockid] ** ** Deletes the range of blocks, inclusive, used to delete the blocks ** which form a segment. */ static int block_delete(fulltext_vtab *v, sqlite_int64 iStartBlockid, sqlite_int64 iEndBlockid){ sqlite3_stmt *s; |
︙ | ︙ | |||
2799 2800 2801 2802 2803 2804 2805 | rc = constructVtab(db, (fts3Hash *)pAux, &spec, ppVTab, pzErr); clearTableSpec(&spec); return rc; } /* The %_content table holds the text of each document, with | | | 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 | rc = constructVtab(db, (fts3Hash *)pAux, &spec, ppVTab, pzErr); clearTableSpec(&spec); return rc; } /* The %_content table holds the text of each document, with ** the docid column exposed as the SQLite rowid for the table. */ /* TODO(shess) This comment needs elaboration to match the updated ** code. Work it into the top-of-file comment at that time. */ static int fulltextCreate(sqlite3 *db, void *pAux, int argc, const char * const *argv, sqlite3_vtab **ppVTab, char **pzErr){ |
︙ | ︙ | |||
2862 2863 2864 2865 2866 2867 2868 | 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 ){ | | | | | 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 | 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_DOCID; /* lookup by docid */ TRACE(("FTS3 QUERY_DOCID\n")); } else if( pConstraint->iColumn>=0 && pConstraint->op==SQLITE_INDEX_CONSTRAINT_MATCH ){ /* full-text search */ pInfo->idxNum = QUERY_FULLTEXT + pConstraint->iColumn; TRACE(("FTS3 QUERY_FULLTEXT %d\n", pConstraint->iColumn)); } else continue; pInfo->aConstraintUsage[i].argvIndex = 1; pInfo->aConstraintUsage[i].omit = 1; /* An arbitrary value for now. * TODO: Perhaps docid matches should be considered cheaper than * full-text searches. */ pInfo->estimatedCost = 1.0; return SQLITE_OK; } } pInfo->idxNum = QUERY_GENERIC; |
︙ | ︙ | |||
3657 3658 3659 3660 3661 3662 3663 | ** This is the xFilter interface for the virtual table. See ** the virtual table xFilter method documentation for additional ** information. ** ** If idxNum==QUERY_GENERIC then do a full table scan against ** the %_content table. ** | | | 3661 3662 3663 3664 3665 3666 3667 3668 3669 3670 3671 3672 3673 3674 3675 | ** This is the xFilter interface for the virtual table. See ** the virtual table xFilter method documentation for additional ** information. ** ** If idxNum==QUERY_GENERIC then do a full table scan against ** the %_content table. ** ** If idxNum==QUERY_DOCID then do a docid lookup for a single entry ** in the %_content table. ** ** If idxNum>=QUERY_FULLTEXT then use the full text index. The ** column on the left-hand side of the MATCH operator is column ** number idxNum-QUERY_FULLTEXT, 0 indexed. argv[0] is the right-hand ** side of the MATCH operator. */ |
︙ | ︙ | |||
3697 3698 3699 3700 3701 3702 3703 | if( rc!=SQLITE_OK ) return rc; c->iCursorType = idxNum; switch( idxNum ){ case QUERY_GENERIC: break; | | | 3701 3702 3703 3704 3705 3706 3707 3708 3709 3710 3711 3712 3713 3714 3715 | if( rc!=SQLITE_OK ) return rc; c->iCursorType = idxNum; switch( idxNum ){ case QUERY_GENERIC: break; case QUERY_DOCID: rc = sqlite3_bind_int64(c->pStmt, 1, sqlite3_value_int64(argv[0])); if( rc!=SQLITE_OK ) return rc; break; default: /* full-text search */ { const char *zQuery = (const char *)sqlite3_value_text(argv[0]); |
︙ | ︙ | |||
3760 3761 3762 3763 3764 3765 3766 | */ sqlite3_result_blob(pContext, &c, sizeof(c), SQLITE_TRANSIENT); } return SQLITE_OK; } /* This is the xRowid method. The SQLite core calls this routine to | | > | 3764 3765 3766 3767 3768 3769 3770 3771 3772 3773 3774 3775 3776 3777 3778 3779 | */ sqlite3_result_blob(pContext, &c, sizeof(c), SQLITE_TRANSIENT); } return SQLITE_OK; } /* 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 fulltextRowid(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){ fulltext_cursor *c = (fulltext_cursor *) pCursor; *pRowid = sqlite3_column_int64(c->pStmt, 0); return SQLITE_OK; |
︙ | ︙ | |||
3830 3831 3832 3833 3834 3835 3836 | ** not durable. *ponder* */ pTokenizer->pModule->xClose(pCursor); return rc; } /* Add doclists for all terms in [pValues] to pendingTerms table. */ | | | | | | | | | | > | | | | 3835 3836 3837 3838 3839 3840 3841 3842 3843 3844 3845 3846 3847 3848 3849 3850 3851 3852 3853 3854 3855 3856 3857 3858 3859 3860 3861 3862 3863 3864 3865 3866 3867 3868 3869 3870 3871 3872 3873 3874 3875 3876 3877 3878 3879 3880 3881 3882 3883 3884 3885 3886 3887 3888 3889 3890 3891 3892 3893 3894 3895 3896 3897 3898 3899 3900 | ** not durable. *ponder* */ pTokenizer->pModule->xClose(pCursor); return rc; } /* Add doclists for all terms in [pValues] to pendingTerms table. */ static int insertTerms(fulltext_vtab *v, sqlite_int64 iDocid, sqlite3_value **pValues){ int i; for(i = 0; i < v->nColumn ; ++i){ char *zText = (char*)sqlite3_value_text(pValues[i]); int rc = buildTerms(v, iDocid, zText, i); if( rc!=SQLITE_OK ) return rc; } return SQLITE_OK; } /* Add empty doclists for all terms in the given row's content to ** pendingTerms. */ static int deleteTerms(fulltext_vtab *v, sqlite_int64 iDocid){ const char **pValues; int i, rc; /* TODO(shess) Should we allow such tables at all? */ if( DL_DEFAULT==DL_DOCIDS ) return SQLITE_ERROR; rc = content_select(v, iDocid, &pValues); if( rc!=SQLITE_OK ) return rc; for(i = 0 ; i < v->nColumn; ++i) { rc = buildTerms(v, iDocid, pValues[i], -1); if( rc!=SQLITE_OK ) break; } freeStringArray(v->nColumn, pValues); return SQLITE_OK; } /* TODO(shess) Refactor the code to remove this forward decl. */ static int initPendingTerms(fulltext_vtab *v, sqlite_int64 iDocid); /* Insert a row into the %_content table; set *piDocid to be the ID of the ** new row. Add doclists for terms to pendingTerms. */ static int index_insert(fulltext_vtab *v, sqlite3_value *pRequestDocid, sqlite3_value **pValues, sqlite_int64 *piDocid){ int rc; rc = content_insert(v, pRequestDocid, pValues); /* execute an SQL INSERT */ if( rc!=SQLITE_OK ) return rc; /* docid column is an alias for rowid. */ *piDocid = sqlite3_last_insert_rowid(v->db); rc = initPendingTerms(v, *piDocid); if( rc!=SQLITE_OK ) return rc; return insertTerms(v, *piDocid, pValues); } /* Delete a row from the %_content table; add empty doclists for terms ** to pendingTerms. */ static int index_delete(fulltext_vtab *v, sqlite_int64 iRow){ int rc = initPendingTerms(v, iRow); |
︙ | ︙ | |||
5649 5650 5651 5652 5653 5654 5655 | v->iPrevDocid = iDocid; return SQLITE_OK; } /* This function implements the xUpdate callback; it's the top-level entry * point for inserting, deleting or updating a row in a full-text table. */ static int fulltextUpdate(sqlite3_vtab *pVtab, int nArg, sqlite3_value **ppArg, | | | 5655 5656 5657 5658 5659 5660 5661 5662 5663 5664 5665 5666 5667 5668 5669 | v->iPrevDocid = iDocid; return SQLITE_OK; } /* This function implements the xUpdate callback; it's the top-level entry * point for inserting, deleting or updating a row in a full-text table. */ static int fulltextUpdate(sqlite3_vtab *pVtab, int nArg, sqlite3_value **ppArg, sqlite_int64 *pRowid){ fulltext_vtab *v = (fulltext_vtab *) pVtab; int rc; TRACE(("FTS3 Update %p\n", pVtab)); if( nArg<2 ){ rc = index_delete(v, sqlite3_value_int64(ppArg[0])); |
︙ | ︙ |