OLD | NEW |
1 /* | 1 /* |
2 ** 2009 Oct 23 | 2 ** 2009 Oct 23 |
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 308 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
319 /* 18 */ "INSERT INTO %Q.'%q_content' VALUES(%s)", | 319 /* 18 */ "INSERT INTO %Q.'%q_content' VALUES(%s)", |
320 /* 19 */ "DELETE FROM %Q.'%q_docsize' WHERE docid = ?", | 320 /* 19 */ "DELETE FROM %Q.'%q_docsize' WHERE docid = ?", |
321 /* 20 */ "REPLACE INTO %Q.'%q_docsize' VALUES(?,?)", | 321 /* 20 */ "REPLACE INTO %Q.'%q_docsize' VALUES(?,?)", |
322 /* 21 */ "SELECT size FROM %Q.'%q_docsize' WHERE docid=?", | 322 /* 21 */ "SELECT size FROM %Q.'%q_docsize' WHERE docid=?", |
323 /* 22 */ "SELECT value FROM %Q.'%q_stat' WHERE id=?", | 323 /* 22 */ "SELECT value FROM %Q.'%q_stat' WHERE id=?", |
324 /* 23 */ "REPLACE INTO %Q.'%q_stat' VALUES(?,?)", | 324 /* 23 */ "REPLACE INTO %Q.'%q_stat' VALUES(?,?)", |
325 /* 24 */ "", | 325 /* 24 */ "", |
326 /* 25 */ "", | 326 /* 25 */ "", |
327 | 327 |
328 /* 26 */ "DELETE FROM %Q.'%q_segdir' WHERE level BETWEEN ? AND ?", | 328 /* 26 */ "DELETE FROM %Q.'%q_segdir' WHERE level BETWEEN ? AND ?", |
329 /* 27 */ "SELECT DISTINCT level / (1024 * ?) FROM %Q.'%q_segdir'", | 329 /* 27 */ "SELECT ? UNION SELECT level / (1024 * ?) FROM %Q.'%q_segdir'", |
330 | 330 |
331 /* This statement is used to determine which level to read the input from | 331 /* This statement is used to determine which level to read the input from |
332 ** when performing an incremental merge. It returns the absolute level number | 332 ** when performing an incremental merge. It returns the absolute level number |
333 ** of the oldest level in the db that contains at least ? segments. Or, | 333 ** of the oldest level in the db that contains at least ? segments. Or, |
334 ** if no level in the FTS index contains more than ? segments, the statement | 334 ** if no level in the FTS index contains more than ? segments, the statement |
335 ** returns zero rows. */ | 335 ** returns zero rows. */ |
336 /* 28 */ "SELECT level FROM %Q.'%q_segdir' GROUP BY level HAVING count(*)>=?" | 336 /* 28 */ "SELECT level FROM %Q.'%q_segdir' GROUP BY level HAVING count(*)>=?" |
337 " ORDER BY (level %% 1024) ASC LIMIT 1", | 337 " ORDER BY (level %% 1024) ASC LIMIT 1", |
338 | 338 |
339 /* Estimate the upper limit on the number of leaf nodes in a new segment | 339 /* Estimate the upper limit on the number of leaf nodes in a new segment |
(...skipping 513 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
853 return (rc==SQLITE_DONE ? SQLITE_OK : rc); | 853 return (rc==SQLITE_DONE ? SQLITE_OK : rc); |
854 } | 854 } |
855 | 855 |
856 /* | 856 /* |
857 ** Calling this function indicates that subsequent calls to | 857 ** Calling this function indicates that subsequent calls to |
858 ** fts3PendingTermsAdd() are to add term/position-list pairs for the | 858 ** fts3PendingTermsAdd() are to add term/position-list pairs for the |
859 ** contents of the document with docid iDocid. | 859 ** contents of the document with docid iDocid. |
860 */ | 860 */ |
861 static int fts3PendingTermsDocid( | 861 static int fts3PendingTermsDocid( |
862 Fts3Table *p, /* Full-text table handle */ | 862 Fts3Table *p, /* Full-text table handle */ |
| 863 int bDelete, /* True if this op is a delete */ |
863 int iLangid, /* Language id of row being written */ | 864 int iLangid, /* Language id of row being written */ |
864 sqlite_int64 iDocid /* Docid of row being written */ | 865 sqlite_int64 iDocid /* Docid of row being written */ |
865 ){ | 866 ){ |
866 assert( iLangid>=0 ); | 867 assert( iLangid>=0 ); |
| 868 assert( bDelete==1 || bDelete==0 ); |
867 | 869 |
868 /* TODO(shess) Explore whether partially flushing the buffer on | 870 /* TODO(shess) Explore whether partially flushing the buffer on |
869 ** forced-flush would provide better performance. I suspect that if | 871 ** forced-flush would provide better performance. I suspect that if |
870 ** we ordered the doclists by size and flushed the largest until the | 872 ** we ordered the doclists by size and flushed the largest until the |
871 ** buffer was half empty, that would let the less frequent terms | 873 ** buffer was half empty, that would let the less frequent terms |
872 ** generate longer doclists. | 874 ** generate longer doclists. |
873 */ | 875 */ |
874 if( iDocid<=p->iPrevDocid | 876 if( iDocid<p->iPrevDocid |
| 877 || (iDocid==p->iPrevDocid && p->bPrevDelete==0) |
875 || p->iPrevLangid!=iLangid | 878 || p->iPrevLangid!=iLangid |
876 || p->nPendingData>p->nMaxPendingData | 879 || p->nPendingData>p->nMaxPendingData |
877 ){ | 880 ){ |
878 int rc = sqlite3Fts3PendingTermsFlush(p); | 881 int rc = sqlite3Fts3PendingTermsFlush(p); |
879 if( rc!=SQLITE_OK ) return rc; | 882 if( rc!=SQLITE_OK ) return rc; |
880 } | 883 } |
881 p->iPrevDocid = iDocid; | 884 p->iPrevDocid = iDocid; |
882 p->iPrevLangid = iLangid; | 885 p->iPrevLangid = iLangid; |
| 886 p->bPrevDelete = bDelete; |
883 return SQLITE_OK; | 887 return SQLITE_OK; |
884 } | 888 } |
885 | 889 |
886 /* | 890 /* |
887 ** Discard the contents of the pending-terms hash tables. | 891 ** Discard the contents of the pending-terms hash tables. |
888 */ | 892 */ |
889 void sqlite3Fts3PendingTermsClear(Fts3Table *p){ | 893 void sqlite3Fts3PendingTermsClear(Fts3Table *p){ |
890 int i; | 894 int i; |
891 for(i=0; i<p->nIndex; i++){ | 895 for(i=0; i<p->nIndex; i++){ |
892 Fts3HashElem *pElem; | 896 Fts3HashElem *pElem; |
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1062 int rc; | 1066 int rc; |
1063 sqlite3_stmt *pSelect; | 1067 sqlite3_stmt *pSelect; |
1064 | 1068 |
1065 assert( *pbFound==0 ); | 1069 assert( *pbFound==0 ); |
1066 if( *pRC ) return; | 1070 if( *pRC ) return; |
1067 rc = fts3SqlStmt(p, SQL_SELECT_CONTENT_BY_ROWID, &pSelect, &pRowid); | 1071 rc = fts3SqlStmt(p, SQL_SELECT_CONTENT_BY_ROWID, &pSelect, &pRowid); |
1068 if( rc==SQLITE_OK ){ | 1072 if( rc==SQLITE_OK ){ |
1069 if( SQLITE_ROW==sqlite3_step(pSelect) ){ | 1073 if( SQLITE_ROW==sqlite3_step(pSelect) ){ |
1070 int i; | 1074 int i; |
1071 int iLangid = langidFromSelect(p, pSelect); | 1075 int iLangid = langidFromSelect(p, pSelect); |
1072 rc = fts3PendingTermsDocid(p, iLangid, sqlite3_column_int64(pSelect, 0)); | 1076 i64 iDocid = sqlite3_column_int64(pSelect, 0); |
| 1077 rc = fts3PendingTermsDocid(p, 1, iLangid, iDocid); |
1073 for(i=1; rc==SQLITE_OK && i<=p->nColumn; i++){ | 1078 for(i=1; rc==SQLITE_OK && i<=p->nColumn; i++){ |
1074 int iCol = i-1; | 1079 int iCol = i-1; |
1075 if( p->abNotindexed[iCol]==0 ){ | 1080 if( p->abNotindexed[iCol]==0 ){ |
1076 const char *zText = (const char *)sqlite3_column_text(pSelect, i); | 1081 const char *zText = (const char *)sqlite3_column_text(pSelect, i); |
1077 rc = fts3PendingTermsAdd(p, iLangid, zText, -1, &aSz[iCol]); | 1082 rc = fts3PendingTermsAdd(p, iLangid, zText, -1, &aSz[iCol]); |
1078 aSz[p->nColumn] += sqlite3_column_bytes(pSelect, i); | 1083 aSz[p->nColumn] += sqlite3_column_bytes(pSelect, i); |
1079 } | 1084 } |
1080 } | 1085 } |
1081 if( rc!=SQLITE_OK ){ | 1086 if( rc!=SQLITE_OK ){ |
1082 sqlite3_reset(pSelect); | 1087 sqlite3_reset(pSelect); |
(...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1310 if( !pReader->aDoclist ){ | 1315 if( !pReader->aDoclist ){ |
1311 pNext = pReader->aNode; | 1316 pNext = pReader->aNode; |
1312 }else{ | 1317 }else{ |
1313 pNext = &pReader->aDoclist[pReader->nDoclist]; | 1318 pNext = &pReader->aDoclist[pReader->nDoclist]; |
1314 } | 1319 } |
1315 | 1320 |
1316 if( !pNext || pNext>=&pReader->aNode[pReader->nNode] ){ | 1321 if( !pNext || pNext>=&pReader->aNode[pReader->nNode] ){ |
1317 | 1322 |
1318 if( fts3SegReaderIsPending(pReader) ){ | 1323 if( fts3SegReaderIsPending(pReader) ){ |
1319 Fts3HashElem *pElem = *(pReader->ppNextElem); | 1324 Fts3HashElem *pElem = *(pReader->ppNextElem); |
1320 if( pElem==0 ){ | 1325 sqlite3_free(pReader->aNode); |
1321 pReader->aNode = 0; | 1326 pReader->aNode = 0; |
1322 }else{ | 1327 if( pElem ){ |
| 1328 char *aCopy; |
1323 PendingList *pList = (PendingList *)fts3HashData(pElem); | 1329 PendingList *pList = (PendingList *)fts3HashData(pElem); |
| 1330 int nCopy = pList->nData+1; |
1324 pReader->zTerm = (char *)fts3HashKey(pElem); | 1331 pReader->zTerm = (char *)fts3HashKey(pElem); |
1325 pReader->nTerm = fts3HashKeysize(pElem); | 1332 pReader->nTerm = fts3HashKeysize(pElem); |
1326 pReader->nNode = pReader->nDoclist = pList->nData + 1; | 1333 aCopy = (char*)sqlite3_malloc(nCopy); |
1327 pReader->aNode = pReader->aDoclist = pList->aData; | 1334 if( !aCopy ) return SQLITE_NOMEM; |
| 1335 memcpy(aCopy, pList->aData, nCopy); |
| 1336 pReader->nNode = pReader->nDoclist = nCopy; |
| 1337 pReader->aNode = pReader->aDoclist = aCopy; |
1328 pReader->ppNextElem++; | 1338 pReader->ppNextElem++; |
1329 assert( pReader->aNode ); | 1339 assert( pReader->aNode ); |
1330 } | 1340 } |
1331 return SQLITE_OK; | 1341 return SQLITE_OK; |
1332 } | 1342 } |
1333 | 1343 |
1334 fts3SegReaderSetEof(pReader); | 1344 fts3SegReaderSetEof(pReader); |
1335 | 1345 |
1336 /* If iCurrentBlock>=iLeafEndBlock, this is an EOF condition. All leaf | 1346 /* If iCurrentBlock>=iLeafEndBlock, this is an EOF condition. All leaf |
1337 ** blocks have already been traversed. */ | 1347 ** blocks have already been traversed. */ |
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1557 } | 1567 } |
1558 *pnOvfl = nOvfl; | 1568 *pnOvfl = nOvfl; |
1559 return rc; | 1569 return rc; |
1560 } | 1570 } |
1561 | 1571 |
1562 /* | 1572 /* |
1563 ** Free all allocations associated with the iterator passed as the | 1573 ** Free all allocations associated with the iterator passed as the |
1564 ** second argument. | 1574 ** second argument. |
1565 */ | 1575 */ |
1566 void sqlite3Fts3SegReaderFree(Fts3SegReader *pReader){ | 1576 void sqlite3Fts3SegReaderFree(Fts3SegReader *pReader){ |
1567 if( pReader && !fts3SegReaderIsPending(pReader) ){ | 1577 if( pReader ){ |
1568 sqlite3_free(pReader->zTerm); | 1578 if( !fts3SegReaderIsPending(pReader) ){ |
| 1579 sqlite3_free(pReader->zTerm); |
| 1580 } |
1569 if( !fts3SegReaderIsRootOnly(pReader) ){ | 1581 if( !fts3SegReaderIsRootOnly(pReader) ){ |
1570 sqlite3_free(pReader->aNode); | 1582 sqlite3_free(pReader->aNode); |
1571 sqlite3_blob_close(pReader->pBlob); | |
1572 } | 1583 } |
| 1584 sqlite3_blob_close(pReader->pBlob); |
1573 } | 1585 } |
1574 sqlite3_free(pReader); | 1586 sqlite3_free(pReader); |
1575 } | 1587 } |
1576 | 1588 |
1577 /* | 1589 /* |
1578 ** Allocate a new SegReader object. | 1590 ** Allocate a new SegReader object. |
1579 */ | 1591 */ |
1580 int sqlite3Fts3SegReaderNew( | 1592 int sqlite3Fts3SegReaderNew( |
1581 int iAge, /* Segment "age". */ | 1593 int iAge, /* Segment "age". */ |
1582 int bLookup, /* True for a lookup only */ | 1594 int bLookup, /* True for a lookup only */ |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1618 } | 1630 } |
1619 *ppReader = pReader; | 1631 *ppReader = pReader; |
1620 return SQLITE_OK; | 1632 return SQLITE_OK; |
1621 } | 1633 } |
1622 | 1634 |
1623 /* | 1635 /* |
1624 ** This is a comparison function used as a qsort() callback when sorting | 1636 ** This is a comparison function used as a qsort() callback when sorting |
1625 ** an array of pending terms by term. This occurs as part of flushing | 1637 ** an array of pending terms by term. This occurs as part of flushing |
1626 ** the contents of the pending-terms hash table to the database. | 1638 ** the contents of the pending-terms hash table to the database. |
1627 */ | 1639 */ |
1628 static int fts3CompareElemByTerm(const void *lhs, const void *rhs){ | 1640 static int SQLITE_CDECL fts3CompareElemByTerm( |
| 1641 const void *lhs, |
| 1642 const void *rhs |
| 1643 ){ |
1629 char *z1 = fts3HashKey(*(Fts3HashElem **)lhs); | 1644 char *z1 = fts3HashKey(*(Fts3HashElem **)lhs); |
1630 char *z2 = fts3HashKey(*(Fts3HashElem **)rhs); | 1645 char *z2 = fts3HashKey(*(Fts3HashElem **)rhs); |
1631 int n1 = fts3HashKeysize(*(Fts3HashElem **)lhs); | 1646 int n1 = fts3HashKeysize(*(Fts3HashElem **)lhs); |
1632 int n2 = fts3HashKeysize(*(Fts3HashElem **)rhs); | 1647 int n2 = fts3HashKeysize(*(Fts3HashElem **)rhs); |
1633 | 1648 |
1634 int n = (n1<n2 ? n1 : n2); | 1649 int n = (n1<n2 ? n1 : n2); |
1635 int c = memcmp(z1, z2, n); | 1650 int c = memcmp(z1, z2, n); |
1636 if( c==0 ){ | 1651 if( c==0 ){ |
1637 c = n1 - n2; | 1652 c = n1 - n2; |
1638 } | 1653 } |
(...skipping 1436 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3075 ** take place. */ | 3090 ** take place. */ |
3076 bOk = 0; | 3091 bOk = 0; |
3077 break; | 3092 break; |
3078 } | 3093 } |
3079 bOk = 1; | 3094 bOk = 1; |
3080 } | 3095 } |
3081 rc = sqlite3_reset(pRange); | 3096 rc = sqlite3_reset(pRange); |
3082 | 3097 |
3083 if( bOk ){ | 3098 if( bOk ){ |
3084 int iIdx = 0; | 3099 int iIdx = 0; |
3085 sqlite3_stmt *pUpdate1; | 3100 sqlite3_stmt *pUpdate1 = 0; |
3086 sqlite3_stmt *pUpdate2; | 3101 sqlite3_stmt *pUpdate2 = 0; |
3087 | 3102 |
3088 if( rc==SQLITE_OK ){ | 3103 if( rc==SQLITE_OK ){ |
3089 rc = fts3SqlStmt(p, SQL_UPDATE_LEVEL_IDX, &pUpdate1, 0); | 3104 rc = fts3SqlStmt(p, SQL_UPDATE_LEVEL_IDX, &pUpdate1, 0); |
3090 } | 3105 } |
3091 if( rc==SQLITE_OK ){ | 3106 if( rc==SQLITE_OK ){ |
3092 rc = fts3SqlStmt(p, SQL_UPDATE_LEVEL, &pUpdate2, 0); | 3107 rc = fts3SqlStmt(p, SQL_UPDATE_LEVEL, &pUpdate2, 0); |
3093 } | 3108 } |
3094 | 3109 |
3095 if( rc==SQLITE_OK ){ | 3110 if( rc==SQLITE_OK ){ |
3096 | 3111 |
(...skipping 337 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3434 ** iIndex/iLangid combination. | 3449 ** iIndex/iLangid combination. |
3435 */ | 3450 */ |
3436 static int fts3DoOptimize(Fts3Table *p, int bReturnDone){ | 3451 static int fts3DoOptimize(Fts3Table *p, int bReturnDone){ |
3437 int bSeenDone = 0; | 3452 int bSeenDone = 0; |
3438 int rc; | 3453 int rc; |
3439 sqlite3_stmt *pAllLangid = 0; | 3454 sqlite3_stmt *pAllLangid = 0; |
3440 | 3455 |
3441 rc = fts3SqlStmt(p, SQL_SELECT_ALL_LANGID, &pAllLangid, 0); | 3456 rc = fts3SqlStmt(p, SQL_SELECT_ALL_LANGID, &pAllLangid, 0); |
3442 if( rc==SQLITE_OK ){ | 3457 if( rc==SQLITE_OK ){ |
3443 int rc2; | 3458 int rc2; |
3444 sqlite3_bind_int(pAllLangid, 1, p->nIndex); | 3459 sqlite3_bind_int(pAllLangid, 1, p->iPrevLangid); |
| 3460 sqlite3_bind_int(pAllLangid, 2, p->nIndex); |
3445 while( sqlite3_step(pAllLangid)==SQLITE_ROW ){ | 3461 while( sqlite3_step(pAllLangid)==SQLITE_ROW ){ |
3446 int i; | 3462 int i; |
3447 int iLangid = sqlite3_column_int(pAllLangid, 0); | 3463 int iLangid = sqlite3_column_int(pAllLangid, 0); |
3448 for(i=0; rc==SQLITE_OK && i<p->nIndex; i++){ | 3464 for(i=0; rc==SQLITE_OK && i<p->nIndex; i++){ |
3449 rc = fts3SegmentMerge(p, iLangid, i, FTS3_SEGCURSOR_ALL); | 3465 rc = fts3SegmentMerge(p, iLangid, i, FTS3_SEGCURSOR_ALL); |
3450 if( rc==SQLITE_DONE ){ | 3466 if( rc==SQLITE_DONE ){ |
3451 bSeenDone = 1; | 3467 bSeenDone = 1; |
3452 rc = SQLITE_OK; | 3468 rc = SQLITE_OK; |
3453 } | 3469 } |
3454 } | 3470 } |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3501 }else{ | 3517 }else{ |
3502 memset(aSz, 0, nByte); | 3518 memset(aSz, 0, nByte); |
3503 aSzIns = &aSz[p->nColumn+1]; | 3519 aSzIns = &aSz[p->nColumn+1]; |
3504 aSzDel = &aSzIns[p->nColumn+1]; | 3520 aSzDel = &aSzIns[p->nColumn+1]; |
3505 } | 3521 } |
3506 } | 3522 } |
3507 | 3523 |
3508 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){ | 3524 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){ |
3509 int iCol; | 3525 int iCol; |
3510 int iLangid = langidFromSelect(p, pStmt); | 3526 int iLangid = langidFromSelect(p, pStmt); |
3511 rc = fts3PendingTermsDocid(p, iLangid, sqlite3_column_int64(pStmt, 0)); | 3527 rc = fts3PendingTermsDocid(p, 0, iLangid, sqlite3_column_int64(pStmt, 0)); |
3512 memset(aSz, 0, sizeof(aSz[0]) * (p->nColumn+1)); | 3528 memset(aSz, 0, sizeof(aSz[0]) * (p->nColumn+1)); |
3513 for(iCol=0; rc==SQLITE_OK && iCol<p->nColumn; iCol++){ | 3529 for(iCol=0; rc==SQLITE_OK && iCol<p->nColumn; iCol++){ |
3514 if( p->abNotindexed[iCol]==0 ){ | 3530 if( p->abNotindexed[iCol]==0 ){ |
3515 const char *z = (const char *) sqlite3_column_text(pStmt, iCol+1); | 3531 const char *z = (const char *) sqlite3_column_text(pStmt, iCol+1); |
3516 rc = fts3PendingTermsAdd(p, iLangid, z, iCol, &aSz[iCol]); | 3532 rc = fts3PendingTermsAdd(p, iLangid, z, iCol, &aSz[iCol]); |
3517 aSz[p->nColumn] += sqlite3_column_bytes(pStmt, iCol+1); | 3533 aSz[p->nColumn] += sqlite3_column_bytes(pStmt, iCol+1); |
3518 } | 3534 } |
3519 } | 3535 } |
3520 if( p->bHasDocsize ){ | 3536 if( p->bHasDocsize ){ |
3521 fts3InsertDocsize(&rc, p, aSz); | 3537 fts3InsertDocsize(&rc, p, aSz); |
(...skipping 1244 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4766 const int nHint = pHint->n; | 4782 const int nHint = pHint->n; |
4767 int i; | 4783 int i; |
4768 | 4784 |
4769 i = pHint->n-2; | 4785 i = pHint->n-2; |
4770 while( i>0 && (pHint->a[i-1] & 0x80) ) i--; | 4786 while( i>0 && (pHint->a[i-1] & 0x80) ) i--; |
4771 while( i>0 && (pHint->a[i-1] & 0x80) ) i--; | 4787 while( i>0 && (pHint->a[i-1] & 0x80) ) i--; |
4772 | 4788 |
4773 pHint->n = i; | 4789 pHint->n = i; |
4774 i += sqlite3Fts3GetVarint(&pHint->a[i], piAbsLevel); | 4790 i += sqlite3Fts3GetVarint(&pHint->a[i], piAbsLevel); |
4775 i += fts3GetVarint32(&pHint->a[i], pnInput); | 4791 i += fts3GetVarint32(&pHint->a[i], pnInput); |
4776 if( i!=nHint ) return SQLITE_CORRUPT_VTAB; | 4792 if( i!=nHint ) return FTS_CORRUPT_VTAB; |
4777 | 4793 |
4778 return SQLITE_OK; | 4794 return SQLITE_OK; |
4779 } | 4795 } |
4780 | 4796 |
4781 | 4797 |
4782 /* | 4798 /* |
4783 ** Attempt an incremental merge that writes nMerge leaf blocks. | 4799 ** Attempt an incremental merge that writes nMerge leaf blocks. |
4784 ** | 4800 ** |
4785 ** Incremental merges happen nMin segments at a time. The segments | 4801 ** Incremental merges happen nMin segments at a time. The segments |
4786 ** to be merged are the nMin oldest segments (the ones with the smallest | 4802 ** to be merged are the nMin oldest segments (the ones with the smallest |
(...skipping 347 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5134 static int fts3IntegrityCheck(Fts3Table *p, int *pbOk){ | 5150 static int fts3IntegrityCheck(Fts3Table *p, int *pbOk){ |
5135 int rc = SQLITE_OK; /* Return code */ | 5151 int rc = SQLITE_OK; /* Return code */ |
5136 u64 cksum1 = 0; /* Checksum based on FTS index contents */ | 5152 u64 cksum1 = 0; /* Checksum based on FTS index contents */ |
5137 u64 cksum2 = 0; /* Checksum based on %_content contents */ | 5153 u64 cksum2 = 0; /* Checksum based on %_content contents */ |
5138 sqlite3_stmt *pAllLangid = 0; /* Statement to return all language-ids */ | 5154 sqlite3_stmt *pAllLangid = 0; /* Statement to return all language-ids */ |
5139 | 5155 |
5140 /* This block calculates the checksum according to the FTS index. */ | 5156 /* This block calculates the checksum according to the FTS index. */ |
5141 rc = fts3SqlStmt(p, SQL_SELECT_ALL_LANGID, &pAllLangid, 0); | 5157 rc = fts3SqlStmt(p, SQL_SELECT_ALL_LANGID, &pAllLangid, 0); |
5142 if( rc==SQLITE_OK ){ | 5158 if( rc==SQLITE_OK ){ |
5143 int rc2; | 5159 int rc2; |
5144 sqlite3_bind_int(pAllLangid, 1, p->nIndex); | 5160 sqlite3_bind_int(pAllLangid, 1, p->iPrevLangid); |
| 5161 sqlite3_bind_int(pAllLangid, 2, p->nIndex); |
5145 while( rc==SQLITE_OK && sqlite3_step(pAllLangid)==SQLITE_ROW ){ | 5162 while( rc==SQLITE_OK && sqlite3_step(pAllLangid)==SQLITE_ROW ){ |
5146 int iLangid = sqlite3_column_int(pAllLangid, 0); | 5163 int iLangid = sqlite3_column_int(pAllLangid, 0); |
5147 int i; | 5164 int i; |
5148 for(i=0; i<p->nIndex; i++){ | 5165 for(i=0; i<p->nIndex; i++){ |
5149 cksum1 = cksum1 ^ fts3ChecksumIndex(p, iLangid, i, &rc); | 5166 cksum1 = cksum1 ^ fts3ChecksumIndex(p, iLangid, i, &rc); |
5150 } | 5167 } |
5151 } | 5168 } |
5152 rc2 = sqlite3_reset(pAllLangid); | 5169 rc2 = sqlite3_reset(pAllLangid); |
5153 if( rc==SQLITE_OK ) rc = rc2; | 5170 if( rc==SQLITE_OK ) rc = rc2; |
5154 } | 5171 } |
5155 | 5172 |
5156 /* This block calculates the checksum according to the %_content table */ | 5173 /* This block calculates the checksum according to the %_content table */ |
5157 rc = fts3SqlStmt(p, SQL_SELECT_ALL_LANGID, &pAllLangid, 0); | |
5158 if( rc==SQLITE_OK ){ | 5174 if( rc==SQLITE_OK ){ |
5159 sqlite3_tokenizer_module const *pModule = p->pTokenizer->pModule; | 5175 sqlite3_tokenizer_module const *pModule = p->pTokenizer->pModule; |
5160 sqlite3_stmt *pStmt = 0; | 5176 sqlite3_stmt *pStmt = 0; |
5161 char *zSql; | 5177 char *zSql; |
5162 | 5178 |
5163 zSql = sqlite3_mprintf("SELECT %s" , p->zReadExprlist); | 5179 zSql = sqlite3_mprintf("SELECT %s" , p->zReadExprlist); |
5164 if( !zSql ){ | 5180 if( !zSql ){ |
5165 rc = SQLITE_NOMEM; | 5181 rc = SQLITE_NOMEM; |
5166 }else{ | 5182 }else{ |
5167 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); | 5183 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5244 ** | 5260 ** |
5245 ** If the two checksums are identical, the integrity-check is deemed to have | 5261 ** If the two checksums are identical, the integrity-check is deemed to have |
5246 ** passed. | 5262 ** passed. |
5247 */ | 5263 */ |
5248 static int fts3DoIntegrityCheck( | 5264 static int fts3DoIntegrityCheck( |
5249 Fts3Table *p /* FTS3 table handle */ | 5265 Fts3Table *p /* FTS3 table handle */ |
5250 ){ | 5266 ){ |
5251 int rc; | 5267 int rc; |
5252 int bOk = 0; | 5268 int bOk = 0; |
5253 rc = fts3IntegrityCheck(p, &bOk); | 5269 rc = fts3IntegrityCheck(p, &bOk); |
5254 if( rc==SQLITE_OK && bOk==0 ) rc = SQLITE_CORRUPT_VTAB; | 5270 if( rc==SQLITE_OK && bOk==0 ) rc = FTS_CORRUPT_VTAB; |
5255 return rc; | 5271 return rc; |
5256 } | 5272 } |
5257 | 5273 |
5258 /* | 5274 /* |
5259 ** Handle a 'special' INSERT of the form: | 5275 ** Handle a 'special' INSERT of the form: |
5260 ** | 5276 ** |
5261 ** "INSERT INTO tbl(tbl) VALUES(<expr>)" | 5277 ** "INSERT INTO tbl(tbl) VALUES(<expr>)" |
5262 ** | 5278 ** |
5263 ** Argument pVal contains the result of <expr>. Currently the only | 5279 ** Argument pVal contains the result of <expr>. Currently the only |
5264 ** meaningful value to insert is the text 'optimize'. | 5280 ** meaningful value to insert is the text 'optimize'. |
(...skipping 341 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5606 /* If this is an INSERT or UPDATE operation, insert the new record. */ | 5622 /* If this is an INSERT or UPDATE operation, insert the new record. */ |
5607 if( nArg>1 && rc==SQLITE_OK ){ | 5623 if( nArg>1 && rc==SQLITE_OK ){ |
5608 int iLangid = sqlite3_value_int(apVal[2 + p->nColumn + 2]); | 5624 int iLangid = sqlite3_value_int(apVal[2 + p->nColumn + 2]); |
5609 if( bInsertDone==0 ){ | 5625 if( bInsertDone==0 ){ |
5610 rc = fts3InsertData(p, apVal, pRowid); | 5626 rc = fts3InsertData(p, apVal, pRowid); |
5611 if( rc==SQLITE_CONSTRAINT && p->zContentTbl==0 ){ | 5627 if( rc==SQLITE_CONSTRAINT && p->zContentTbl==0 ){ |
5612 rc = FTS_CORRUPT_VTAB; | 5628 rc = FTS_CORRUPT_VTAB; |
5613 } | 5629 } |
5614 } | 5630 } |
5615 if( rc==SQLITE_OK && (!isRemove || *pRowid!=p->iPrevDocid ) ){ | 5631 if( rc==SQLITE_OK && (!isRemove || *pRowid!=p->iPrevDocid ) ){ |
5616 rc = fts3PendingTermsDocid(p, iLangid, *pRowid); | 5632 rc = fts3PendingTermsDocid(p, 0, iLangid, *pRowid); |
5617 } | 5633 } |
5618 if( rc==SQLITE_OK ){ | 5634 if( rc==SQLITE_OK ){ |
5619 assert( p->iPrevDocid==*pRowid ); | 5635 assert( p->iPrevDocid==*pRowid ); |
5620 rc = fts3InsertTerms(p, iLangid, apVal, aSzIns); | 5636 rc = fts3InsertTerms(p, iLangid, apVal, aSzIns); |
5621 } | 5637 } |
5622 if( p->bHasDocsize ){ | 5638 if( p->bHasDocsize ){ |
5623 fts3InsertDocsize(&rc, p, aSzIns); | 5639 fts3InsertDocsize(&rc, p, aSzIns); |
5624 } | 5640 } |
5625 nChng++; | 5641 nChng++; |
5626 } | 5642 } |
(...skipping 24 matching lines...) Expand all Loading... |
5651 }else{ | 5667 }else{ |
5652 sqlite3_exec(p->db, "ROLLBACK TO fts3", 0, 0, 0); | 5668 sqlite3_exec(p->db, "ROLLBACK TO fts3", 0, 0, 0); |
5653 sqlite3_exec(p->db, "RELEASE fts3", 0, 0, 0); | 5669 sqlite3_exec(p->db, "RELEASE fts3", 0, 0, 0); |
5654 } | 5670 } |
5655 } | 5671 } |
5656 sqlite3Fts3SegmentsClose(p); | 5672 sqlite3Fts3SegmentsClose(p); |
5657 return rc; | 5673 return rc; |
5658 } | 5674 } |
5659 | 5675 |
5660 #endif | 5676 #endif |
OLD | NEW |