OLD | NEW |
1 /* | 1 /* |
2 ** 2006 Oct 10 | 2 ** 2006 Oct 10 |
3 ** | 3 ** |
4 ** The author disclaims copyright to this source code. In place of | 4 ** The author disclaims copyright to this source code. In place of |
5 ** a legal notice, here is a blessing: | 5 ** a legal notice, here is a blessing: |
6 ** | 6 ** |
7 ** May you do good and not evil. | 7 ** May you do good and not evil. |
8 ** May you find forgiveness for yourself and forgive others. | 8 ** May you find forgiveness for yourself and forgive others. |
9 ** May you share freely, never taking more than you give. | 9 ** May you share freely, never taking more than you give. |
10 ** | 10 ** |
(...skipping 475 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
486 ** The xDisconnect() virtual table method. | 486 ** The xDisconnect() virtual table method. |
487 */ | 487 */ |
488 static int fts3DisconnectMethod(sqlite3_vtab *pVtab){ | 488 static int fts3DisconnectMethod(sqlite3_vtab *pVtab){ |
489 Fts3Table *p = (Fts3Table *)pVtab; | 489 Fts3Table *p = (Fts3Table *)pVtab; |
490 int i; | 490 int i; |
491 | 491 |
492 assert( p->nPendingData==0 ); | 492 assert( p->nPendingData==0 ); |
493 assert( p->pSegments==0 ); | 493 assert( p->pSegments==0 ); |
494 | 494 |
495 /* Free any prepared statements held */ | 495 /* Free any prepared statements held */ |
| 496 sqlite3_finalize(p->pSeekStmt); |
496 for(i=0; i<SizeofArray(p->aStmt); i++){ | 497 for(i=0; i<SizeofArray(p->aStmt); i++){ |
497 sqlite3_finalize(p->aStmt[i]); | 498 sqlite3_finalize(p->aStmt[i]); |
498 } | 499 } |
499 sqlite3_free(p->zSegmentsTbl); | 500 sqlite3_free(p->zSegmentsTbl); |
500 sqlite3_free(p->zReadExprlist); | 501 sqlite3_free(p->zReadExprlist); |
501 sqlite3_free(p->zWriteExprlist); | 502 sqlite3_free(p->zWriteExprlist); |
502 sqlite3_free(p->zContentTbl); | 503 sqlite3_free(p->zContentTbl); |
503 sqlite3_free(p->zLanguageid); | 504 sqlite3_free(p->zLanguageid); |
504 | 505 |
505 /* Invoke the tokenizer destructor to free the tokenizer. */ | 506 /* Invoke the tokenizer destructor to free the tokenizer. */ |
(...skipping 851 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1357 goto fts3_init_out; | 1358 goto fts3_init_out; |
1358 } | 1359 } |
1359 memset(p, 0, nByte); | 1360 memset(p, 0, nByte); |
1360 p->db = db; | 1361 p->db = db; |
1361 p->nColumn = nCol; | 1362 p->nColumn = nCol; |
1362 p->nPendingData = 0; | 1363 p->nPendingData = 0; |
1363 p->azColumn = (char **)&p[1]; | 1364 p->azColumn = (char **)&p[1]; |
1364 p->pTokenizer = pTokenizer; | 1365 p->pTokenizer = pTokenizer; |
1365 p->nMaxPendingData = FTS3_MAX_PENDING_DATA; | 1366 p->nMaxPendingData = FTS3_MAX_PENDING_DATA; |
1366 p->bHasDocsize = (isFts4 && bNoDocsize==0); | 1367 p->bHasDocsize = (isFts4 && bNoDocsize==0); |
1367 p->bHasStat = isFts4; | 1368 p->bHasStat = (u8)isFts4; |
1368 p->bFts4 = isFts4; | 1369 p->bFts4 = (u8)isFts4; |
1369 p->bDescIdx = bDescIdx; | 1370 p->bDescIdx = (u8)bDescIdx; |
1370 p->nAutoincrmerge = 0xff; /* 0xff means setting unknown */ | 1371 p->nAutoincrmerge = 0xff; /* 0xff means setting unknown */ |
1371 p->zContentTbl = zContent; | 1372 p->zContentTbl = zContent; |
1372 p->zLanguageid = zLanguageid; | 1373 p->zLanguageid = zLanguageid; |
1373 zContent = 0; | 1374 zContent = 0; |
1374 zLanguageid = 0; | 1375 zLanguageid = 0; |
1375 TESTONLY( p->inTransaction = -1 ); | 1376 TESTONLY( p->inTransaction = -1 ); |
1376 TESTONLY( p->mxSavepoint = -1 ); | 1377 TESTONLY( p->mxSavepoint = -1 ); |
1377 | 1378 |
1378 p->aIndex = (struct Fts3Index *)&p->azColumn[nCol]; | 1379 p->aIndex = (struct Fts3Index *)&p->azColumn[nCol]; |
1379 memcpy(p->aIndex, aIndex, sizeof(struct Fts3Index) * nIndex); | 1380 memcpy(p->aIndex, aIndex, sizeof(struct Fts3Index) * nIndex); |
(...skipping 295 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1675 */ | 1676 */ |
1676 *ppCsr = pCsr = (sqlite3_vtab_cursor *)sqlite3_malloc(sizeof(Fts3Cursor)); | 1677 *ppCsr = pCsr = (sqlite3_vtab_cursor *)sqlite3_malloc(sizeof(Fts3Cursor)); |
1677 if( !pCsr ){ | 1678 if( !pCsr ){ |
1678 return SQLITE_NOMEM; | 1679 return SQLITE_NOMEM; |
1679 } | 1680 } |
1680 memset(pCsr, 0, sizeof(Fts3Cursor)); | 1681 memset(pCsr, 0, sizeof(Fts3Cursor)); |
1681 return SQLITE_OK; | 1682 return SQLITE_OK; |
1682 } | 1683 } |
1683 | 1684 |
1684 /* | 1685 /* |
| 1686 ** Finalize the statement handle at pCsr->pStmt. |
| 1687 ** |
| 1688 ** Or, if that statement handle is one created by fts3CursorSeekStmt(), |
| 1689 ** and the Fts3Table.pSeekStmt slot is currently NULL, save the statement |
| 1690 ** pointer there instead of finalizing it. |
| 1691 */ |
| 1692 static void fts3CursorFinalizeStmt(Fts3Cursor *pCsr){ |
| 1693 if( pCsr->bSeekStmt ){ |
| 1694 Fts3Table *p = (Fts3Table *)pCsr->base.pVtab; |
| 1695 if( p->pSeekStmt==0 ){ |
| 1696 p->pSeekStmt = pCsr->pStmt; |
| 1697 sqlite3_reset(pCsr->pStmt); |
| 1698 pCsr->pStmt = 0; |
| 1699 } |
| 1700 pCsr->bSeekStmt = 0; |
| 1701 } |
| 1702 sqlite3_finalize(pCsr->pStmt); |
| 1703 } |
| 1704 |
| 1705 /* |
1685 ** Close the cursor. For additional information see the documentation | 1706 ** Close the cursor. For additional information see the documentation |
1686 ** on the xClose method of the virtual table interface. | 1707 ** on the xClose method of the virtual table interface. |
1687 */ | 1708 */ |
1688 static int fts3CloseMethod(sqlite3_vtab_cursor *pCursor){ | 1709 static int fts3CloseMethod(sqlite3_vtab_cursor *pCursor){ |
1689 Fts3Cursor *pCsr = (Fts3Cursor *)pCursor; | 1710 Fts3Cursor *pCsr = (Fts3Cursor *)pCursor; |
1690 assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 ); | 1711 assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 ); |
1691 sqlite3_finalize(pCsr->pStmt); | 1712 fts3CursorFinalizeStmt(pCsr); |
1692 sqlite3Fts3ExprFree(pCsr->pExpr); | 1713 sqlite3Fts3ExprFree(pCsr->pExpr); |
1693 sqlite3Fts3FreeDeferredTokens(pCsr); | 1714 sqlite3Fts3FreeDeferredTokens(pCsr); |
1694 sqlite3_free(pCsr->aDoclist); | 1715 sqlite3_free(pCsr->aDoclist); |
1695 sqlite3Fts3MIBufferFree(pCsr->pMIBuffer); | 1716 sqlite3Fts3MIBufferFree(pCsr->pMIBuffer); |
1696 assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 ); | 1717 assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 ); |
1697 sqlite3_free(pCsr); | 1718 sqlite3_free(pCsr); |
1698 return SQLITE_OK; | 1719 return SQLITE_OK; |
1699 } | 1720 } |
1700 | 1721 |
1701 /* | 1722 /* |
1702 ** If pCsr->pStmt has not been prepared (i.e. if pCsr->pStmt==0), then | 1723 ** If pCsr->pStmt has not been prepared (i.e. if pCsr->pStmt==0), then |
1703 ** compose and prepare an SQL statement of the form: | 1724 ** compose and prepare an SQL statement of the form: |
1704 ** | 1725 ** |
1705 ** "SELECT <columns> FROM %_content WHERE rowid = ?" | 1726 ** "SELECT <columns> FROM %_content WHERE rowid = ?" |
1706 ** | 1727 ** |
1707 ** (or the equivalent for a content=xxx table) and set pCsr->pStmt to | 1728 ** (or the equivalent for a content=xxx table) and set pCsr->pStmt to |
1708 ** it. If an error occurs, return an SQLite error code. | 1729 ** it. If an error occurs, return an SQLite error code. |
1709 ** | |
1710 ** Otherwise, set *ppStmt to point to pCsr->pStmt and return SQLITE_OK. | |
1711 */ | 1730 */ |
1712 static int fts3CursorSeekStmt(Fts3Cursor *pCsr, sqlite3_stmt **ppStmt){ | 1731 static int fts3CursorSeekStmt(Fts3Cursor *pCsr){ |
1713 int rc = SQLITE_OK; | 1732 int rc = SQLITE_OK; |
1714 if( pCsr->pStmt==0 ){ | 1733 if( pCsr->pStmt==0 ){ |
1715 Fts3Table *p = (Fts3Table *)pCsr->base.pVtab; | 1734 Fts3Table *p = (Fts3Table *)pCsr->base.pVtab; |
1716 char *zSql; | 1735 char *zSql; |
1717 zSql = sqlite3_mprintf("SELECT %s WHERE rowid = ?", p->zReadExprlist); | 1736 if( p->pSeekStmt ){ |
1718 if( !zSql ) return SQLITE_NOMEM; | 1737 pCsr->pStmt = p->pSeekStmt; |
1719 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pCsr->pStmt, 0); | 1738 p->pSeekStmt = 0; |
1720 sqlite3_free(zSql); | 1739 }else{ |
| 1740 zSql = sqlite3_mprintf("SELECT %s WHERE rowid = ?", p->zReadExprlist); |
| 1741 if( !zSql ) return SQLITE_NOMEM; |
| 1742 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pCsr->pStmt, 0); |
| 1743 sqlite3_free(zSql); |
| 1744 } |
| 1745 if( rc==SQLITE_OK ) pCsr->bSeekStmt = 1; |
1721 } | 1746 } |
1722 *ppStmt = pCsr->pStmt; | |
1723 return rc; | 1747 return rc; |
1724 } | 1748 } |
1725 | 1749 |
1726 /* | 1750 /* |
1727 ** Position the pCsr->pStmt statement so that it is on the row | 1751 ** Position the pCsr->pStmt statement so that it is on the row |
1728 ** of the %_content table that contains the last match. Return | 1752 ** of the %_content table that contains the last match. Return |
1729 ** SQLITE_OK on success. | 1753 ** SQLITE_OK on success. |
1730 */ | 1754 */ |
1731 static int fts3CursorSeek(sqlite3_context *pContext, Fts3Cursor *pCsr){ | 1755 static int fts3CursorSeek(sqlite3_context *pContext, Fts3Cursor *pCsr){ |
1732 int rc = SQLITE_OK; | 1756 int rc = SQLITE_OK; |
1733 if( pCsr->isRequireSeek ){ | 1757 if( pCsr->isRequireSeek ){ |
1734 sqlite3_stmt *pStmt = 0; | 1758 rc = fts3CursorSeekStmt(pCsr); |
1735 | |
1736 rc = fts3CursorSeekStmt(pCsr, &pStmt); | |
1737 if( rc==SQLITE_OK ){ | 1759 if( rc==SQLITE_OK ){ |
1738 sqlite3_bind_int64(pCsr->pStmt, 1, pCsr->iPrevId); | 1760 sqlite3_bind_int64(pCsr->pStmt, 1, pCsr->iPrevId); |
1739 pCsr->isRequireSeek = 0; | 1761 pCsr->isRequireSeek = 0; |
1740 if( SQLITE_ROW==sqlite3_step(pCsr->pStmt) ){ | 1762 if( SQLITE_ROW==sqlite3_step(pCsr->pStmt) ){ |
1741 return SQLITE_OK; | 1763 return SQLITE_OK; |
1742 }else{ | 1764 }else{ |
1743 rc = sqlite3_reset(pCsr->pStmt); | 1765 rc = sqlite3_reset(pCsr->pStmt); |
1744 if( rc==SQLITE_OK && ((Fts3Table *)pCsr->base.pVtab)->zContentTbl==0 ){ | 1766 if( rc==SQLITE_OK && ((Fts3Table *)pCsr->base.pVtab)->zContentTbl==0 ){ |
1745 /* If no row was found and no error has occurred, then the %_content | 1767 /* If no row was found and no error has occurred, then the %_content |
1746 ** table is missing a row that is present in the full-text index. | 1768 ** table is missing a row that is present in the full-text index. |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1822 isFirstTerm = 0; | 1844 isFirstTerm = 0; |
1823 zCsr += fts3GetVarint32(zCsr, &nSuffix); | 1845 zCsr += fts3GetVarint32(zCsr, &nSuffix); |
1824 | 1846 |
1825 /* NOTE(shess): Previous code checked for negative nPrefix and | 1847 /* NOTE(shess): Previous code checked for negative nPrefix and |
1826 ** nSuffix and suffix overrunning zEnd. Additionally corrupt if | 1848 ** nSuffix and suffix overrunning zEnd. Additionally corrupt if |
1827 ** the prefix is longer than the previous term, or if the suffix | 1849 ** the prefix is longer than the previous term, or if the suffix |
1828 ** causes overflow. | 1850 ** causes overflow. |
1829 */ | 1851 */ |
1830 if( nPrefix<0 || nSuffix<0 /* || nPrefix>nBuffer */ | 1852 if( nPrefix<0 || nSuffix<0 /* || nPrefix>nBuffer */ |
1831 || &zCsr[nSuffix]<zCsr || &zCsr[nSuffix]>zEnd ){ | 1853 || &zCsr[nSuffix]<zCsr || &zCsr[nSuffix]>zEnd ){ |
1832 rc = SQLITE_CORRUPT; | 1854 rc = FTS_CORRUPT_VTAB; |
1833 goto finish_scan; | 1855 goto finish_scan; |
1834 } | 1856 } |
1835 if( nPrefix+nSuffix>nAlloc ){ | 1857 if( nPrefix+nSuffix>nAlloc ){ |
1836 char *zNew; | 1858 char *zNew; |
1837 nAlloc = (nPrefix+nSuffix) * 2; | 1859 nAlloc = (nPrefix+nSuffix) * 2; |
1838 zNew = (char *)sqlite3_realloc(zBuffer, nAlloc); | 1860 zNew = (char *)sqlite3_realloc(zBuffer, nAlloc); |
1839 if( !zNew ){ | 1861 if( !zNew ){ |
1840 rc = SQLITE_NOMEM; | 1862 rc = SQLITE_NOMEM; |
1841 goto finish_scan; | 1863 goto finish_scan; |
1842 } | 1864 } |
(...skipping 1347 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3190 | 3212 |
3191 /* Collect arguments into local variables */ | 3213 /* Collect arguments into local variables */ |
3192 iIdx = 0; | 3214 iIdx = 0; |
3193 if( eSearch!=FTS3_FULLSCAN_SEARCH ) pCons = apVal[iIdx++]; | 3215 if( eSearch!=FTS3_FULLSCAN_SEARCH ) pCons = apVal[iIdx++]; |
3194 if( idxNum & FTS3_HAVE_LANGID ) pLangid = apVal[iIdx++]; | 3216 if( idxNum & FTS3_HAVE_LANGID ) pLangid = apVal[iIdx++]; |
3195 if( idxNum & FTS3_HAVE_DOCID_GE ) pDocidGe = apVal[iIdx++]; | 3217 if( idxNum & FTS3_HAVE_DOCID_GE ) pDocidGe = apVal[iIdx++]; |
3196 if( idxNum & FTS3_HAVE_DOCID_LE ) pDocidLe = apVal[iIdx++]; | 3218 if( idxNum & FTS3_HAVE_DOCID_LE ) pDocidLe = apVal[iIdx++]; |
3197 assert( iIdx==nVal ); | 3219 assert( iIdx==nVal ); |
3198 | 3220 |
3199 /* In case the cursor has been used before, clear it now. */ | 3221 /* In case the cursor has been used before, clear it now. */ |
3200 sqlite3_finalize(pCsr->pStmt); | 3222 fts3CursorFinalizeStmt(pCsr); |
3201 sqlite3_free(pCsr->aDoclist); | 3223 sqlite3_free(pCsr->aDoclist); |
3202 sqlite3Fts3MIBufferFree(pCsr->pMIBuffer); | 3224 sqlite3Fts3MIBufferFree(pCsr->pMIBuffer); |
3203 sqlite3Fts3ExprFree(pCsr->pExpr); | 3225 sqlite3Fts3ExprFree(pCsr->pExpr); |
3204 memset(&pCursor[1], 0, sizeof(Fts3Cursor)-sizeof(sqlite3_vtab_cursor)); | 3226 memset(&pCursor[1], 0, sizeof(Fts3Cursor)-sizeof(sqlite3_vtab_cursor)); |
3205 | 3227 |
3206 /* Set the lower and upper bounds on docids to return */ | 3228 /* Set the lower and upper bounds on docids to return */ |
3207 pCsr->iMinDocid = fts3DocidRange(pDocidGe, SMALLEST_INT64); | 3229 pCsr->iMinDocid = fts3DocidRange(pDocidGe, SMALLEST_INT64); |
3208 pCsr->iMaxDocid = fts3DocidRange(pDocidLe, LARGEST_INT64); | 3230 pCsr->iMaxDocid = fts3DocidRange(pDocidLe, LARGEST_INT64); |
3209 | 3231 |
3210 if( idxStr ){ | 3232 if( idxStr ){ |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3258 p->zReadExprlist, (pCsr->bDesc ? "DESC" : "ASC") | 3280 p->zReadExprlist, (pCsr->bDesc ? "DESC" : "ASC") |
3259 ); | 3281 ); |
3260 } | 3282 } |
3261 if( zSql ){ | 3283 if( zSql ){ |
3262 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pCsr->pStmt, 0); | 3284 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pCsr->pStmt, 0); |
3263 sqlite3_free(zSql); | 3285 sqlite3_free(zSql); |
3264 }else{ | 3286 }else{ |
3265 rc = SQLITE_NOMEM; | 3287 rc = SQLITE_NOMEM; |
3266 } | 3288 } |
3267 }else if( eSearch==FTS3_DOCID_SEARCH ){ | 3289 }else if( eSearch==FTS3_DOCID_SEARCH ){ |
3268 rc = fts3CursorSeekStmt(pCsr, &pCsr->pStmt); | 3290 rc = fts3CursorSeekStmt(pCsr); |
3269 if( rc==SQLITE_OK ){ | 3291 if( rc==SQLITE_OK ){ |
3270 rc = sqlite3_bind_value(pCsr->pStmt, 1, pCons); | 3292 rc = sqlite3_bind_value(pCsr->pStmt, 1, pCons); |
3271 } | 3293 } |
3272 } | 3294 } |
3273 if( rc!=SQLITE_OK ) return rc; | 3295 if( rc!=SQLITE_OK ) return rc; |
3274 | 3296 |
3275 return fts3NextMethod(pCursor); | 3297 return fts3NextMethod(pCursor); |
3276 } | 3298 } |
3277 | 3299 |
3278 /* | 3300 /* |
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3422 int rc = SQLITE_OK; | 3444 int rc = SQLITE_OK; |
3423 if( p->bHasStat==2 ){ | 3445 if( p->bHasStat==2 ){ |
3424 const char *zFmt ="SELECT 1 FROM %Q.sqlite_master WHERE tbl_name='%q_stat'"; | 3446 const char *zFmt ="SELECT 1 FROM %Q.sqlite_master WHERE tbl_name='%q_stat'"; |
3425 char *zSql = sqlite3_mprintf(zFmt, p->zDb, p->zName); | 3447 char *zSql = sqlite3_mprintf(zFmt, p->zDb, p->zName); |
3426 if( zSql ){ | 3448 if( zSql ){ |
3427 sqlite3_stmt *pStmt = 0; | 3449 sqlite3_stmt *pStmt = 0; |
3428 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); | 3450 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); |
3429 if( rc==SQLITE_OK ){ | 3451 if( rc==SQLITE_OK ){ |
3430 int bHasStat = (sqlite3_step(pStmt)==SQLITE_ROW); | 3452 int bHasStat = (sqlite3_step(pStmt)==SQLITE_ROW); |
3431 rc = sqlite3_finalize(pStmt); | 3453 rc = sqlite3_finalize(pStmt); |
3432 if( rc==SQLITE_OK ) p->bHasStat = bHasStat; | 3454 if( rc==SQLITE_OK ) p->bHasStat = (u8)bHasStat; |
3433 } | 3455 } |
3434 sqlite3_free(zSql); | 3456 sqlite3_free(zSql); |
3435 }else{ | 3457 }else{ |
3436 rc = SQLITE_NOMEM; | 3458 rc = SQLITE_NOMEM; |
3437 } | 3459 } |
3438 } | 3460 } |
3439 return rc; | 3461 return rc; |
3440 } | 3462 } |
3441 | 3463 |
3442 /* | 3464 /* |
(...skipping 2487 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5930 sqlite3 *db, | 5952 sqlite3 *db, |
5931 char **pzErrMsg, | 5953 char **pzErrMsg, |
5932 const sqlite3_api_routines *pApi | 5954 const sqlite3_api_routines *pApi |
5933 ){ | 5955 ){ |
5934 SQLITE_EXTENSION_INIT2(pApi) | 5956 SQLITE_EXTENSION_INIT2(pApi) |
5935 return sqlite3Fts3Init(db); | 5957 return sqlite3Fts3Init(db); |
5936 } | 5958 } |
5937 #endif | 5959 #endif |
5938 | 5960 |
5939 #endif | 5961 #endif |
OLD | NEW |