Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2)

Side by Side Diff: third_party/sqlite/src/ext/fts5/fts5_main.c

Issue 2751253002: [sql] Import SQLite 3.17.0. (Closed)
Patch Set: also clang on Linux i386 Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 ** 2014 Jun 09 2 ** 2014 Jun 09
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 202 matching lines...) Expand 10 before | Expand all | Expand 10 after
213 #define FTS5_BI_ROWID_LE 0x0008 /* rowid <= ? */ 213 #define FTS5_BI_ROWID_LE 0x0008 /* rowid <= ? */
214 #define FTS5_BI_ROWID_GE 0x0010 /* rowid >= ? */ 214 #define FTS5_BI_ROWID_GE 0x0010 /* rowid >= ? */
215 215
216 #define FTS5_BI_ORDER_RANK 0x0020 216 #define FTS5_BI_ORDER_RANK 0x0020
217 #define FTS5_BI_ORDER_ROWID 0x0040 217 #define FTS5_BI_ORDER_ROWID 0x0040
218 #define FTS5_BI_ORDER_DESC 0x0080 218 #define FTS5_BI_ORDER_DESC 0x0080
219 219
220 /* 220 /*
221 ** Values for Fts5Cursor.csrflags 221 ** Values for Fts5Cursor.csrflags
222 */ 222 */
223 #define FTS5CSR_REQUIRE_CONTENT 0x01 223 #define FTS5CSR_EOF 0x01
224 #define FTS5CSR_REQUIRE_DOCSIZE 0x02 224 #define FTS5CSR_REQUIRE_CONTENT 0x02
225 #define FTS5CSR_REQUIRE_INST 0x04 225 #define FTS5CSR_REQUIRE_DOCSIZE 0x04
226 #define FTS5CSR_EOF 0x08 226 #define FTS5CSR_REQUIRE_INST 0x08
227 #define FTS5CSR_FREE_ZRANK 0x10 227 #define FTS5CSR_FREE_ZRANK 0x10
228 #define FTS5CSR_REQUIRE_RESEEK 0x20 228 #define FTS5CSR_REQUIRE_RESEEK 0x20
229 #define FTS5CSR_REQUIRE_POSLIST 0x40
229 230
230 #define BitFlagAllTest(x,y) (((x) & (y))==(y)) 231 #define BitFlagAllTest(x,y) (((x) & (y))==(y))
231 #define BitFlagTest(x,y) (((x) & (y))!=0) 232 #define BitFlagTest(x,y) (((x) & (y))!=0)
232 233
233 234
234 /* 235 /*
235 ** Macros to Set(), Clear() and Test() cursor flags. 236 ** Macros to Set(), Clear() and Test() cursor flags.
236 */ 237 */
237 #define CsrFlagSet(pCsr, flag) ((pCsr)->csrflags |= (flag)) 238 #define CsrFlagSet(pCsr, flag) ((pCsr)->csrflags |= (flag))
238 #define CsrFlagClear(pCsr, flag) ((pCsr)->csrflags &= ~(flag)) 239 #define CsrFlagClear(pCsr, flag) ((pCsr)->csrflags &= ~(flag))
(...skipping 291 matching lines...) Expand 10 before | Expand all | Expand 10 after
530 531
531 int aColMap[3]; 532 int aColMap[3];
532 aColMap[0] = -1; 533 aColMap[0] = -1;
533 aColMap[1] = pConfig->nCol; 534 aColMap[1] = pConfig->nCol;
534 aColMap[2] = pConfig->nCol+1; 535 aColMap[2] = pConfig->nCol+1;
535 536
536 /* Set idxFlags flags for all WHERE clause terms that will be used. */ 537 /* Set idxFlags flags for all WHERE clause terms that will be used. */
537 for(i=0; i<pInfo->nConstraint; i++){ 538 for(i=0; i<pInfo->nConstraint; i++){
538 struct sqlite3_index_constraint *p = &pInfo->aConstraint[i]; 539 struct sqlite3_index_constraint *p = &pInfo->aConstraint[i];
539 int j; 540 int j;
540 for(j=0; j<(int)ArraySize(aConstraint); j++){ 541 for(j=0; j<ArraySize(aConstraint); j++){
541 struct Constraint *pC = &aConstraint[j]; 542 struct Constraint *pC = &aConstraint[j];
542 if( p->iColumn==aColMap[pC->iCol] && p->op & pC->op ){ 543 if( p->iColumn==aColMap[pC->iCol] && p->op & pC->op ){
543 if( p->usable ){ 544 if( p->usable ){
544 pC->iConsIndex = i; 545 pC->iConsIndex = i;
545 idxFlags |= pC->fts5op; 546 idxFlags |= pC->fts5op;
546 }else if( j==0 ){ 547 }else if( j==0 ){
547 /* As there exists an unusable MATCH constraint this is an 548 /* As there exists an unusable MATCH constraint this is an
548 ** unusable plan. Set a prohibitively high cost. */ 549 ** unusable plan. Set a prohibitively high cost. */
549 pInfo->estimatedCost = 1e50; 550 pInfo->estimatedCost = 1e50;
550 return SQLITE_OK; 551 return SQLITE_OK;
(...skipping 26 matching lines...) Expand all
577 }else if( BitFlagAllTest(idxFlags, FTS5_BI_ROWID_LE|FTS5_BI_ROWID_GE) ){ 578 }else if( BitFlagAllTest(idxFlags, FTS5_BI_ROWID_LE|FTS5_BI_ROWID_GE) ){
578 pInfo->estimatedCost = bHasMatch ? 500.0 : 250000.0; 579 pInfo->estimatedCost = bHasMatch ? 500.0 : 250000.0;
579 }else if( BitFlagTest(idxFlags, FTS5_BI_ROWID_LE|FTS5_BI_ROWID_GE) ){ 580 }else if( BitFlagTest(idxFlags, FTS5_BI_ROWID_LE|FTS5_BI_ROWID_GE) ){
580 pInfo->estimatedCost = bHasMatch ? 750.0 : 750000.0; 581 pInfo->estimatedCost = bHasMatch ? 750.0 : 750000.0;
581 }else{ 582 }else{
582 pInfo->estimatedCost = bHasMatch ? 1000.0 : 1000000.0; 583 pInfo->estimatedCost = bHasMatch ? 1000.0 : 1000000.0;
583 } 584 }
584 585
585 /* Assign argvIndex values to each constraint in use. */ 586 /* Assign argvIndex values to each constraint in use. */
586 iNext = 1; 587 iNext = 1;
587 for(i=0; i<(int)ArraySize(aConstraint); i++){ 588 for(i=0; i<ArraySize(aConstraint); i++){
588 struct Constraint *pC = &aConstraint[i]; 589 struct Constraint *pC = &aConstraint[i];
589 if( pC->iConsIndex>=0 ){ 590 if( pC->iConsIndex>=0 ){
590 pInfo->aConstraintUsage[pC->iConsIndex].argvIndex = iNext++; 591 pInfo->aConstraintUsage[pC->iConsIndex].argvIndex = iNext++;
591 pInfo->aConstraintUsage[pC->iConsIndex].omit = (unsigned char)pC->omit; 592 pInfo->aConstraintUsage[pC->iConsIndex].omit = (unsigned char)pC->omit;
592 } 593 }
593 } 594 }
594 595
595 pInfo->idxNum = idxFlags; 596 pInfo->idxNum = idxFlags;
596 return SQLITE_OK; 597 return SQLITE_OK;
597 } 598 }
598 599
600 static int fts5NewTransaction(Fts5Table *pTab){
601 Fts5Cursor *pCsr;
602 for(pCsr=pTab->pGlobal->pCsr; pCsr; pCsr=pCsr->pNext){
603 if( pCsr->base.pVtab==(sqlite3_vtab*)pTab ) return SQLITE_OK;
604 }
605 return sqlite3Fts5StorageReset(pTab->pStorage);
606 }
607
599 /* 608 /*
600 ** Implementation of xOpen method. 609 ** Implementation of xOpen method.
601 */ 610 */
602 static int fts5OpenMethod(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCsr){ 611 static int fts5OpenMethod(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCsr){
603 Fts5Table *pTab = (Fts5Table*)pVTab; 612 Fts5Table *pTab = (Fts5Table*)pVTab;
604 Fts5Config *pConfig = pTab->pConfig; 613 Fts5Config *pConfig = pTab->pConfig;
605 Fts5Cursor *pCsr; /* New cursor object */ 614 Fts5Cursor *pCsr = 0; /* New cursor object */
606 int nByte; /* Bytes of space to allocate */ 615 int nByte; /* Bytes of space to allocate */
607 int rc = SQLITE_OK; /* Return code */ 616 int rc; /* Return code */
608 617
609 nByte = sizeof(Fts5Cursor) + pConfig->nCol * sizeof(int); 618 rc = fts5NewTransaction(pTab);
610 pCsr = (Fts5Cursor*)sqlite3_malloc(nByte); 619 if( rc==SQLITE_OK ){
611 if( pCsr ){ 620 nByte = sizeof(Fts5Cursor) + pConfig->nCol * sizeof(int);
612 Fts5Global *pGlobal = pTab->pGlobal; 621 pCsr = (Fts5Cursor*)sqlite3_malloc(nByte);
613 memset(pCsr, 0, nByte); 622 if( pCsr ){
614 pCsr->aColumnSize = (int*)&pCsr[1]; 623 Fts5Global *pGlobal = pTab->pGlobal;
615 pCsr->pNext = pGlobal->pCsr; 624 memset(pCsr, 0, nByte);
616 pGlobal->pCsr = pCsr; 625 pCsr->aColumnSize = (int*)&pCsr[1];
617 pCsr->iCsrId = ++pGlobal->iNextId; 626 pCsr->pNext = pGlobal->pCsr;
618 }else{ 627 pGlobal->pCsr = pCsr;
619 rc = SQLITE_NOMEM; 628 pCsr->iCsrId = ++pGlobal->iNextId;
629 }else{
630 rc = SQLITE_NOMEM;
631 }
620 } 632 }
621 *ppCsr = (sqlite3_vtab_cursor*)pCsr; 633 *ppCsr = (sqlite3_vtab_cursor*)pCsr;
622 return rc; 634 return rc;
623 } 635 }
624 636
625 static int fts5StmtType(Fts5Cursor *pCsr){ 637 static int fts5StmtType(Fts5Cursor *pCsr){
626 if( pCsr->ePlan==FTS5_PLAN_SCAN ){ 638 if( pCsr->ePlan==FTS5_PLAN_SCAN ){
627 return (pCsr->bDesc) ? FTS5_STMT_SCAN_DESC : FTS5_STMT_SCAN_ASC; 639 return (pCsr->bDesc) ? FTS5_STMT_SCAN_DESC : FTS5_STMT_SCAN_ASC;
628 } 640 }
629 return FTS5_STMT_LOOKUP; 641 return FTS5_STMT_LOOKUP;
630 } 642 }
631 643
632 /* 644 /*
633 ** This function is called after the cursor passed as the only argument 645 ** This function is called after the cursor passed as the only argument
634 ** is moved to point at a different row. It clears all cached data 646 ** is moved to point at a different row. It clears all cached data
635 ** specific to the previous row stored by the cursor object. 647 ** specific to the previous row stored by the cursor object.
636 */ 648 */
637 static void fts5CsrNewrow(Fts5Cursor *pCsr){ 649 static void fts5CsrNewrow(Fts5Cursor *pCsr){
638 CsrFlagSet(pCsr, 650 CsrFlagSet(pCsr,
639 FTS5CSR_REQUIRE_CONTENT 651 FTS5CSR_REQUIRE_CONTENT
640 | FTS5CSR_REQUIRE_DOCSIZE 652 | FTS5CSR_REQUIRE_DOCSIZE
641 | FTS5CSR_REQUIRE_INST 653 | FTS5CSR_REQUIRE_INST
654 | FTS5CSR_REQUIRE_POSLIST
642 ); 655 );
643 } 656 }
644 657
645 static void fts5FreeCursorComponents(Fts5Cursor *pCsr){ 658 static void fts5FreeCursorComponents(Fts5Cursor *pCsr){
646 Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab); 659 Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab);
647 Fts5Auxdata *pData; 660 Fts5Auxdata *pData;
648 Fts5Auxdata *pNext; 661 Fts5Auxdata *pNext;
649 662
650 sqlite3_free(pCsr->aInstIter); 663 sqlite3_free(pCsr->aInstIter);
651 sqlite3_free(pCsr->aInst); 664 sqlite3_free(pCsr->aInst);
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
714 const u8 *aBlob; 727 const u8 *aBlob;
715 int nBlob; 728 int nBlob;
716 int i; 729 int i;
717 int iOff = 0; 730 int iOff = 0;
718 rc = SQLITE_OK; 731 rc = SQLITE_OK;
719 732
720 pSorter->iRowid = sqlite3_column_int64(pSorter->pStmt, 0); 733 pSorter->iRowid = sqlite3_column_int64(pSorter->pStmt, 0);
721 nBlob = sqlite3_column_bytes(pSorter->pStmt, 1); 734 nBlob = sqlite3_column_bytes(pSorter->pStmt, 1);
722 aBlob = a = sqlite3_column_blob(pSorter->pStmt, 1); 735 aBlob = a = sqlite3_column_blob(pSorter->pStmt, 1);
723 736
724 for(i=0; i<(pSorter->nIdx-1); i++){ 737 /* nBlob==0 in detail=none mode. */
725 int iVal; 738 if( nBlob>0 ){
726 a += fts5GetVarint32(a, iVal); 739 for(i=0; i<(pSorter->nIdx-1); i++){
727 iOff += iVal; 740 int iVal;
728 pSorter->aIdx[i] = iOff; 741 a += fts5GetVarint32(a, iVal);
742 iOff += iVal;
743 pSorter->aIdx[i] = iOff;
744 }
745 pSorter->aIdx[i] = &aBlob[nBlob] - a;
746 pSorter->aPoslist = a;
729 } 747 }
730 pSorter->aIdx[i] = &aBlob[nBlob] - a;
731 748
732 pSorter->aPoslist = a;
733 fts5CsrNewrow(pCsr); 749 fts5CsrNewrow(pCsr);
734 } 750 }
735 751
736 return rc; 752 return rc;
737 } 753 }
738 754
739 755
740 /* 756 /*
741 ** Set the FTS5CSR_REQUIRE_RESEEK flag on all FTS5_PLAN_MATCH cursors 757 ** Set the FTS5CSR_REQUIRE_RESEEK flag on all FTS5_PLAN_MATCH cursors
742 ** open on table pTab. 758 ** open on table pTab.
(...skipping 23 matching lines...) Expand all
766 */ 782 */
767 static int fts5CursorReseek(Fts5Cursor *pCsr, int *pbSkip){ 783 static int fts5CursorReseek(Fts5Cursor *pCsr, int *pbSkip){
768 int rc = SQLITE_OK; 784 int rc = SQLITE_OK;
769 assert( *pbSkip==0 ); 785 assert( *pbSkip==0 );
770 if( CsrFlagTest(pCsr, FTS5CSR_REQUIRE_RESEEK) ){ 786 if( CsrFlagTest(pCsr, FTS5CSR_REQUIRE_RESEEK) ){
771 Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab); 787 Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab);
772 int bDesc = pCsr->bDesc; 788 int bDesc = pCsr->bDesc;
773 i64 iRowid = sqlite3Fts5ExprRowid(pCsr->pExpr); 789 i64 iRowid = sqlite3Fts5ExprRowid(pCsr->pExpr);
774 790
775 rc = sqlite3Fts5ExprFirst(pCsr->pExpr, pTab->pIndex, iRowid, bDesc); 791 rc = sqlite3Fts5ExprFirst(pCsr->pExpr, pTab->pIndex, iRowid, bDesc);
776 if( rc==SQLITE_OK && iRowid!=sqlite3Fts5ExprRowid(pCsr->pExpr) ){ 792 if( rc==SQLITE_OK && iRowid!=sqlite3Fts5ExprRowid(pCsr->pExpr) ){
777 *pbSkip = 1; 793 *pbSkip = 1;
778 } 794 }
779 795
780 CsrFlagClear(pCsr, FTS5CSR_REQUIRE_RESEEK); 796 CsrFlagClear(pCsr, FTS5CSR_REQUIRE_RESEEK);
781 fts5CsrNewrow(pCsr); 797 fts5CsrNewrow(pCsr);
782 if( sqlite3Fts5ExprEof(pCsr->pExpr) ){ 798 if( sqlite3Fts5ExprEof(pCsr->pExpr) ){
783 CsrFlagSet(pCsr, FTS5CSR_EOF); 799 CsrFlagSet(pCsr, FTS5CSR_EOF);
800 *pbSkip = 1;
784 } 801 }
785 } 802 }
786 return rc; 803 return rc;
787 } 804 }
788 805
789 806
790 /* 807 /*
791 ** Advance the cursor to the next row in the table that matches the 808 ** Advance the cursor to the next row in the table that matches the
792 ** search criteria. 809 ** search criteria.
793 ** 810 **
794 ** Return SQLITE_OK if nothing goes wrong. SQLITE_OK is returned 811 ** Return SQLITE_OK if nothing goes wrong. SQLITE_OK is returned
795 ** even if we reach end-of-file. The fts5EofMethod() will be called 812 ** even if we reach end-of-file. The fts5EofMethod() will be called
796 ** subsequently to determine whether or not an EOF was hit. 813 ** subsequently to determine whether or not an EOF was hit.
797 */ 814 */
798 static int fts5NextMethod(sqlite3_vtab_cursor *pCursor){ 815 static int fts5NextMethod(sqlite3_vtab_cursor *pCursor){
799 Fts5Cursor *pCsr = (Fts5Cursor*)pCursor; 816 Fts5Cursor *pCsr = (Fts5Cursor*)pCursor;
800 int rc = SQLITE_OK; 817 int rc;
801 818
802 assert( (pCsr->ePlan<3)== 819 assert( (pCsr->ePlan<3)==
803 (pCsr->ePlan==FTS5_PLAN_MATCH || pCsr->ePlan==FTS5_PLAN_SOURCE) 820 (pCsr->ePlan==FTS5_PLAN_MATCH || pCsr->ePlan==FTS5_PLAN_SOURCE)
804 ); 821 );
822 assert( !CsrFlagTest(pCsr, FTS5CSR_EOF) );
805 823
806 if( pCsr->ePlan<3 ){ 824 if( pCsr->ePlan<3 ){
807 int bSkip = 0; 825 int bSkip = 0;
808 if( (rc = fts5CursorReseek(pCsr, &bSkip)) || bSkip ) return rc; 826 if( (rc = fts5CursorReseek(pCsr, &bSkip)) || bSkip ) return rc;
809 rc = sqlite3Fts5ExprNext(pCsr->pExpr, pCsr->iLastRowid); 827 rc = sqlite3Fts5ExprNext(pCsr->pExpr, pCsr->iLastRowid);
810 if( sqlite3Fts5ExprEof(pCsr->pExpr) ){ 828 CsrFlagSet(pCsr, sqlite3Fts5ExprEof(pCsr->pExpr));
811 CsrFlagSet(pCsr, FTS5CSR_EOF);
812 }
813 fts5CsrNewrow(pCsr); 829 fts5CsrNewrow(pCsr);
814 }else{ 830 }else{
815 switch( pCsr->ePlan ){ 831 switch( pCsr->ePlan ){
816 case FTS5_PLAN_SPECIAL: { 832 case FTS5_PLAN_SPECIAL: {
817 CsrFlagSet(pCsr, FTS5CSR_EOF); 833 CsrFlagSet(pCsr, FTS5CSR_EOF);
834 rc = SQLITE_OK;
818 break; 835 break;
819 } 836 }
820 837
821 case FTS5_PLAN_SORTED_MATCH: { 838 case FTS5_PLAN_SORTED_MATCH: {
822 rc = fts5SorterNext(pCsr); 839 rc = fts5SorterNext(pCsr);
823 break; 840 break;
824 } 841 }
825 842
826 default: 843 default:
827 rc = sqlite3_step(pCsr->pStmt); 844 rc = sqlite3_step(pCsr->pStmt);
828 if( rc!=SQLITE_ROW ){ 845 if( rc!=SQLITE_ROW ){
829 CsrFlagSet(pCsr, FTS5CSR_EOF); 846 CsrFlagSet(pCsr, FTS5CSR_EOF);
830 rc = sqlite3_reset(pCsr->pStmt); 847 rc = sqlite3_reset(pCsr->pStmt);
831 }else{ 848 }else{
832 rc = SQLITE_OK; 849 rc = SQLITE_OK;
833 } 850 }
834 break; 851 break;
835 } 852 }
836 } 853 }
837 854
838 return rc; 855 return rc;
839 } 856 }
840 857
841 858
842 static sqlite3_stmt *fts5PrepareStatement( 859 static int fts5PrepareStatement(
843 int *pRc, 860 sqlite3_stmt **ppStmt,
844 Fts5Config *pConfig, 861 Fts5Config *pConfig,
845 const char *zFmt, 862 const char *zFmt,
846 ... 863 ...
847 ){ 864 ){
848 sqlite3_stmt *pRet = 0; 865 sqlite3_stmt *pRet = 0;
866 int rc;
867 char *zSql;
849 va_list ap; 868 va_list ap;
869
850 va_start(ap, zFmt); 870 va_start(ap, zFmt);
851 871 zSql = sqlite3_vmprintf(zFmt, ap);
852 if( *pRc==SQLITE_OK ){ 872 if( zSql==0 ){
853 int rc; 873 rc = SQLITE_NOMEM;
854 char *zSql = sqlite3_vmprintf(zFmt, ap); 874 }else{
855 if( zSql==0 ){ 875 rc = sqlite3_prepare_v2(pConfig->db, zSql, -1, &pRet, 0);
856 rc = SQLITE_NOMEM; 876 if( rc!=SQLITE_OK ){
857 }else{ 877 *pConfig->pzErrmsg = sqlite3_mprintf("%s", sqlite3_errmsg(pConfig->db));
858 rc = sqlite3_prepare_v2(pConfig->db, zSql, -1, &pRet, 0);
859 if( rc!=SQLITE_OK ){
860 *pConfig->pzErrmsg = sqlite3_mprintf("%s", sqlite3_errmsg(pConfig->db));
861 }
862 sqlite3_free(zSql);
863 } 878 }
864 *pRc = rc; 879 sqlite3_free(zSql);
865 } 880 }
866 881
867 va_end(ap); 882 va_end(ap);
868 return pRet; 883 *ppStmt = pRet;
884 return rc;
869 } 885 }
870 886
871 static int fts5CursorFirstSorted(Fts5Table *pTab, Fts5Cursor *pCsr, int bDesc){ 887 static int fts5CursorFirstSorted(Fts5Table *pTab, Fts5Cursor *pCsr, int bDesc){
872 Fts5Config *pConfig = pTab->pConfig; 888 Fts5Config *pConfig = pTab->pConfig;
873 Fts5Sorter *pSorter; 889 Fts5Sorter *pSorter;
874 int nPhrase; 890 int nPhrase;
875 int nByte; 891 int nByte;
876 int rc = SQLITE_OK; 892 int rc;
877 const char *zRank = pCsr->zRank; 893 const char *zRank = pCsr->zRank;
878 const char *zRankArgs = pCsr->zRankArgs; 894 const char *zRankArgs = pCsr->zRankArgs;
879 895
880 nPhrase = sqlite3Fts5ExprPhraseCount(pCsr->pExpr); 896 nPhrase = sqlite3Fts5ExprPhraseCount(pCsr->pExpr);
881 nByte = sizeof(Fts5Sorter) + sizeof(int) * (nPhrase-1); 897 nByte = sizeof(Fts5Sorter) + sizeof(int) * (nPhrase-1);
882 pSorter = (Fts5Sorter*)sqlite3_malloc(nByte); 898 pSorter = (Fts5Sorter*)sqlite3_malloc(nByte);
883 if( pSorter==0 ) return SQLITE_NOMEM; 899 if( pSorter==0 ) return SQLITE_NOMEM;
884 memset(pSorter, 0, nByte); 900 memset(pSorter, 0, nByte);
885 pSorter->nIdx = nPhrase; 901 pSorter->nIdx = nPhrase;
886 902
887 /* TODO: It would be better to have some system for reusing statement 903 /* TODO: It would be better to have some system for reusing statement
888 ** handles here, rather than preparing a new one for each query. But that 904 ** handles here, rather than preparing a new one for each query. But that
889 ** is not possible as SQLite reference counts the virtual table objects. 905 ** is not possible as SQLite reference counts the virtual table objects.
890 ** And since the statement required here reads from this very virtual 906 ** And since the statement required here reads from this very virtual
891 ** table, saving it creates a circular reference. 907 ** table, saving it creates a circular reference.
892 ** 908 **
893 ** If SQLite a built-in statement cache, this wouldn't be a problem. */ 909 ** If SQLite a built-in statement cache, this wouldn't be a problem. */
894 pSorter->pStmt = fts5PrepareStatement(&rc, pConfig, 910 rc = fts5PrepareStatement(&pSorter->pStmt, pConfig,
895 "SELECT rowid, rank FROM %Q.%Q ORDER BY %s(%s%s%s) %s", 911 "SELECT rowid, rank FROM %Q.%Q ORDER BY %s(%s%s%s) %s",
896 pConfig->zDb, pConfig->zName, zRank, pConfig->zName, 912 pConfig->zDb, pConfig->zName, zRank, pConfig->zName,
897 (zRankArgs ? ", " : ""), 913 (zRankArgs ? ", " : ""),
898 (zRankArgs ? zRankArgs : ""), 914 (zRankArgs ? zRankArgs : ""),
899 bDesc ? "DESC" : "ASC" 915 bDesc ? "DESC" : "ASC"
900 ); 916 );
901 917
902 pCsr->pSorter = pSorter; 918 pCsr->pSorter = pSorter;
903 if( rc==SQLITE_OK ){ 919 if( rc==SQLITE_OK ){
904 assert( pTab->pSortCsr==0 ); 920 assert( pTab->pSortCsr==0 );
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after
1084 ** 1100 **
1085 ** There are three possible query strategies: 1101 ** There are three possible query strategies:
1086 ** 1102 **
1087 ** 1. Full-text search using a MATCH operator. 1103 ** 1. Full-text search using a MATCH operator.
1088 ** 2. A by-rowid lookup. 1104 ** 2. A by-rowid lookup.
1089 ** 3. A full-table scan. 1105 ** 3. A full-table scan.
1090 */ 1106 */
1091 static int fts5FilterMethod( 1107 static int fts5FilterMethod(
1092 sqlite3_vtab_cursor *pCursor, /* The cursor used for this query */ 1108 sqlite3_vtab_cursor *pCursor, /* The cursor used for this query */
1093 int idxNum, /* Strategy index */ 1109 int idxNum, /* Strategy index */
1094 const char *idxStr, /* Unused */ 1110 const char *zUnused, /* Unused */
1095 int nVal, /* Number of elements in apVal */ 1111 int nVal, /* Number of elements in apVal */
1096 sqlite3_value **apVal /* Arguments for the indexing scheme */ 1112 sqlite3_value **apVal /* Arguments for the indexing scheme */
1097 ){ 1113 ){
1098 Fts5Table *pTab = (Fts5Table*)(pCursor->pVtab); 1114 Fts5Table *pTab = (Fts5Table*)(pCursor->pVtab);
1099 Fts5Config *pConfig = pTab->pConfig; 1115 Fts5Config *pConfig = pTab->pConfig;
1100 Fts5Cursor *pCsr = (Fts5Cursor*)pCursor; 1116 Fts5Cursor *pCsr = (Fts5Cursor*)pCursor;
1101 int rc = SQLITE_OK; /* Error code */ 1117 int rc = SQLITE_OK; /* Error code */
1102 int iVal = 0; /* Counter for apVal[] */ 1118 int iVal = 0; /* Counter for apVal[] */
1103 int bDesc; /* True if ORDER BY [rank|rowid] DESC */ 1119 int bDesc; /* True if ORDER BY [rank|rowid] DESC */
1104 int bOrderByRank; /* True if ORDER BY rank */ 1120 int bOrderByRank; /* True if ORDER BY rank */
1105 sqlite3_value *pMatch = 0; /* <tbl> MATCH ? expression (or NULL) */ 1121 sqlite3_value *pMatch = 0; /* <tbl> MATCH ? expression (or NULL) */
1106 sqlite3_value *pRank = 0; /* rank MATCH ? expression (or NULL) */ 1122 sqlite3_value *pRank = 0; /* rank MATCH ? expression (or NULL) */
1107 sqlite3_value *pRowidEq = 0; /* rowid = ? expression (or NULL) */ 1123 sqlite3_value *pRowidEq = 0; /* rowid = ? expression (or NULL) */
1108 sqlite3_value *pRowidLe = 0; /* rowid <= ? expression (or NULL) */ 1124 sqlite3_value *pRowidLe = 0; /* rowid <= ? expression (or NULL) */
1109 sqlite3_value *pRowidGe = 0; /* rowid >= ? expression (or NULL) */ 1125 sqlite3_value *pRowidGe = 0; /* rowid >= ? expression (or NULL) */
1110 char **pzErrmsg = pConfig->pzErrmsg; 1126 char **pzErrmsg = pConfig->pzErrmsg;
1111 1127
1128 UNUSED_PARAM(zUnused);
1129 UNUSED_PARAM(nVal);
1130
1112 if( pCsr->ePlan ){ 1131 if( pCsr->ePlan ){
1113 fts5FreeCursorComponents(pCsr); 1132 fts5FreeCursorComponents(pCsr);
1114 memset(&pCsr->ePlan, 0, sizeof(Fts5Cursor) - ((u8*)&pCsr->ePlan-(u8*)pCsr)); 1133 memset(&pCsr->ePlan, 0, sizeof(Fts5Cursor) - ((u8*)&pCsr->ePlan-(u8*)pCsr));
1115 } 1134 }
1116 1135
1117 assert( pCsr->pStmt==0 ); 1136 assert( pCsr->pStmt==0 );
1118 assert( pCsr->pExpr==0 ); 1137 assert( pCsr->pExpr==0 );
1119 assert( pCsr->csrflags==0 ); 1138 assert( pCsr->csrflags==0 );
1120 assert( pCsr->pRank==0 ); 1139 assert( pCsr->pRank==0 );
1121 assert( pCsr->zRank==0 ); 1140 assert( pCsr->zRank==0 );
(...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after
1385 }else{ 1404 }else{
1386 rc = sqlite3Fts5StorageConfigValue(pTab->pStorage, zCmd, pVal, 0); 1405 rc = sqlite3Fts5StorageConfigValue(pTab->pStorage, zCmd, pVal, 0);
1387 } 1406 }
1388 } 1407 }
1389 } 1408 }
1390 return rc; 1409 return rc;
1391 } 1410 }
1392 1411
1393 static int fts5SpecialDelete( 1412 static int fts5SpecialDelete(
1394 Fts5Table *pTab, 1413 Fts5Table *pTab,
1395 sqlite3_value **apVal, 1414 sqlite3_value **apVal
1396 sqlite3_int64 *piRowid
1397 ){ 1415 ){
1398 int rc = SQLITE_OK; 1416 int rc = SQLITE_OK;
1399 int eType1 = sqlite3_value_type(apVal[1]); 1417 int eType1 = sqlite3_value_type(apVal[1]);
1400 if( eType1==SQLITE_INTEGER ){ 1418 if( eType1==SQLITE_INTEGER ){
1401 sqlite3_int64 iDel = sqlite3_value_int64(apVal[1]); 1419 sqlite3_int64 iDel = sqlite3_value_int64(apVal[1]);
1402 rc = sqlite3Fts5StorageSpecialDelete(pTab->pStorage, iDel, &apVal[2]); 1420 rc = sqlite3Fts5StorageDelete(pTab->pStorage, iDel, &apVal[2]);
1403 } 1421 }
1404 return rc; 1422 return rc;
1405 } 1423 }
1406 1424
1407 static void fts5StorageInsert( 1425 static void fts5StorageInsert(
1408 int *pRc, 1426 int *pRc,
1409 Fts5Table *pTab, 1427 Fts5Table *pTab,
1410 sqlite3_value **apVal, 1428 sqlite3_value **apVal,
1411 i64 *piRowid 1429 i64 *piRowid
1412 ){ 1430 ){
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
1462 1480
1463 eType0 = sqlite3_value_type(apVal[0]); 1481 eType0 = sqlite3_value_type(apVal[0]);
1464 if( eType0==SQLITE_NULL 1482 if( eType0==SQLITE_NULL
1465 && sqlite3_value_type(apVal[2+pConfig->nCol])!=SQLITE_NULL 1483 && sqlite3_value_type(apVal[2+pConfig->nCol])!=SQLITE_NULL
1466 ){ 1484 ){
1467 /* A "special" INSERT op. These are handled separately. */ 1485 /* A "special" INSERT op. These are handled separately. */
1468 const char *z = (const char*)sqlite3_value_text(apVal[2+pConfig->nCol]); 1486 const char *z = (const char*)sqlite3_value_text(apVal[2+pConfig->nCol]);
1469 if( pConfig->eContent!=FTS5_CONTENT_NORMAL 1487 if( pConfig->eContent!=FTS5_CONTENT_NORMAL
1470 && 0==sqlite3_stricmp("delete", z) 1488 && 0==sqlite3_stricmp("delete", z)
1471 ){ 1489 ){
1472 rc = fts5SpecialDelete(pTab, apVal, pRowid); 1490 rc = fts5SpecialDelete(pTab, apVal);
1473 }else{ 1491 }else{
1474 rc = fts5SpecialInsert(pTab, z, apVal[2 + pConfig->nCol + 1]); 1492 rc = fts5SpecialInsert(pTab, z, apVal[2 + pConfig->nCol + 1]);
1475 } 1493 }
1476 }else{ 1494 }else{
1477 /* A regular INSERT, UPDATE or DELETE statement. The trick here is that 1495 /* A regular INSERT, UPDATE or DELETE statement. The trick here is that
1478 ** any conflict on the rowid value must be detected before any 1496 ** any conflict on the rowid value must be detected before any
1479 ** modifications are made to the database file. There are 4 cases: 1497 ** modifications are made to the database file. There are 4 cases:
1480 ** 1498 **
1481 ** 1) DELETE 1499 ** 1) DELETE
1482 ** 2) UPDATE (rowid not modified) 1500 ** 2) UPDATE (rowid not modified)
(...skipping 13 matching lines...) Expand all
1496 /* Filter out attempts to run UPDATE or DELETE on contentless tables. 1514 /* Filter out attempts to run UPDATE or DELETE on contentless tables.
1497 ** This is not suported. */ 1515 ** This is not suported. */
1498 if( eType0==SQLITE_INTEGER && fts5IsContentless(pTab) ){ 1516 if( eType0==SQLITE_INTEGER && fts5IsContentless(pTab) ){
1499 pTab->base.zErrMsg = sqlite3_mprintf( 1517 pTab->base.zErrMsg = sqlite3_mprintf(
1500 "cannot %s contentless fts5 table: %s", 1518 "cannot %s contentless fts5 table: %s",
1501 (nArg>1 ? "UPDATE" : "DELETE from"), pConfig->zName 1519 (nArg>1 ? "UPDATE" : "DELETE from"), pConfig->zName
1502 ); 1520 );
1503 rc = SQLITE_ERROR; 1521 rc = SQLITE_ERROR;
1504 } 1522 }
1505 1523
1506 /* Case 1: DELETE */ 1524 /* DELETE */
1507 else if( nArg==1 ){ 1525 else if( nArg==1 ){
1508 i64 iDel = sqlite3_value_int64(apVal[0]); /* Rowid to delete */ 1526 i64 iDel = sqlite3_value_int64(apVal[0]); /* Rowid to delete */
1509 rc = sqlite3Fts5StorageDelete(pTab->pStorage, iDel); 1527 rc = sqlite3Fts5StorageDelete(pTab->pStorage, iDel, 0);
1510 } 1528 }
1511 1529
1512 /* Case 2: INSERT */ 1530 /* INSERT */
1513 else if( eType0!=SQLITE_INTEGER ){ 1531 else if( eType0!=SQLITE_INTEGER ){
1514 /* If this is a REPLACE, first remove the current entry (if any) */ 1532 /* If this is a REPLACE, first remove the current entry (if any) */
1515 if( eConflict==SQLITE_REPLACE 1533 if( eConflict==SQLITE_REPLACE
1516 && sqlite3_value_type(apVal[1])==SQLITE_INTEGER 1534 && sqlite3_value_type(apVal[1])==SQLITE_INTEGER
1517 ){ 1535 ){
1518 i64 iNew = sqlite3_value_int64(apVal[1]); /* Rowid to delete */ 1536 i64 iNew = sqlite3_value_int64(apVal[1]); /* Rowid to delete */
1519 rc = sqlite3Fts5StorageDelete(pTab->pStorage, iNew); 1537 rc = sqlite3Fts5StorageDelete(pTab->pStorage, iNew, 0);
1520 } 1538 }
1521 fts5StorageInsert(&rc, pTab, apVal, pRowid); 1539 fts5StorageInsert(&rc, pTab, apVal, pRowid);
1522 } 1540 }
1523 1541
1524 /* Case 2: UPDATE */ 1542 /* UPDATE */
1525 else{ 1543 else{
1526 i64 iOld = sqlite3_value_int64(apVal[0]); /* Old rowid */ 1544 i64 iOld = sqlite3_value_int64(apVal[0]); /* Old rowid */
1527 i64 iNew = sqlite3_value_int64(apVal[1]); /* New rowid */ 1545 i64 iNew = sqlite3_value_int64(apVal[1]); /* New rowid */
1528 if( iOld!=iNew ){ 1546 if( iOld!=iNew ){
1529 if( eConflict==SQLITE_REPLACE ){ 1547 if( eConflict==SQLITE_REPLACE ){
1530 rc = sqlite3Fts5StorageDelete(pTab->pStorage, iOld); 1548 rc = sqlite3Fts5StorageDelete(pTab->pStorage, iOld, 0);
1531 if( rc==SQLITE_OK ){ 1549 if( rc==SQLITE_OK ){
1532 rc = sqlite3Fts5StorageDelete(pTab->pStorage, iNew); 1550 rc = sqlite3Fts5StorageDelete(pTab->pStorage, iNew, 0);
1533 } 1551 }
1534 fts5StorageInsert(&rc, pTab, apVal, pRowid); 1552 fts5StorageInsert(&rc, pTab, apVal, pRowid);
1535 }else{ 1553 }else{
1536 rc = sqlite3Fts5StorageContentInsert(pTab->pStorage, apVal, pRowid); 1554 rc = sqlite3Fts5StorageContentInsert(pTab->pStorage, apVal, pRowid);
1537 if( rc==SQLITE_OK ){ 1555 if( rc==SQLITE_OK ){
1538 rc = sqlite3Fts5StorageDelete(pTab->pStorage, iOld); 1556 rc = sqlite3Fts5StorageDelete(pTab->pStorage, iOld, 0);
1539 } 1557 }
1540 if( rc==SQLITE_OK ){ 1558 if( rc==SQLITE_OK ){
1541 rc = sqlite3Fts5StorageIndexInsert(pTab->pStorage, apVal, *pRowid); 1559 rc = sqlite3Fts5StorageIndexInsert(pTab->pStorage, apVal, *pRowid);
1542 } 1560 }
1543 } 1561 }
1544 }else{ 1562 }else{
1545 rc = sqlite3Fts5StorageDelete(pTab->pStorage, iOld); 1563 rc = sqlite3Fts5StorageDelete(pTab->pStorage, iOld, 0);
1546 fts5StorageInsert(&rc, pTab, apVal, pRowid); 1564 fts5StorageInsert(&rc, pTab, apVal, pRowid);
1547 } 1565 }
1548 } 1566 }
1549 } 1567 }
1550 1568
1551 pTab->pConfig->pzErrmsg = 0; 1569 pTab->pConfig->pzErrmsg = 0;
1552 return rc; 1570 return rc;
1553 } 1571 }
1554 1572
1555 /* 1573 /*
1556 ** Implementation of xSync() method. 1574 ** Implementation of xSync() method.
1557 */ 1575 */
1558 static int fts5SyncMethod(sqlite3_vtab *pVtab){ 1576 static int fts5SyncMethod(sqlite3_vtab *pVtab){
1559 int rc; 1577 int rc;
1560 Fts5Table *pTab = (Fts5Table*)pVtab; 1578 Fts5Table *pTab = (Fts5Table*)pVtab;
1561 fts5CheckTransactionState(pTab, FTS5_SYNC, 0); 1579 fts5CheckTransactionState(pTab, FTS5_SYNC, 0);
1562 pTab->pConfig->pzErrmsg = &pTab->base.zErrMsg; 1580 pTab->pConfig->pzErrmsg = &pTab->base.zErrMsg;
1563 fts5TripCursors(pTab); 1581 fts5TripCursors(pTab);
1564 rc = sqlite3Fts5StorageSync(pTab->pStorage, 1); 1582 rc = sqlite3Fts5StorageSync(pTab->pStorage, 1);
1565 pTab->pConfig->pzErrmsg = 0; 1583 pTab->pConfig->pzErrmsg = 0;
1566 return rc; 1584 return rc;
1567 } 1585 }
1568 1586
1569 /* 1587 /*
1570 ** Implementation of xBegin() method. 1588 ** Implementation of xBegin() method.
1571 */ 1589 */
1572 static int fts5BeginMethod(sqlite3_vtab *pVtab){ 1590 static int fts5BeginMethod(sqlite3_vtab *pVtab){
1573 fts5CheckTransactionState((Fts5Table*)pVtab, FTS5_BEGIN, 0); 1591 fts5CheckTransactionState((Fts5Table*)pVtab, FTS5_BEGIN, 0);
1592 fts5NewTransaction((Fts5Table*)pVtab);
1574 return SQLITE_OK; 1593 return SQLITE_OK;
1575 } 1594 }
1576 1595
1577 /* 1596 /*
1578 ** Implementation of xCommit() method. This is a no-op. The contents of 1597 ** Implementation of xCommit() method. This is a no-op. The contents of
1579 ** the pending-terms hash-table have already been flushed into the database 1598 ** the pending-terms hash-table have already been flushed into the database
1580 ** by fts5SyncMethod(). 1599 ** by fts5SyncMethod().
1581 */ 1600 */
1582 static int fts5CommitMethod(sqlite3_vtab *pVtab){ 1601 static int fts5CommitMethod(sqlite3_vtab *pVtab){
1602 UNUSED_PARAM(pVtab); /* Call below is a no-op for NDEBUG builds */
1583 fts5CheckTransactionState((Fts5Table*)pVtab, FTS5_COMMIT, 0); 1603 fts5CheckTransactionState((Fts5Table*)pVtab, FTS5_COMMIT, 0);
1584 return SQLITE_OK; 1604 return SQLITE_OK;
1585 } 1605 }
1586 1606
1587 /* 1607 /*
1588 ** Implementation of xRollback(). Discard the contents of the pending-terms 1608 ** Implementation of xRollback(). Discard the contents of the pending-terms
1589 ** hash-table. Any changes made to the database are reverted by SQLite. 1609 ** hash-table. Any changes made to the database are reverted by SQLite.
1590 */ 1610 */
1591 static int fts5RollbackMethod(sqlite3_vtab *pVtab){ 1611 static int fts5RollbackMethod(sqlite3_vtab *pVtab){
1592 int rc; 1612 int rc;
1593 Fts5Table *pTab = (Fts5Table*)pVtab; 1613 Fts5Table *pTab = (Fts5Table*)pVtab;
1594 fts5CheckTransactionState(pTab, FTS5_ROLLBACK, 0); 1614 fts5CheckTransactionState(pTab, FTS5_ROLLBACK, 0);
1595 rc = sqlite3Fts5StorageRollback(pTab->pStorage); 1615 rc = sqlite3Fts5StorageRollback(pTab->pStorage);
1596 return rc; 1616 return rc;
1597 } 1617 }
1598 1618
1619 static int fts5CsrPoslist(Fts5Cursor*, int, const u8**, int*);
1620
1599 static void *fts5ApiUserData(Fts5Context *pCtx){ 1621 static void *fts5ApiUserData(Fts5Context *pCtx){
1600 Fts5Cursor *pCsr = (Fts5Cursor*)pCtx; 1622 Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
1601 return pCsr->pAux->pUserData; 1623 return pCsr->pAux->pUserData;
1602 } 1624 }
1603 1625
1604 static int fts5ApiColumnCount(Fts5Context *pCtx){ 1626 static int fts5ApiColumnCount(Fts5Context *pCtx){
1605 Fts5Cursor *pCsr = (Fts5Cursor*)pCtx; 1627 Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
1606 return ((Fts5Table*)(pCsr->base.pVtab))->pConfig->nCol; 1628 return ((Fts5Table*)(pCsr->base.pVtab))->pConfig->nCol;
1607 } 1629 }
1608 1630
(...skipping 29 matching lines...) Expand all
1638 static int fts5ApiPhraseCount(Fts5Context *pCtx){ 1660 static int fts5ApiPhraseCount(Fts5Context *pCtx){
1639 Fts5Cursor *pCsr = (Fts5Cursor*)pCtx; 1661 Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
1640 return sqlite3Fts5ExprPhraseCount(pCsr->pExpr); 1662 return sqlite3Fts5ExprPhraseCount(pCsr->pExpr);
1641 } 1663 }
1642 1664
1643 static int fts5ApiPhraseSize(Fts5Context *pCtx, int iPhrase){ 1665 static int fts5ApiPhraseSize(Fts5Context *pCtx, int iPhrase){
1644 Fts5Cursor *pCsr = (Fts5Cursor*)pCtx; 1666 Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
1645 return sqlite3Fts5ExprPhraseSize(pCsr->pExpr, iPhrase); 1667 return sqlite3Fts5ExprPhraseSize(pCsr->pExpr, iPhrase);
1646 } 1668 }
1647 1669
1648 static int fts5CsrPoslist(Fts5Cursor *pCsr, int iPhrase, const u8 **pa){ 1670 static int fts5ApiColumnText(
1649 int n; 1671 Fts5Context *pCtx,
1650 if( pCsr->pSorter ){ 1672 int iCol,
1673 const char **pz,
1674 int *pn
1675 ){
1676 int rc = SQLITE_OK;
1677 Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
1678 if( fts5IsContentless((Fts5Table*)(pCsr->base.pVtab)) ){
1679 *pz = 0;
1680 *pn = 0;
1681 }else{
1682 rc = fts5SeekCursor(pCsr, 0);
1683 if( rc==SQLITE_OK ){
1684 *pz = (const char*)sqlite3_column_text(pCsr->pStmt, iCol+1);
1685 *pn = sqlite3_column_bytes(pCsr->pStmt, iCol+1);
1686 }
1687 }
1688 return rc;
1689 }
1690
1691 static int fts5CsrPoslist(
1692 Fts5Cursor *pCsr,
1693 int iPhrase,
1694 const u8 **pa,
1695 int *pn
1696 ){
1697 Fts5Config *pConfig = ((Fts5Table*)(pCsr->base.pVtab))->pConfig;
1698 int rc = SQLITE_OK;
1699 int bLive = (pCsr->pSorter==0);
1700
1701 if( CsrFlagTest(pCsr, FTS5CSR_REQUIRE_POSLIST) ){
1702
1703 if( pConfig->eDetail!=FTS5_DETAIL_FULL ){
1704 Fts5PoslistPopulator *aPopulator;
1705 int i;
1706 aPopulator = sqlite3Fts5ExprClearPoslists(pCsr->pExpr, bLive);
1707 if( aPopulator==0 ) rc = SQLITE_NOMEM;
1708 for(i=0; i<pConfig->nCol && rc==SQLITE_OK; i++){
1709 int n; const char *z;
1710 rc = fts5ApiColumnText((Fts5Context*)pCsr, i, &z, &n);
1711 if( rc==SQLITE_OK ){
1712 rc = sqlite3Fts5ExprPopulatePoslists(
1713 pConfig, pCsr->pExpr, aPopulator, i, z, n
1714 );
1715 }
1716 }
1717 sqlite3_free(aPopulator);
1718
1719 if( pCsr->pSorter ){
1720 sqlite3Fts5ExprCheckPoslists(pCsr->pExpr, pCsr->pSorter->iRowid);
1721 }
1722 }
1723 CsrFlagClear(pCsr, FTS5CSR_REQUIRE_POSLIST);
1724 }
1725
1726 if( pCsr->pSorter && pConfig->eDetail==FTS5_DETAIL_FULL ){
1651 Fts5Sorter *pSorter = pCsr->pSorter; 1727 Fts5Sorter *pSorter = pCsr->pSorter;
1652 int i1 = (iPhrase==0 ? 0 : pSorter->aIdx[iPhrase-1]); 1728 int i1 = (iPhrase==0 ? 0 : pSorter->aIdx[iPhrase-1]);
1653 n = pSorter->aIdx[iPhrase] - i1; 1729 *pn = pSorter->aIdx[iPhrase] - i1;
1654 *pa = &pSorter->aPoslist[i1]; 1730 *pa = &pSorter->aPoslist[i1];
1655 }else{ 1731 }else{
1656 n = sqlite3Fts5ExprPoslist(pCsr->pExpr, iPhrase, pa); 1732 *pn = sqlite3Fts5ExprPoslist(pCsr->pExpr, iPhrase, pa);
1657 } 1733 }
1658 return n; 1734
1735 return rc;
1659 } 1736 }
1660 1737
1661 /* 1738 /*
1662 ** Ensure that the Fts5Cursor.nInstCount and aInst[] variables are populated 1739 ** Ensure that the Fts5Cursor.nInstCount and aInst[] variables are populated
1663 ** correctly for the current view. Return SQLITE_OK if successful, or an 1740 ** correctly for the current view. Return SQLITE_OK if successful, or an
1664 ** SQLite error code otherwise. 1741 ** SQLite error code otherwise.
1665 */ 1742 */
1666 static int fts5CacheInstArray(Fts5Cursor *pCsr){ 1743 static int fts5CacheInstArray(Fts5Cursor *pCsr){
1667 int rc = SQLITE_OK; 1744 int rc = SQLITE_OK;
1668 Fts5PoslistReader *aIter; /* One iterator for each phrase */ 1745 Fts5PoslistReader *aIter; /* One iterator for each phrase */
1669 int nIter; /* Number of iterators/phrases */ 1746 int nIter; /* Number of iterators/phrases */
1670 1747
1671 nIter = sqlite3Fts5ExprPhraseCount(pCsr->pExpr); 1748 nIter = sqlite3Fts5ExprPhraseCount(pCsr->pExpr);
1672 if( pCsr->aInstIter==0 ){ 1749 if( pCsr->aInstIter==0 ){
1673 int nByte = sizeof(Fts5PoslistReader) * nIter; 1750 int nByte = sizeof(Fts5PoslistReader) * nIter;
1674 pCsr->aInstIter = (Fts5PoslistReader*)sqlite3Fts5MallocZero(&rc, nByte); 1751 pCsr->aInstIter = (Fts5PoslistReader*)sqlite3Fts5MallocZero(&rc, nByte);
1675 } 1752 }
1676 aIter = pCsr->aInstIter; 1753 aIter = pCsr->aInstIter;
1677 1754
1678 if( aIter ){ 1755 if( aIter ){
1679 int nInst = 0; /* Number instances seen so far */ 1756 int nInst = 0; /* Number instances seen so far */
1680 int i; 1757 int i;
1681 1758
1682 /* Initialize all iterators */ 1759 /* Initialize all iterators */
1683 for(i=0; i<nIter; i++){ 1760 for(i=0; i<nIter && rc==SQLITE_OK; i++){
1684 const u8 *a; 1761 const u8 *a;
1685 int n = fts5CsrPoslist(pCsr, i, &a); 1762 int n;
1686 sqlite3Fts5PoslistReaderInit(a, n, &aIter[i]); 1763 rc = fts5CsrPoslist(pCsr, i, &a, &n);
1764 if( rc==SQLITE_OK ){
1765 sqlite3Fts5PoslistReaderInit(a, n, &aIter[i]);
1766 }
1687 } 1767 }
1688 1768
1689 while( 1 ){ 1769 if( rc==SQLITE_OK ){
1690 int *aInst; 1770 while( 1 ){
1691 int iBest = -1; 1771 int *aInst;
1692 for(i=0; i<nIter; i++){ 1772 int iBest = -1;
1693 if( (aIter[i].bEof==0) 1773 for(i=0; i<nIter; i++){
1694 && (iBest<0 || aIter[i].iPos<aIter[iBest].iPos) 1774 if( (aIter[i].bEof==0)
1695 ){ 1775 && (iBest<0 || aIter[i].iPos<aIter[iBest].iPos)
1696 iBest = i; 1776 ){
1777 iBest = i;
1778 }
1697 } 1779 }
1780 if( iBest<0 ) break;
1781
1782 nInst++;
1783 if( nInst>=pCsr->nInstAlloc ){
1784 pCsr->nInstAlloc = pCsr->nInstAlloc ? pCsr->nInstAlloc*2 : 32;
1785 aInst = (int*)sqlite3_realloc(
1786 pCsr->aInst, pCsr->nInstAlloc*sizeof(int)*3
1787 );
1788 if( aInst ){
1789 pCsr->aInst = aInst;
1790 }else{
1791 rc = SQLITE_NOMEM;
1792 break;
1793 }
1794 }
1795
1796 aInst = &pCsr->aInst[3 * (nInst-1)];
1797 aInst[0] = iBest;
1798 aInst[1] = FTS5_POS2COLUMN(aIter[iBest].iPos);
1799 aInst[2] = FTS5_POS2OFFSET(aIter[iBest].iPos);
1800 sqlite3Fts5PoslistReaderNext(&aIter[iBest]);
1698 } 1801 }
1699 if( iBest<0 ) break;
1700
1701 nInst++;
1702 if( nInst>=pCsr->nInstAlloc ){
1703 pCsr->nInstAlloc = pCsr->nInstAlloc ? pCsr->nInstAlloc*2 : 32;
1704 aInst = (int*)sqlite3_realloc(
1705 pCsr->aInst, pCsr->nInstAlloc*sizeof(int)*3
1706 );
1707 if( aInst ){
1708 pCsr->aInst = aInst;
1709 }else{
1710 rc = SQLITE_NOMEM;
1711 break;
1712 }
1713 }
1714
1715 aInst = &pCsr->aInst[3 * (nInst-1)];
1716 aInst[0] = iBest;
1717 aInst[1] = FTS5_POS2COLUMN(aIter[iBest].iPos);
1718 aInst[2] = FTS5_POS2OFFSET(aIter[iBest].iPos);
1719 sqlite3Fts5PoslistReaderNext(&aIter[iBest]);
1720 } 1802 }
1721 1803
1722 pCsr->nInstCount = nInst; 1804 pCsr->nInstCount = nInst;
1723 CsrFlagClear(pCsr, FTS5CSR_REQUIRE_INST); 1805 CsrFlagClear(pCsr, FTS5CSR_REQUIRE_INST);
1724 } 1806 }
1725 return rc; 1807 return rc;
1726 } 1808 }
1727 1809
1728 static int fts5ApiInstCount(Fts5Context *pCtx, int *pnInst){ 1810 static int fts5ApiInstCount(Fts5Context *pCtx, int *pnInst){
1729 Fts5Cursor *pCsr = (Fts5Cursor*)pCtx; 1811 Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
(...skipping 12 matching lines...) Expand all
1742 int *piCol, 1824 int *piCol,
1743 int *piOff 1825 int *piOff
1744 ){ 1826 ){
1745 Fts5Cursor *pCsr = (Fts5Cursor*)pCtx; 1827 Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
1746 int rc = SQLITE_OK; 1828 int rc = SQLITE_OK;
1747 if( CsrFlagTest(pCsr, FTS5CSR_REQUIRE_INST)==0 1829 if( CsrFlagTest(pCsr, FTS5CSR_REQUIRE_INST)==0
1748 || SQLITE_OK==(rc = fts5CacheInstArray(pCsr)) 1830 || SQLITE_OK==(rc = fts5CacheInstArray(pCsr))
1749 ){ 1831 ){
1750 if( iIdx<0 || iIdx>=pCsr->nInstCount ){ 1832 if( iIdx<0 || iIdx>=pCsr->nInstCount ){
1751 rc = SQLITE_RANGE; 1833 rc = SQLITE_RANGE;
1834 #if 0
1835 }else if( fts5IsOffsetless((Fts5Table*)pCsr->base.pVtab) ){
1836 *piPhrase = pCsr->aInst[iIdx*3];
1837 *piCol = pCsr->aInst[iIdx*3 + 2];
1838 *piOff = -1;
1839 #endif
1752 }else{ 1840 }else{
1753 *piPhrase = pCsr->aInst[iIdx*3]; 1841 *piPhrase = pCsr->aInst[iIdx*3];
1754 *piCol = pCsr->aInst[iIdx*3 + 1]; 1842 *piCol = pCsr->aInst[iIdx*3 + 1];
1755 *piOff = pCsr->aInst[iIdx*3 + 2]; 1843 *piOff = pCsr->aInst[iIdx*3 + 2];
1756 } 1844 }
1757 } 1845 }
1758 return rc; 1846 return rc;
1759 } 1847 }
1760 1848
1761 static sqlite3_int64 fts5ApiRowid(Fts5Context *pCtx){ 1849 static sqlite3_int64 fts5ApiRowid(Fts5Context *pCtx){
1762 return fts5CursorRowid((Fts5Cursor*)pCtx); 1850 return fts5CursorRowid((Fts5Cursor*)pCtx);
1763 } 1851 }
1764 1852
1765 static int fts5ApiColumnText(
1766 Fts5Context *pCtx,
1767 int iCol,
1768 const char **pz,
1769 int *pn
1770 ){
1771 int rc = SQLITE_OK;
1772 Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
1773 if( fts5IsContentless((Fts5Table*)(pCsr->base.pVtab)) ){
1774 *pz = 0;
1775 *pn = 0;
1776 }else{
1777 rc = fts5SeekCursor(pCsr, 0);
1778 if( rc==SQLITE_OK ){
1779 *pz = (const char*)sqlite3_column_text(pCsr->pStmt, iCol+1);
1780 *pn = sqlite3_column_bytes(pCsr->pStmt, iCol+1);
1781 }
1782 }
1783 return rc;
1784 }
1785
1786 static int fts5ColumnSizeCb( 1853 static int fts5ColumnSizeCb(
1787 void *pContext, /* Pointer to int */ 1854 void *pContext, /* Pointer to int */
1788 int tflags, 1855 int tflags,
1789 const char *pToken, /* Buffer containing token */ 1856 const char *pUnused, /* Buffer containing token */
1790 int nToken, /* Size of token in bytes */ 1857 int nUnused, /* Size of token in bytes */
1791 int iStart, /* Start offset of token */ 1858 int iUnused1, /* Start offset of token */
1792 int iEnd /* End offset of token */ 1859 int iUnused2 /* End offset of token */
1793 ){ 1860 ){
1794 int *pCnt = (int*)pContext; 1861 int *pCnt = (int*)pContext;
1862 UNUSED_PARAM2(pUnused, nUnused);
1863 UNUSED_PARAM2(iUnused1, iUnused2);
1795 if( (tflags & FTS5_TOKEN_COLOCATED)==0 ){ 1864 if( (tflags & FTS5_TOKEN_COLOCATED)==0 ){
1796 (*pCnt)++; 1865 (*pCnt)++;
1797 } 1866 }
1798 return SQLITE_OK; 1867 return SQLITE_OK;
1799 } 1868 }
1800 1869
1801 static int fts5ApiColumnSize(Fts5Context *pCtx, int iCol, int *pnToken){ 1870 static int fts5ApiColumnSize(Fts5Context *pCtx, int iCol, int *pnToken){
1802 Fts5Cursor *pCsr = (Fts5Cursor*)pCtx; 1871 Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
1803 Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab); 1872 Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab);
1804 Fts5Config *pConfig = pTab->pConfig; 1873 Fts5Config *pConfig = pTab->pConfig;
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
1900 if( bClear ){ 1969 if( bClear ){
1901 pData->pPtr = 0; 1970 pData->pPtr = 0;
1902 pData->xDelete = 0; 1971 pData->xDelete = 0;
1903 } 1972 }
1904 } 1973 }
1905 1974
1906 return pRet; 1975 return pRet;
1907 } 1976 }
1908 1977
1909 static void fts5ApiPhraseNext( 1978 static void fts5ApiPhraseNext(
1910 Fts5Context *pCtx, 1979 Fts5Context *pUnused,
1911 Fts5PhraseIter *pIter, 1980 Fts5PhraseIter *pIter,
1912 int *piCol, int *piOff 1981 int *piCol, int *piOff
1913 ){ 1982 ){
1983 UNUSED_PARAM(pUnused);
1914 if( pIter->a>=pIter->b ){ 1984 if( pIter->a>=pIter->b ){
1915 *piCol = -1; 1985 *piCol = -1;
1916 *piOff = -1; 1986 *piOff = -1;
1917 }else{ 1987 }else{
1918 int iVal; 1988 int iVal;
1919 pIter->a += fts5GetVarint32(pIter->a, iVal); 1989 pIter->a += fts5GetVarint32(pIter->a, iVal);
1920 if( iVal==1 ){ 1990 if( iVal==1 ){
1921 pIter->a += fts5GetVarint32(pIter->a, iVal); 1991 pIter->a += fts5GetVarint32(pIter->a, iVal);
1922 *piCol = iVal; 1992 *piCol = iVal;
1923 *piOff = 0; 1993 *piOff = 0;
1924 pIter->a += fts5GetVarint32(pIter->a, iVal); 1994 pIter->a += fts5GetVarint32(pIter->a, iVal);
1925 } 1995 }
1926 *piOff += (iVal-2); 1996 *piOff += (iVal-2);
1927 } 1997 }
1928 } 1998 }
1929 1999
1930 static void fts5ApiPhraseFirst( 2000 static int fts5ApiPhraseFirst(
1931 Fts5Context *pCtx, 2001 Fts5Context *pCtx,
1932 int iPhrase, 2002 int iPhrase,
1933 Fts5PhraseIter *pIter, 2003 Fts5PhraseIter *pIter,
1934 int *piCol, int *piOff 2004 int *piCol, int *piOff
1935 ){ 2005 ){
1936 Fts5Cursor *pCsr = (Fts5Cursor*)pCtx; 2006 Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
1937 int n = fts5CsrPoslist(pCsr, iPhrase, &pIter->a); 2007 int n;
1938 pIter->b = &pIter->a[n]; 2008 int rc = fts5CsrPoslist(pCsr, iPhrase, &pIter->a, &n);
1939 *piCol = 0; 2009 if( rc==SQLITE_OK ){
1940 *piOff = 0; 2010 pIter->b = &pIter->a[n];
1941 fts5ApiPhraseNext(pCtx, pIter, piCol, piOff); 2011 *piCol = 0;
2012 *piOff = 0;
2013 fts5ApiPhraseNext(pCtx, pIter, piCol, piOff);
2014 }
2015 return rc;
1942 } 2016 }
1943 2017
2018 static void fts5ApiPhraseNextColumn(
2019 Fts5Context *pCtx,
2020 Fts5PhraseIter *pIter,
2021 int *piCol
2022 ){
2023 Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
2024 Fts5Config *pConfig = ((Fts5Table*)(pCsr->base.pVtab))->pConfig;
2025
2026 if( pConfig->eDetail==FTS5_DETAIL_COLUMNS ){
2027 if( pIter->a>=pIter->b ){
2028 *piCol = -1;
2029 }else{
2030 int iIncr;
2031 pIter->a += fts5GetVarint32(&pIter->a[0], iIncr);
2032 *piCol += (iIncr-2);
2033 }
2034 }else{
2035 while( 1 ){
2036 int dummy;
2037 if( pIter->a>=pIter->b ){
2038 *piCol = -1;
2039 return;
2040 }
2041 if( pIter->a[0]==0x01 ) break;
2042 pIter->a += fts5GetVarint32(pIter->a, dummy);
2043 }
2044 pIter->a += 1 + fts5GetVarint32(&pIter->a[1], *piCol);
2045 }
2046 }
2047
2048 static int fts5ApiPhraseFirstColumn(
2049 Fts5Context *pCtx,
2050 int iPhrase,
2051 Fts5PhraseIter *pIter,
2052 int *piCol
2053 ){
2054 int rc = SQLITE_OK;
2055 Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
2056 Fts5Config *pConfig = ((Fts5Table*)(pCsr->base.pVtab))->pConfig;
2057
2058 if( pConfig->eDetail==FTS5_DETAIL_COLUMNS ){
2059 Fts5Sorter *pSorter = pCsr->pSorter;
2060 int n;
2061 if( pSorter ){
2062 int i1 = (iPhrase==0 ? 0 : pSorter->aIdx[iPhrase-1]);
2063 n = pSorter->aIdx[iPhrase] - i1;
2064 pIter->a = &pSorter->aPoslist[i1];
2065 }else{
2066 rc = sqlite3Fts5ExprPhraseCollist(pCsr->pExpr, iPhrase, &pIter->a, &n);
2067 }
2068 if( rc==SQLITE_OK ){
2069 pIter->b = &pIter->a[n];
2070 *piCol = 0;
2071 fts5ApiPhraseNextColumn(pCtx, pIter, piCol);
2072 }
2073 }else{
2074 int n;
2075 rc = fts5CsrPoslist(pCsr, iPhrase, &pIter->a, &n);
2076 if( rc==SQLITE_OK ){
2077 pIter->b = &pIter->a[n];
2078 if( n<=0 ){
2079 *piCol = -1;
2080 }else if( pIter->a[0]==0x01 ){
2081 pIter->a += 1 + fts5GetVarint32(&pIter->a[1], *piCol);
2082 }else{
2083 *piCol = 0;
2084 }
2085 }
2086 }
2087
2088 return rc;
2089 }
2090
2091
1944 static int fts5ApiQueryPhrase(Fts5Context*, int, void*, 2092 static int fts5ApiQueryPhrase(Fts5Context*, int, void*,
1945 int(*)(const Fts5ExtensionApi*, Fts5Context*, void*) 2093 int(*)(const Fts5ExtensionApi*, Fts5Context*, void*)
1946 ); 2094 );
1947 2095
1948 static const Fts5ExtensionApi sFts5Api = { 2096 static const Fts5ExtensionApi sFts5Api = {
1949 2, /* iVersion */ 2097 2, /* iVersion */
1950 fts5ApiUserData, 2098 fts5ApiUserData,
1951 fts5ApiColumnCount, 2099 fts5ApiColumnCount,
1952 fts5ApiRowCount, 2100 fts5ApiRowCount,
1953 fts5ApiColumnTotalSize, 2101 fts5ApiColumnTotalSize,
1954 fts5ApiTokenize, 2102 fts5ApiTokenize,
1955 fts5ApiPhraseCount, 2103 fts5ApiPhraseCount,
1956 fts5ApiPhraseSize, 2104 fts5ApiPhraseSize,
1957 fts5ApiInstCount, 2105 fts5ApiInstCount,
1958 fts5ApiInst, 2106 fts5ApiInst,
1959 fts5ApiRowid, 2107 fts5ApiRowid,
1960 fts5ApiColumnText, 2108 fts5ApiColumnText,
1961 fts5ApiColumnSize, 2109 fts5ApiColumnSize,
1962 fts5ApiQueryPhrase, 2110 fts5ApiQueryPhrase,
1963 fts5ApiSetAuxdata, 2111 fts5ApiSetAuxdata,
1964 fts5ApiGetAuxdata, 2112 fts5ApiGetAuxdata,
1965 fts5ApiPhraseFirst, 2113 fts5ApiPhraseFirst,
1966 fts5ApiPhraseNext, 2114 fts5ApiPhraseNext,
2115 fts5ApiPhraseFirstColumn,
2116 fts5ApiPhraseNextColumn,
1967 }; 2117 };
1968 2118
1969
1970 /* 2119 /*
1971 ** Implementation of API function xQueryPhrase(). 2120 ** Implementation of API function xQueryPhrase().
1972 */ 2121 */
1973 static int fts5ApiQueryPhrase( 2122 static int fts5ApiQueryPhrase(
1974 Fts5Context *pCtx, 2123 Fts5Context *pCtx,
1975 int iPhrase, 2124 int iPhrase,
1976 void *pUserData, 2125 void *pUserData,
1977 int(*xCallback)(const Fts5ExtensionApi*, Fts5Context*, void*) 2126 int(*xCallback)(const Fts5ExtensionApi*, Fts5Context*, void*)
1978 ){ 2127 ){
1979 Fts5Cursor *pCsr = (Fts5Cursor*)pCtx; 2128 Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
1980 Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab); 2129 Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab);
1981 int rc; 2130 int rc;
1982 Fts5Cursor *pNew = 0; 2131 Fts5Cursor *pNew = 0;
1983 2132
1984 rc = fts5OpenMethod(pCsr->base.pVtab, (sqlite3_vtab_cursor**)&pNew); 2133 rc = fts5OpenMethod(pCsr->base.pVtab, (sqlite3_vtab_cursor**)&pNew);
1985 if( rc==SQLITE_OK ){ 2134 if( rc==SQLITE_OK ){
1986 Fts5Config *pConf = pTab->pConfig;
1987 pNew->ePlan = FTS5_PLAN_MATCH; 2135 pNew->ePlan = FTS5_PLAN_MATCH;
1988 pNew->iFirstRowid = SMALLEST_INT64; 2136 pNew->iFirstRowid = SMALLEST_INT64;
1989 pNew->iLastRowid = LARGEST_INT64; 2137 pNew->iLastRowid = LARGEST_INT64;
1990 pNew->base.pVtab = (sqlite3_vtab*)pTab; 2138 pNew->base.pVtab = (sqlite3_vtab*)pTab;
1991 rc = sqlite3Fts5ExprClonePhrase(pConf, pCsr->pExpr, iPhrase, &pNew->pExpr); 2139 rc = sqlite3Fts5ExprClonePhrase(pCsr->pExpr, iPhrase, &pNew->pExpr);
1992 } 2140 }
1993 2141
1994 if( rc==SQLITE_OK ){ 2142 if( rc==SQLITE_OK ){
1995 for(rc = fts5CursorFirst(pTab, pNew, 0); 2143 for(rc = fts5CursorFirst(pTab, pNew, 0);
1996 rc==SQLITE_OK && CsrFlagTest(pNew, FTS5CSR_EOF)==0; 2144 rc==SQLITE_OK && CsrFlagTest(pNew, FTS5CSR_EOF)==0;
1997 rc = fts5NextMethod((sqlite3_vtab_cursor*)pNew) 2145 rc = fts5NextMethod((sqlite3_vtab_cursor*)pNew)
1998 ){ 2146 ){
1999 rc = xCallback(&sFts5Api, (Fts5Context*)pNew, pUserData); 2147 rc = xCallback(&sFts5Api, (Fts5Context*)pNew, pUserData);
2000 if( rc!=SQLITE_OK ){ 2148 if( rc!=SQLITE_OK ){
2001 if( rc==SQLITE_DONE ) rc = SQLITE_OK; 2149 if( rc==SQLITE_DONE ) rc = SQLITE_OK;
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
2091 ** list 1. And so on. There is no size field for the final position list, 2239 ** list 1. And so on. There is no size field for the final position list,
2092 ** as it can be derived from the total size of the blob. 2240 ** as it can be derived from the total size of the blob.
2093 */ 2241 */
2094 static int fts5PoslistBlob(sqlite3_context *pCtx, Fts5Cursor *pCsr){ 2242 static int fts5PoslistBlob(sqlite3_context *pCtx, Fts5Cursor *pCsr){
2095 int i; 2243 int i;
2096 int rc = SQLITE_OK; 2244 int rc = SQLITE_OK;
2097 int nPhrase = sqlite3Fts5ExprPhraseCount(pCsr->pExpr); 2245 int nPhrase = sqlite3Fts5ExprPhraseCount(pCsr->pExpr);
2098 Fts5Buffer val; 2246 Fts5Buffer val;
2099 2247
2100 memset(&val, 0, sizeof(Fts5Buffer)); 2248 memset(&val, 0, sizeof(Fts5Buffer));
2249 switch( ((Fts5Table*)(pCsr->base.pVtab))->pConfig->eDetail ){
2250 case FTS5_DETAIL_FULL:
2101 2251
2102 /* Append the varints */ 2252 /* Append the varints */
2103 for(i=0; i<(nPhrase-1); i++){ 2253 for(i=0; i<(nPhrase-1); i++){
2104 const u8 *dummy; 2254 const u8 *dummy;
2105 int nByte = sqlite3Fts5ExprPoslist(pCsr->pExpr, i, &dummy); 2255 int nByte = sqlite3Fts5ExprPoslist(pCsr->pExpr, i, &dummy);
2106 sqlite3Fts5BufferAppendVarint(&rc, &val, nByte); 2256 sqlite3Fts5BufferAppendVarint(&rc, &val, nByte);
2107 } 2257 }
2108 2258
2109 /* Append the position lists */ 2259 /* Append the position lists */
2110 for(i=0; i<nPhrase; i++){ 2260 for(i=0; i<nPhrase; i++){
2111 const u8 *pPoslist; 2261 const u8 *pPoslist;
2112 int nPoslist; 2262 int nPoslist;
2113 nPoslist = sqlite3Fts5ExprPoslist(pCsr->pExpr, i, &pPoslist); 2263 nPoslist = sqlite3Fts5ExprPoslist(pCsr->pExpr, i, &pPoslist);
2114 sqlite3Fts5BufferAppendBlob(&rc, &val, nPoslist, pPoslist); 2264 sqlite3Fts5BufferAppendBlob(&rc, &val, nPoslist, pPoslist);
2265 }
2266 break;
2267
2268 case FTS5_DETAIL_COLUMNS:
2269
2270 /* Append the varints */
2271 for(i=0; rc==SQLITE_OK && i<(nPhrase-1); i++){
2272 const u8 *dummy;
2273 int nByte;
2274 rc = sqlite3Fts5ExprPhraseCollist(pCsr->pExpr, i, &dummy, &nByte);
2275 sqlite3Fts5BufferAppendVarint(&rc, &val, nByte);
2276 }
2277
2278 /* Append the position lists */
2279 for(i=0; rc==SQLITE_OK && i<nPhrase; i++){
2280 const u8 *pPoslist;
2281 int nPoslist;
2282 rc = sqlite3Fts5ExprPhraseCollist(pCsr->pExpr, i, &pPoslist, &nPoslist);
2283 sqlite3Fts5BufferAppendBlob(&rc, &val, nPoslist, pPoslist);
2284 }
2285 break;
2286
2287 default:
2288 break;
2115 } 2289 }
2116 2290
2117 sqlite3_result_blob(pCtx, val.p, val.n, sqlite3_free); 2291 sqlite3_result_blob(pCtx, val.p, val.n, sqlite3_free);
2118 return rc; 2292 return rc;
2119 } 2293 }
2120 2294
2121 /* 2295 /*
2122 ** This is the xColumn method, called by SQLite to request a value from 2296 ** This is the xColumn method, called by SQLite to request a value from
2123 ** the row that the supplied cursor currently points to. 2297 ** the row that the supplied cursor currently points to.
2124 */ 2298 */
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
2168 return rc; 2342 return rc;
2169 } 2343 }
2170 2344
2171 2345
2172 /* 2346 /*
2173 ** This routine implements the xFindFunction method for the FTS3 2347 ** This routine implements the xFindFunction method for the FTS3
2174 ** virtual table. 2348 ** virtual table.
2175 */ 2349 */
2176 static int fts5FindFunctionMethod( 2350 static int fts5FindFunctionMethod(
2177 sqlite3_vtab *pVtab, /* Virtual table handle */ 2351 sqlite3_vtab *pVtab, /* Virtual table handle */
2178 int nArg, /* Number of SQL function arguments */ 2352 int nUnused, /* Number of SQL function arguments */
2179 const char *zName, /* Name of SQL function */ 2353 const char *zName, /* Name of SQL function */
2180 void (**pxFunc)(sqlite3_context*,int,sqlite3_value**), /* OUT: Result */ 2354 void (**pxFunc)(sqlite3_context*,int,sqlite3_value**), /* OUT: Result */
2181 void **ppArg /* OUT: User data for *pxFunc */ 2355 void **ppArg /* OUT: User data for *pxFunc */
2182 ){ 2356 ){
2183 Fts5Table *pTab = (Fts5Table*)pVtab; 2357 Fts5Table *pTab = (Fts5Table*)pVtab;
2184 Fts5Auxiliary *pAux; 2358 Fts5Auxiliary *pAux;
2185 2359
2360 UNUSED_PARAM(nUnused);
2186 pAux = fts5FindAuxiliary(pTab, zName); 2361 pAux = fts5FindAuxiliary(pTab, zName);
2187 if( pAux ){ 2362 if( pAux ){
2188 *pxFunc = fts5ApiCallback; 2363 *pxFunc = fts5ApiCallback;
2189 *ppArg = (void*)pAux; 2364 *ppArg = (void*)pAux;
2190 return 1; 2365 return 1;
2191 } 2366 }
2192 2367
2193 /* No function of the specified name was found. Return 0. */ 2368 /* No function of the specified name was found. Return 0. */
2194 return 0; 2369 return 0;
2195 } 2370 }
2196 2371
2197 /* 2372 /*
2198 ** Implementation of FTS5 xRename method. Rename an fts5 table. 2373 ** Implementation of FTS5 xRename method. Rename an fts5 table.
2199 */ 2374 */
2200 static int fts5RenameMethod( 2375 static int fts5RenameMethod(
2201 sqlite3_vtab *pVtab, /* Virtual table handle */ 2376 sqlite3_vtab *pVtab, /* Virtual table handle */
2202 const char *zName /* New name of table */ 2377 const char *zName /* New name of table */
2203 ){ 2378 ){
2204 Fts5Table *pTab = (Fts5Table*)pVtab; 2379 Fts5Table *pTab = (Fts5Table*)pVtab;
2205 return sqlite3Fts5StorageRename(pTab->pStorage, zName); 2380 return sqlite3Fts5StorageRename(pTab->pStorage, zName);
2206 } 2381 }
2207 2382
2208 /* 2383 /*
2209 ** The xSavepoint() method. 2384 ** The xSavepoint() method.
2210 ** 2385 **
2211 ** Flush the contents of the pending-terms table to disk. 2386 ** Flush the contents of the pending-terms table to disk.
2212 */ 2387 */
2213 static int fts5SavepointMethod(sqlite3_vtab *pVtab, int iSavepoint){ 2388 static int fts5SavepointMethod(sqlite3_vtab *pVtab, int iSavepoint){
2214 Fts5Table *pTab = (Fts5Table*)pVtab; 2389 Fts5Table *pTab = (Fts5Table*)pVtab;
2390 UNUSED_PARAM(iSavepoint); /* Call below is a no-op for NDEBUG builds */
2215 fts5CheckTransactionState(pTab, FTS5_SAVEPOINT, iSavepoint); 2391 fts5CheckTransactionState(pTab, FTS5_SAVEPOINT, iSavepoint);
2216 fts5TripCursors(pTab); 2392 fts5TripCursors(pTab);
2217 return sqlite3Fts5StorageSync(pTab->pStorage, 0); 2393 return sqlite3Fts5StorageSync(pTab->pStorage, 0);
2218 } 2394 }
2219 2395
2220 /* 2396 /*
2221 ** The xRelease() method. 2397 ** The xRelease() method.
2222 ** 2398 **
2223 ** This is a no-op. 2399 ** This is a no-op.
2224 */ 2400 */
2225 static int fts5ReleaseMethod(sqlite3_vtab *pVtab, int iSavepoint){ 2401 static int fts5ReleaseMethod(sqlite3_vtab *pVtab, int iSavepoint){
2226 Fts5Table *pTab = (Fts5Table*)pVtab; 2402 Fts5Table *pTab = (Fts5Table*)pVtab;
2403 UNUSED_PARAM(iSavepoint); /* Call below is a no-op for NDEBUG builds */
2227 fts5CheckTransactionState(pTab, FTS5_RELEASE, iSavepoint); 2404 fts5CheckTransactionState(pTab, FTS5_RELEASE, iSavepoint);
2228 fts5TripCursors(pTab); 2405 fts5TripCursors(pTab);
2229 return sqlite3Fts5StorageSync(pTab->pStorage, 0); 2406 return sqlite3Fts5StorageSync(pTab->pStorage, 0);
2230 } 2407 }
2231 2408
2232 /* 2409 /*
2233 ** The xRollbackTo() method. 2410 ** The xRollbackTo() method.
2234 ** 2411 **
2235 ** Discard the contents of the pending terms table. 2412 ** Discard the contents of the pending terms table.
2236 */ 2413 */
2237 static int fts5RollbackToMethod(sqlite3_vtab *pVtab, int iSavepoint){ 2414 static int fts5RollbackToMethod(sqlite3_vtab *pVtab, int iSavepoint){
2238 Fts5Table *pTab = (Fts5Table*)pVtab; 2415 Fts5Table *pTab = (Fts5Table*)pVtab;
2416 UNUSED_PARAM(iSavepoint); /* Call below is a no-op for NDEBUG builds */
2239 fts5CheckTransactionState(pTab, FTS5_ROLLBACKTO, iSavepoint); 2417 fts5CheckTransactionState(pTab, FTS5_ROLLBACKTO, iSavepoint);
2240 fts5TripCursors(pTab); 2418 fts5TripCursors(pTab);
2241 return sqlite3Fts5StorageRollback(pTab->pStorage); 2419 return sqlite3Fts5StorageRollback(pTab->pStorage);
2242 } 2420 }
2243 2421
2244 /* 2422 /*
2245 ** Register a new auxiliary function with global context pGlobal. 2423 ** Register a new auxiliary function with global context pGlobal.
2246 */ 2424 */
2247 static int fts5CreateAux( 2425 static int fts5CreateAux(
2248 fts5_api *pApi, /* Global context (one per db handle) */ 2426 fts5_api *pApi, /* Global context (one per db handle) */
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after
2408 if( pTok->xDestroy ) pTok->xDestroy(pTok->pUserData); 2586 if( pTok->xDestroy ) pTok->xDestroy(pTok->pUserData);
2409 sqlite3_free(pTok); 2587 sqlite3_free(pTok);
2410 } 2588 }
2411 2589
2412 sqlite3_free(pGlobal); 2590 sqlite3_free(pGlobal);
2413 } 2591 }
2414 2592
2415 static void fts5Fts5Func( 2593 static void fts5Fts5Func(
2416 sqlite3_context *pCtx, /* Function call context */ 2594 sqlite3_context *pCtx, /* Function call context */
2417 int nArg, /* Number of args */ 2595 int nArg, /* Number of args */
2418 sqlite3_value **apVal /* Function arguments */ 2596 sqlite3_value **apUnused /* Function arguments */
2419 ){ 2597 ){
2420 Fts5Global *pGlobal = (Fts5Global*)sqlite3_user_data(pCtx); 2598 Fts5Global *pGlobal = (Fts5Global*)sqlite3_user_data(pCtx);
2421 char buf[8]; 2599 char buf[8];
2600 UNUSED_PARAM2(nArg, apUnused);
2422 assert( nArg==0 ); 2601 assert( nArg==0 );
2423 assert( sizeof(buf)>=sizeof(pGlobal) ); 2602 assert( sizeof(buf)>=sizeof(pGlobal) );
2424 memcpy(buf, (void*)&pGlobal, sizeof(pGlobal)); 2603 memcpy(buf, (void*)&pGlobal, sizeof(pGlobal));
2425 sqlite3_result_blob(pCtx, buf, sizeof(pGlobal), SQLITE_TRANSIENT); 2604 sqlite3_result_blob(pCtx, buf, sizeof(pGlobal), SQLITE_TRANSIENT);
2426 } 2605 }
2427 2606
2428 /* 2607 /*
2429 ** Implementation of fts5_source_id() function. 2608 ** Implementation of fts5_source_id() function.
2430 */ 2609 */
2431 static void fts5SourceIdFunc( 2610 static void fts5SourceIdFunc(
2432 sqlite3_context *pCtx, /* Function call context */ 2611 sqlite3_context *pCtx, /* Function call context */
2433 int nArg, /* Number of args */ 2612 int nArg, /* Number of args */
2434 sqlite3_value **apVal /* Function arguments */ 2613 sqlite3_value **apUnused /* Function arguments */
2435 ){ 2614 ){
2436 assert( nArg==0 ); 2615 assert( nArg==0 );
2616 UNUSED_PARAM2(nArg, apUnused);
2437 sqlite3_result_text(pCtx, "--FTS5-SOURCE-ID--", -1, SQLITE_TRANSIENT); 2617 sqlite3_result_text(pCtx, "--FTS5-SOURCE-ID--", -1, SQLITE_TRANSIENT);
2438 } 2618 }
2439 2619
2440 static int fts5Init(sqlite3 *db){ 2620 static int fts5Init(sqlite3 *db){
2441 static const sqlite3_module fts5Mod = { 2621 static const sqlite3_module fts5Mod = {
2442 /* iVersion */ 2, 2622 /* iVersion */ 2,
2443 /* xCreate */ fts5CreateMethod, 2623 /* xCreate */ fts5CreateMethod,
2444 /* xConnect */ fts5ConnectMethod, 2624 /* xConnect */ fts5ConnectMethod,
2445 /* xBestIndex */ fts5BestIndexMethod, 2625 /* xBestIndex */ fts5BestIndexMethod,
2446 /* xDisconnect */ fts5DisconnectMethod, 2626 /* xDisconnect */ fts5DisconnectMethod,
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
2488 rc = sqlite3_create_function( 2668 rc = sqlite3_create_function(
2489 db, "fts5", 0, SQLITE_UTF8, p, fts5Fts5Func, 0, 0 2669 db, "fts5", 0, SQLITE_UTF8, p, fts5Fts5Func, 0, 0
2490 ); 2670 );
2491 } 2671 }
2492 if( rc==SQLITE_OK ){ 2672 if( rc==SQLITE_OK ){
2493 rc = sqlite3_create_function( 2673 rc = sqlite3_create_function(
2494 db, "fts5_source_id", 0, SQLITE_UTF8, p, fts5SourceIdFunc, 0, 0 2674 db, "fts5_source_id", 0, SQLITE_UTF8, p, fts5SourceIdFunc, 0, 0
2495 ); 2675 );
2496 } 2676 }
2497 } 2677 }
2678
2679 /* If SQLITE_FTS5_ENABLE_TEST_MI is defined, assume that the file
2680 ** fts5_test_mi.c is compiled and linked into the executable. And call
2681 ** its entry point to enable the matchinfo() demo. */
2682 #ifdef SQLITE_FTS5_ENABLE_TEST_MI
2683 if( rc==SQLITE_OK ){
2684 extern int sqlite3Fts5TestRegisterMatchinfo(sqlite3*);
2685 rc = sqlite3Fts5TestRegisterMatchinfo(db);
2686 }
2687 #endif
2688
2498 return rc; 2689 return rc;
2499 } 2690 }
2500 2691
2501 /* 2692 /*
2502 ** The following functions are used to register the module with SQLite. If 2693 ** The following functions are used to register the module with SQLite. If
2503 ** this module is being built as part of the SQLite core (SQLITE_CORE is 2694 ** this module is being built as part of the SQLite core (SQLITE_CORE is
2504 ** defined), then sqlite3_open() will call sqlite3Fts5Init() directly. 2695 ** defined), then sqlite3_open() will call sqlite3Fts5Init() directly.
2505 ** 2696 **
2506 ** Or, if this module is being built as a loadable extension, 2697 ** Or, if this module is being built as a loadable extension,
2507 ** sqlite3Fts5Init() is omitted and the two standard entry points 2698 ** sqlite3Fts5Init() is omitted and the two standard entry points
(...skipping 23 matching lines...) Expand all
2531 ){ 2722 ){
2532 SQLITE_EXTENSION_INIT2(pApi); 2723 SQLITE_EXTENSION_INIT2(pApi);
2533 (void)pzErrMsg; /* Unused parameter */ 2724 (void)pzErrMsg; /* Unused parameter */
2534 return fts5Init(db); 2725 return fts5Init(db);
2535 } 2726 }
2536 #else 2727 #else
2537 int sqlite3Fts5Init(sqlite3 *db){ 2728 int sqlite3Fts5Init(sqlite3 *db){
2538 return fts5Init(db); 2729 return fts5Init(db);
2539 } 2730 }
2540 #endif 2731 #endif
OLDNEW
« no previous file with comments | « third_party/sqlite/src/ext/fts5/fts5_index.c ('k') | third_party/sqlite/src/ext/fts5/fts5_storage.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698