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

Side by Side Diff: third_party/sqlite/ext/fts2/fts2.c

Issue 216026: Fix numerous bugs in fts2 where a corrupt fts2 database could cause... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 11 years, 2 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* fts2 has a design flaw which can lead to database corruption (see 1 /* fts2 has a design flaw which can lead to database corruption (see
2 ** below). It is recommended not to use it any longer, instead use 2 ** below). It is recommended not to use it any longer, instead use
3 ** fts3 (or higher). If you believe that your use of fts2 is safe, 3 ** fts3 (or higher). If you believe that your use of fts2 is safe,
4 ** add -DSQLITE_ENABLE_BROKEN_FTS2=1 to your CFLAGS. 4 ** add -DSQLITE_ENABLE_BROKEN_FTS2=1 to your CFLAGS.
5 */ 5 */
6 #if (!defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS2)) \ 6 #if (!defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS2)) \
7 && !defined(SQLITE_ENABLE_BROKEN_FTS2) 7 && !defined(SQLITE_ENABLE_BROKEN_FTS2)
8 #error fts2 has a design flaw and has been deprecated. 8 #error fts2 has a design flaw and has been deprecated.
9 #endif 9 #endif
10 /* The flaw is that fts2 uses the content table's unaliased rowid as 10 /* The flaw is that fts2 uses the content table's unaliased rowid as
(...skipping 429 matching lines...) Expand 10 before | Expand all | Expand 10 after
440 vu >>= 7; 440 vu >>= 7;
441 }while( vu!=0 ); 441 }while( vu!=0 );
442 q[-1] &= 0x7f; /* turn off high bit in final byte */ 442 q[-1] &= 0x7f; /* turn off high bit in final byte */
443 assert( q - (unsigned char *)p <= VARINT_MAX ); 443 assert( q - (unsigned char *)p <= VARINT_MAX );
444 return (int) (q - (unsigned char *)p); 444 return (int) (q - (unsigned char *)p);
445 } 445 }
446 446
447 /* Read a 64-bit variable-length integer from memory starting at p[0]. 447 /* Read a 64-bit variable-length integer from memory starting at p[0].
448 * Return the number of bytes read, or 0 on error. 448 * Return the number of bytes read, or 0 on error.
449 * The value is stored in *v. */ 449 * The value is stored in *v. */
450 static int getVarint(const char *p, sqlite_int64 *v){ 450 static int getVarintSafe(const char *p, sqlite_int64 *v, int max){
451 const unsigned char *q = (const unsigned char *) p; 451 const unsigned char *q = (const unsigned char *) p;
452 sqlite_uint64 x = 0, y = 1; 452 sqlite_uint64 x = 0, y = 1;
453 while( (*q & 0x80) == 0x80 ){ 453 if( max>VARINT_MAX ) max = VARINT_MAX;
454 while( max && (*q & 0x80) == 0x80 ){
455 max--;
454 x += y * (*q++ & 0x7f); 456 x += y * (*q++ & 0x7f);
455 y <<= 7; 457 y <<= 7;
456 if( q - (unsigned char *)p >= VARINT_MAX ){ /* bad data */ 458 }
457 assert( 0 ); 459 if ( !max ){
458 return 0; 460 assert( 0 );
459 } 461 return 0; /* tried to read too much; bad data */
460 } 462 }
461 x += y * (*q++); 463 x += y * (*q++);
462 *v = (sqlite_int64) x; 464 *v = (sqlite_int64) x;
463 return (int) (q - (unsigned char *)p); 465 return (int) (q - (unsigned char *)p);
464 } 466 }
465 467
466 static int getVarint32(const char *p, int *pi){ 468 static int getVarint(const char *p, sqlite_int64 *v){
469 return getVarintSafe(p, v, VARINT_MAX);
470 }
471
472 static int getVarint32Safe(const char *p, int *pi, int max){
467 sqlite_int64 i; 473 sqlite_int64 i;
468 int ret = getVarint(p, &i); 474 int ret = getVarintSafe(p, &i, max);
475 if( !ret ) return ret;
469 *pi = (int) i; 476 *pi = (int) i;
470 assert( *pi==i ); 477 assert( *pi==i );
471 return ret; 478 return ret;
472 } 479 }
473 480
481 static int getVarint32(const char* p, int *pi){
482 return getVarint32Safe(p, pi, VARINT_MAX);
483 }
484
474 /*******************************************************************/ 485 /*******************************************************************/
475 /* DataBuffer is used to collect data into a buffer in piecemeal 486 /* DataBuffer is used to collect data into a buffer in piecemeal
476 ** fashion. It implements the usual distinction between amount of 487 ** fashion. It implements the usual distinction between amount of
477 ** data currently stored (nData) and buffer capacity (nCapacity). 488 ** data currently stored (nData) and buffer capacity (nCapacity).
478 ** 489 **
479 ** dataBufferInit - create a buffer with given initial capacity. 490 ** dataBufferInit - create a buffer with given initial capacity.
480 ** dataBufferReset - forget buffer's data, retaining capacity. 491 ** dataBufferReset - forget buffer's data, retaining capacity.
481 ** dataBufferDestroy - free buffer's data. 492 ** dataBufferDestroy - free buffer's data.
482 ** dataBufferSwap - swap contents of two buffers. 493 ** dataBufferSwap - swap contents of two buffers.
483 ** dataBufferExpand - expand capacity without adding data. 494 ** dataBufferExpand - expand capacity without adding data.
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after
632 DocListType iType; 643 DocListType iType;
633 const char *pData; 644 const char *pData;
634 int nData; 645 int nData;
635 646
636 sqlite_int64 iDocid; 647 sqlite_int64 iDocid;
637 int nElement; 648 int nElement;
638 } DLReader; 649 } DLReader;
639 650
640 static int dlrAtEnd(DLReader *pReader){ 651 static int dlrAtEnd(DLReader *pReader){
641 assert( pReader->nData>=0 ); 652 assert( pReader->nData>=0 );
642 return pReader->nData==0; 653 return pReader->nData<=0;
643 } 654 }
644 static sqlite_int64 dlrDocid(DLReader *pReader){ 655 static sqlite_int64 dlrDocid(DLReader *pReader){
645 assert( !dlrAtEnd(pReader) ); 656 assert( !dlrAtEnd(pReader) );
646 return pReader->iDocid; 657 return pReader->iDocid;
647 } 658 }
648 static const char *dlrDocData(DLReader *pReader){ 659 static const char *dlrDocData(DLReader *pReader){
649 assert( !dlrAtEnd(pReader) ); 660 assert( !dlrAtEnd(pReader) );
650 return pReader->pData; 661 return pReader->pData;
651 } 662 }
652 static int dlrDocDataBytes(DLReader *pReader){ 663 static int dlrDocDataBytes(DLReader *pReader){
653 assert( !dlrAtEnd(pReader) ); 664 assert( !dlrAtEnd(pReader) );
654 return pReader->nElement; 665 return pReader->nElement;
655 } 666 }
656 static int dlrAllDataBytes(DLReader *pReader){ 667 static int dlrAllDataBytes(DLReader *pReader){
657 assert( !dlrAtEnd(pReader) ); 668 assert( !dlrAtEnd(pReader) );
658 return pReader->nData; 669 return pReader->nData;
659 } 670 }
660 /* TODO(shess) Consider adding a field to track iDocid varint length 671 /* TODO(shess) Consider adding a field to track iDocid varint length
661 ** to make these two functions faster. This might matter (a tiny bit) 672 ** to make these two functions faster. This might matter (a tiny bit)
662 ** for queries. 673 ** for queries.
663 */ 674 */
664 static const char *dlrPosData(DLReader *pReader){ 675 static const char *dlrPosData(DLReader *pReader){
665 sqlite_int64 iDummy; 676 sqlite_int64 iDummy;
666 int n = getVarint(pReader->pData, &iDummy); 677 int n = getVarintSafe(pReader->pData, &iDummy, pReader->nElement);
678 if( !n ) return NULL;
667 assert( !dlrAtEnd(pReader) ); 679 assert( !dlrAtEnd(pReader) );
668 return pReader->pData+n; 680 return pReader->pData+n;
669 } 681 }
670 static int dlrPosDataLen(DLReader *pReader){ 682 static int dlrPosDataLen(DLReader *pReader){
671 sqlite_int64 iDummy; 683 sqlite_int64 iDummy;
672 int n = getVarint(pReader->pData, &iDummy); 684 int n = getVarint(pReader->pData, &iDummy);
673 assert( !dlrAtEnd(pReader) ); 685 assert( !dlrAtEnd(pReader) );
674 return pReader->nElement-n; 686 return pReader->nElement-n;
675 } 687 }
676 static void dlrStep(DLReader *pReader){ 688 static int dlrStep(DLReader *pReader){
677 assert( !dlrAtEnd(pReader) ); 689 assert( !dlrAtEnd(pReader) );
678 690
679 /* Skip past current doclist element. */ 691 /* Skip past current doclist element. */
680 assert( pReader->nElement<=pReader->nData ); 692 assert( pReader->nElement<=pReader->nData );
681 pReader->pData += pReader->nElement; 693 pReader->pData += pReader->nElement;
682 pReader->nData -= pReader->nElement; 694 pReader->nData -= pReader->nElement;
683 695
684 /* If there is more data, read the next doclist element. */ 696 /* If there is more data, read the next doclist element. */
685 if( pReader->nData!=0 ){ 697 if( pReader->nData>0 ){
686 sqlite_int64 iDocidDelta; 698 sqlite_int64 iDocidDelta;
687 int iDummy, n = getVarint(pReader->pData, &iDocidDelta); 699 int nTotal = 0;
700 int iDummy, n = getVarintSafe(pReader->pData, &iDocidDelta, pReader->nData);
701 if( !n ) return SQLITE_CORRUPT_BKPT;
702 nTotal += n;
688 pReader->iDocid += iDocidDelta; 703 pReader->iDocid += iDocidDelta;
689 if( pReader->iType>=DL_POSITIONS ){ 704 if( pReader->iType>=DL_POSITIONS ){
690 assert( n<pReader->nData );
691 while( 1 ){ 705 while( 1 ){
692 n += getVarint32(pReader->pData+n, &iDummy); 706 n = getVarint32Safe(pReader->pData+nTotal, &iDummy,
693 assert( n<=pReader->nData ); 707 pReader->nData-nTotal);
708 if( !n ) return SQLITE_CORRUPT_BKPT;
709 nTotal += n;
694 if( iDummy==POS_END ) break; 710 if( iDummy==POS_END ) break;
695 if( iDummy==POS_COLUMN ){ 711 if( iDummy==POS_COLUMN ){
696 n += getVarint32(pReader->pData+n, &iDummy); 712 n = getVarint32Safe(pReader->pData+nTotal, &iDummy,
697 assert( n<pReader->nData ); 713 pReader->nData-nTotal);
714 if( !n ) return SQLITE_CORRUPT_BKPT;
715 nTotal += n;
698 }else if( pReader->iType==DL_POSITIONS_OFFSETS ){ 716 }else if( pReader->iType==DL_POSITIONS_OFFSETS ){
699 n += getVarint32(pReader->pData+n, &iDummy); 717 n = getVarint32Safe(pReader->pData+nTotal, &iDummy,
700 n += getVarint32(pReader->pData+n, &iDummy); 718 pReader->nData-nTotal);
701 assert( n<pReader->nData ); 719 if( !n ) return SQLITE_CORRUPT_BKPT;
720 nTotal += n;
721 n = getVarint32Safe(pReader->pData+nTotal, &iDummy,
722 pReader->nData-nTotal);
723 if( !n ) return SQLITE_CORRUPT_BKPT;
724 nTotal += n;
702 } 725 }
703 } 726 }
704 } 727 }
705 pReader->nElement = n; 728 pReader->nElement = nTotal;
706 assert( pReader->nElement<=pReader->nData ); 729 assert( pReader->nElement<=pReader->nData );
707 } 730 }
731 return SQLITE_OK;
708 } 732 }
709 static void dlrInit(DLReader *pReader, DocListType iType, 733 static void dlrDestroy(DLReader *pReader){
710 const char *pData, int nData){ 734 SCRAMBLE(pReader);
735 }
736 static int dlrInit(DLReader *pReader, DocListType iType,
737 const char *pData, int nData){
738 int rc;
711 assert( pData!=NULL && nData!=0 ); 739 assert( pData!=NULL && nData!=0 );
712 pReader->iType = iType; 740 pReader->iType = iType;
713 pReader->pData = pData; 741 pReader->pData = pData;
714 pReader->nData = nData; 742 pReader->nData = nData;
715 pReader->nElement = 0; 743 pReader->nElement = 0;
716 pReader->iDocid = 0; 744 pReader->iDocid = 0;
717 745
718 /* Load the first element's data. There must be a first element. */ 746 /* Load the first element's data. There must be a first element. */
719 dlrStep(pReader); 747 rc = dlrStep(pReader);
720 } 748 if( rc!=SQLITE_OK ) dlrDestroy(pReader);
721 static void dlrDestroy(DLReader *pReader){ 749 return rc;
722 SCRAMBLE(pReader);
723 } 750 }
724 751
725 #ifndef NDEBUG 752 #ifndef NDEBUG
726 /* Verify that the doclist can be validly decoded. Also returns the 753 /* Verify that the doclist can be validly decoded. Also returns the
727 ** last docid found because it is convenient in other assertions for 754 ** last docid found because it is convenient in other assertions for
728 ** DLWriter. 755 ** DLWriter.
729 */ 756 */
730 static void docListValidate(DocListType iType, const char *pData, int nData, 757 static void docListValidate(DocListType iType, const char *pData, int nData,
731 sqlite_int64 *pLastDocid){ 758 sqlite_int64 *pLastDocid){
732 sqlite_int64 iPrevDocid = 0; 759 sqlite_int64 iPrevDocid = 0;
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
799 ** 826 **
800 ** iLastDocid is the final docid in the doclist in pData. It is 827 ** iLastDocid is the final docid in the doclist in pData. It is
801 ** needed to create the new iPrevDocid for future delta-encoding. The 828 ** needed to create the new iPrevDocid for future delta-encoding. The
802 ** code could decode the passed doclist to recreate iLastDocid, but 829 ** code could decode the passed doclist to recreate iLastDocid, but
803 ** the only current user (docListMerge) already has decoded this 830 ** the only current user (docListMerge) already has decoded this
804 ** information. 831 ** information.
805 */ 832 */
806 /* TODO(shess) This has become just a helper for docListMerge. 833 /* TODO(shess) This has become just a helper for docListMerge.
807 ** Consider a refactor to make this cleaner. 834 ** Consider a refactor to make this cleaner.
808 */ 835 */
809 static void dlwAppend(DLWriter *pWriter, 836 static int dlwAppend(DLWriter *pWriter,
810 const char *pData, int nData, 837 const char *pData, int nData,
811 sqlite_int64 iFirstDocid, sqlite_int64 iLastDocid){ 838 sqlite_int64 iFirstDocid, sqlite_int64 iLastDocid){
812 sqlite_int64 iDocid = 0; 839 sqlite_int64 iDocid = 0;
813 char c[VARINT_MAX]; 840 char c[VARINT_MAX];
814 int nFirstOld, nFirstNew; /* Old and new varint len of first docid. */ 841 int nFirstOld, nFirstNew; /* Old and new varint len of first docid. */
815 #ifndef NDEBUG 842 #ifndef NDEBUG
816 sqlite_int64 iLastDocidDelta; 843 sqlite_int64 iLastDocidDelta;
817 #endif 844 #endif
818 845
819 /* Recode the initial docid as delta from iPrevDocid. */ 846 /* Recode the initial docid as delta from iPrevDocid. */
820 nFirstOld = getVarint(pData, &iDocid); 847 nFirstOld = getVarintSafe(pData, &iDocid, nData);
848 if( !nFirstOld ) return SQLITE_CORRUPT_BKPT;
821 assert( nFirstOld<nData || (nFirstOld==nData && pWriter->iType==DL_DOCIDS) ); 849 assert( nFirstOld<nData || (nFirstOld==nData && pWriter->iType==DL_DOCIDS) );
822 nFirstNew = putVarint(c, iFirstDocid-pWriter->iPrevDocid); 850 nFirstNew = putVarint(c, iFirstDocid-pWriter->iPrevDocid);
823 851
824 /* Verify that the incoming doclist is valid AND that it ends with 852 /* Verify that the incoming doclist is valid AND that it ends with
825 ** the expected docid. This is essential because we'll trust this 853 ** the expected docid. This is essential because we'll trust this
826 ** docid in future delta-encoding. 854 ** docid in future delta-encoding.
827 */ 855 */
828 ASSERT_VALID_DOCLIST(pWriter->iType, pData, nData, &iLastDocidDelta); 856 ASSERT_VALID_DOCLIST(pWriter->iType, pData, nData, &iLastDocidDelta);
829 assert( iLastDocid==iFirstDocid-iDocid+iLastDocidDelta ); 857 assert( iLastDocid==iFirstDocid-iDocid+iLastDocidDelta );
830 858
831 /* Append recoded initial docid and everything else. Rest of docids 859 /* Append recoded initial docid and everything else. Rest of docids
832 ** should have been delta-encoded from previous initial docid. 860 ** should have been delta-encoded from previous initial docid.
833 */ 861 */
834 if( nFirstOld<nData ){ 862 if( nFirstOld<nData ){
835 dataBufferAppend2(pWriter->b, c, nFirstNew, 863 dataBufferAppend2(pWriter->b, c, nFirstNew,
836 pData+nFirstOld, nData-nFirstOld); 864 pData+nFirstOld, nData-nFirstOld);
837 }else{ 865 }else{
838 dataBufferAppend(pWriter->b, c, nFirstNew); 866 dataBufferAppend(pWriter->b, c, nFirstNew);
839 } 867 }
840 pWriter->iPrevDocid = iLastDocid; 868 pWriter->iPrevDocid = iLastDocid;
869 return SQLITE_OK;
841 } 870 }
842 static void dlwCopy(DLWriter *pWriter, DLReader *pReader){ 871 static int dlwCopy(DLWriter *pWriter, DLReader *pReader){
843 dlwAppend(pWriter, dlrDocData(pReader), dlrDocDataBytes(pReader), 872 return dlwAppend(pWriter, dlrDocData(pReader), dlrDocDataBytes(pReader),
844 dlrDocid(pReader), dlrDocid(pReader)); 873 dlrDocid(pReader), dlrDocid(pReader));
845 } 874 }
846 static void dlwAdd(DLWriter *pWriter, sqlite_int64 iDocid){ 875 static void dlwAdd(DLWriter *pWriter, sqlite_int64 iDocid){
847 char c[VARINT_MAX]; 876 char c[VARINT_MAX];
848 int n = putVarint(c, iDocid-pWriter->iPrevDocid); 877 int n = putVarint(c, iDocid-pWriter->iPrevDocid);
849 878
850 /* Docids must ascend. */ 879 /* Docids must ascend. */
851 assert( !pWriter->has_iPrevDocid || iDocid>pWriter->iPrevDocid ); 880 assert( !pWriter->has_iPrevDocid || iDocid>pWriter->iPrevDocid );
852 assert( pWriter->iType==DL_DOCIDS ); 881 assert( pWriter->iType==DL_DOCIDS );
853 882
854 dataBufferAppend(pWriter->b, c, n); 883 dataBufferAppend(pWriter->b, c, n);
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
895 return pReader->iPosition; 924 return pReader->iPosition;
896 } 925 }
897 static int plrStartOffset(PLReader *pReader){ 926 static int plrStartOffset(PLReader *pReader){
898 assert( !plrAtEnd(pReader) ); 927 assert( !plrAtEnd(pReader) );
899 return pReader->iStartOffset; 928 return pReader->iStartOffset;
900 } 929 }
901 static int plrEndOffset(PLReader *pReader){ 930 static int plrEndOffset(PLReader *pReader){
902 assert( !plrAtEnd(pReader) ); 931 assert( !plrAtEnd(pReader) );
903 return pReader->iEndOffset; 932 return pReader->iEndOffset;
904 } 933 }
905 static void plrStep(PLReader *pReader){ 934 static int plrStep(PLReader *pReader){
906 int i, n; 935 int i, n, nTotal = 0;
907 936
908 assert( !plrAtEnd(pReader) ); 937 assert( !plrAtEnd(pReader) );
909 938
910 if( pReader->nData==0 ){ 939 if( pReader->nData<=0 ){
911 pReader->pData = NULL; 940 pReader->pData = NULL;
912 return; 941 return SQLITE_OK;
913 } 942 }
914 943
915 n = getVarint32(pReader->pData, &i); 944 n = getVarint32Safe(pReader->pData, &i, pReader->nData);
945 if( !n ) return SQLITE_CORRUPT_BKPT;
946 nTotal += n;
916 if( i==POS_COLUMN ){ 947 if( i==POS_COLUMN ){
917 n += getVarint32(pReader->pData+n, &pReader->iColumn); 948 n = getVarint32Safe(pReader->pData+nTotal, &pReader->iColumn,
949 pReader->nData-nTotal);
950 if( !n ) return SQLITE_CORRUPT_BKPT;
951 nTotal += n;
918 pReader->iPosition = 0; 952 pReader->iPosition = 0;
919 pReader->iStartOffset = 0; 953 pReader->iStartOffset = 0;
920 n += getVarint32(pReader->pData+n, &i); 954 n = getVarint32Safe(pReader->pData+nTotal, &i, pReader->nData-nTotal);
955 if( !n ) return SQLITE_CORRUPT_BKPT;
956 nTotal += n;
921 } 957 }
922 /* Should never see adjacent column changes. */ 958 /* Should never see adjacent column changes. */
923 assert( i!=POS_COLUMN ); 959 assert( i!=POS_COLUMN );
924 960
925 if( i==POS_END ){ 961 if( i==POS_END ){
962 assert( nTotal<=pReader->nData );
926 pReader->nData = 0; 963 pReader->nData = 0;
927 pReader->pData = NULL; 964 pReader->pData = NULL;
928 return; 965 return SQLITE_OK;
929 } 966 }
930 967
931 pReader->iPosition += i-POS_BASE; 968 pReader->iPosition += i-POS_BASE;
932 if( pReader->iType==DL_POSITIONS_OFFSETS ){ 969 if( pReader->iType==DL_POSITIONS_OFFSETS ){
933 n += getVarint32(pReader->pData+n, &i); 970 n = getVarint32Safe(pReader->pData+nTotal, &i, pReader->nData-nTotal);
971 if( !n ) return SQLITE_CORRUPT_BKPT;
972 nTotal += n;
934 pReader->iStartOffset += i; 973 pReader->iStartOffset += i;
935 n += getVarint32(pReader->pData+n, &i); 974 n = getVarint32Safe(pReader->pData+nTotal, &i, pReader->nData-nTotal);
975 if( !n ) return SQLITE_CORRUPT_BKPT;
976 nTotal += n;
936 pReader->iEndOffset = pReader->iStartOffset+i; 977 pReader->iEndOffset = pReader->iStartOffset+i;
937 } 978 }
938 assert( n<=pReader->nData ); 979 assert( nTotal<=pReader->nData );
939 pReader->pData += n; 980 pReader->pData += nTotal;
940 pReader->nData -= n; 981 pReader->nData -= nTotal;
982 return SQLITE_OK;
941 } 983 }
942 984
943 static void plrInit(PLReader *pReader, DLReader *pDLReader){ 985 static void plrDestroy(PLReader *pReader){
986 SCRAMBLE(pReader);
987 }
988
989 static int plrInit(PLReader *pReader, DLReader *pDLReader){
990 int rc;
944 pReader->pData = dlrPosData(pDLReader); 991 pReader->pData = dlrPosData(pDLReader);
945 pReader->nData = dlrPosDataLen(pDLReader); 992 pReader->nData = dlrPosDataLen(pDLReader);
946 pReader->iType = pDLReader->iType; 993 pReader->iType = pDLReader->iType;
947 pReader->iColumn = 0; 994 pReader->iColumn = 0;
948 pReader->iPosition = 0; 995 pReader->iPosition = 0;
949 pReader->iStartOffset = 0; 996 pReader->iStartOffset = 0;
950 pReader->iEndOffset = 0; 997 pReader->iEndOffset = 0;
951 plrStep(pReader); 998 rc = plrStep(pReader);
952 } 999 if( rc!=SQLITE_OK ) plrDestroy(pReader);
953 static void plrDestroy(PLReader *pReader){ 1000 return rc;
954 SCRAMBLE(pReader);
955 } 1001 }
956 1002
957 /*******************************************************************/ 1003 /*******************************************************************/
958 /* PLWriter is used in constructing a document's position list. As a 1004 /* PLWriter is used in constructing a document's position list. As a
959 ** convenience, if iType is DL_DOCIDS, PLWriter becomes a no-op. 1005 ** convenience, if iType is DL_DOCIDS, PLWriter becomes a no-op.
960 ** PLWriter writes to the associated DLWriter's buffer. 1006 ** PLWriter writes to the associated DLWriter's buffer.
961 ** 1007 **
962 ** plwInit - init for writing a document's poslist. 1008 ** plwInit - init for writing a document's poslist.
963 ** plwDestroy - clear a writer. 1009 ** plwDestroy - clear a writer.
964 ** plwAdd - append position and offset information. 1010 ** plwAdd - append position and offset information.
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after
1130 /* Copy the doclist data of iType in pData/nData into *out, trimming 1176 /* Copy the doclist data of iType in pData/nData into *out, trimming
1131 ** unnecessary data as we go. Only columns matching iColumn are 1177 ** unnecessary data as we go. Only columns matching iColumn are
1132 ** copied, all columns copied if iColumn is -1. Elements with no 1178 ** copied, all columns copied if iColumn is -1. Elements with no
1133 ** matching columns are dropped. The output is an iOutType doclist. 1179 ** matching columns are dropped. The output is an iOutType doclist.
1134 */ 1180 */
1135 /* NOTE(shess) This code is only valid after all doclists are merged. 1181 /* NOTE(shess) This code is only valid after all doclists are merged.
1136 ** If this is run before merges, then doclist items which represent 1182 ** If this is run before merges, then doclist items which represent
1137 ** deletion will be trimmed, and will thus not effect a deletion 1183 ** deletion will be trimmed, and will thus not effect a deletion
1138 ** during the merge. 1184 ** during the merge.
1139 */ 1185 */
1140 static void docListTrim(DocListType iType, const char *pData, int nData, 1186 static int docListTrim(DocListType iType, const char *pData, int nData,
1141 int iColumn, DocListType iOutType, DataBuffer *out){ 1187 int iColumn, DocListType iOutType, DataBuffer *out){
1142 DLReader dlReader; 1188 DLReader dlReader;
1143 DLWriter dlWriter; 1189 DLWriter dlWriter;
1190 int rc;
1144 1191
1145 assert( iOutType<=iType ); 1192 assert( iOutType<=iType );
1146 1193
1147 dlrInit(&dlReader, iType, pData, nData); 1194 rc = dlrInit(&dlReader, iType, pData, nData);
1195 if( rc!=SQLITE_OK ) return rc;
1148 dlwInit(&dlWriter, iOutType, out); 1196 dlwInit(&dlWriter, iOutType, out);
1149 1197
1150 while( !dlrAtEnd(&dlReader) ){ 1198 while( !dlrAtEnd(&dlReader) ){
1151 PLReader plReader; 1199 PLReader plReader;
1152 PLWriter plWriter; 1200 PLWriter plWriter;
1153 int match = 0; 1201 int match = 0;
1154 1202
1155 plrInit(&plReader, &dlReader); 1203 rc = plrInit(&plReader, &dlReader);
1204 if( rc!=SQLITE_OK ) break;
1156 1205
1157 while( !plrAtEnd(&plReader) ){ 1206 while( !plrAtEnd(&plReader) ){
1158 if( iColumn==-1 || plrColumn(&plReader)==iColumn ){ 1207 if( iColumn==-1 || plrColumn(&plReader)==iColumn ){
1159 if( !match ){ 1208 if( !match ){
1160 plwInit(&plWriter, &dlWriter, dlrDocid(&dlReader)); 1209 plwInit(&plWriter, &dlWriter, dlrDocid(&dlReader));
1161 match = 1; 1210 match = 1;
1162 } 1211 }
1163 plwAdd(&plWriter, plrColumn(&plReader), plrPosition(&plReader), 1212 plwAdd(&plWriter, plrColumn(&plReader), plrPosition(&plReader),
1164 plrStartOffset(&plReader), plrEndOffset(&plReader)); 1213 plrStartOffset(&plReader), plrEndOffset(&plReader));
1165 } 1214 }
1166 plrStep(&plReader); 1215 rc = plrStep(&plReader);
1216 if( rc!=SQLITE_OK ){
1217 plrDestroy(&plReader);
1218 goto err;
1219 }
1167 } 1220 }
1168 if( match ){ 1221 if( match ){
1169 plwTerminate(&plWriter); 1222 plwTerminate(&plWriter);
1170 plwDestroy(&plWriter); 1223 plwDestroy(&plWriter);
1171 } 1224 }
1172 1225
1173 plrDestroy(&plReader); 1226 plrDestroy(&plReader);
1174 dlrStep(&dlReader); 1227 rc = dlrStep(&dlReader);
1228 if( rc!=SQLITE_OK ) break;
1175 } 1229 }
1230 err:
1176 dlwDestroy(&dlWriter); 1231 dlwDestroy(&dlWriter);
1177 dlrDestroy(&dlReader); 1232 dlrDestroy(&dlReader);
1233 return rc;
1178 } 1234 }
1179 1235
1180 /* Used by docListMerge() to keep doclists in the ascending order by 1236 /* Used by docListMerge() to keep doclists in the ascending order by
1181 ** docid, then ascending order by age (so the newest comes first). 1237 ** docid, then ascending order by age (so the newest comes first).
1182 */ 1238 */
1183 typedef struct OrderedDLReader { 1239 typedef struct OrderedDLReader {
1184 DLReader *pReader; 1240 DLReader *pReader;
1185 1241
1186 /* TODO(shess) If we assume that docListMerge pReaders is ordered by 1242 /* TODO(shess) If we assume that docListMerge pReaders is ordered by
1187 ** age (which we do), then we could use pReader comparisons to break 1243 ** age (which we do), then we could use pReader comparisons to break
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
1224 } 1280 }
1225 1281
1226 /* Given an array of doclist readers, merge their doclist elements 1282 /* Given an array of doclist readers, merge their doclist elements
1227 ** into out in sorted order (by docid), dropping elements from older 1283 ** into out in sorted order (by docid), dropping elements from older
1228 ** readers when there is a duplicate docid. pReaders is assumed to be 1284 ** readers when there is a duplicate docid. pReaders is assumed to be
1229 ** ordered by age, oldest first. 1285 ** ordered by age, oldest first.
1230 */ 1286 */
1231 /* TODO(shess) nReaders must be <= MERGE_COUNT. This should probably 1287 /* TODO(shess) nReaders must be <= MERGE_COUNT. This should probably
1232 ** be fixed. 1288 ** be fixed.
1233 */ 1289 */
1234 static void docListMerge(DataBuffer *out, 1290 static int docListMerge(DataBuffer *out,
1235 DLReader *pReaders, int nReaders){ 1291 DLReader *pReaders, int nReaders){
1236 OrderedDLReader readers[MERGE_COUNT]; 1292 OrderedDLReader readers[MERGE_COUNT];
1237 DLWriter writer; 1293 DLWriter writer;
1238 int i, n; 1294 int i, n;
1239 const char *pStart = 0; 1295 const char *pStart = 0;
1240 int nStart = 0; 1296 int nStart = 0;
1241 sqlite_int64 iFirstDocid = 0, iLastDocid = 0; 1297 sqlite_int64 iFirstDocid = 0, iLastDocid = 0;
1298 int rc = SQLITE_OK;
1242 1299
1243 assert( nReaders>0 ); 1300 assert( nReaders>0 );
1244 if( nReaders==1 ){ 1301 if( nReaders==1 ){
1245 dataBufferAppend(out, dlrDocData(pReaders), dlrAllDataBytes(pReaders)); 1302 dataBufferAppend(out, dlrDocData(pReaders), dlrAllDataBytes(pReaders));
1246 return; 1303 return SQLITE_OK;
1247 } 1304 }
1248 1305
1249 assert( nReaders<=MERGE_COUNT ); 1306 assert( nReaders<=MERGE_COUNT );
1250 n = 0; 1307 n = 0;
1251 for(i=0; i<nReaders; i++){ 1308 for(i=0; i<nReaders; i++){
1252 assert( pReaders[i].iType==pReaders[0].iType ); 1309 assert( pReaders[i].iType==pReaders[0].iType );
1253 readers[i].pReader = pReaders+i; 1310 readers[i].pReader = pReaders+i;
1254 readers[i].idx = i; 1311 readers[i].idx = i;
1255 n += dlrAllDataBytes(&pReaders[i]); 1312 n += dlrAllDataBytes(&pReaders[i]);
1256 } 1313 }
(...skipping 12 matching lines...) Expand all
1269 sqlite_int64 iDocid = dlrDocid(readers[0].pReader); 1326 sqlite_int64 iDocid = dlrDocid(readers[0].pReader);
1270 1327
1271 /* If this is a continuation of the current buffer to copy, extend 1328 /* If this is a continuation of the current buffer to copy, extend
1272 ** that buffer. memcpy() seems to be more efficient if it has a 1329 ** that buffer. memcpy() seems to be more efficient if it has a
1273 ** lots of data to copy. 1330 ** lots of data to copy.
1274 */ 1331 */
1275 if( dlrDocData(readers[0].pReader)==pStart+nStart ){ 1332 if( dlrDocData(readers[0].pReader)==pStart+nStart ){
1276 nStart += dlrDocDataBytes(readers[0].pReader); 1333 nStart += dlrDocDataBytes(readers[0].pReader);
1277 }else{ 1334 }else{
1278 if( pStart!=0 ){ 1335 if( pStart!=0 ){
1279 dlwAppend(&writer, pStart, nStart, iFirstDocid, iLastDocid); 1336 rc = dlwAppend(&writer, pStart, nStart, iFirstDocid, iLastDocid);
1337 if( rc!=SQLITE_OK ) goto err;
1280 } 1338 }
1281 pStart = dlrDocData(readers[0].pReader); 1339 pStart = dlrDocData(readers[0].pReader);
1282 nStart = dlrDocDataBytes(readers[0].pReader); 1340 nStart = dlrDocDataBytes(readers[0].pReader);
1283 iFirstDocid = iDocid; 1341 iFirstDocid = iDocid;
1284 } 1342 }
1285 iLastDocid = iDocid; 1343 iLastDocid = iDocid;
1286 dlrStep(readers[0].pReader); 1344 rc = dlrStep(readers[0].pReader);
1345 if( rc!=SQLITE_OK ) goto err;
1287 1346
1288 /* Drop all of the older elements with the same docid. */ 1347 /* Drop all of the older elements with the same docid. */
1289 for(i=1; i<nReaders && 1348 for(i=1; i<nReaders &&
1290 !dlrAtEnd(readers[i].pReader) && 1349 !dlrAtEnd(readers[i].pReader) &&
1291 dlrDocid(readers[i].pReader)==iDocid; i++){ 1350 dlrDocid(readers[i].pReader)==iDocid; i++){
1292 dlrStep(readers[i].pReader); 1351 rc = dlrStep(readers[i].pReader);
1352 if( rc!=SQLITE_OK ) goto err;
1293 } 1353 }
1294 1354
1295 /* Get the readers back into order. */ 1355 /* Get the readers back into order. */
1296 while( i-->0 ){ 1356 while( i-->0 ){
1297 orderedDLReaderReorder(readers+i, nReaders-i); 1357 orderedDLReaderReorder(readers+i, nReaders-i);
1298 } 1358 }
1299 } 1359 }
1300 1360
1301 /* Copy over any remaining elements. */ 1361 /* Copy over any remaining elements. */
1302 if( nStart>0 ) dlwAppend(&writer, pStart, nStart, iFirstDocid, iLastDocid); 1362 if( nStart>0 )
1363 rc = dlwAppend(&writer, pStart, nStart, iFirstDocid, iLastDocid);
1364 err:
1303 dlwDestroy(&writer); 1365 dlwDestroy(&writer);
1366 return rc;
1304 } 1367 }
1305 1368
1306 /* Helper function for posListUnion(). Compares the current position 1369 /* Helper function for posListUnion(). Compares the current position
1307 ** between left and right, returning as standard C idiom of <0 if 1370 ** between left and right, returning as standard C idiom of <0 if
1308 ** left<right, >0 if left>right, and 0 if left==right. "End" always 1371 ** left<right, >0 if left>right, and 0 if left==right. "End" always
1309 ** compares greater. 1372 ** compares greater.
1310 */ 1373 */
1311 static int posListCmp(PLReader *pLeft, PLReader *pRight){ 1374 static int posListCmp(PLReader *pLeft, PLReader *pRight){
1312 assert( pLeft->iType==pRight->iType ); 1375 assert( pLeft->iType==pRight->iType );
1313 if( pLeft->iType==DL_DOCIDS ) return 0; 1376 if( pLeft->iType==DL_DOCIDS ) return 0;
(...skipping 15 matching lines...) Expand all
1329 if( plrEndOffset(pLeft)>plrEndOffset(pRight) ) return 1; 1392 if( plrEndOffset(pLeft)>plrEndOffset(pRight) ) return 1;
1330 1393
1331 return 0; 1394 return 0;
1332 } 1395 }
1333 1396
1334 /* Write the union of position lists in pLeft and pRight to pOut. 1397 /* Write the union of position lists in pLeft and pRight to pOut.
1335 ** "Union" in this case meaning "All unique position tuples". Should 1398 ** "Union" in this case meaning "All unique position tuples". Should
1336 ** work with any doclist type, though both inputs and the output 1399 ** work with any doclist type, though both inputs and the output
1337 ** should be the same type. 1400 ** should be the same type.
1338 */ 1401 */
1339 static void posListUnion(DLReader *pLeft, DLReader *pRight, DLWriter *pOut){ 1402 static int posListUnion(DLReader *pLeft, DLReader *pRight, DLWriter *pOut){
1340 PLReader left, right; 1403 PLReader left, right;
1341 PLWriter writer; 1404 PLWriter writer;
1405 int rc;
1342 1406
1343 assert( dlrDocid(pLeft)==dlrDocid(pRight) ); 1407 assert( dlrDocid(pLeft)==dlrDocid(pRight) );
1344 assert( pLeft->iType==pRight->iType ); 1408 assert( pLeft->iType==pRight->iType );
1345 assert( pLeft->iType==pOut->iType ); 1409 assert( pLeft->iType==pOut->iType );
1346 1410
1347 plrInit(&left, pLeft); 1411 rc = plrInit(&left, pLeft);
1348 plrInit(&right, pRight); 1412 if( rc != SQLITE_OK ) return rc;
1413 rc = plrInit(&right, pRight);
1414 if( rc != SQLITE_OK ){
1415 plrDestroy(&left);
1416 return rc;
1417 }
1349 plwInit(&writer, pOut, dlrDocid(pLeft)); 1418 plwInit(&writer, pOut, dlrDocid(pLeft));
1350 1419
1351 while( !plrAtEnd(&left) || !plrAtEnd(&right) ){ 1420 while( !plrAtEnd(&left) || !plrAtEnd(&right) ){
1352 int c = posListCmp(&left, &right); 1421 int c = posListCmp(&left, &right);
1353 if( c<0 ){ 1422 if( c<0 ){
1354 plwCopy(&writer, &left); 1423 plwCopy(&writer, &left);
1355 plrStep(&left); 1424 rc = plrStep(&left);
1425 if( rc != SQLITE_OK ) break;
1356 }else if( c>0 ){ 1426 }else if( c>0 ){
1357 plwCopy(&writer, &right); 1427 plwCopy(&writer, &right);
1358 plrStep(&right); 1428 rc = plrStep(&right);
1429 if( rc != SQLITE_OK ) break;
1359 }else{ 1430 }else{
1360 plwCopy(&writer, &left); 1431 plwCopy(&writer, &left);
1361 plrStep(&left); 1432 rc = plrStep(&left);
1362 plrStep(&right); 1433 if( rc != SQLITE_OK ) break;
1434 rc = plrStep(&right);
1435 if( rc != SQLITE_OK ) break;
1363 } 1436 }
1364 } 1437 }
1365 1438
1366 plwTerminate(&writer); 1439 plwTerminate(&writer);
1367 plwDestroy(&writer); 1440 plwDestroy(&writer);
1368 plrDestroy(&left); 1441 plrDestroy(&left);
1369 plrDestroy(&right); 1442 plrDestroy(&right);
1443 return rc;
1370 } 1444 }
1371 1445
1372 /* Write the union of doclists in pLeft and pRight to pOut. For 1446 /* Write the union of doclists in pLeft and pRight to pOut. For
1373 ** docids in common between the inputs, the union of the position 1447 ** docids in common between the inputs, the union of the position
1374 ** lists is written. Inputs and outputs are always type DL_DEFAULT. 1448 ** lists is written. Inputs and outputs are always type DL_DEFAULT.
1375 */ 1449 */
1376 static void docListUnion( 1450 static int docListUnion(
1377 const char *pLeft, int nLeft, 1451 const char *pLeft, int nLeft,
1378 const char *pRight, int nRight, 1452 const char *pRight, int nRight,
1379 DataBuffer *pOut /* Write the combined doclist here */ 1453 DataBuffer *pOut /* Write the combined doclist here */
1380 ){ 1454 ){
1381 DLReader left, right; 1455 DLReader left, right;
1382 DLWriter writer; 1456 DLWriter writer;
1457 int rc;
1383 1458
1384 if( nLeft==0 ){ 1459 if( nLeft==0 ){
1385 if( nRight!=0) dataBufferAppend(pOut, pRight, nRight); 1460 if( nRight!=0) dataBufferAppend(pOut, pRight, nRight);
1386 return; 1461 return SQLITE_OK;
1387 } 1462 }
1388 if( nRight==0 ){ 1463 if( nRight==0 ){
1389 dataBufferAppend(pOut, pLeft, nLeft); 1464 dataBufferAppend(pOut, pLeft, nLeft);
1390 return; 1465 return SQLITE_OK;
1391 } 1466 }
1392 1467
1393 dlrInit(&left, DL_DEFAULT, pLeft, nLeft); 1468 rc = dlrInit(&left, DL_DEFAULT, pLeft, nLeft);
1394 dlrInit(&right, DL_DEFAULT, pRight, nRight); 1469 if( rc!=SQLITE_OK ) return rc;
1470 rc = dlrInit(&right, DL_DEFAULT, pRight, nRight);
1471 if( rc!=SQLITE_OK ){
1472 dlrDestroy(&left);
1473 return rc;
1474 }
1395 dlwInit(&writer, DL_DEFAULT, pOut); 1475 dlwInit(&writer, DL_DEFAULT, pOut);
1396 1476
1397 while( !dlrAtEnd(&left) || !dlrAtEnd(&right) ){ 1477 while( !dlrAtEnd(&left) || !dlrAtEnd(&right) ){
1398 if( dlrAtEnd(&right) ){ 1478 if( dlrAtEnd(&right) ){
1399 dlwCopy(&writer, &left); 1479 rc = dlwCopy(&writer, &left);
1400 dlrStep(&left); 1480 if( rc!=SQLITE_OK ) break;
1481 rc = dlrStep(&left);
1482 if( rc!=SQLITE_OK ) break;
1401 }else if( dlrAtEnd(&left) ){ 1483 }else if( dlrAtEnd(&left) ){
1402 dlwCopy(&writer, &right); 1484 rc = dlwCopy(&writer, &right);
1403 dlrStep(&right); 1485 if( rc!=SQLITE_OK ) break;
1486 rc = dlrStep(&right);
1487 if( rc!=SQLITE_OK ) break;
1404 }else if( dlrDocid(&left)<dlrDocid(&right) ){ 1488 }else if( dlrDocid(&left)<dlrDocid(&right) ){
1405 dlwCopy(&writer, &left); 1489 rc = dlwCopy(&writer, &left);
1406 dlrStep(&left); 1490 if( rc!=SQLITE_OK ) break;
1491 rc = dlrStep(&left);
1492 if( rc!=SQLITE_OK ) break;
1407 }else if( dlrDocid(&left)>dlrDocid(&right) ){ 1493 }else if( dlrDocid(&left)>dlrDocid(&right) ){
1408 dlwCopy(&writer, &right); 1494 rc = dlwCopy(&writer, &right);
1409 dlrStep(&right); 1495 if( rc!=SQLITE_OK ) break;
1496 rc = dlrStep(&right);
1497 if( rc!=SQLITE_OK ) break;
1410 }else{ 1498 }else{
1411 posListUnion(&left, &right, &writer); 1499 rc = posListUnion(&left, &right, &writer);
1412 dlrStep(&left); 1500 if( rc!=SQLITE_OK ) break;
1413 dlrStep(&right); 1501 rc = dlrStep(&left);
1502 if( rc!=SQLITE_OK ) break;
1503 rc = dlrStep(&right);
1504 if( rc!=SQLITE_OK ) break;
1414 } 1505 }
1415 } 1506 }
1416 1507
1417 dlrDestroy(&left); 1508 dlrDestroy(&left);
1418 dlrDestroy(&right); 1509 dlrDestroy(&right);
1419 dlwDestroy(&writer); 1510 dlwDestroy(&writer);
1511 return rc;
1420 } 1512 }
1421 1513
1422 /* pLeft and pRight are DLReaders positioned to the same docid. 1514 /* pLeft and pRight are DLReaders positioned to the same docid.
1423 ** 1515 **
1424 ** If there are no instances in pLeft or pRight where the position 1516 ** If there are no instances in pLeft or pRight where the position
1425 ** of pLeft is one less than the position of pRight, then this 1517 ** of pLeft is one less than the position of pRight, then this
1426 ** routine adds nothing to pOut. 1518 ** routine adds nothing to pOut.
1427 ** 1519 **
1428 ** If there are one or more instances where positions from pLeft 1520 ** If there are one or more instances where positions from pLeft
1429 ** are exactly one less than positions from pRight, then add a new 1521 ** are exactly one less than positions from pRight, then add a new
1430 ** document record to pOut. If pOut wants to hold positions, then 1522 ** document record to pOut. If pOut wants to hold positions, then
1431 ** include the positions from pRight that are one more than a 1523 ** include the positions from pRight that are one more than a
1432 ** position in pLeft. In other words: pRight.iPos==pLeft.iPos+1. 1524 ** position in pLeft. In other words: pRight.iPos==pLeft.iPos+1.
1433 */ 1525 */
1434 static void posListPhraseMerge(DLReader *pLeft, DLReader *pRight, 1526 static int posListPhraseMerge(DLReader *pLeft, DLReader *pRight,
1435 DLWriter *pOut){ 1527 DLWriter *pOut){
1436 PLReader left, right; 1528 PLReader left, right;
1437 PLWriter writer; 1529 PLWriter writer;
1438 int match = 0; 1530 int match = 0;
1531 int rc;
1439 1532
1440 assert( dlrDocid(pLeft)==dlrDocid(pRight) ); 1533 assert( dlrDocid(pLeft)==dlrDocid(pRight) );
1441 assert( pOut->iType!=DL_POSITIONS_OFFSETS ); 1534 assert( pOut->iType!=DL_POSITIONS_OFFSETS );
1442 1535
1443 plrInit(&left, pLeft); 1536 rc = plrInit(&left, pLeft);
1444 plrInit(&right, pRight); 1537 if( rc!=SQLITE_OK ) return rc;
1538 rc = plrInit(&right, pRight);
1539 if( rc!=SQLITE_OK ){
1540 plrDestroy(&left);
1541 return rc;
1542 }
1445 1543
1446 while( !plrAtEnd(&left) && !plrAtEnd(&right) ){ 1544 while( !plrAtEnd(&left) && !plrAtEnd(&right) ){
1447 if( plrColumn(&left)<plrColumn(&right) ){ 1545 if( plrColumn(&left)<plrColumn(&right) ){
1448 plrStep(&left); 1546 rc = plrStep(&left);
1547 if( rc!=SQLITE_OK ) break;
1449 }else if( plrColumn(&left)>plrColumn(&right) ){ 1548 }else if( plrColumn(&left)>plrColumn(&right) ){
1450 plrStep(&right); 1549 rc = plrStep(&right);
1550 if( rc!=SQLITE_OK ) break;
1451 }else if( plrPosition(&left)+1<plrPosition(&right) ){ 1551 }else if( plrPosition(&left)+1<plrPosition(&right) ){
1452 plrStep(&left); 1552 rc = plrStep(&left);
1553 if( rc!=SQLITE_OK ) break;
1453 }else if( plrPosition(&left)+1>plrPosition(&right) ){ 1554 }else if( plrPosition(&left)+1>plrPosition(&right) ){
1454 plrStep(&right); 1555 rc = plrStep(&right);
1556 if( rc!=SQLITE_OK ) break;
1455 }else{ 1557 }else{
1456 if( !match ){ 1558 if( !match ){
1457 plwInit(&writer, pOut, dlrDocid(pLeft)); 1559 plwInit(&writer, pOut, dlrDocid(pLeft));
1458 match = 1; 1560 match = 1;
1459 } 1561 }
1460 plwAdd(&writer, plrColumn(&right), plrPosition(&right), 0, 0); 1562 plwAdd(&writer, plrColumn(&right), plrPosition(&right), 0, 0);
1461 plrStep(&left); 1563 rc = plrStep(&left);
1462 plrStep(&right); 1564 if( rc!=SQLITE_OK ) break;
1565 rc = plrStep(&right);
1566 if( rc!=SQLITE_OK ) break;
1463 } 1567 }
1464 } 1568 }
1465 1569
1466 if( match ){ 1570 if( match ){
1467 plwTerminate(&writer); 1571 plwTerminate(&writer);
1468 plwDestroy(&writer); 1572 plwDestroy(&writer);
1469 } 1573 }
1470 1574
1471 plrDestroy(&left); 1575 plrDestroy(&left);
1472 plrDestroy(&right); 1576 plrDestroy(&right);
1577 return rc;
1473 } 1578 }
1474 1579
1475 /* We have two doclists with positions: pLeft and pRight. 1580 /* We have two doclists with positions: pLeft and pRight.
1476 ** Write the phrase intersection of these two doclists into pOut. 1581 ** Write the phrase intersection of these two doclists into pOut.
1477 ** 1582 **
1478 ** A phrase intersection means that two documents only match 1583 ** A phrase intersection means that two documents only match
1479 ** if pLeft.iPos+1==pRight.iPos. 1584 ** if pLeft.iPos+1==pRight.iPos.
1480 ** 1585 **
1481 ** iType controls the type of data written to pOut. If iType is 1586 ** iType controls the type of data written to pOut. If iType is
1482 ** DL_POSITIONS, the positions are those from pRight. 1587 ** DL_POSITIONS, the positions are those from pRight.
1483 */ 1588 */
1484 static void docListPhraseMerge( 1589 static int docListPhraseMerge(
1485 const char *pLeft, int nLeft, 1590 const char *pLeft, int nLeft,
1486 const char *pRight, int nRight, 1591 const char *pRight, int nRight,
1487 DocListType iType, 1592 DocListType iType,
1488 DataBuffer *pOut /* Write the combined doclist here */ 1593 DataBuffer *pOut /* Write the combined doclist here */
1489 ){ 1594 ){
1490 DLReader left, right; 1595 DLReader left, right;
1491 DLWriter writer; 1596 DLWriter writer;
1597 int rc;
1492 1598
1493 if( nLeft==0 || nRight==0 ) return; 1599 if( nLeft==0 || nRight==0 ) return SQLITE_OK;
1494 1600
1495 assert( iType!=DL_POSITIONS_OFFSETS ); 1601 assert( iType!=DL_POSITIONS_OFFSETS );
1496 1602
1497 dlrInit(&left, DL_POSITIONS, pLeft, nLeft); 1603 rc = dlrInit(&left, DL_POSITIONS, pLeft, nLeft);
1498 dlrInit(&right, DL_POSITIONS, pRight, nRight); 1604 if( rc!=SQLITE_OK ) return rc;
1605 rc = dlrInit(&right, DL_POSITIONS, pRight, nRight);
1606 if( rc!=SQLITE_OK ){
1607 dlrDestroy(&left);
1608 return rc;
1609 }
1499 dlwInit(&writer, iType, pOut); 1610 dlwInit(&writer, iType, pOut);
1500 1611
1501 while( !dlrAtEnd(&left) && !dlrAtEnd(&right) ){ 1612 while( !dlrAtEnd(&left) && !dlrAtEnd(&right) ){
1502 if( dlrDocid(&left)<dlrDocid(&right) ){ 1613 if( dlrDocid(&left)<dlrDocid(&right) ){
1503 dlrStep(&left); 1614 rc = dlrStep(&left);
1615 if( rc!=SQLITE_OK ) break;
1504 }else if( dlrDocid(&right)<dlrDocid(&left) ){ 1616 }else if( dlrDocid(&right)<dlrDocid(&left) ){
1505 dlrStep(&right); 1617 rc = dlrStep(&right);
1618 if( rc!=SQLITE_OK ) break;
1506 }else{ 1619 }else{
1507 posListPhraseMerge(&left, &right, &writer); 1620 rc = posListPhraseMerge(&left, &right, &writer);
1508 dlrStep(&left); 1621 if( rc!=SQLITE_OK ) break;
1509 dlrStep(&right); 1622 rc = dlrStep(&left);
1623 if( rc!=SQLITE_OK ) break;
1624 rc = dlrStep(&right);
1625 if( rc!=SQLITE_OK ) break;
1510 } 1626 }
1511 } 1627 }
1512 1628
1513 dlrDestroy(&left); 1629 dlrDestroy(&left);
1514 dlrDestroy(&right); 1630 dlrDestroy(&right);
1515 dlwDestroy(&writer); 1631 dlwDestroy(&writer);
1632 return rc;
1516 } 1633 }
1517 1634
1518 /* We have two DL_DOCIDS doclists: pLeft and pRight. 1635 /* We have two DL_DOCIDS doclists: pLeft and pRight.
1519 ** Write the intersection of these two doclists into pOut as a 1636 ** Write the intersection of these two doclists into pOut as a
1520 ** DL_DOCIDS doclist. 1637 ** DL_DOCIDS doclist.
1521 */ 1638 */
1522 static void docListAndMerge( 1639 static int docListAndMerge(
1523 const char *pLeft, int nLeft, 1640 const char *pLeft, int nLeft,
1524 const char *pRight, int nRight, 1641 const char *pRight, int nRight,
1525 DataBuffer *pOut /* Write the combined doclist here */ 1642 DataBuffer *pOut /* Write the combined doclist here */
1526 ){ 1643 ){
1527 DLReader left, right; 1644 DLReader left, right;
1528 DLWriter writer; 1645 DLWriter writer;
1646 int rc;
1529 1647
1530 if( nLeft==0 || nRight==0 ) return; 1648 if( nLeft==0 || nRight==0 ) return SQLITE_OK;
1531 1649
1532 dlrInit(&left, DL_DOCIDS, pLeft, nLeft); 1650 rc = dlrInit(&left, DL_DOCIDS, pLeft, nLeft);
1533 dlrInit(&right, DL_DOCIDS, pRight, nRight); 1651 if( rc!=SQLITE_OK ) return rc;
1652 rc = dlrInit(&right, DL_DOCIDS, pRight, nRight);
1653 if( rc!=SQLITE_OK ){
1654 dlrDestroy(&left);
1655 return rc;
1656 }
1534 dlwInit(&writer, DL_DOCIDS, pOut); 1657 dlwInit(&writer, DL_DOCIDS, pOut);
1535 1658
1536 while( !dlrAtEnd(&left) && !dlrAtEnd(&right) ){ 1659 while( !dlrAtEnd(&left) && !dlrAtEnd(&right) ){
1537 if( dlrDocid(&left)<dlrDocid(&right) ){ 1660 if( dlrDocid(&left)<dlrDocid(&right) ){
1538 dlrStep(&left); 1661 rc = dlrStep(&left);
1662 if( rc!=SQLITE_OK ) break;
1539 }else if( dlrDocid(&right)<dlrDocid(&left) ){ 1663 }else if( dlrDocid(&right)<dlrDocid(&left) ){
1540 dlrStep(&right); 1664 rc = dlrStep(&right);
1665 if( rc!=SQLITE_OK ) break;
1541 }else{ 1666 }else{
1542 dlwAdd(&writer, dlrDocid(&left)); 1667 dlwAdd(&writer, dlrDocid(&left));
1543 dlrStep(&left); 1668 rc = dlrStep(&left);
1544 dlrStep(&right); 1669 if( rc!=SQLITE_OK ) break;
1670 rc = dlrStep(&right);
1671 if( rc!=SQLITE_OK ) break;
1545 } 1672 }
1546 } 1673 }
1547 1674
1548 dlrDestroy(&left); 1675 dlrDestroy(&left);
1549 dlrDestroy(&right); 1676 dlrDestroy(&right);
1550 dlwDestroy(&writer); 1677 dlwDestroy(&writer);
1678 return rc;
1551 } 1679 }
1552 1680
1553 /* We have two DL_DOCIDS doclists: pLeft and pRight. 1681 /* We have two DL_DOCIDS doclists: pLeft and pRight.
1554 ** Write the union of these two doclists into pOut as a 1682 ** Write the union of these two doclists into pOut as a
1555 ** DL_DOCIDS doclist. 1683 ** DL_DOCIDS doclist.
1556 */ 1684 */
1557 static void docListOrMerge( 1685 static int docListOrMerge(
1558 const char *pLeft, int nLeft, 1686 const char *pLeft, int nLeft,
1559 const char *pRight, int nRight, 1687 const char *pRight, int nRight,
1560 DataBuffer *pOut /* Write the combined doclist here */ 1688 DataBuffer *pOut /* Write the combined doclist here */
1561 ){ 1689 ){
1562 DLReader left, right; 1690 DLReader left, right;
1563 DLWriter writer; 1691 DLWriter writer;
1692 int rc;
1564 1693
1565 if( nLeft==0 ){ 1694 if( nLeft==0 ){
1566 if( nRight!=0 ) dataBufferAppend(pOut, pRight, nRight); 1695 if( nRight!=0 ) dataBufferAppend(pOut, pRight, nRight);
1567 return; 1696 return SQLITE_OK;
1568 } 1697 }
1569 if( nRight==0 ){ 1698 if( nRight==0 ){
1570 dataBufferAppend(pOut, pLeft, nLeft); 1699 dataBufferAppend(pOut, pLeft, nLeft);
1571 return; 1700 return SQLITE_OK;
1572 } 1701 }
1573 1702
1574 dlrInit(&left, DL_DOCIDS, pLeft, nLeft); 1703 rc = dlrInit(&left, DL_DOCIDS, pLeft, nLeft);
1575 dlrInit(&right, DL_DOCIDS, pRight, nRight); 1704 if( rc!=SQLITE_OK ) return rc;
1705 rc = dlrInit(&right, DL_DOCIDS, pRight, nRight);
1706 if( rc!=SQLITE_OK ){
1707 dlrDestroy(&left);
1708 return rc;
1709 }
1576 dlwInit(&writer, DL_DOCIDS, pOut); 1710 dlwInit(&writer, DL_DOCIDS, pOut);
1577 1711
1578 while( !dlrAtEnd(&left) || !dlrAtEnd(&right) ){ 1712 while( !dlrAtEnd(&left) || !dlrAtEnd(&right) ){
1579 if( dlrAtEnd(&right) ){ 1713 if( dlrAtEnd(&right) ){
1580 dlwAdd(&writer, dlrDocid(&left)); 1714 dlwAdd(&writer, dlrDocid(&left));
1581 dlrStep(&left); 1715 rc = dlrStep(&left);
1716 if( rc!=SQLITE_OK ) break;
1582 }else if( dlrAtEnd(&left) ){ 1717 }else if( dlrAtEnd(&left) ){
1583 dlwAdd(&writer, dlrDocid(&right)); 1718 dlwAdd(&writer, dlrDocid(&right));
1584 dlrStep(&right); 1719 rc = dlrStep(&right);
1720 if( rc!=SQLITE_OK ) break;
1585 }else if( dlrDocid(&left)<dlrDocid(&right) ){ 1721 }else if( dlrDocid(&left)<dlrDocid(&right) ){
1586 dlwAdd(&writer, dlrDocid(&left)); 1722 dlwAdd(&writer, dlrDocid(&left));
1587 dlrStep(&left); 1723 rc = dlrStep(&left);
1724 if( rc!=SQLITE_OK ) break;
1588 }else if( dlrDocid(&right)<dlrDocid(&left) ){ 1725 }else if( dlrDocid(&right)<dlrDocid(&left) ){
1589 dlwAdd(&writer, dlrDocid(&right)); 1726 dlwAdd(&writer, dlrDocid(&right));
1590 dlrStep(&right); 1727 rc = dlrStep(&right);
1728 if( rc!=SQLITE_OK ) break;
1591 }else{ 1729 }else{
1592 dlwAdd(&writer, dlrDocid(&left)); 1730 dlwAdd(&writer, dlrDocid(&left));
1593 dlrStep(&left); 1731 rc = dlrStep(&left);
1594 dlrStep(&right); 1732 if( rc!=SQLITE_OK ) break;
1733 rc = dlrStep(&right);
1734 if( rc!=SQLITE_OK ) break;
1595 } 1735 }
1596 } 1736 }
1597 1737
1598 dlrDestroy(&left); 1738 dlrDestroy(&left);
1599 dlrDestroy(&right); 1739 dlrDestroy(&right);
1600 dlwDestroy(&writer); 1740 dlwDestroy(&writer);
1741 return rc;
1601 } 1742 }
1602 1743
1603 /* We have two DL_DOCIDS doclists: pLeft and pRight. 1744 /* We have two DL_DOCIDS doclists: pLeft and pRight.
1604 ** Write into pOut as DL_DOCIDS doclist containing all documents that 1745 ** Write into pOut as DL_DOCIDS doclist containing all documents that
1605 ** occur in pLeft but not in pRight. 1746 ** occur in pLeft but not in pRight.
1606 */ 1747 */
1607 static void docListExceptMerge( 1748 static int docListExceptMerge(
1608 const char *pLeft, int nLeft, 1749 const char *pLeft, int nLeft,
1609 const char *pRight, int nRight, 1750 const char *pRight, int nRight,
1610 DataBuffer *pOut /* Write the combined doclist here */ 1751 DataBuffer *pOut /* Write the combined doclist here */
1611 ){ 1752 ){
1612 DLReader left, right; 1753 DLReader left, right;
1613 DLWriter writer; 1754 DLWriter writer;
1755 int rc;
1614 1756
1615 if( nLeft==0 ) return; 1757 if( nLeft==0 ) return SQLITE_OK;
1616 if( nRight==0 ){ 1758 if( nRight==0 ){
1617 dataBufferAppend(pOut, pLeft, nLeft); 1759 dataBufferAppend(pOut, pLeft, nLeft);
1618 return; 1760 return SQLITE_OK;
1619 } 1761 }
1620 1762
1621 dlrInit(&left, DL_DOCIDS, pLeft, nLeft); 1763 rc = dlrInit(&left, DL_DOCIDS, pLeft, nLeft);
1622 dlrInit(&right, DL_DOCIDS, pRight, nRight); 1764 if( rc!=SQLITE_OK ) return rc;
1765 rc = dlrInit(&right, DL_DOCIDS, pRight, nRight);
1766 if( rc!=SQLITE_OK ){
1767 dlrDestroy(&left);
1768 return rc;
1769 }
1623 dlwInit(&writer, DL_DOCIDS, pOut); 1770 dlwInit(&writer, DL_DOCIDS, pOut);
1624 1771
1625 while( !dlrAtEnd(&left) ){ 1772 while( !dlrAtEnd(&left) ){
1626 while( !dlrAtEnd(&right) && dlrDocid(&right)<dlrDocid(&left) ){ 1773 while( !dlrAtEnd(&right) && dlrDocid(&right)<dlrDocid(&left) ){
1627 dlrStep(&right); 1774 rc = dlrStep(&right);
1775 if( rc!=SQLITE_OK ) goto err;
1628 } 1776 }
1629 if( dlrAtEnd(&right) || dlrDocid(&left)<dlrDocid(&right) ){ 1777 if( dlrAtEnd(&right) || dlrDocid(&left)<dlrDocid(&right) ){
1630 dlwAdd(&writer, dlrDocid(&left)); 1778 dlwAdd(&writer, dlrDocid(&left));
1631 } 1779 }
1632 dlrStep(&left); 1780 rc = dlrStep(&left);
1781 if( rc!=SQLITE_OK ) break;
1633 } 1782 }
1634 1783
1784 err:
1635 dlrDestroy(&left); 1785 dlrDestroy(&left);
1636 dlrDestroy(&right); 1786 dlrDestroy(&right);
1637 dlwDestroy(&writer); 1787 dlwDestroy(&writer);
1788 return rc;
1638 } 1789 }
1639 1790
1640 static char *string_dup_n(const char *s, int n){ 1791 static char *string_dup_n(const char *s, int n){
1641 char *str = sqlite3_malloc(n + 1); 1792 char *str = sqlite3_malloc(n + 1);
1642 memcpy(str, s, n); 1793 memcpy(str, s, n);
1643 str[n] = '\0'; 1794 str[n] = '\0';
1644 return str; 1795 return str;
1645 } 1796 }
1646 1797
1647 /* Duplicate a string; the caller must free() the returned string. 1798 /* Duplicate a string; the caller must free() the returned string.
(...skipping 1782 matching lines...) Expand 10 before | Expand all | Expand 10 after
3430 } 3581 }
3431 } else { /* full-text query */ 3582 } else { /* full-text query */
3432 rc = sqlite3_reset(c->pStmt); 3583 rc = sqlite3_reset(c->pStmt);
3433 if( rc!=SQLITE_OK ) return rc; 3584 if( rc!=SQLITE_OK ) return rc;
3434 3585
3435 if( c->result.nData==0 || dlrAtEnd(&c->reader) ){ 3586 if( c->result.nData==0 || dlrAtEnd(&c->reader) ){
3436 c->eof = 1; 3587 c->eof = 1;
3437 return SQLITE_OK; 3588 return SQLITE_OK;
3438 } 3589 }
3439 rc = sqlite3_bind_int64(c->pStmt, 1, dlrDocid(&c->reader)); 3590 rc = sqlite3_bind_int64(c->pStmt, 1, dlrDocid(&c->reader));
3440 dlrStep(&c->reader); 3591 if( rc!=SQLITE_OK ) return rc;
3592 rc = dlrStep(&c->reader);
3441 if( rc!=SQLITE_OK ) return rc; 3593 if( rc!=SQLITE_OK ) return rc;
3442 /* TODO(shess) Handle SQLITE_SCHEMA AND SQLITE_BUSY. */ 3594 /* TODO(shess) Handle SQLITE_SCHEMA AND SQLITE_BUSY. */
3443 rc = sqlite3_step(c->pStmt); 3595 rc = sqlite3_step(c->pStmt);
3444 if( rc==SQLITE_ROW ){ /* the case we expect */ 3596 if( rc==SQLITE_ROW ){ /* the case we expect */
3445 c->eof = 0; 3597 c->eof = 0;
3446 return SQLITE_OK; 3598 return SQLITE_OK;
3447 } 3599 }
3448 3600
3449 /* Corrupt if the index refers to missing document. */ 3601 /* Corrupt if the index refers to missing document. */
3450 if( rc==SQLITE_DONE ) return SQLITE_CORRUPT_BKPT; 3602 if( rc==SQLITE_DONE ) return SQLITE_CORRUPT_BKPT;
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
3490 if( rc ) return rc; 3642 if( rc ) return rc;
3491 for(i=1; i<=pQTerm->nPhrase && left.nData>0; i++){ 3643 for(i=1; i<=pQTerm->nPhrase && left.nData>0; i++){
3492 dataBufferInit(&right, 0); 3644 dataBufferInit(&right, 0);
3493 rc = termSelect(v, iColumn, pQTerm[i].pTerm, pQTerm[i].nTerm, 3645 rc = termSelect(v, iColumn, pQTerm[i].pTerm, pQTerm[i].nTerm,
3494 pQTerm[i].isPrefix, DL_POSITIONS, &right); 3646 pQTerm[i].isPrefix, DL_POSITIONS, &right);
3495 if( rc ){ 3647 if( rc ){
3496 dataBufferDestroy(&left); 3648 dataBufferDestroy(&left);
3497 return rc; 3649 return rc;
3498 } 3650 }
3499 dataBufferInit(&new, 0); 3651 dataBufferInit(&new, 0);
3500 docListPhraseMerge(left.pData, left.nData, right.pData, right.nData, 3652 rc = docListPhraseMerge(left.pData, left.nData, right.pData, right.nData,
3501 i<pQTerm->nPhrase ? DL_POSITIONS : DL_DOCIDS, &new); 3653 i<pQTerm->nPhrase ? DL_POSITIONS : DL_DOCIDS, &new);
3502 dataBufferDestroy(&left); 3654 dataBufferDestroy(&left);
3503 dataBufferDestroy(&right); 3655 dataBufferDestroy(&right);
3656 if( rc!=SQLITE_OK ){
3657 dataBufferDestroy(&new);
3658 return rc;
3659 }
3504 left = new; 3660 left = new;
3505 } 3661 }
3506 *pResult = left; 3662 *pResult = left;
3507 return SQLITE_OK; 3663 return rc;
3508 } 3664 }
3509 3665
3510 /* Add a new term pTerm[0..nTerm-1] to the query *q. 3666 /* Add a new term pTerm[0..nTerm-1] to the query *q.
3511 */ 3667 */
3512 static void queryAdd(Query *q, const char *pTerm, int nTerm){ 3668 static void queryAdd(Query *q, const char *pTerm, int nTerm){
3513 QueryTerm *t; 3669 QueryTerm *t;
3514 ++q->nTerms; 3670 ++q->nTerms;
3515 q->pTerms = sqlite3_realloc(q->pTerms, q->nTerms * sizeof(q->pTerms[0])); 3671 q->pTerms = sqlite3_realloc(q->pTerms, q->nTerms * sizeof(q->pTerms[0]));
3516 if( q->pTerms==0 ){ 3672 if( q->pTerms==0 ){
3517 q->nTerms = 0; 3673 q->nTerms = 0;
(...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after
3742 while( iNext<pQuery->nTerms && aTerm[iNext].isOr ){ 3898 while( iNext<pQuery->nTerms && aTerm[iNext].isOr ){
3743 rc = docListOfTerm(v, aTerm[iNext].iColumn, &aTerm[iNext], &or); 3899 rc = docListOfTerm(v, aTerm[iNext].iColumn, &aTerm[iNext], &or);
3744 iNext += aTerm[iNext].nPhrase + 1; 3900 iNext += aTerm[iNext].nPhrase + 1;
3745 if( rc ){ 3901 if( rc ){
3746 if( i!=nNot ) dataBufferDestroy(&left); 3902 if( i!=nNot ) dataBufferDestroy(&left);
3747 dataBufferDestroy(&right); 3903 dataBufferDestroy(&right);
3748 queryClear(pQuery); 3904 queryClear(pQuery);
3749 return rc; 3905 return rc;
3750 } 3906 }
3751 dataBufferInit(&new, 0); 3907 dataBufferInit(&new, 0);
3752 docListOrMerge(right.pData, right.nData, or.pData, or.nData, &new); 3908 rc = docListOrMerge(right.pData, right.nData, or.pData, or.nData, &new);
3753 dataBufferDestroy(&right); 3909 dataBufferDestroy(&right);
3754 dataBufferDestroy(&or); 3910 dataBufferDestroy(&or);
3911 if( rc!=SQLITE_OK ){
3912 if( i!=nNot ) dataBufferDestroy(&left);
3913 queryClear(pQuery);
3914 dataBufferDestroy(&new);
3915 return rc;
3916 }
3755 right = new; 3917 right = new;
3756 } 3918 }
3757 if( i==nNot ){ /* first term processed. */ 3919 if( i==nNot ){ /* first term processed. */
3758 left = right; 3920 left = right;
3759 }else{ 3921 }else{
3760 dataBufferInit(&new, 0); 3922 dataBufferInit(&new, 0);
3761 docListAndMerge(left.pData, left.nData, right.pData, right.nData, &new); 3923 rc = docListAndMerge(left.pData, left.nData,
3924 right.pData, right.nData, &new);
3762 dataBufferDestroy(&right); 3925 dataBufferDestroy(&right);
3763 dataBufferDestroy(&left); 3926 dataBufferDestroy(&left);
3927 if( rc!=SQLITE_OK ){
3928 queryClear(pQuery);
3929 dataBufferDestroy(&new);
3930 return rc;
3931 }
3764 left = new; 3932 left = new;
3765 } 3933 }
3766 } 3934 }
3767 3935
3768 if( nNot==pQuery->nTerms ){ 3936 if( nNot==pQuery->nTerms ){
3769 /* We do not yet know how to handle a query of only NOT terms */ 3937 /* We do not yet know how to handle a query of only NOT terms */
3770 return SQLITE_ERROR; 3938 return SQLITE_ERROR;
3771 } 3939 }
3772 3940
3773 /* Do the EXCEPT terms */ 3941 /* Do the EXCEPT terms */
3774 for(i=0; i<pQuery->nTerms; i += aTerm[i].nPhrase + 1){ 3942 for(i=0; i<pQuery->nTerms; i += aTerm[i].nPhrase + 1){
3775 if( !aTerm[i].isNot ) continue; 3943 if( !aTerm[i].isNot ) continue;
3776 rc = docListOfTerm(v, aTerm[i].iColumn, &aTerm[i], &right); 3944 rc = docListOfTerm(v, aTerm[i].iColumn, &aTerm[i], &right);
3777 if( rc ){ 3945 if( rc ){
3778 queryClear(pQuery); 3946 queryClear(pQuery);
3779 dataBufferDestroy(&left); 3947 dataBufferDestroy(&left);
3780 return rc; 3948 return rc;
3781 } 3949 }
3782 dataBufferInit(&new, 0); 3950 dataBufferInit(&new, 0);
3783 docListExceptMerge(left.pData, left.nData, right.pData, right.nData, &new); 3951 rc = docListExceptMerge(left.pData, left.nData,
3952 right.pData, right.nData, &new);
3784 dataBufferDestroy(&right); 3953 dataBufferDestroy(&right);
3785 dataBufferDestroy(&left); 3954 dataBufferDestroy(&left);
3955 if( rc!=SQLITE_OK ){
3956 queryClear(pQuery);
3957 dataBufferDestroy(&new);
3958 return rc;
3959 }
3786 left = new; 3960 left = new;
3787 } 3961 }
3788 3962
3789 *pResult = left; 3963 *pResult = left;
3790 return rc; 3964 return rc;
3791 } 3965 }
3792 3966
3793 /* 3967 /*
3794 ** This is the xFilter interface for the virtual table. See 3968 ** This is the xFilter interface for the virtual table. See
3795 ** the virtual table xFilter method documentation for additional 3969 ** the virtual table xFilter method documentation for additional
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
3869 if( c->result.nData!=0 ){ 4043 if( c->result.nData!=0 ){
3870 /* This case happens if the same cursor is used repeatedly. */ 4044 /* This case happens if the same cursor is used repeatedly. */
3871 dlrDestroy(&c->reader); 4045 dlrDestroy(&c->reader);
3872 dataBufferReset(&c->result); 4046 dataBufferReset(&c->result);
3873 }else{ 4047 }else{
3874 dataBufferInit(&c->result, 0); 4048 dataBufferInit(&c->result, 0);
3875 } 4049 }
3876 rc = fulltextQuery(v, idxNum-QUERY_FULLTEXT, zQuery, -1, &c->result, &c->q ); 4050 rc = fulltextQuery(v, idxNum-QUERY_FULLTEXT, zQuery, -1, &c->result, &c->q );
3877 if( rc!=SQLITE_OK ) return rc; 4051 if( rc!=SQLITE_OK ) return rc;
3878 if( c->result.nData!=0 ){ 4052 if( c->result.nData!=0 ){
3879 dlrInit(&c->reader, DL_DOCIDS, c->result.pData, c->result.nData); 4053 rc = dlrInit(&c->reader, DL_DOCIDS, c->result.pData, c->result.nData);
4054 if( rc!=SQLITE_OK ) return rc;
3880 } 4055 }
3881 break; 4056 break;
3882 } 4057 }
3883 } 4058 }
3884 4059
3885 return fulltextNext(pCursor); 4060 return fulltextNext(pCursor);
3886 } 4061 }
3887 4062
3888 /* This is the xEof method of the virtual table. The SQLite core 4063 /* This is the xEof method of the virtual table. The SQLite core
3889 ** calls this routine to find out if it has reached the end of 4064 ** calls this routine to find out if it has reached the end of
(...skipping 480 matching lines...) Expand 10 before | Expand all | Expand 10 after
4370 DataBuffer term; /* previous term, for decoding term delta. */ 4545 DataBuffer term; /* previous term, for decoding term delta. */
4371 4546
4372 sqlite_int64 iBlockid; 4547 sqlite_int64 iBlockid;
4373 } InteriorReader; 4548 } InteriorReader;
4374 4549
4375 static void interiorReaderDestroy(InteriorReader *pReader){ 4550 static void interiorReaderDestroy(InteriorReader *pReader){
4376 dataBufferDestroy(&pReader->term); 4551 dataBufferDestroy(&pReader->term);
4377 SCRAMBLE(pReader); 4552 SCRAMBLE(pReader);
4378 } 4553 }
4379 4554
4380 /* TODO(shess) The assertions are great, but what if we're in NDEBUG 4555 static int interiorReaderInit(const char *pData, int nData,
4381 ** and the blob is empty or otherwise contains suspect data? 4556 InteriorReader *pReader){
4382 */
4383 static void interiorReaderInit(const char *pData, int nData,
4384 InteriorReader *pReader){
4385 int n, nTerm; 4557 int n, nTerm;
4386 4558
4387 /* Require at least the leading flag byte */ 4559 /* These conditions are checked and met by the callers. */
4388 assert( nData>0 ); 4560 assert( nData>0 );
4389 assert( pData[0]!='\0' ); 4561 assert( pData[0]!='\0' );
4390 4562
4391 CLEAR(pReader); 4563 CLEAR(pReader);
4392 4564
4393 /* Decode the base blockid, and set the cursor to the first term. */ 4565 /* Decode the base blockid, and set the cursor to the first term. */
4394 n = getVarint(pData+1, &pReader->iBlockid); 4566 n = getVarintSafe(pData+1, &pReader->iBlockid, nData-1);
4395 assert( 1+n<=nData ); 4567 if( !n ) return SQLITE_CORRUPT_BKPT;
4396 pReader->pData = pData+1+n; 4568 pReader->pData = pData+1+n;
4397 pReader->nData = nData-(1+n); 4569 pReader->nData = nData-(1+n);
4398 4570
4399 /* A single-child interior node (such as when a leaf node was too 4571 /* A single-child interior node (such as when a leaf node was too
4400 ** large for the segment directory) won't have any terms. 4572 ** large for the segment directory) won't have any terms.
4401 ** Otherwise, decode the first term. 4573 ** Otherwise, decode the first term.
4402 */ 4574 */
4403 if( pReader->nData==0 ){ 4575 if( pReader->nData==0 ){
4404 dataBufferInit(&pReader->term, 0); 4576 dataBufferInit(&pReader->term, 0);
4405 }else{ 4577 }else{
4406 n = getVarint32(pReader->pData, &nTerm); 4578 n = getVarint32Safe(pReader->pData, &nTerm, pReader->nData);
4579 if( !n || nTerm<0 || nTerm>pReader->nData-n) return SQLITE_CORRUPT_BKPT;
4407 dataBufferInit(&pReader->term, nTerm); 4580 dataBufferInit(&pReader->term, nTerm);
4408 dataBufferReplace(&pReader->term, pReader->pData+n, nTerm); 4581 dataBufferReplace(&pReader->term, pReader->pData+n, nTerm);
4409 assert( n+nTerm<=pReader->nData );
4410 pReader->pData += n+nTerm; 4582 pReader->pData += n+nTerm;
4411 pReader->nData -= n+nTerm; 4583 pReader->nData -= n+nTerm;
4412 } 4584 }
4585 return SQLITE_OK;
4413 } 4586 }
4414 4587
4415 static int interiorReaderAtEnd(InteriorReader *pReader){ 4588 static int interiorReaderAtEnd(InteriorReader *pReader){
4416 return pReader->term.nData==0; 4589 return pReader->term.nData<=0;
4417 } 4590 }
4418 4591
4419 static sqlite_int64 interiorReaderCurrentBlockid(InteriorReader *pReader){ 4592 static sqlite_int64 interiorReaderCurrentBlockid(InteriorReader *pReader){
4420 return pReader->iBlockid; 4593 return pReader->iBlockid;
4421 } 4594 }
4422 4595
4423 static int interiorReaderTermBytes(InteriorReader *pReader){ 4596 static int interiorReaderTermBytes(InteriorReader *pReader){
4424 assert( !interiorReaderAtEnd(pReader) ); 4597 assert( !interiorReaderAtEnd(pReader) );
4425 return pReader->term.nData; 4598 return pReader->term.nData;
4426 } 4599 }
4427 static const char *interiorReaderTerm(InteriorReader *pReader){ 4600 static const char *interiorReaderTerm(InteriorReader *pReader){
4428 assert( !interiorReaderAtEnd(pReader) ); 4601 assert( !interiorReaderAtEnd(pReader) );
4429 return pReader->term.pData; 4602 return pReader->term.pData;
4430 } 4603 }
4431 4604
4432 /* Step forward to the next term in the node. */ 4605 /* Step forward to the next term in the node. */
4433 static void interiorReaderStep(InteriorReader *pReader){ 4606 static int interiorReaderStep(InteriorReader *pReader){
4434 assert( !interiorReaderAtEnd(pReader) ); 4607 assert( !interiorReaderAtEnd(pReader) );
4435 4608
4436 /* If the last term has been read, signal eof, else construct the 4609 /* If the last term has been read, signal eof, else construct the
4437 ** next term. 4610 ** next term.
4438 */ 4611 */
4439 if( pReader->nData==0 ){ 4612 if( pReader->nData==0 ){
4440 dataBufferReset(&pReader->term); 4613 dataBufferReset(&pReader->term);
4441 }else{ 4614 }else{
4442 int n, nPrefix, nSuffix; 4615 int n, nPrefix, nSuffix;
4443 4616
4444 n = getVarint32(pReader->pData, &nPrefix); 4617 n = getVarint32Safe(pReader->pData, &nPrefix, pReader->nData);
4445 n += getVarint32(pReader->pData+n, &nSuffix); 4618 if( !n ) return SQLITE_CORRUPT_BKPT;
4619 pReader->nData -= n;
4620 pReader->pData += n;
4621 n = getVarint32Safe(pReader->pData, &nSuffix, pReader->nData);
4622 if( !n ) return SQLITE_CORRUPT_BKPT;
4623 pReader->nData -= n;
4624 pReader->pData += n;
4625 if( nSuffix<0 || nSuffix>pReader->nData ) return SQLITE_CORRUPT_BKPT;
4626 if( nPrefix<0 || nPrefix>pReader->term.nData ) return SQLITE_CORRUPT_BKPT;
4446 4627
4447 /* Truncate the current term and append suffix data. */ 4628 /* Truncate the current term and append suffix data. */
4448 pReader->term.nData = nPrefix; 4629 pReader->term.nData = nPrefix;
4449 dataBufferAppend(&pReader->term, pReader->pData+n, nSuffix); 4630 dataBufferAppend(&pReader->term, pReader->pData, nSuffix);
4450 4631
4451 assert( n+nSuffix<=pReader->nData ); 4632 pReader->pData += nSuffix;
4452 pReader->pData += n+nSuffix; 4633 pReader->nData -= nSuffix;
4453 pReader->nData -= n+nSuffix;
4454 } 4634 }
4455 pReader->iBlockid++; 4635 pReader->iBlockid++;
4636 return SQLITE_OK;
4456 } 4637 }
4457 4638
4458 /* Compare the current term to pTerm[nTerm], returning strcmp-style 4639 /* Compare the current term to pTerm[nTerm], returning strcmp-style
4459 ** results. If isPrefix, equality means equal through nTerm bytes. 4640 ** results. If isPrefix, equality means equal through nTerm bytes.
4460 */ 4641 */
4461 static int interiorReaderTermCmp(InteriorReader *pReader, 4642 static int interiorReaderTermCmp(InteriorReader *pReader,
4462 const char *pTerm, int nTerm, int isPrefix){ 4643 const char *pTerm, int nTerm, int isPrefix){
4463 const char *pReaderTerm = interiorReaderTerm(pReader); 4644 const char *pReaderTerm = interiorReaderTerm(pReader);
4464 int nReaderTerm = interiorReaderTermBytes(pReader); 4645 int nReaderTerm = interiorReaderTermBytes(pReader);
4465 int c, n = nReaderTerm<nTerm ? nReaderTerm : nTerm; 4646 int c, n = nReaderTerm<nTerm ? nReaderTerm : nTerm;
(...skipping 351 matching lines...) Expand 10 before | Expand all | Expand 10 after
4817 4998
4818 /* Estimate the length of the merged doclist so we can leave space 4999 /* Estimate the length of the merged doclist so we can leave space
4819 ** to encode it. 5000 ** to encode it.
4820 */ 5001 */
4821 for(i=0, nData=0; i<nReaders; i++){ 5002 for(i=0, nData=0; i<nReaders; i++){
4822 nData += dlrAllDataBytes(&pReaders[i]); 5003 nData += dlrAllDataBytes(&pReaders[i]);
4823 } 5004 }
4824 n = putVarint(c, nData); 5005 n = putVarint(c, nData);
4825 dataBufferAppend(&pWriter->data, c, n); 5006 dataBufferAppend(&pWriter->data, c, n);
4826 5007
4827 docListMerge(&pWriter->data, pReaders, nReaders); 5008 rc = docListMerge(&pWriter->data, pReaders, nReaders);
5009 if( rc!= SQLITE_OK ) return rc;
4828 ASSERT_VALID_DOCLIST(DL_DEFAULT, 5010 ASSERT_VALID_DOCLIST(DL_DEFAULT,
4829 pWriter->data.pData+iDoclistData+n, 5011 pWriter->data.pData+iDoclistData+n,
4830 pWriter->data.nData-iDoclistData-n, NULL); 5012 pWriter->data.nData-iDoclistData-n, NULL);
4831 5013
4832 /* The actual amount of doclist data at this point could be smaller 5014 /* The actual amount of doclist data at this point could be smaller
4833 ** than the length we encoded. Additionally, the space required to 5015 ** than the length we encoded. Additionally, the space required to
4834 ** encode this length could be smaller. For small doclists, this is 5016 ** encode this length could be smaller. For small doclists, this is
4835 ** not a big deal, we can just use memmove() to adjust things. 5017 ** not a big deal, we can just use memmove() to adjust things.
4836 */ 5018 */
4837 nActualData = pWriter->data.nData-(iDoclistData+n); 5019 nActualData = pWriter->data.nData-(iDoclistData+n);
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
4927 */ 5109 */
4928 /* TODO(shess) Revise writeZeroSegment() so that doclists are 5110 /* TODO(shess) Revise writeZeroSegment() so that doclists are
4929 ** constructed directly in pWriter->data. 5111 ** constructed directly in pWriter->data.
4930 */ 5112 */
4931 static int leafWriterStep(fulltext_vtab *v, LeafWriter *pWriter, 5113 static int leafWriterStep(fulltext_vtab *v, LeafWriter *pWriter,
4932 const char *pTerm, int nTerm, 5114 const char *pTerm, int nTerm,
4933 const char *pData, int nData){ 5115 const char *pData, int nData){
4934 int rc; 5116 int rc;
4935 DLReader reader; 5117 DLReader reader;
4936 5118
4937 dlrInit(&reader, DL_DEFAULT, pData, nData); 5119 rc = dlrInit(&reader, DL_DEFAULT, pData, nData);
5120 if( rc!=SQLITE_OK ) return rc;
4938 rc = leafWriterStepMerge(v, pWriter, pTerm, nTerm, &reader, 1); 5121 rc = leafWriterStepMerge(v, pWriter, pTerm, nTerm, &reader, 1);
4939 dlrDestroy(&reader); 5122 dlrDestroy(&reader);
4940 5123
4941 return rc; 5124 return rc;
4942 } 5125 }
4943 5126
4944 5127
4945 /****************************************************************/ 5128 /****************************************************************/
4946 /* LeafReader is used to iterate over an individual leaf node. */ 5129 /* LeafReader is used to iterate over an individual leaf node. */
4947 typedef struct LeafReader { 5130 typedef struct LeafReader {
(...skipping 24 matching lines...) Expand all
4972 /* Access the doclist data for the current term. */ 5155 /* Access the doclist data for the current term. */
4973 static int leafReaderDataBytes(LeafReader *pReader){ 5156 static int leafReaderDataBytes(LeafReader *pReader){
4974 int nData; 5157 int nData;
4975 assert( pReader->term.nData>0 ); 5158 assert( pReader->term.nData>0 );
4976 getVarint32(pReader->pData, &nData); 5159 getVarint32(pReader->pData, &nData);
4977 return nData; 5160 return nData;
4978 } 5161 }
4979 static const char *leafReaderData(LeafReader *pReader){ 5162 static const char *leafReaderData(LeafReader *pReader){
4980 int n, nData; 5163 int n, nData;
4981 assert( pReader->term.nData>0 ); 5164 assert( pReader->term.nData>0 );
4982 n = getVarint32(pReader->pData, &nData); 5165 n = getVarint32Safe(pReader->pData, &nData, pReader->nData);
5166 if( !n || nData>pReader->nData-n ) return NULL;
4983 return pReader->pData+n; 5167 return pReader->pData+n;
4984 } 5168 }
4985 5169
4986 static void leafReaderInit(const char *pData, int nData, 5170 static int leafReaderInit(const char *pData, int nData, LeafReader *pReader){
4987 LeafReader *pReader){
4988 int nTerm, n; 5171 int nTerm, n;
4989 5172
5173 /* All callers check this precondition. */
4990 assert( nData>0 ); 5174 assert( nData>0 );
4991 assert( pData[0]=='\0' ); 5175 assert( pData[0]=='\0' );
4992 5176
4993 CLEAR(pReader); 5177 CLEAR(pReader);
4994 5178
4995 /* Read the first term, skipping the header byte. */ 5179 /* Read the first term, skipping the header byte. */
4996 n = getVarint32(pData+1, &nTerm); 5180 n = getVarint32Safe(pData+1, &nTerm, nData-1);
5181 if( !n || nTerm<0 || nTerm>nData-1-n ) return SQLITE_CORRUPT_BKPT;
4997 dataBufferInit(&pReader->term, nTerm); 5182 dataBufferInit(&pReader->term, nTerm);
4998 dataBufferReplace(&pReader->term, pData+1+n, nTerm); 5183 dataBufferReplace(&pReader->term, pData+1+n, nTerm);
4999 5184
5000 /* Position after the first term. */ 5185 /* Position after the first term. */
5001 assert( 1+n+nTerm<nData );
5002 pReader->pData = pData+1+n+nTerm; 5186 pReader->pData = pData+1+n+nTerm;
5003 pReader->nData = nData-1-n-nTerm; 5187 pReader->nData = nData-1-n-nTerm;
5188 return SQLITE_OK;
5004 } 5189 }
5005 5190
5006 /* Step the reader forward to the next term. */ 5191 /* Step the reader forward to the next term. */
5007 static void leafReaderStep(LeafReader *pReader){ 5192 static int leafReaderStep(LeafReader *pReader){
5008 int n, nData, nPrefix, nSuffix; 5193 int n, nData, nPrefix, nSuffix;
5009 assert( !leafReaderAtEnd(pReader) ); 5194 assert( !leafReaderAtEnd(pReader) );
5010 5195
5011 /* Skip previous entry's data block. */ 5196 /* Skip previous entry's data block. */
5012 n = getVarint32(pReader->pData, &nData); 5197 n = getVarint32Safe(pReader->pData, &nData, pReader->nData);
5013 assert( n+nData<=pReader->nData ); 5198 if( !n || nData<0 || nData>pReader->nData-n ) return SQLITE_CORRUPT_BKPT;
5014 pReader->pData += n+nData; 5199 pReader->pData += n+nData;
5015 pReader->nData -= n+nData; 5200 pReader->nData -= n+nData;
5016 5201
5017 if( !leafReaderAtEnd(pReader) ){ 5202 if( !leafReaderAtEnd(pReader) ){
5018 /* Construct the new term using a prefix from the old term plus a 5203 /* Construct the new term using a prefix from the old term plus a
5019 ** suffix from the leaf data. 5204 ** suffix from the leaf data.
5020 */ 5205 */
5021 n = getVarint32(pReader->pData, &nPrefix); 5206 n = getVarint32Safe(pReader->pData, &nPrefix, pReader->nData);
5022 n += getVarint32(pReader->pData+n, &nSuffix); 5207 if( !n ) return SQLITE_CORRUPT_BKPT;
5023 assert( n+nSuffix<pReader->nData ); 5208 pReader->nData -= n;
5209 pReader->pData += n;
5210 n = getVarint32Safe(pReader->pData, &nSuffix, pReader->nData);
5211 if( !n ) return SQLITE_CORRUPT_BKPT;
5212 pReader->nData -= n;
5213 pReader->pData += n;
5214 if( nSuffix<0 || nSuffix>pReader->nData ) return SQLITE_CORRUPT_BKPT;
5215 if( nPrefix<0 || nPrefix>pReader->term.nData ) return SQLITE_CORRUPT_BKPT;
5024 pReader->term.nData = nPrefix; 5216 pReader->term.nData = nPrefix;
5025 dataBufferAppend(&pReader->term, pReader->pData+n, nSuffix); 5217 dataBufferAppend(&pReader->term, pReader->pData, nSuffix);
5026 5218
5027 pReader->pData += n+nSuffix; 5219 pReader->pData += nSuffix;
5028 pReader->nData -= n+nSuffix; 5220 pReader->nData -= nSuffix;
5029 } 5221 }
5222 return SQLITE_OK;
5030 } 5223 }
5031 5224
5032 /* strcmp-style comparison of pReader's current term against pTerm. 5225 /* strcmp-style comparison of pReader's current term against pTerm.
5033 ** If isPrefix, equality means equal through nTerm bytes. 5226 ** If isPrefix, equality means equal through nTerm bytes.
5034 */ 5227 */
5035 static int leafReaderTermCmp(LeafReader *pReader, 5228 static int leafReaderTermCmp(LeafReader *pReader,
5036 const char *pTerm, int nTerm, int isPrefix){ 5229 const char *pTerm, int nTerm, int isPrefix){
5037 int c, n = pReader->term.nData<nTerm ? pReader->term.nData : nTerm; 5230 int c, n = pReader->term.nData<nTerm ? pReader->term.nData : nTerm;
5038 if( n==0 ){ 5231 if( n==0 ){
5039 if( pReader->term.nData>0 ) return -1; 5232 if( pReader->term.nData>0 ) return -1;
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
5126 int idx, 5319 int idx,
5127 sqlite_int64 iStartBlockid, 5320 sqlite_int64 iStartBlockid,
5128 sqlite_int64 iEndBlockid, 5321 sqlite_int64 iEndBlockid,
5129 const char *pRootData, int nRootData, 5322 const char *pRootData, int nRootData,
5130 LeavesReader *pReader){ 5323 LeavesReader *pReader){
5131 CLEAR(pReader); 5324 CLEAR(pReader);
5132 pReader->idx = idx; 5325 pReader->idx = idx;
5133 5326
5134 dataBufferInit(&pReader->rootData, 0); 5327 dataBufferInit(&pReader->rootData, 0);
5135 if( iStartBlockid==0 ){ 5328 if( iStartBlockid==0 ){
5329 int rc;
5136 /* Corrupt if this can't be a leaf node. */ 5330 /* Corrupt if this can't be a leaf node. */
5137 if( pRootData==NULL || nRootData<1 || pRootData[0]!='\0' ){ 5331 if( pRootData==NULL || nRootData<1 || pRootData[0]!='\0' ){
5138 return SQLITE_CORRUPT_BKPT; 5332 return SQLITE_CORRUPT_BKPT;
5139 } 5333 }
5140 /* Entire leaf level fit in root data. */ 5334 /* Entire leaf level fit in root data. */
5141 dataBufferReplace(&pReader->rootData, pRootData, nRootData); 5335 dataBufferReplace(&pReader->rootData, pRootData, nRootData);
5142 leafReaderInit(pReader->rootData.pData, pReader->rootData.nData, 5336 rc = leafReaderInit(pReader->rootData.pData, pReader->rootData.nData,
5143 &pReader->leafReader); 5337 &pReader->leafReader);
5338 if( rc!=SQLITE_OK ){
5339 dataBufferDestroy(&pReader->rootData);
5340 return rc;
5341 }
5144 }else{ 5342 }else{
5145 sqlite3_stmt *s; 5343 sqlite3_stmt *s;
5146 int rc = sql_get_leaf_statement(v, idx, &s); 5344 int rc = sql_get_leaf_statement(v, idx, &s);
5147 if( rc!=SQLITE_OK ) return rc; 5345 if( rc!=SQLITE_OK ) return rc;
5148 5346
5149 rc = sqlite3_bind_int64(s, 1, iStartBlockid); 5347 rc = sqlite3_bind_int64(s, 1, iStartBlockid);
5150 if( rc!=SQLITE_OK ) goto err; 5348 if( rc!=SQLITE_OK ) goto err;
5151 5349
5152 rc = sqlite3_bind_int64(s, 2, iEndBlockid); 5350 rc = sqlite3_bind_int64(s, 2, iEndBlockid);
5153 if( rc!=SQLITE_OK ) goto err; 5351 if( rc!=SQLITE_OK ) goto err;
(...skipping 13 matching lines...) Expand all
5167 if( sqlite3_column_type(s, 0)!=SQLITE_BLOB ){ 5365 if( sqlite3_column_type(s, 0)!=SQLITE_BLOB ){
5168 rc = SQLITE_CORRUPT_BKPT; 5366 rc = SQLITE_CORRUPT_BKPT;
5169 }else{ 5367 }else{
5170 const char *pLeafData = sqlite3_column_blob(s, 0); 5368 const char *pLeafData = sqlite3_column_blob(s, 0);
5171 int nLeafData = sqlite3_column_bytes(s, 0); 5369 int nLeafData = sqlite3_column_bytes(s, 0);
5172 5370
5173 /* Corrupt if this can't be a leaf node. */ 5371 /* Corrupt if this can't be a leaf node. */
5174 if( pLeafData==NULL || nLeafData<1 || pLeafData[0]!='\0' ){ 5372 if( pLeafData==NULL || nLeafData<1 || pLeafData[0]!='\0' ){
5175 rc = SQLITE_CORRUPT_BKPT; 5373 rc = SQLITE_CORRUPT_BKPT;
5176 }else{ 5374 }else{
5177 leafReaderInit(pLeafData, nLeafData, &pReader->leafReader); 5375 rc = leafReaderInit(pLeafData, nLeafData, &pReader->leafReader);
5178 } 5376 }
5179 } 5377 }
5180 5378
5181 err: 5379 err:
5182 if( rc!=SQLITE_OK ){ 5380 if( rc!=SQLITE_OK ){
5183 if( idx==-1 ){ 5381 if( idx==-1 ){
5184 sqlite3_finalize(s); 5382 sqlite3_finalize(s);
5185 }else{ 5383 }else{
5186 sqlite3_reset(s); 5384 sqlite3_reset(s);
5187 } 5385 }
5188 return rc; 5386 return rc;
5189 } 5387 }
5190 5388
5191 pReader->pStmt = s; 5389 pReader->pStmt = s;
5192 } 5390 }
5193 return SQLITE_OK; 5391 return SQLITE_OK;
5194 } 5392 }
5195 5393
5196 /* Step the current leaf forward to the next term. If we reach the 5394 /* Step the current leaf forward to the next term. If we reach the
5197 ** end of the current leaf, step forward to the next leaf block. 5395 ** end of the current leaf, step forward to the next leaf block.
5198 */ 5396 */
5199 static int leavesReaderStep(fulltext_vtab *v, LeavesReader *pReader){ 5397 static int leavesReaderStep(fulltext_vtab *v, LeavesReader *pReader){
5398 int rc;
5200 assert( !leavesReaderAtEnd(pReader) ); 5399 assert( !leavesReaderAtEnd(pReader) );
5201 leafReaderStep(&pReader->leafReader); 5400 rc = leafReaderStep(&pReader->leafReader);
5401 if( rc!=SQLITE_OK ) return rc;
5202 5402
5203 if( leafReaderAtEnd(&pReader->leafReader) ){ 5403 if( leafReaderAtEnd(&pReader->leafReader) ){
5204 int rc;
5205 if( pReader->rootData.pData ){ 5404 if( pReader->rootData.pData ){
5206 pReader->eof = 1; 5405 pReader->eof = 1;
5207 return SQLITE_OK; 5406 return SQLITE_OK;
5208 } 5407 }
5209 rc = sqlite3_step(pReader->pStmt); 5408 rc = sqlite3_step(pReader->pStmt);
5210 if( rc!=SQLITE_ROW ){ 5409 if( rc!=SQLITE_ROW ){
5211 pReader->eof = 1; 5410 pReader->eof = 1;
5212 return rc==SQLITE_DONE ? SQLITE_OK : rc; 5411 return rc==SQLITE_DONE ? SQLITE_OK : rc;
5213 } 5412 }
5214 5413
5215 /* Corrupt if leaf data isn't a blob. */ 5414 /* Corrupt if leaf data isn't a blob. */
5216 if( sqlite3_column_type(pReader->pStmt, 0)!=SQLITE_BLOB ){ 5415 if( sqlite3_column_type(pReader->pStmt, 0)!=SQLITE_BLOB ){
5217 return SQLITE_CORRUPT_BKPT; 5416 return SQLITE_CORRUPT_BKPT;
5218 }else{ 5417 }else{
5418 LeafReader tmp;
5219 const char *pLeafData = sqlite3_column_blob(pReader->pStmt, 0); 5419 const char *pLeafData = sqlite3_column_blob(pReader->pStmt, 0);
5220 int nLeafData = sqlite3_column_bytes(pReader->pStmt, 0); 5420 int nLeafData = sqlite3_column_bytes(pReader->pStmt, 0);
5221 5421
5222 /* Corrupt if this can't be a leaf node. */ 5422 /* Corrupt if this can't be a leaf node. */
5223 if( pLeafData==NULL || nLeafData<1 || pLeafData[0]!='\0' ){ 5423 if( pLeafData==NULL || nLeafData<1 || pLeafData[0]!='\0' ){
5224 return SQLITE_CORRUPT_BKPT; 5424 return SQLITE_CORRUPT_BKPT;
5225 } 5425 }
5226 5426
5427 rc = leafReaderInit(pLeafData, nLeafData, &tmp);
5428 if( rc!=SQLITE_OK ) return rc;
5227 leafReaderDestroy(&pReader->leafReader); 5429 leafReaderDestroy(&pReader->leafReader);
5228 leafReaderInit(pLeafData, nLeafData, &pReader->leafReader); 5430 pReader->leafReader = tmp;
5229 } 5431 }
5230 } 5432 }
5231 return SQLITE_OK; 5433 return SQLITE_OK;
5232 } 5434 }
5233 5435
5234 /* Order LeavesReaders by their term, ignoring idx. Readers at eof 5436 /* Order LeavesReaders by their term, ignoring idx. Readers at eof
5235 ** always sort to the end. 5437 ** always sort to the end.
5236 */ 5438 */
5237 static int leavesReaderTermCmp(LeavesReader *lr1, LeavesReader *lr2){ 5439 static int leavesReaderTermCmp(LeavesReader *lr1, LeavesReader *lr2){
5238 if( leavesReaderAtEnd(lr1) ){ 5440 if( leavesReaderAtEnd(lr1) ){
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
5327 ** is written to pWriter. Assumes pReaders is ordered oldest to 5529 ** is written to pWriter. Assumes pReaders is ordered oldest to
5328 ** newest. 5530 ** newest.
5329 */ 5531 */
5330 /* TODO(shess) Consider putting this inline in segmentMerge(). */ 5532 /* TODO(shess) Consider putting this inline in segmentMerge(). */
5331 static int leavesReadersMerge(fulltext_vtab *v, 5533 static int leavesReadersMerge(fulltext_vtab *v,
5332 LeavesReader *pReaders, int nReaders, 5534 LeavesReader *pReaders, int nReaders,
5333 LeafWriter *pWriter){ 5535 LeafWriter *pWriter){
5334 DLReader dlReaders[MERGE_COUNT]; 5536 DLReader dlReaders[MERGE_COUNT];
5335 const char *pTerm = leavesReaderTerm(pReaders); 5537 const char *pTerm = leavesReaderTerm(pReaders);
5336 int i, nTerm = leavesReaderTermBytes(pReaders); 5538 int i, nTerm = leavesReaderTermBytes(pReaders);
5539 int rc;
5337 5540
5338 assert( nReaders<=MERGE_COUNT ); 5541 assert( nReaders<=MERGE_COUNT );
5339 5542
5340 for(i=0; i<nReaders; i++){ 5543 for(i=0; i<nReaders; i++){
5341 dlrInit(&dlReaders[i], DL_DEFAULT, 5544 const char *pData = leavesReaderData(pReaders+i);
5342 leavesReaderData(pReaders+i), 5545 if( pData==NULL ){
5343 leavesReaderDataBytes(pReaders+i)); 5546 rc = SQLITE_CORRUPT_BKPT;
5547 break;
5548 }
5549 rc = dlrInit(&dlReaders[i], DL_DEFAULT,
5550 pData,
5551 leavesReaderDataBytes(pReaders+i));
5552 if( rc!=SQLITE_OK ) break;
5553 }
5554 if( rc!=SQLITE_OK ){
5555 while( i-->0 ){
5556 dlrDestroy(&dlReaders[i]);
5557 }
5558 return rc;
5344 } 5559 }
5345 5560
5346 return leafWriterStepMerge(v, pWriter, pTerm, nTerm, dlReaders, nReaders); 5561 return leafWriterStepMerge(v, pWriter, pTerm, nTerm, dlReaders, nReaders);
5347 } 5562 }
5348 5563
5349 /* Forward ref due to mutual recursion with segdirNextIndex(). */ 5564 /* Forward ref due to mutual recursion with segdirNextIndex(). */
5350 static int segmentMerge(fulltext_vtab *v, int iLevel); 5565 static int segmentMerge(fulltext_vtab *v, int iLevel);
5351 5566
5352 /* Put the next available index at iLevel into *pidx. If iLevel 5567 /* Put the next available index at iLevel into *pidx. If iLevel
5353 ** already has MERGE_COUNT segments, they are merged to a higher 5568 ** already has MERGE_COUNT segments, they are merged to a higher
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
5437 5652
5438 err: 5653 err:
5439 for(i=0; i<MERGE_COUNT; i++){ 5654 for(i=0; i<MERGE_COUNT; i++){
5440 leavesReaderDestroy(&lrs[i]); 5655 leavesReaderDestroy(&lrs[i]);
5441 } 5656 }
5442 leafWriterDestroy(&writer); 5657 leafWriterDestroy(&writer);
5443 return rc; 5658 return rc;
5444 } 5659 }
5445 5660
5446 /* Accumulate the union of *acc and *pData into *acc. */ 5661 /* Accumulate the union of *acc and *pData into *acc. */
5447 static void docListAccumulateUnion(DataBuffer *acc, 5662 static int docListAccumulateUnion(DataBuffer *acc,
5448 const char *pData, int nData) { 5663 const char *pData, int nData) {
5449 DataBuffer tmp = *acc; 5664 DataBuffer tmp = *acc;
5665 int rc;
5450 dataBufferInit(acc, tmp.nData+nData); 5666 dataBufferInit(acc, tmp.nData+nData);
5451 docListUnion(tmp.pData, tmp.nData, pData, nData, acc); 5667 rc = docListUnion(tmp.pData, tmp.nData, pData, nData, acc);
5452 dataBufferDestroy(&tmp); 5668 dataBufferDestroy(&tmp);
5669 return rc;
5453 } 5670 }
5454 5671
5455 /* TODO(shess) It might be interesting to explore different merge 5672 /* TODO(shess) It might be interesting to explore different merge
5456 ** strategies, here. For instance, since this is a sorted merge, we 5673 ** strategies, here. For instance, since this is a sorted merge, we
5457 ** could easily merge many doclists in parallel. With some 5674 ** could easily merge many doclists in parallel. With some
5458 ** comprehension of the storage format, we could merge all of the 5675 ** comprehension of the storage format, we could merge all of the
5459 ** doclists within a leaf node directly from the leaf node's storage. 5676 ** doclists within a leaf node directly from the leaf node's storage.
5460 ** It may be worthwhile to merge smaller doclists before larger 5677 ** It may be worthwhile to merge smaller doclists before larger
5461 ** doclists, since they can be traversed more quickly - but the 5678 ** doclists, since they can be traversed more quickly - but the
5462 ** results may have less overlap, making them more expensive in a 5679 ** results may have less overlap, making them more expensive in a
(...skipping 21 matching lines...) Expand all
5484 for(rc=SQLITE_OK; rc==SQLITE_OK && !leavesReaderAtEnd(pReader); 5701 for(rc=SQLITE_OK; rc==SQLITE_OK && !leavesReaderAtEnd(pReader);
5485 rc=leavesReaderStep(v, pReader)){ 5702 rc=leavesReaderStep(v, pReader)){
5486 /* TODO(shess) Really want leavesReaderTermCmp(), but that name is 5703 /* TODO(shess) Really want leavesReaderTermCmp(), but that name is
5487 ** already taken to compare the terms of two LeavesReaders. Think 5704 ** already taken to compare the terms of two LeavesReaders. Think
5488 ** on a better name. [Meanwhile, break encapsulation rather than 5705 ** on a better name. [Meanwhile, break encapsulation rather than
5489 ** use a confusing name.] 5706 ** use a confusing name.]
5490 */ 5707 */
5491 int c = leafReaderTermCmp(&pReader->leafReader, pTerm, nTerm, isPrefix); 5708 int c = leafReaderTermCmp(&pReader->leafReader, pTerm, nTerm, isPrefix);
5492 if( c>0 ) break; /* Past any possible matches. */ 5709 if( c>0 ) break; /* Past any possible matches. */
5493 if( c==0 ){ 5710 if( c==0 ){
5711 int iBuffer, nData;
5494 const char *pData = leavesReaderData(pReader); 5712 const char *pData = leavesReaderData(pReader);
5495 int iBuffer, nData = leavesReaderDataBytes(pReader); 5713 if( pData==NULL ){
5714 rc = SQLITE_CORRUPT_BKPT;
5715 break;
5716 }
5717 nData = leavesReaderDataBytes(pReader);
5496 5718
5497 /* Find the first empty buffer. */ 5719 /* Find the first empty buffer. */
5498 for(iBuffer=0; iBuffer<nBuffers; ++iBuffer){ 5720 for(iBuffer=0; iBuffer<nBuffers; ++iBuffer){
5499 if( 0==pBuffers[iBuffer].nData ) break; 5721 if( 0==pBuffers[iBuffer].nData ) break;
5500 } 5722 }
5501 5723
5502 /* Out of buffers, add an empty one. */ 5724 /* Out of buffers, add an empty one. */
5503 if( iBuffer==nBuffers ){ 5725 if( iBuffer==nBuffers ){
5504 if( nBuffers==nMaxBuffers ){ 5726 if( nBuffers==nMaxBuffers ){
5505 DataBuffer *p; 5727 DataBuffer *p;
(...skipping 25 matching lines...) Expand all
5531 dataBufferReplace(&(pBuffers[0]), pData, nData); 5753 dataBufferReplace(&(pBuffers[0]), pData, nData);
5532 }else{ 5754 }else{
5533 /* pAcc is the empty buffer the merged data will end up in. */ 5755 /* pAcc is the empty buffer the merged data will end up in. */
5534 DataBuffer *pAcc = &(pBuffers[iBuffer]); 5756 DataBuffer *pAcc = &(pBuffers[iBuffer]);
5535 DataBuffer *p = &(pBuffers[0]); 5757 DataBuffer *p = &(pBuffers[0]);
5536 5758
5537 /* Handle position 0 specially to avoid need to prime pAcc 5759 /* Handle position 0 specially to avoid need to prime pAcc
5538 ** with pData/nData. 5760 ** with pData/nData.
5539 */ 5761 */
5540 dataBufferSwap(p, pAcc); 5762 dataBufferSwap(p, pAcc);
5541 docListAccumulateUnion(pAcc, pData, nData); 5763 rc = docListAccumulateUnion(pAcc, pData, nData);
5764 if( rc!=SQLITE_OK ) goto err;
5542 5765
5543 /* Accumulate remaining doclists into pAcc. */ 5766 /* Accumulate remaining doclists into pAcc. */
5544 for(++p; p<pAcc; ++p){ 5767 for(++p; p<pAcc; ++p){
5545 docListAccumulateUnion(pAcc, p->pData, p->nData); 5768 rc = docListAccumulateUnion(pAcc, p->pData, p->nData);
5769 if( rc!=SQLITE_OK ) goto err;
5546 5770
5547 /* dataBufferReset() could allow a large doclist to blow up 5771 /* dataBufferReset() could allow a large doclist to blow up
5548 ** our memory requirements. 5772 ** our memory requirements.
5549 */ 5773 */
5550 if( p->nCapacity<1024 ){ 5774 if( p->nCapacity<1024 ){
5551 dataBufferReset(p); 5775 dataBufferReset(p);
5552 }else{ 5776 }else{
5553 dataBufferDestroy(p); 5777 dataBufferDestroy(p);
5554 dataBufferInit(p, 0); 5778 dataBufferInit(p, 0);
5555 } 5779 }
5556 } 5780 }
5557 } 5781 }
5558 } 5782 }
5559 } 5783 }
5560 5784
5561 /* Union all the doclists together into *out. */ 5785 /* Union all the doclists together into *out. */
5562 /* TODO(shess) What if *out is big? Sigh. */ 5786 /* TODO(shess) What if *out is big? Sigh. */
5563 if( rc==SQLITE_OK && nBuffers>0 ){ 5787 if( rc==SQLITE_OK && nBuffers>0 ){
5564 int iBuffer; 5788 int iBuffer;
5565 for(iBuffer=0; iBuffer<nBuffers; ++iBuffer){ 5789 for(iBuffer=0; iBuffer<nBuffers; ++iBuffer){
5566 if( pBuffers[iBuffer].nData>0 ){ 5790 if( pBuffers[iBuffer].nData>0 ){
5567 if( out->nData==0 ){ 5791 if( out->nData==0 ){
5568 dataBufferSwap(out, &(pBuffers[iBuffer])); 5792 dataBufferSwap(out, &(pBuffers[iBuffer]));
5569 }else{ 5793 }else{
5570 docListAccumulateUnion(out, pBuffers[iBuffer].pData, 5794 rc = docListAccumulateUnion(out, pBuffers[iBuffer].pData,
5571 pBuffers[iBuffer].nData); 5795 pBuffers[iBuffer].nData);
5796 if( rc!=SQLITE_OK ) break;
5572 } 5797 }
5573 } 5798 }
5574 } 5799 }
5575 } 5800 }
5576 5801
5802 err:
5577 while( nBuffers-- ){ 5803 while( nBuffers-- ){
5578 dataBufferDestroy(&(pBuffers[nBuffers])); 5804 dataBufferDestroy(&(pBuffers[nBuffers]));
5579 } 5805 }
5580 if( pBuffers!=NULL ) sqlite3_free(pBuffers); 5806 if( pBuffers!=NULL ) sqlite3_free(pBuffers);
5581 5807
5582 return rc; 5808 return rc;
5583 } 5809 }
5584 5810
5585 /* Call loadSegmentLeavesInt() with pData/nData as input. */ 5811 /* Call loadSegmentLeavesInt() with pData/nData as input. */
5586 static int loadSegmentLeaf(fulltext_vtab *v, const char *pData, int nData, 5812 static int loadSegmentLeaf(fulltext_vtab *v, const char *pData, int nData,
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
5625 ** nodes which could include pTerm/nTerm/isPrefix. Note that the 5851 ** nodes which could include pTerm/nTerm/isPrefix. Note that the
5626 ** interior node terms logically come between the blocks, so there is 5852 ** interior node terms logically come between the blocks, so there is
5627 ** one more blockid than there are terms (that block contains terms >= 5853 ** one more blockid than there are terms (that block contains terms >=
5628 ** the last interior-node term). 5854 ** the last interior-node term).
5629 */ 5855 */
5630 /* TODO(shess) The calling code may already know that the end child is 5856 /* TODO(shess) The calling code may already know that the end child is
5631 ** not worth calculating, because the end may be in a later sibling 5857 ** not worth calculating, because the end may be in a later sibling
5632 ** node. Consider whether breaking symmetry is worthwhile. I suspect 5858 ** node. Consider whether breaking symmetry is worthwhile. I suspect
5633 ** it is not worthwhile. 5859 ** it is not worthwhile.
5634 */ 5860 */
5635 static void getChildrenContaining(const char *pData, int nData, 5861 static int getChildrenContaining(const char *pData, int nData,
5636 const char *pTerm, int nTerm, int isPrefix, 5862 const char *pTerm, int nTerm, int isPrefix,
5637 sqlite_int64 *piStartChild, 5863 sqlite_int64 *piStartChild,
5638 sqlite_int64 *piEndChild){ 5864 sqlite_int64 *piEndChild){
5639 InteriorReader reader; 5865 InteriorReader reader;
5866 int rc;
5640 5867
5641 assert( nData>1 ); 5868 assert( nData>1 );
5642 assert( *pData!='\0' ); 5869 assert( *pData!='\0' );
5643 interiorReaderInit(pData, nData, &reader); 5870 rc = interiorReaderInit(pData, nData, &reader);
5871 if( rc!=SQLITE_OK ) return rc;
5644 5872
5645 /* Scan for the first child which could contain pTerm/nTerm. */ 5873 /* Scan for the first child which could contain pTerm/nTerm. */
5646 while( !interiorReaderAtEnd(&reader) ){ 5874 while( !interiorReaderAtEnd(&reader) ){
5647 if( interiorReaderTermCmp(&reader, pTerm, nTerm, 0)>0 ) break; 5875 if( interiorReaderTermCmp(&reader, pTerm, nTerm, 0)>0 ) break;
5648 interiorReaderStep(&reader); 5876 rc = interiorReaderStep(&reader);
5877 if( rc!=SQLITE_OK ){
5878 interiorReaderDestroy(&reader);
5879 return rc;
5880 }
5649 } 5881 }
5650 *piStartChild = interiorReaderCurrentBlockid(&reader); 5882 *piStartChild = interiorReaderCurrentBlockid(&reader);
5651 5883
5652 /* Keep scanning to find a term greater than our term, using prefix 5884 /* Keep scanning to find a term greater than our term, using prefix
5653 ** comparison if indicated. If isPrefix is false, this will be the 5885 ** comparison if indicated. If isPrefix is false, this will be the
5654 ** same blockid as the starting block. 5886 ** same blockid as the starting block.
5655 */ 5887 */
5656 while( !interiorReaderAtEnd(&reader) ){ 5888 while( !interiorReaderAtEnd(&reader) ){
5657 if( interiorReaderTermCmp(&reader, pTerm, nTerm, isPrefix)>0 ) break; 5889 if( interiorReaderTermCmp(&reader, pTerm, nTerm, isPrefix)>0 ) break;
5658 interiorReaderStep(&reader); 5890 rc = interiorReaderStep(&reader);
5891 if( rc!=SQLITE_OK ){
5892 interiorReaderDestroy(&reader);
5893 return rc;
5894 }
5659 } 5895 }
5660 *piEndChild = interiorReaderCurrentBlockid(&reader); 5896 *piEndChild = interiorReaderCurrentBlockid(&reader);
5661 5897
5662 interiorReaderDestroy(&reader); 5898 interiorReaderDestroy(&reader);
5663 5899
5664 /* Children must ascend, and if !prefix, both must be the same. */ 5900 /* Children must ascend, and if !prefix, both must be the same. */
5665 assert( *piEndChild>=*piStartChild ); 5901 assert( *piEndChild>=*piStartChild );
5666 assert( isPrefix || *piStartChild==*piEndChild ); 5902 assert( isPrefix || *piStartChild==*piEndChild );
5903 return rc;
5667 } 5904 }
5668 5905
5669 /* Read block at iBlockid and pass it with other params to 5906 /* Read block at iBlockid and pass it with other params to
5670 ** getChildrenContaining(). 5907 ** getChildrenContaining().
5671 */ 5908 */
5672 static int loadAndGetChildrenContaining( 5909 static int loadAndGetChildrenContaining(
5673 fulltext_vtab *v, 5910 fulltext_vtab *v,
5674 sqlite_int64 iBlockid, 5911 sqlite_int64 iBlockid,
5675 const char *pTerm, int nTerm, int isPrefix, 5912 const char *pTerm, int nTerm, int isPrefix,
5676 sqlite_int64 *piStartChild, sqlite_int64 *piEndChild 5913 sqlite_int64 *piStartChild, sqlite_int64 *piEndChild
(...skipping 25 matching lines...) Expand all
5702 }else{ 5939 }else{
5703 const char *pData = sqlite3_column_blob(s, 0); 5940 const char *pData = sqlite3_column_blob(s, 0);
5704 int nData = sqlite3_column_bytes(s, 0); 5941 int nData = sqlite3_column_bytes(s, 0);
5705 5942
5706 /* Corrupt if child is not a valid interior node. */ 5943 /* Corrupt if child is not a valid interior node. */
5707 if( pData==NULL || nData<1 || pData[0]=='\0' ){ 5944 if( pData==NULL || nData<1 || pData[0]=='\0' ){
5708 sqlite3_reset(s); /* So we don't leave a lock. */ 5945 sqlite3_reset(s); /* So we don't leave a lock. */
5709 return SQLITE_CORRUPT_BKPT; 5946 return SQLITE_CORRUPT_BKPT;
5710 } 5947 }
5711 5948
5712 getChildrenContaining(pData, nData, pTerm, nTerm, 5949 rc = getChildrenContaining(pData, nData, pTerm, nTerm,
5713 isPrefix, piStartChild, piEndChild); 5950 isPrefix, piStartChild, piEndChild);
5951 if( rc!=SQLITE_OK ){
5952 sqlite3_reset(s);
5953 return rc;
5954 }
5714 } 5955 }
5715 5956
5716 /* We expect only one row. We must execute another sqlite3_step() 5957 /* We expect only one row. We must execute another sqlite3_step()
5717 * to complete the iteration; otherwise the table will remain 5958 * to complete the iteration; otherwise the table will remain
5718 * locked. */ 5959 * locked. */
5719 rc = sqlite3_step(s); 5960 rc = sqlite3_step(s);
5720 if( rc==SQLITE_ROW ) return SQLITE_ERROR; 5961 if( rc==SQLITE_ROW ) return SQLITE_ERROR;
5721 if( rc!=SQLITE_DONE ) return rc; 5962 if( rc!=SQLITE_DONE ) return rc;
5722 5963
5723 return SQLITE_OK; 5964 return SQLITE_OK;
(...skipping 10 matching lines...) Expand all
5734 /* Special case where root is a leaf. */ 5975 /* Special case where root is a leaf. */
5735 if( *pData=='\0' ){ 5976 if( *pData=='\0' ){
5736 return loadSegmentLeaf(v, pData, nData, pTerm, nTerm, isPrefix, out); 5977 return loadSegmentLeaf(v, pData, nData, pTerm, nTerm, isPrefix, out);
5737 }else{ 5978 }else{
5738 int rc; 5979 int rc;
5739 sqlite_int64 iStartChild, iEndChild; 5980 sqlite_int64 iStartChild, iEndChild;
5740 5981
5741 /* Process pData as an interior node, then loop down the tree 5982 /* Process pData as an interior node, then loop down the tree
5742 ** until we find the set of leaf nodes to scan for the term. 5983 ** until we find the set of leaf nodes to scan for the term.
5743 */ 5984 */
5744 getChildrenContaining(pData, nData, pTerm, nTerm, isPrefix, 5985 rc = getChildrenContaining(pData, nData, pTerm, nTerm, isPrefix,
5745 &iStartChild, &iEndChild); 5986 &iStartChild, &iEndChild);
5987 if( rc!=SQLITE_OK ) return rc;
5746 while( iStartChild>iLeavesEnd ){ 5988 while( iStartChild>iLeavesEnd ){
5747 sqlite_int64 iNextStart, iNextEnd; 5989 sqlite_int64 iNextStart, iNextEnd;
5748 rc = loadAndGetChildrenContaining(v, iStartChild, pTerm, nTerm, isPrefix, 5990 rc = loadAndGetChildrenContaining(v, iStartChild, pTerm, nTerm, isPrefix,
5749 &iNextStart, &iNextEnd); 5991 &iNextStart, &iNextEnd);
5750 if( rc!=SQLITE_OK ) return rc; 5992 if( rc!=SQLITE_OK ) return rc;
5751 5993
5752 /* If we've branched, follow the end branch, too. */ 5994 /* If we've branched, follow the end branch, too. */
5753 if( iStartChild!=iEndChild ){ 5995 if( iStartChild!=iEndChild ){
5754 sqlite_int64 iDummy; 5996 sqlite_int64 iDummy;
5755 rc = loadAndGetChildrenContaining(v, iEndChild, pTerm, nTerm, isPrefix, 5997 rc = loadAndGetChildrenContaining(v, iEndChild, pTerm, nTerm, isPrefix,
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
5805 pTerm, nTerm, isPrefix, &result); 6047 pTerm, nTerm, isPrefix, &result);
5806 if( rc==SQLITE_OK && result.nData>0 ){ 6048 if( rc==SQLITE_OK && result.nData>0 ){
5807 if( out->nData==0 ){ 6049 if( out->nData==0 ){
5808 DataBuffer tmp = *out; 6050 DataBuffer tmp = *out;
5809 *out = result; 6051 *out = result;
5810 result = tmp; 6052 result = tmp;
5811 }else{ 6053 }else{
5812 DataBuffer merged; 6054 DataBuffer merged;
5813 DLReader readers[2]; 6055 DLReader readers[2];
5814 6056
5815 dlrInit(&readers[0], DL_DEFAULT, out->pData, out->nData); 6057 rc = dlrInit(&readers[0], DL_DEFAULT, out->pData, out->nData);
5816 dlrInit(&readers[1], DL_DEFAULT, result.pData, result.nData); 6058 if( rc==SQLITE_OK ){
5817 dataBufferInit(&merged, out->nData+result.nData); 6059 rc = dlrInit(&readers[1], DL_DEFAULT, result.pData, result.nData);
5818 docListMerge(&merged, readers, 2); 6060 if( rc==SQLITE_OK ){
5819 dataBufferDestroy(out); 6061 dataBufferInit(&merged, out->nData+result.nData);
5820 *out = merged; 6062 rc = docListMerge(&merged, readers, 2);
5821 dlrDestroy(&readers[0]); 6063 dataBufferDestroy(out);
5822 dlrDestroy(&readers[1]); 6064 *out = merged;
6065 dlrDestroy(&readers[1]);
6066 }
6067 dlrDestroy(&readers[0]);
6068 }
5823 } 6069 }
5824 } 6070 }
6071
5825 dataBufferDestroy(&result); 6072 dataBufferDestroy(&result);
5826 return rc; 6073 return rc;
5827 } 6074 }
5828 6075
5829 /* Scan the database and merge together the posting lists for the term 6076 /* Scan the database and merge together the posting lists for the term
5830 ** into *out. 6077 ** into *out.
5831 */ 6078 */
5832 static int termSelect(fulltext_vtab *v, int iColumn, 6079 static int termSelect(fulltext_vtab *v, int iColumn,
5833 const char *pTerm, int nTerm, int isPrefix, 6080 const char *pTerm, int nTerm, int isPrefix,
5834 DocListType iType, DataBuffer *out){ 6081 DocListType iType, DataBuffer *out){
(...skipping 20 matching lines...) Expand all
5855 sqlite3_column_type(s, 2)!=SQLITE_BLOB ){ 6102 sqlite3_column_type(s, 2)!=SQLITE_BLOB ){
5856 rc = SQLITE_CORRUPT_BKPT; 6103 rc = SQLITE_CORRUPT_BKPT;
5857 goto err; 6104 goto err;
5858 } 6105 }
5859 6106
5860 rc = loadSegment(v, pData, nData, iLeavesEnd, pTerm, nTerm, isPrefix, 6107 rc = loadSegment(v, pData, nData, iLeavesEnd, pTerm, nTerm, isPrefix,
5861 &doclist); 6108 &doclist);
5862 if( rc!=SQLITE_OK ) goto err; 6109 if( rc!=SQLITE_OK ) goto err;
5863 } 6110 }
5864 if( rc==SQLITE_DONE ){ 6111 if( rc==SQLITE_DONE ){
6112 rc = SQLITE_OK;
5865 if( doclist.nData!=0 ){ 6113 if( doclist.nData!=0 ){
5866 /* TODO(shess) The old term_select_all() code applied the column 6114 /* TODO(shess) The old term_select_all() code applied the column
5867 ** restrict as we merged segments, leading to smaller buffers. 6115 ** restrict as we merged segments, leading to smaller buffers.
5868 ** This is probably worthwhile to bring back, once the new storage 6116 ** This is probably worthwhile to bring back, once the new storage
5869 ** system is checked in. 6117 ** system is checked in.
5870 */ 6118 */
5871 if( iColumn==v->nColumn) iColumn = -1; 6119 if( iColumn==v->nColumn) iColumn = -1;
5872 docListTrim(DL_DEFAULT, doclist.pData, doclist.nData, 6120 rc = docListTrim(DL_DEFAULT, doclist.pData, doclist.nData,
5873 iColumn, iType, out); 6121 iColumn, iType, out);
5874 } 6122 }
5875 rc = SQLITE_OK;
5876 } 6123 }
5877 6124
5878 err: 6125 err:
5879 sqlite3_reset(s); /* So we don't leave a lock. */ 6126 sqlite3_reset(s); /* So we don't leave a lock. */
5880 dataBufferDestroy(&doclist); 6127 dataBufferDestroy(&doclist);
5881 return rc; 6128 return rc;
5882 } 6129 }
5883 6130
5884 /****************************************************************/ 6131 /****************************************************************/
5885 /* Used to hold hashtable data for sorting. */ 6132 /* Used to hold hashtable data for sorting. */
(...skipping 325 matching lines...) Expand 10 before | Expand all | Expand 10 after
6211 /* optimize() helper function. Put the readers in order and iterate 6458 /* optimize() helper function. Put the readers in order and iterate
6212 ** through them, merging doclists for matching terms into pWriter. 6459 ** through them, merging doclists for matching terms into pWriter.
6213 ** Returns SQLITE_OK on success, or the SQLite error code which 6460 ** Returns SQLITE_OK on success, or the SQLite error code which
6214 ** prevented success. 6461 ** prevented success.
6215 */ 6462 */
6216 static int optimizeInternal(fulltext_vtab *v, 6463 static int optimizeInternal(fulltext_vtab *v,
6217 OptLeavesReader *readers, int nReaders, 6464 OptLeavesReader *readers, int nReaders,
6218 LeafWriter *pWriter){ 6465 LeafWriter *pWriter){
6219 int i, rc = SQLITE_OK; 6466 int i, rc = SQLITE_OK;
6220 DataBuffer doclist, merged, tmp; 6467 DataBuffer doclist, merged, tmp;
6468 const char *pData;
6221 6469
6222 /* Order the readers. */ 6470 /* Order the readers. */
6223 i = nReaders; 6471 i = nReaders;
6224 while( i-- > 0 ){ 6472 while( i-- > 0 ){
6225 optLeavesReaderReorder(&readers[i], nReaders-i); 6473 optLeavesReaderReorder(&readers[i], nReaders-i);
6226 } 6474 }
6227 6475
6228 dataBufferInit(&doclist, LEAF_MAX); 6476 dataBufferInit(&doclist, LEAF_MAX);
6229 dataBufferInit(&merged, LEAF_MAX); 6477 dataBufferInit(&merged, LEAF_MAX);
6230 6478
6231 /* Exhausted readers bubble to the end, so when the first reader is 6479 /* Exhausted readers bubble to the end, so when the first reader is
6232 ** at eof, all are at eof. 6480 ** at eof, all are at eof.
6233 */ 6481 */
6234 while( !optLeavesReaderAtEnd(&readers[0]) ){ 6482 while( !optLeavesReaderAtEnd(&readers[0]) ){
6235 6483
6236 /* Figure out how many readers share the next term. */ 6484 /* Figure out how many readers share the next term. */
6237 for(i=1; i<nReaders && !optLeavesReaderAtEnd(&readers[i]); i++){ 6485 for(i=1; i<nReaders && !optLeavesReaderAtEnd(&readers[i]); i++){
6238 if( 0!=optLeavesReaderTermCmp(&readers[0], &readers[i]) ) break; 6486 if( 0!=optLeavesReaderTermCmp(&readers[0], &readers[i]) ) break;
6239 } 6487 }
6240 6488
6489 pData = optLeavesReaderData(&readers[0]);
6490 if( pData==NULL ){
6491 rc = SQLITE_CORRUPT_BKPT;
6492 break;
6493 }
6494
6241 /* Special-case for no merge. */ 6495 /* Special-case for no merge. */
6242 if( i==1 ){ 6496 if( i==1 ){
6243 /* Trim deletions from the doclist. */ 6497 /* Trim deletions from the doclist. */
6244 dataBufferReset(&merged); 6498 dataBufferReset(&merged);
6245 docListTrim(DL_DEFAULT, 6499 rc = docListTrim(DL_DEFAULT,
6246 optLeavesReaderData(&readers[0]), 6500 pData,
6247 optLeavesReaderDataBytes(&readers[0]), 6501 optLeavesReaderDataBytes(&readers[0]),
6248 -1, DL_DEFAULT, &merged); 6502 -1, DL_DEFAULT, &merged);
6503 if( rc!= SQLITE_OK ) break;
6249 }else{ 6504 }else{
6250 DLReader dlReaders[MERGE_COUNT]; 6505 DLReader dlReaders[MERGE_COUNT];
6251 int iReader, nReaders; 6506 int iReader, nReaders;
6252 6507
6253 /* Prime the pipeline with the first reader's doclist. After 6508 /* Prime the pipeline with the first reader's doclist. After
6254 ** one pass index 0 will reference the accumulated doclist. 6509 ** one pass index 0 will reference the accumulated doclist.
6255 */ 6510 */
6256 dlrInit(&dlReaders[0], DL_DEFAULT, 6511 rc = dlrInit(&dlReaders[0], DL_DEFAULT,
6257 optLeavesReaderData(&readers[0]), 6512 pData,
6258 optLeavesReaderDataBytes(&readers[0])); 6513 optLeavesReaderDataBytes(&readers[0]));
6514 if( rc!=SQLITE_OK ) break;
6259 iReader = 1; 6515 iReader = 1;
6260 6516
6261 assert( iReader<i ); /* Must execute the loop at least once. */ 6517 assert( iReader<i ); /* Must execute the loop at least once. */
6262 while( iReader<i ){ 6518 while( iReader<i ){
6263 /* Merge 16 inputs per pass. */ 6519 /* Merge 16 inputs per pass. */
6264 for( nReaders=1; iReader<i && nReaders<MERGE_COUNT; 6520 for( nReaders=1; iReader<i && nReaders<MERGE_COUNT;
6265 iReader++, nReaders++ ){ 6521 iReader++, nReaders++ ){
6266 dlrInit(&dlReaders[nReaders], DL_DEFAULT, 6522 pData = optLeavesReaderData(&readers[iReader]);
6267 optLeavesReaderData(&readers[iReader]), 6523 if( pData == NULL ){
6268 optLeavesReaderDataBytes(&readers[iReader])); 6524 rc = SQLITE_CORRUPT_BKPT;
6525 break;
6526 }
6527 rc = dlrInit(&dlReaders[nReaders], DL_DEFAULT,
6528 pData,
6529 optLeavesReaderDataBytes(&readers[iReader]));
6530 if( rc != SQLITE_OK ) break;
6269 } 6531 }
6270 6532
6271 /* Merge doclists and swap result into accumulator. */ 6533 /* Merge doclists and swap result into accumulator. */
6272 dataBufferReset(&merged); 6534 if( rc==SQLITE_OK ){
6273 docListMerge(&merged, dlReaders, nReaders); 6535 dataBufferReset(&merged);
6274 tmp = merged; 6536 rc = docListMerge(&merged, dlReaders, nReaders);
6275 merged = doclist; 6537 tmp = merged;
6276 doclist = tmp; 6538 merged = doclist;
6539 doclist = tmp;
6540 }
6277 6541
6278 while( nReaders-- > 0 ){ 6542 while( nReaders-- > 0 ){
6279 dlrDestroy(&dlReaders[nReaders]); 6543 dlrDestroy(&dlReaders[nReaders]);
6280 } 6544 }
6281 6545
6546 if( rc!=SQLITE_OK ) goto err;
6547
6282 /* Accumulated doclist to reader 0 for next pass. */ 6548 /* Accumulated doclist to reader 0 for next pass. */
6283 dlrInit(&dlReaders[0], DL_DEFAULT, doclist.pData, doclist.nData); 6549 rc = dlrInit(&dlReaders[0], DL_DEFAULT, doclist.pData, doclist.nData);
6550 if( rc!=SQLITE_OK ) goto err;
6284 } 6551 }
6285 6552
6286 /* Destroy reader that was left in the pipeline. */ 6553 /* Destroy reader that was left in the pipeline. */
6287 dlrDestroy(&dlReaders[0]); 6554 dlrDestroy(&dlReaders[0]);
6288 6555
6289 /* Trim deletions from the doclist. */ 6556 /* Trim deletions from the doclist. */
6290 dataBufferReset(&merged); 6557 dataBufferReset(&merged);
6291 docListTrim(DL_DEFAULT, doclist.pData, doclist.nData, 6558 rc = docListTrim(DL_DEFAULT, doclist.pData, doclist.nData,
6292 -1, DL_DEFAULT, &merged); 6559 -1, DL_DEFAULT, &merged);
6560 if( rc!=SQLITE_OK ) goto err;
6293 } 6561 }
6294 6562
6295 /* Only pass doclists with hits (skip if all hits deleted). */ 6563 /* Only pass doclists with hits (skip if all hits deleted). */
6296 if( merged.nData>0 ){ 6564 if( merged.nData>0 ){
6297 rc = leafWriterStep(v, pWriter, 6565 rc = leafWriterStep(v, pWriter,
6298 optLeavesReaderTerm(&readers[0]), 6566 optLeavesReaderTerm(&readers[0]),
6299 optLeavesReaderTermBytes(&readers[0]), 6567 optLeavesReaderTermBytes(&readers[0]),
6300 merged.pData, merged.nData); 6568 merged.pData, merged.nData);
6301 if( rc!=SQLITE_OK ) goto err; 6569 if( rc!=SQLITE_OK ) goto err;
6302 } 6570 }
(...skipping 318 matching lines...) Expand 10 before | Expand all | Expand 10 after
6621 } 6889 }
6622 } 6890 }
6623 6891
6624 /* Expand the DL_DEFAULT doclist in pData into a text result in 6892 /* Expand the DL_DEFAULT doclist in pData into a text result in
6625 ** pContext. 6893 ** pContext.
6626 */ 6894 */
6627 static void createDoclistResult(sqlite3_context *pContext, 6895 static void createDoclistResult(sqlite3_context *pContext,
6628 const char *pData, int nData){ 6896 const char *pData, int nData){
6629 DataBuffer dump; 6897 DataBuffer dump;
6630 DLReader dlReader; 6898 DLReader dlReader;
6899 int rc;
6631 6900
6632 assert( pData!=NULL && nData>0 ); 6901 assert( pData!=NULL && nData>0 );
6633 6902
6903 rc = dlrInit(&dlReader, DL_DEFAULT, pData, nData);
6904 if( rc!=SQLITE_OK ) return rc;
6634 dataBufferInit(&dump, 0); 6905 dataBufferInit(&dump, 0);
6635 dlrInit(&dlReader, DL_DEFAULT, pData, nData); 6906 for( ; rc==SQLITE_OK && !dlrAtEnd(&dlReader); rc = dlrStep(&dlReader) ){
6636 for( ; !dlrAtEnd(&dlReader); dlrStep(&dlReader) ){
6637 char buf[256]; 6907 char buf[256];
6638 PLReader plReader; 6908 PLReader plReader;
6639 6909
6640 plrInit(&plReader, &dlReader); 6910 rc = plrInit(&plReader, &dlReader);
6911 if( rc!=SQLITE_OK ) break;
6641 if( DL_DEFAULT==DL_DOCIDS || plrAtEnd(&plReader) ){ 6912 if( DL_DEFAULT==DL_DOCIDS || plrAtEnd(&plReader) ){
6642 sqlite3_snprintf(sizeof(buf), buf, "[%lld] ", dlrDocid(&dlReader)); 6913 sqlite3_snprintf(sizeof(buf), buf, "[%lld] ", dlrDocid(&dlReader));
6643 dataBufferAppend(&dump, buf, strlen(buf)); 6914 dataBufferAppend(&dump, buf, strlen(buf));
6644 }else{ 6915 }else{
6645 int iColumn = plrColumn(&plReader); 6916 int iColumn = plrColumn(&plReader);
6646 6917
6647 sqlite3_snprintf(sizeof(buf), buf, "[%lld %d[", 6918 sqlite3_snprintf(sizeof(buf), buf, "[%lld %d[",
6648 dlrDocid(&dlReader), iColumn); 6919 dlrDocid(&dlReader), iColumn);
6649 dataBufferAppend(&dump, buf, strlen(buf)); 6920 dataBufferAppend(&dump, buf, strlen(buf));
6650 6921
6651 for( ; !plrAtEnd(&plReader); plrStep(&plReader) ){ 6922 for( ; !plrAtEnd(&plReader); rc = plrStep(&plReader) ){
6923 if( rc!=SQLITE_OK ) break;
6652 if( plrColumn(&plReader)!=iColumn ){ 6924 if( plrColumn(&plReader)!=iColumn ){
6653 iColumn = plrColumn(&plReader); 6925 iColumn = plrColumn(&plReader);
6654 sqlite3_snprintf(sizeof(buf), buf, "] %d[", iColumn); 6926 sqlite3_snprintf(sizeof(buf), buf, "] %d[", iColumn);
6655 assert( dump.nData>0 ); 6927 assert( dump.nData>0 );
6656 dump.nData--; /* Overwrite trailing space. */ 6928 dump.nData--; /* Overwrite trailing space. */
6657 assert( dump.pData[dump.nData]==' '); 6929 assert( dump.pData[dump.nData]==' ');
6658 dataBufferAppend(&dump, buf, strlen(buf)); 6930 dataBufferAppend(&dump, buf, strlen(buf));
6659 } 6931 }
6660 if( DL_DEFAULT==DL_POSITIONS_OFFSETS ){ 6932 if( DL_DEFAULT==DL_POSITIONS_OFFSETS ){
6661 sqlite3_snprintf(sizeof(buf), buf, "%d,%d,%d ", 6933 sqlite3_snprintf(sizeof(buf), buf, "%d,%d,%d ",
6662 plrPosition(&plReader), 6934 plrPosition(&plReader),
6663 plrStartOffset(&plReader), plrEndOffset(&plReader)); 6935 plrStartOffset(&plReader), plrEndOffset(&plReader));
6664 }else if( DL_DEFAULT==DL_POSITIONS ){ 6936 }else if( DL_DEFAULT==DL_POSITIONS ){
6665 sqlite3_snprintf(sizeof(buf), buf, "%d ", plrPosition(&plReader)); 6937 sqlite3_snprintf(sizeof(buf), buf, "%d ", plrPosition(&plReader));
6666 }else{ 6938 }else{
6667 assert( NULL=="Unhandled DL_DEFAULT value"); 6939 assert( NULL=="Unhandled DL_DEFAULT value");
6668 } 6940 }
6669 dataBufferAppend(&dump, buf, strlen(buf)); 6941 dataBufferAppend(&dump, buf, strlen(buf));
6670 } 6942 }
6671 plrDestroy(&plReader); 6943 plrDestroy(&plReader);
6944 if( rc!= SQLITE_OK ) break;
6672 6945
6673 assert( dump.nData>0 ); 6946 assert( dump.nData>0 );
6674 dump.nData--; /* Overwrite trailing space. */ 6947 dump.nData--; /* Overwrite trailing space. */
6675 assert( dump.pData[dump.nData]==' '); 6948 assert( dump.pData[dump.nData]==' ');
6676 dataBufferAppend(&dump, "]] ", 3); 6949 dataBufferAppend(&dump, "]] ", 3);
6677 } 6950 }
6678 } 6951 }
6679 dlrDestroy(&dlReader); 6952 dlrDestroy(&dlReader);
6953 if( rc!=SQLITE_OK ){
6954 dataBufferDestroy(&dump);
6955 return rc;
6956 }
6680 6957
6681 assert( dump.nData>0 ); 6958 assert( dump.nData>0 );
6682 dump.nData--; /* Overwrite trailing space. */ 6959 dump.nData--; /* Overwrite trailing space. */
6683 assert( dump.pData[dump.nData]==' '); 6960 assert( dump.pData[dump.nData]==' ');
6684 dump.pData[dump.nData] = '\0'; 6961 dump.pData[dump.nData] = '\0';
6685 assert( dump.nData>0 ); 6962 assert( dump.nData>0 );
6686 6963
6687 /* Passes ownership of dump's buffer to pContext. */ 6964 /* Passes ownership of dump's buffer to pContext. */
6688 sqlite3_result_text(pContext, dump.pData, dump.nData, sqlite3_free); 6965 sqlite3_result_text(pContext, dump.pData, dump.nData, sqlite3_free);
6689 dump.pData = NULL; 6966 dump.pData = NULL;
6690 dump.nData = dump.nCapacity = 0; 6967 dump.nData = dump.nCapacity = 0;
6968 return SQLITE_OK;
6691 } 6969 }
6692 6970
6693 /* Implements dump_doclist() for use in inspecting the fts2 index from 6971 /* Implements dump_doclist() for use in inspecting the fts2 index from
6694 ** tests. TEXT result containing a string representation of the 6972 ** tests. TEXT result containing a string representation of the
6695 ** doclist for the indicated term. dump_doclist(t, term, level, idx) 6973 ** doclist for the indicated term. dump_doclist(t, term, level, idx)
6696 ** dumps the doclist for term from the segment specified by level, idx 6974 ** dumps the doclist for term from the segment specified by level, idx
6697 ** (in %_segdir), while dump_doclist(t, term) dumps the logical 6975 ** (in %_segdir), while dump_doclist(t, term) dumps the logical
6698 ** doclist for the term across all segments. The per-segment doclist 6976 ** doclist for the term across all segments. The per-segment doclist
6699 ** can contain deletions, while the full-index doclist will not 6977 ** can contain deletions, while the full-index doclist will not
6700 ** (deletions are omitted). 6978 ** (deletions are omitted).
(...skipping 301 matching lines...) Expand 10 before | Expand all | Expand 10 after
7002 sqlite3 *db, 7280 sqlite3 *db,
7003 char **pzErrMsg, 7281 char **pzErrMsg,
7004 const sqlite3_api_routines *pApi 7282 const sqlite3_api_routines *pApi
7005 ){ 7283 ){
7006 SQLITE_EXTENSION_INIT2(pApi) 7284 SQLITE_EXTENSION_INIT2(pApi)
7007 return sqlite3Fts2Init(db); 7285 return sqlite3Fts2Init(db);
7008 } 7286 }
7009 #endif 7287 #endif
7010 7288
7011 #endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS2) */ 7289 #endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS2) */
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698