Fossil SCM

Merge latest changes from trunk

ben 2011-06-18 17:00 ben-testing merge
Commit 7bbeb8820592aea52f3d0aadfd7568c3c7b1febb
+1
--- a/VERSION
+++ b/VERSION
@@ -0,0 +1 @@
1
+1.18
--- a/VERSION
+++ b/VERSION
@@ -0,0 +1 @@
 
--- a/VERSION
+++ b/VERSION
@@ -0,0 +1 @@
1 1.18
--- src/checkout.c
+++ src/checkout.c
@@ -74,20 +74,10 @@
7474
}
7575
load_vfile_from_rid(vid);
7676
return vid;
7777
}
7878
79
-/*
80
-** Load a vfile from a record ID.
81
-*/
82
-void load_vfile_from_rid(int vid){
83
- if( db_exists("SELECT 1 FROM vfile WHERE vid=%d", vid) ){
84
- return;
85
- }
86
- vfile_build(vid);
87
-}
88
-
8979
/*
9080
** Set or clear the vfile.isexe flag for a file.
9181
*/
9282
static void set_or_clear_isexe(const char *zFilename, int vid, int onoff){
9383
static Stmt s;
9484
--- src/checkout.c
+++ src/checkout.c
@@ -74,20 +74,10 @@
74 }
75 load_vfile_from_rid(vid);
76 return vid;
77 }
78
79 /*
80 ** Load a vfile from a record ID.
81 */
82 void load_vfile_from_rid(int vid){
83 if( db_exists("SELECT 1 FROM vfile WHERE vid=%d", vid) ){
84 return;
85 }
86 vfile_build(vid);
87 }
88
89 /*
90 ** Set or clear the vfile.isexe flag for a file.
91 */
92 static void set_or_clear_isexe(const char *zFilename, int vid, int onoff){
93 static Stmt s;
94
--- src/checkout.c
+++ src/checkout.c
@@ -74,20 +74,10 @@
74 }
75 load_vfile_from_rid(vid);
76 return vid;
77 }
78
 
 
 
 
 
 
 
 
 
 
79 /*
80 ** Set or clear the vfile.isexe flag for a file.
81 */
82 static void set_or_clear_isexe(const char *zFilename, int vid, int onoff){
83 static Stmt s;
84
--- src/checkout.c
+++ src/checkout.c
@@ -74,20 +74,10 @@
7474
}
7575
load_vfile_from_rid(vid);
7676
return vid;
7777
}
7878
79
-/*
80
-** Load a vfile from a record ID.
81
-*/
82
-void load_vfile_from_rid(int vid){
83
- if( db_exists("SELECT 1 FROM vfile WHERE vid=%d", vid) ){
84
- return;
85
- }
86
- vfile_build(vid);
87
-}
88
-
8979
/*
9080
** Set or clear the vfile.isexe flag for a file.
9181
*/
9282
static void set_or_clear_isexe(const char *zFilename, int vid, int onoff){
9383
static Stmt s;
9484
--- src/checkout.c
+++ src/checkout.c
@@ -74,20 +74,10 @@
74 }
75 load_vfile_from_rid(vid);
76 return vid;
77 }
78
79 /*
80 ** Load a vfile from a record ID.
81 */
82 void load_vfile_from_rid(int vid){
83 if( db_exists("SELECT 1 FROM vfile WHERE vid=%d", vid) ){
84 return;
85 }
86 vfile_build(vid);
87 }
88
89 /*
90 ** Set or clear the vfile.isexe flag for a file.
91 */
92 static void set_or_clear_isexe(const char *zFilename, int vid, int onoff){
93 static Stmt s;
94
--- src/checkout.c
+++ src/checkout.c
@@ -74,20 +74,10 @@
74 }
75 load_vfile_from_rid(vid);
76 return vid;
77 }
78
 
 
 
 
 
 
 
 
 
 
79 /*
80 ** Set or clear the vfile.isexe flag for a file.
81 */
82 static void set_or_clear_isexe(const char *zFilename, int vid, int onoff){
83 static Stmt s;
84
--- src/descendants.c
+++ src/descendants.c
@@ -186,10 +186,45 @@
186186
}
187187
db_reset(&q);
188188
}
189189
bag_clear(&seen);
190190
pqueue_clear(&queue);
191
+ db_finalize(&ins);
192
+ db_finalize(&q);
193
+}
194
+
195
+/*
196
+** Compute up to N direct ancestors (merge ancestors do not count)
197
+** for the check-in rid and put them in a table named "ancestor".
198
+** Label each generation with consecutive integers going backwards
199
+** in time such that rid has the smallest generation number and the oldest
200
+** direct ancestor as the largest generation number.
201
+*/
202
+void compute_direct_ancestors(int rid, int N){
203
+ Stmt ins;
204
+ Stmt q;
205
+ int gen = 0;
206
+ db_multi_exec(
207
+ "CREATE TEMP TABLE ancestor(rid INTEGER, generation INTEGER PRIMARY KEY);"
208
+ "INSERT INTO ancestor VALUES(%d, 0);", rid
209
+ );
210
+ db_prepare(&ins, "INSERT INTO ancestor VALUES(:rid, :gen)");
211
+ db_prepare(&q,
212
+ "SELECT pid FROM plink"
213
+ " WHERE cid=:rid AND isprim"
214
+ );
215
+ while( (N--)>0 ){
216
+ db_bind_int(&q, ":rid", rid);
217
+ if( db_step(&q)!=SQLITE_ROW ) break;
218
+ rid = db_column_int(&q, 0);
219
+ db_reset(&q);
220
+ gen++;
221
+ db_bind_int(&ins, ":rid", rid);
222
+ db_bind_int(&ins, ":gen", gen);
223
+ db_step(&ins);
224
+ db_reset(&ins);
225
+ }
191226
db_finalize(&ins);
192227
db_finalize(&q);
193228
}
194229
195230
/*
196231
--- src/descendants.c
+++ src/descendants.c
@@ -186,10 +186,45 @@
186 }
187 db_reset(&q);
188 }
189 bag_clear(&seen);
190 pqueue_clear(&queue);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
191 db_finalize(&ins);
192 db_finalize(&q);
193 }
194
195 /*
196
--- src/descendants.c
+++ src/descendants.c
@@ -186,10 +186,45 @@
186 }
187 db_reset(&q);
188 }
189 bag_clear(&seen);
190 pqueue_clear(&queue);
191 db_finalize(&ins);
192 db_finalize(&q);
193 }
194
195 /*
196 ** Compute up to N direct ancestors (merge ancestors do not count)
197 ** for the check-in rid and put them in a table named "ancestor".
198 ** Label each generation with consecutive integers going backwards
199 ** in time such that rid has the smallest generation number and the oldest
200 ** direct ancestor as the largest generation number.
201 */
202 void compute_direct_ancestors(int rid, int N){
203 Stmt ins;
204 Stmt q;
205 int gen = 0;
206 db_multi_exec(
207 "CREATE TEMP TABLE ancestor(rid INTEGER, generation INTEGER PRIMARY KEY);"
208 "INSERT INTO ancestor VALUES(%d, 0);", rid
209 );
210 db_prepare(&ins, "INSERT INTO ancestor VALUES(:rid, :gen)");
211 db_prepare(&q,
212 "SELECT pid FROM plink"
213 " WHERE cid=:rid AND isprim"
214 );
215 while( (N--)>0 ){
216 db_bind_int(&q, ":rid", rid);
217 if( db_step(&q)!=SQLITE_ROW ) break;
218 rid = db_column_int(&q, 0);
219 db_reset(&q);
220 gen++;
221 db_bind_int(&ins, ":rid", rid);
222 db_bind_int(&ins, ":gen", gen);
223 db_step(&ins);
224 db_reset(&ins);
225 }
226 db_finalize(&ins);
227 db_finalize(&q);
228 }
229
230 /*
231
+8 -7
--- src/diff.c
+++ src/diff.c
@@ -758,16 +758,16 @@
758758
** it was checked in (mlink.mid).
759759
*/
760760
static void annotate_file(
761761
Annotator *p, /* The annotator */
762762
int fnid, /* The name of the file to be annotated */
763
- int mid, /* The specific version of the file for this step */
763
+ int mid, /* Use the version of the file in this check-in */
764764
int webLabel, /* Use web-style annotations if true */
765765
int iLimit, /* Limit the number of levels if greater than zero */
766766
int annFlags /* Flags to alter the annotation */
767767
){
768
- Blob toAnnotate; /* Text of the final version of the file */
768
+ Blob toAnnotate; /* Text of the final (mid) version of the file */
769769
Blob step; /* Text of previous revision */
770770
int rid; /* Artifact ID of the file being annotated */
771771
char *zLabel; /* Label to apply to a line */
772772
Stmt q; /* Query returning all ancestor versions */
773773
@@ -778,23 +778,24 @@
778778
}
779779
if( !content_get(rid, &toAnnotate) ){
780780
fossil_panic("unable to retrieve content of artifact #%d", rid);
781781
}
782782
db_multi_exec("CREATE TEMP TABLE ok(rid INTEGER PRIMARY KEY)");
783
- compute_ancestors(mid, 1000000000);
783
+ if( iLimit<=0 ) iLimit = 1000000000;
784
+ compute_direct_ancestors(mid, iLimit);
784785
annotation_start(p, &toAnnotate);
785786
786787
db_prepare(&q,
787788
"SELECT mlink.fid,"
788789
" (SELECT uuid FROM blob WHERE rid=mlink.%s),"
789790
" date(event.mtime), "
790791
" coalesce(event.euser,event.user) "
791
- " FROM mlink, event"
792
+ " FROM ancestor, mlink, event"
792793
" WHERE mlink.fnid=%d"
793
- " AND mlink.mid IN ok"
794
- " AND event.objid=mlink.mid"
795
- " ORDER BY event.mtime DESC"
794
+ " AND mlink.mid=ancestor.rid"
795
+ " AND event.objid=ancestor.rid"
796
+ " ORDER BY ancestor.generation ASC"
796797
" LIMIT %d",
797798
(annFlags & ANN_FILE_VERS)!=0 ? "fid" : "mid",
798799
fnid,
799800
iLimit>0 ? iLimit : 10000000
800801
);
801802
--- src/diff.c
+++ src/diff.c
@@ -758,16 +758,16 @@
758 ** it was checked in (mlink.mid).
759 */
760 static void annotate_file(
761 Annotator *p, /* The annotator */
762 int fnid, /* The name of the file to be annotated */
763 int mid, /* The specific version of the file for this step */
764 int webLabel, /* Use web-style annotations if true */
765 int iLimit, /* Limit the number of levels if greater than zero */
766 int annFlags /* Flags to alter the annotation */
767 ){
768 Blob toAnnotate; /* Text of the final version of the file */
769 Blob step; /* Text of previous revision */
770 int rid; /* Artifact ID of the file being annotated */
771 char *zLabel; /* Label to apply to a line */
772 Stmt q; /* Query returning all ancestor versions */
773
@@ -778,23 +778,24 @@
778 }
779 if( !content_get(rid, &toAnnotate) ){
780 fossil_panic("unable to retrieve content of artifact #%d", rid);
781 }
782 db_multi_exec("CREATE TEMP TABLE ok(rid INTEGER PRIMARY KEY)");
783 compute_ancestors(mid, 1000000000);
 
784 annotation_start(p, &toAnnotate);
785
786 db_prepare(&q,
787 "SELECT mlink.fid,"
788 " (SELECT uuid FROM blob WHERE rid=mlink.%s),"
789 " date(event.mtime), "
790 " coalesce(event.euser,event.user) "
791 " FROM mlink, event"
792 " WHERE mlink.fnid=%d"
793 " AND mlink.mid IN ok"
794 " AND event.objid=mlink.mid"
795 " ORDER BY event.mtime DESC"
796 " LIMIT %d",
797 (annFlags & ANN_FILE_VERS)!=0 ? "fid" : "mid",
798 fnid,
799 iLimit>0 ? iLimit : 10000000
800 );
801
--- src/diff.c
+++ src/diff.c
@@ -758,16 +758,16 @@
758 ** it was checked in (mlink.mid).
759 */
760 static void annotate_file(
761 Annotator *p, /* The annotator */
762 int fnid, /* The name of the file to be annotated */
763 int mid, /* Use the version of the file in this check-in */
764 int webLabel, /* Use web-style annotations if true */
765 int iLimit, /* Limit the number of levels if greater than zero */
766 int annFlags /* Flags to alter the annotation */
767 ){
768 Blob toAnnotate; /* Text of the final (mid) version of the file */
769 Blob step; /* Text of previous revision */
770 int rid; /* Artifact ID of the file being annotated */
771 char *zLabel; /* Label to apply to a line */
772 Stmt q; /* Query returning all ancestor versions */
773
@@ -778,23 +778,24 @@
778 }
779 if( !content_get(rid, &toAnnotate) ){
780 fossil_panic("unable to retrieve content of artifact #%d", rid);
781 }
782 db_multi_exec("CREATE TEMP TABLE ok(rid INTEGER PRIMARY KEY)");
783 if( iLimit<=0 ) iLimit = 1000000000;
784 compute_direct_ancestors(mid, iLimit);
785 annotation_start(p, &toAnnotate);
786
787 db_prepare(&q,
788 "SELECT mlink.fid,"
789 " (SELECT uuid FROM blob WHERE rid=mlink.%s),"
790 " date(event.mtime), "
791 " coalesce(event.euser,event.user) "
792 " FROM ancestor, mlink, event"
793 " WHERE mlink.fnid=%d"
794 " AND mlink.mid=ancestor.rid"
795 " AND event.objid=ancestor.rid"
796 " ORDER BY ancestor.generation ASC"
797 " LIMIT %d",
798 (annFlags & ANN_FILE_VERS)!=0 ? "fid" : "mid",
799 fnid,
800 iLimit>0 ? iLimit : 10000000
801 );
802
+10 -3
--- src/export.c
+++ src/export.c
@@ -39,11 +39,11 @@
3939
db_bind_text(&q, ":user", zUser);
4040
if( db_step(&q)!=SQLITE_ROW ){
4141
db_reset(&q);
4242
for(i=0; zUser[i] && zUser[i]!='>' && zUser[i]!='<'; i++){}
4343
if( zUser[i]==0 ){
44
- printf(" <%s>", zUser);
44
+ printf(" %s <%s>", zUser, zUser);
4545
return;
4646
}
4747
zName = mprintf("%s", zUser);
4848
for(i=j=0; zName[i]; i++){
4949
if( zName[i]!='<' && zName[i]!='>' ){
@@ -56,11 +56,11 @@
5656
return;
5757
}
5858
zContact = db_column_text(&q, 0);
5959
for(i=0; zContact[i] && zContact[i]!='>' && zContact[i]!='<'; i++){}
6060
if( zContact[i]==0 ){
61
- printf(" %s <%s>", zContact, zUser);
61
+ printf(" %s <%s>", zContact[0] ? zContact : zUser, zUser);
6262
db_reset(&q);
6363
return;
6464
}
6565
if( zContact[i]=='<' ){
6666
zEmail = mprintf("%s", &zContact[i]);
@@ -196,17 +196,24 @@
196196
" FROM tagxref JOIN tag USING(tagid)"
197197
" WHERE tagtype=1 AND tagname GLOB 'sym-*'"
198198
);
199199
while( db_step(&q)==SQLITE_ROW ){
200200
const char *zTagname = db_column_text(&q, 0);
201
+ char *zEncoded = 0;
201202
int rid = db_column_int(&q, 1);
202203
const char *zSecSince1970 = db_column_text(&q, 2);
204
+ int i;
203205
if( rid==0 || !bag_find(&vers, rid) ) continue;
204206
zTagname += 4;
205
- printf("tag %s\n", zTagname);
207
+ zEncoded = mprintf("%s", zTagname);
208
+ for(i=0; zEncoded[i]; i++){
209
+ if( !fossil_isalnum(zEncoded[i]) ) zEncoded[i] = '_';
210
+ }
211
+ printf("tag %s\n", zEncoded);
206212
printf("from :%d\n", rid+firstCkin);
207213
printf("tagger <tagger> %s +0000\n", zSecSince1970);
208214
printf("data 0\n");
215
+ fossil_free(zEncoded);
209216
}
210217
db_finalize(&q);
211218
bag_clear(&vers);
212219
}
213220
--- src/export.c
+++ src/export.c
@@ -39,11 +39,11 @@
39 db_bind_text(&q, ":user", zUser);
40 if( db_step(&q)!=SQLITE_ROW ){
41 db_reset(&q);
42 for(i=0; zUser[i] && zUser[i]!='>' && zUser[i]!='<'; i++){}
43 if( zUser[i]==0 ){
44 printf(" <%s>", zUser);
45 return;
46 }
47 zName = mprintf("%s", zUser);
48 for(i=j=0; zName[i]; i++){
49 if( zName[i]!='<' && zName[i]!='>' ){
@@ -56,11 +56,11 @@
56 return;
57 }
58 zContact = db_column_text(&q, 0);
59 for(i=0; zContact[i] && zContact[i]!='>' && zContact[i]!='<'; i++){}
60 if( zContact[i]==0 ){
61 printf(" %s <%s>", zContact, zUser);
62 db_reset(&q);
63 return;
64 }
65 if( zContact[i]=='<' ){
66 zEmail = mprintf("%s", &zContact[i]);
@@ -196,17 +196,24 @@
196 " FROM tagxref JOIN tag USING(tagid)"
197 " WHERE tagtype=1 AND tagname GLOB 'sym-*'"
198 );
199 while( db_step(&q)==SQLITE_ROW ){
200 const char *zTagname = db_column_text(&q, 0);
 
201 int rid = db_column_int(&q, 1);
202 const char *zSecSince1970 = db_column_text(&q, 2);
 
203 if( rid==0 || !bag_find(&vers, rid) ) continue;
204 zTagname += 4;
205 printf("tag %s\n", zTagname);
 
 
 
 
206 printf("from :%d\n", rid+firstCkin);
207 printf("tagger <tagger> %s +0000\n", zSecSince1970);
208 printf("data 0\n");
 
209 }
210 db_finalize(&q);
211 bag_clear(&vers);
212 }
213
--- src/export.c
+++ src/export.c
@@ -39,11 +39,11 @@
39 db_bind_text(&q, ":user", zUser);
40 if( db_step(&q)!=SQLITE_ROW ){
41 db_reset(&q);
42 for(i=0; zUser[i] && zUser[i]!='>' && zUser[i]!='<'; i++){}
43 if( zUser[i]==0 ){
44 printf(" %s <%s>", zUser, zUser);
45 return;
46 }
47 zName = mprintf("%s", zUser);
48 for(i=j=0; zName[i]; i++){
49 if( zName[i]!='<' && zName[i]!='>' ){
@@ -56,11 +56,11 @@
56 return;
57 }
58 zContact = db_column_text(&q, 0);
59 for(i=0; zContact[i] && zContact[i]!='>' && zContact[i]!='<'; i++){}
60 if( zContact[i]==0 ){
61 printf(" %s <%s>", zContact[0] ? zContact : zUser, zUser);
62 db_reset(&q);
63 return;
64 }
65 if( zContact[i]=='<' ){
66 zEmail = mprintf("%s", &zContact[i]);
@@ -196,17 +196,24 @@
196 " FROM tagxref JOIN tag USING(tagid)"
197 " WHERE tagtype=1 AND tagname GLOB 'sym-*'"
198 );
199 while( db_step(&q)==SQLITE_ROW ){
200 const char *zTagname = db_column_text(&q, 0);
201 char *zEncoded = 0;
202 int rid = db_column_int(&q, 1);
203 const char *zSecSince1970 = db_column_text(&q, 2);
204 int i;
205 if( rid==0 || !bag_find(&vers, rid) ) continue;
206 zTagname += 4;
207 zEncoded = mprintf("%s", zTagname);
208 for(i=0; zEncoded[i]; i++){
209 if( !fossil_isalnum(zEncoded[i]) ) zEncoded[i] = '_';
210 }
211 printf("tag %s\n", zEncoded);
212 printf("from :%d\n", rid+firstCkin);
213 printf("tagger <tagger> %s +0000\n", zSecSince1970);
214 printf("data 0\n");
215 fossil_free(zEncoded);
216 }
217 db_finalize(&q);
218 bag_clear(&vers);
219 }
220
+15 -5
--- src/file.c
+++ src/file.c
@@ -19,10 +19,12 @@
1919
*/
2020
#include "config.h"
2121
#include <sys/types.h>
2222
#include <sys/stat.h>
2323
#include <unistd.h>
24
+#include <string.h>
25
+#include <errno.h>
2426
#include "file.h"
2527
2628
/*
2729
** The file status information from the most recent stat() call.
2830
**
@@ -199,12 +201,13 @@
199201
int rc = 0;
200202
#if !defined(_WIN32)
201203
struct stat buf;
202204
if( stat(zFilename, &buf)!=0 ) return 0;
203205
if( onoff ){
204
- if( (buf.st_mode & 0111)!=0111 ){
205
- chmod(zFilename, buf.st_mode | 0111);
206
+ int targetMode = (buf.st_mode & 0444)>>2;
207
+ if( (buf.st_mode & 0111)!=targetMode ){
208
+ chmod(zFilename, buf.st_mode | targetMode);
206209
rc = 1;
207210
}
208211
}else{
209212
if( (buf.st_mode & 0111)!=0 ){
210213
chmod(zFilename, buf.st_mode & ~0111);
@@ -396,11 +399,11 @@
396399
char *zPwdUtf8;
397400
int nPwd;
398401
int i;
399402
char zPwd[2000];
400403
if( getcwd(zPwd, sizeof(zPwd)-1)==0 ){
401
- fossil_fatal("pwd too big: max %d\n", (int)sizeof(zPwd)-1);
404
+ fossil_fatal("cannot find the current working directory.");
402405
}
403406
zPwdUtf8 = fossil_mbcs_to_utf8(zPwd);
404407
nPwd = strlen(zPwdUtf8);
405408
if( nPwd > nBuf-1 ){
406409
fossil_fatal("pwd too big: max %d\n", nBuf-1);
@@ -408,11 +411,16 @@
408411
for(i=0; zPwdUtf8[i]; i++) if( zPwdUtf8[i]=='\\' ) zPwdUtf8[i] = '/';
409412
memcpy(zBuf, zPwdUtf8, nPwd+1);
410413
fossil_mbcs_free(zPwdUtf8);
411414
#else
412415
if( getcwd(zBuf, nBuf-1)==0 ){
413
- fossil_fatal("pwd too big: max %d\n", nBuf-1);
416
+ if( errno==ERANGE ){
417
+ fossil_fatal("pwd too big: max %d\n", nBuf-1);
418
+ }else{
419
+ fossil_fatal("cannot find current working directory; %s",
420
+ strerror(errno));
421
+ }
414422
}
415423
#endif
416424
}
417425
418426
/*
@@ -671,10 +679,11 @@
671679
"abcdefghijklmnopqrstuvwxyz"
672680
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
673681
"0123456789";
674682
unsigned int i, j;
675683
const char *zDir = ".";
684
+ int cnt = 0;
676685
677686
for(i=0; i<sizeof(azDirs)/sizeof(azDirs[0]); i++){
678687
if( !file_isdir(azDirs[i]) ) continue;
679688
zDir = azDirs[i];
680689
break;
@@ -686,18 +695,19 @@
686695
if( (strlen(zDir) + 17) >= (size_t)nBuf ){
687696
fossil_fatal("insufficient space for temporary filename");
688697
}
689698
690699
do{
700
+ if( cnt++>20 ) fossil_panic("cannot generate a temporary filename");
691701
sqlite3_snprintf(nBuf-17, zBuf, "%s/", zDir);
692702
j = (int)strlen(zBuf);
693703
sqlite3_randomness(15, &zBuf[j]);
694704
for(i=0; i<15; i++, j++){
695705
zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ];
696706
}
697707
zBuf[j] = 0;
698
- }while( file_size(zBuf)<0 );
708
+ }while( file_size(zBuf)>=0 );
699709
}
700710
701711
702712
/*
703713
** Return true if a file named zName exists and has identical content
704714
--- src/file.c
+++ src/file.c
@@ -19,10 +19,12 @@
19 */
20 #include "config.h"
21 #include <sys/types.h>
22 #include <sys/stat.h>
23 #include <unistd.h>
 
 
24 #include "file.h"
25
26 /*
27 ** The file status information from the most recent stat() call.
28 **
@@ -199,12 +201,13 @@
199 int rc = 0;
200 #if !defined(_WIN32)
201 struct stat buf;
202 if( stat(zFilename, &buf)!=0 ) return 0;
203 if( onoff ){
204 if( (buf.st_mode & 0111)!=0111 ){
205 chmod(zFilename, buf.st_mode | 0111);
 
206 rc = 1;
207 }
208 }else{
209 if( (buf.st_mode & 0111)!=0 ){
210 chmod(zFilename, buf.st_mode & ~0111);
@@ -396,11 +399,11 @@
396 char *zPwdUtf8;
397 int nPwd;
398 int i;
399 char zPwd[2000];
400 if( getcwd(zPwd, sizeof(zPwd)-1)==0 ){
401 fossil_fatal("pwd too big: max %d\n", (int)sizeof(zPwd)-1);
402 }
403 zPwdUtf8 = fossil_mbcs_to_utf8(zPwd);
404 nPwd = strlen(zPwdUtf8);
405 if( nPwd > nBuf-1 ){
406 fossil_fatal("pwd too big: max %d\n", nBuf-1);
@@ -408,11 +411,16 @@
408 for(i=0; zPwdUtf8[i]; i++) if( zPwdUtf8[i]=='\\' ) zPwdUtf8[i] = '/';
409 memcpy(zBuf, zPwdUtf8, nPwd+1);
410 fossil_mbcs_free(zPwdUtf8);
411 #else
412 if( getcwd(zBuf, nBuf-1)==0 ){
413 fossil_fatal("pwd too big: max %d\n", nBuf-1);
 
 
 
 
 
414 }
415 #endif
416 }
417
418 /*
@@ -671,10 +679,11 @@
671 "abcdefghijklmnopqrstuvwxyz"
672 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
673 "0123456789";
674 unsigned int i, j;
675 const char *zDir = ".";
 
676
677 for(i=0; i<sizeof(azDirs)/sizeof(azDirs[0]); i++){
678 if( !file_isdir(azDirs[i]) ) continue;
679 zDir = azDirs[i];
680 break;
@@ -686,18 +695,19 @@
686 if( (strlen(zDir) + 17) >= (size_t)nBuf ){
687 fossil_fatal("insufficient space for temporary filename");
688 }
689
690 do{
 
691 sqlite3_snprintf(nBuf-17, zBuf, "%s/", zDir);
692 j = (int)strlen(zBuf);
693 sqlite3_randomness(15, &zBuf[j]);
694 for(i=0; i<15; i++, j++){
695 zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ];
696 }
697 zBuf[j] = 0;
698 }while( file_size(zBuf)<0 );
699 }
700
701
702 /*
703 ** Return true if a file named zName exists and has identical content
704
--- src/file.c
+++ src/file.c
@@ -19,10 +19,12 @@
19 */
20 #include "config.h"
21 #include <sys/types.h>
22 #include <sys/stat.h>
23 #include <unistd.h>
24 #include <string.h>
25 #include <errno.h>
26 #include "file.h"
27
28 /*
29 ** The file status information from the most recent stat() call.
30 **
@@ -199,12 +201,13 @@
201 int rc = 0;
202 #if !defined(_WIN32)
203 struct stat buf;
204 if( stat(zFilename, &buf)!=0 ) return 0;
205 if( onoff ){
206 int targetMode = (buf.st_mode & 0444)>>2;
207 if( (buf.st_mode & 0111)!=targetMode ){
208 chmod(zFilename, buf.st_mode | targetMode);
209 rc = 1;
210 }
211 }else{
212 if( (buf.st_mode & 0111)!=0 ){
213 chmod(zFilename, buf.st_mode & ~0111);
@@ -396,11 +399,11 @@
399 char *zPwdUtf8;
400 int nPwd;
401 int i;
402 char zPwd[2000];
403 if( getcwd(zPwd, sizeof(zPwd)-1)==0 ){
404 fossil_fatal("cannot find the current working directory.");
405 }
406 zPwdUtf8 = fossil_mbcs_to_utf8(zPwd);
407 nPwd = strlen(zPwdUtf8);
408 if( nPwd > nBuf-1 ){
409 fossil_fatal("pwd too big: max %d\n", nBuf-1);
@@ -408,11 +411,16 @@
411 for(i=0; zPwdUtf8[i]; i++) if( zPwdUtf8[i]=='\\' ) zPwdUtf8[i] = '/';
412 memcpy(zBuf, zPwdUtf8, nPwd+1);
413 fossil_mbcs_free(zPwdUtf8);
414 #else
415 if( getcwd(zBuf, nBuf-1)==0 ){
416 if( errno==ERANGE ){
417 fossil_fatal("pwd too big: max %d\n", nBuf-1);
418 }else{
419 fossil_fatal("cannot find current working directory; %s",
420 strerror(errno));
421 }
422 }
423 #endif
424 }
425
426 /*
@@ -671,10 +679,11 @@
679 "abcdefghijklmnopqrstuvwxyz"
680 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
681 "0123456789";
682 unsigned int i, j;
683 const char *zDir = ".";
684 int cnt = 0;
685
686 for(i=0; i<sizeof(azDirs)/sizeof(azDirs[0]); i++){
687 if( !file_isdir(azDirs[i]) ) continue;
688 zDir = azDirs[i];
689 break;
@@ -686,18 +695,19 @@
695 if( (strlen(zDir) + 17) >= (size_t)nBuf ){
696 fossil_fatal("insufficient space for temporary filename");
697 }
698
699 do{
700 if( cnt++>20 ) fossil_panic("cannot generate a temporary filename");
701 sqlite3_snprintf(nBuf-17, zBuf, "%s/", zDir);
702 j = (int)strlen(zBuf);
703 sqlite3_randomness(15, &zBuf[j]);
704 for(i=0; i<15; i++, j++){
705 zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ];
706 }
707 zBuf[j] = 0;
708 }while( file_size(zBuf)>=0 );
709 }
710
711
712 /*
713 ** Return true if a file named zName exists and has identical content
714
+2 -1
--- src/http.c
+++ src/http.c
@@ -110,11 +110,12 @@
110110
blob_appendf(pHdr, "Authorization: Basic %s\r\n", zEncoded);
111111
fossil_free(zEncoded);
112112
fossil_free(zCredentials);
113113
}
114114
blob_appendf(pHdr, "Host: %s\r\n", g.urlHostname);
115
- blob_appendf(pHdr, "User-Agent: Fossil/" MANIFEST_VERSION "\r\n");
115
+ blob_appendf(pHdr, "User-Agent: Fossil/" RELEASE_VERSION
116
+ "-" MANIFEST_VERSION "\r\n");
116117
if( g.fHttpTrace ){
117118
blob_appendf(pHdr, "Content-Type: application/x-fossil-debug\r\n");
118119
}else{
119120
blob_appendf(pHdr, "Content-Type: application/x-fossil\r\n");
120121
}
121122
--- src/http.c
+++ src/http.c
@@ -110,11 +110,12 @@
110 blob_appendf(pHdr, "Authorization: Basic %s\r\n", zEncoded);
111 fossil_free(zEncoded);
112 fossil_free(zCredentials);
113 }
114 blob_appendf(pHdr, "Host: %s\r\n", g.urlHostname);
115 blob_appendf(pHdr, "User-Agent: Fossil/" MANIFEST_VERSION "\r\n");
 
116 if( g.fHttpTrace ){
117 blob_appendf(pHdr, "Content-Type: application/x-fossil-debug\r\n");
118 }else{
119 blob_appendf(pHdr, "Content-Type: application/x-fossil\r\n");
120 }
121
--- src/http.c
+++ src/http.c
@@ -110,11 +110,12 @@
110 blob_appendf(pHdr, "Authorization: Basic %s\r\n", zEncoded);
111 fossil_free(zEncoded);
112 fossil_free(zCredentials);
113 }
114 blob_appendf(pHdr, "Host: %s\r\n", g.urlHostname);
115 blob_appendf(pHdr, "User-Agent: Fossil/" RELEASE_VERSION
116 "-" MANIFEST_VERSION "\r\n");
117 if( g.fHttpTrace ){
118 blob_appendf(pHdr, "Content-Type: application/x-fossil-debug\r\n");
119 }else{
120 blob_appendf(pHdr, "Content-Type: application/x-fossil\r\n");
121 }
122
+30 -6
--- src/import.c
+++ src/import.c
@@ -207,10 +207,19 @@
207207
static int mfile_cmp(const void *pLeft, const void *pRight){
208208
const ImportFile *pA = (const ImportFile*)pLeft;
209209
const ImportFile *pB = (const ImportFile*)pRight;
210210
return fossil_strcmp(pA->zName, pB->zName);
211211
}
212
+
213
+/*
214
+** Compare two strings for sorting.
215
+*/
216
+static int string_cmp(const void *pLeft, const void *pRight){
217
+ const char *zLeft = *(char const **)pLeft;
218
+ const char *zRight = *(char const **)pRight;
219
+ return fossil_strcmp(zLeft, zRight);
220
+}
212221
213222
/* Forward reference */
214223
static void import_prior_files(void);
215224
216225
/*
@@ -218,11 +227,14 @@
218227
** manifest artifact to the BLOB table.
219228
*/
220229
static void finish_commit(void){
221230
int i;
222231
char *zFromBranch;
232
+ char *aTCard[4]; /* Array of T cards for manifest */
233
+ int nTCard = 0; /* Entries used in aTCard[] */
223234
Blob record, cksum;
235
+
224236
import_prior_files();
225237
qsort(gg.aFile, gg.nFile, sizeof(gg.aFile[0]), mfile_cmp);
226238
blob_zero(&record);
227239
blob_appendf(&record, "C %F\n", gg.zComment);
228240
blob_appendf(&record, "D %s\n", gg.zDate);
@@ -245,21 +257,33 @@
245257
zFromBranch = db_text(0, "SELECT brnm FROM xbranch WHERE tname=%Q",
246258
gg.zFromMark);
247259
}else{
248260
zFromBranch = 0;
249261
}
262
+
263
+ /* Add the required "T" cards to the manifest. Make sure they are added
264
+ ** in sorted order and without any duplicates. Otherwise, fossil will not
265
+ ** recognize the document as a valid manifest. */
250266
if( !gg.tagCommit && fossil_strcmp(zFromBranch, gg.zBranch)!=0 ){
251
- blob_appendf(&record, "T *branch * %F\n", gg.zBranch);
252
- blob_appendf(&record, "T *sym-%F *\n", gg.zBranch);
267
+ aTCard[nTCard++] = mprintf("T *branch * %F\n", gg.zBranch);
268
+ aTCard[nTCard++] = mprintf("T *sym-%F *\n", gg.zBranch);
253269
if( zFromBranch ){
254
- blob_appendf(&record, "T -sym-%F *\n", zFromBranch);
270
+ aTCard[nTCard++] = mprintf("T -sym-%F *\n", zFromBranch);
271
+ }
272
+ }
273
+ if( gg.zFrom==0 ){
274
+ aTCard[nTCard++] = mprintf("T *sym-trunk *\n");
275
+ }
276
+ qsort(aTCard, nTCard, sizeof(char *), string_cmp);
277
+ for(i=0; i<nTCard; i++){
278
+ if( i==0 || fossil_strcmp(aTCard[i-1], aTCard[i]) ){
279
+ blob_appendf(&record, "%s", aTCard[i]);
255280
}
256281
}
282
+ for(i=0; i<nTCard; i++) free(aTCard[i]);
283
+
257284
free(zFromBranch);
258
- if( gg.zFrom==0 ){
259
- blob_appendf(&record, "T *sym-trunk *\n");
260
- }
261285
db_multi_exec("INSERT INTO xbranch(tname, brnm) VALUES(%Q,%Q)",
262286
gg.zMark, gg.zBranch);
263287
blob_appendf(&record, "U %F\n", gg.zUser);
264288
md5sum_blob(&record, &cksum);
265289
blob_appendf(&record, "Z %b\n", &cksum);
266290
--- src/import.c
+++ src/import.c
@@ -207,10 +207,19 @@
207 static int mfile_cmp(const void *pLeft, const void *pRight){
208 const ImportFile *pA = (const ImportFile*)pLeft;
209 const ImportFile *pB = (const ImportFile*)pRight;
210 return fossil_strcmp(pA->zName, pB->zName);
211 }
 
 
 
 
 
 
 
 
 
212
213 /* Forward reference */
214 static void import_prior_files(void);
215
216 /*
@@ -218,11 +227,14 @@
218 ** manifest artifact to the BLOB table.
219 */
220 static void finish_commit(void){
221 int i;
222 char *zFromBranch;
 
 
223 Blob record, cksum;
 
224 import_prior_files();
225 qsort(gg.aFile, gg.nFile, sizeof(gg.aFile[0]), mfile_cmp);
226 blob_zero(&record);
227 blob_appendf(&record, "C %F\n", gg.zComment);
228 blob_appendf(&record, "D %s\n", gg.zDate);
@@ -245,21 +257,33 @@
245 zFromBranch = db_text(0, "SELECT brnm FROM xbranch WHERE tname=%Q",
246 gg.zFromMark);
247 }else{
248 zFromBranch = 0;
249 }
 
 
 
 
250 if( !gg.tagCommit && fossil_strcmp(zFromBranch, gg.zBranch)!=0 ){
251 blob_appendf(&record, "T *branch * %F\n", gg.zBranch);
252 blob_appendf(&record, "T *sym-%F *\n", gg.zBranch);
253 if( zFromBranch ){
254 blob_appendf(&record, "T -sym-%F *\n", zFromBranch);
 
 
 
 
 
 
 
 
 
255 }
256 }
 
 
257 free(zFromBranch);
258 if( gg.zFrom==0 ){
259 blob_appendf(&record, "T *sym-trunk *\n");
260 }
261 db_multi_exec("INSERT INTO xbranch(tname, brnm) VALUES(%Q,%Q)",
262 gg.zMark, gg.zBranch);
263 blob_appendf(&record, "U %F\n", gg.zUser);
264 md5sum_blob(&record, &cksum);
265 blob_appendf(&record, "Z %b\n", &cksum);
266
--- src/import.c
+++ src/import.c
@@ -207,10 +207,19 @@
207 static int mfile_cmp(const void *pLeft, const void *pRight){
208 const ImportFile *pA = (const ImportFile*)pLeft;
209 const ImportFile *pB = (const ImportFile*)pRight;
210 return fossil_strcmp(pA->zName, pB->zName);
211 }
212
213 /*
214 ** Compare two strings for sorting.
215 */
216 static int string_cmp(const void *pLeft, const void *pRight){
217 const char *zLeft = *(char const **)pLeft;
218 const char *zRight = *(char const **)pRight;
219 return fossil_strcmp(zLeft, zRight);
220 }
221
222 /* Forward reference */
223 static void import_prior_files(void);
224
225 /*
@@ -218,11 +227,14 @@
227 ** manifest artifact to the BLOB table.
228 */
229 static void finish_commit(void){
230 int i;
231 char *zFromBranch;
232 char *aTCard[4]; /* Array of T cards for manifest */
233 int nTCard = 0; /* Entries used in aTCard[] */
234 Blob record, cksum;
235
236 import_prior_files();
237 qsort(gg.aFile, gg.nFile, sizeof(gg.aFile[0]), mfile_cmp);
238 blob_zero(&record);
239 blob_appendf(&record, "C %F\n", gg.zComment);
240 blob_appendf(&record, "D %s\n", gg.zDate);
@@ -245,21 +257,33 @@
257 zFromBranch = db_text(0, "SELECT brnm FROM xbranch WHERE tname=%Q",
258 gg.zFromMark);
259 }else{
260 zFromBranch = 0;
261 }
262
263 /* Add the required "T" cards to the manifest. Make sure they are added
264 ** in sorted order and without any duplicates. Otherwise, fossil will not
265 ** recognize the document as a valid manifest. */
266 if( !gg.tagCommit && fossil_strcmp(zFromBranch, gg.zBranch)!=0 ){
267 aTCard[nTCard++] = mprintf("T *branch * %F\n", gg.zBranch);
268 aTCard[nTCard++] = mprintf("T *sym-%F *\n", gg.zBranch);
269 if( zFromBranch ){
270 aTCard[nTCard++] = mprintf("T -sym-%F *\n", zFromBranch);
271 }
272 }
273 if( gg.zFrom==0 ){
274 aTCard[nTCard++] = mprintf("T *sym-trunk *\n");
275 }
276 qsort(aTCard, nTCard, sizeof(char *), string_cmp);
277 for(i=0; i<nTCard; i++){
278 if( i==0 || fossil_strcmp(aTCard[i-1], aTCard[i]) ){
279 blob_appendf(&record, "%s", aTCard[i]);
280 }
281 }
282 for(i=0; i<nTCard; i++) free(aTCard[i]);
283
284 free(zFromBranch);
 
 
 
285 db_multi_exec("INSERT INTO xbranch(tname, brnm) VALUES(%Q,%Q)",
286 gg.zMark, gg.zBranch);
287 blob_appendf(&record, "U %F\n", gg.zUser);
288 md5sum_blob(&record, &cksum);
289 blob_appendf(&record, "Z %b\n", &cksum);
290
+3 -3
--- src/info.c
+++ src/info.c
@@ -190,11 +190,11 @@
190190
" (SELECT uuid FROM blob WHERE rid=tagxref.srcid AND rid!=%d),"
191191
" value, datetime(tagxref.mtime,'localtime'), tagtype,"
192192
" (SELECT uuid FROM blob WHERE rid=tagxref.origid AND rid!=%d)"
193193
" FROM tagxref JOIN tag ON tagxref.tagid=tag.tagid"
194194
" WHERE tagxref.rid=%d AND tagname NOT GLOB '%s'"
195
- " ORDER BY tagname", rid, rid, rid, zNotGlob
195
+ " ORDER BY tagname /*sort*/", rid, rid, rid, zNotGlob
196196
);
197197
while( db_step(&q)==SQLITE_ROW ){
198198
const char *zTagname = db_column_text(&q, 1);
199199
const char *zSrcUuid = db_column_text(&q, 2);
200200
const char *zValue = db_column_text(&q, 3);
@@ -525,11 +525,11 @@
525525
" (SELECT uuid FROM blob WHERE rid=mlink.pid),"
526526
" (SELECT uuid FROM blob WHERE rid=mlink.fid),"
527527
" (SELECT name FROM filename WHERE filename.fnid=mlink.pfnid)"
528528
" FROM mlink JOIN filename ON filename.fnid=mlink.fnid"
529529
" WHERE mlink.mid=%d"
530
- " ORDER BY name",
530
+ " ORDER BY name /*sort*/",
531531
rid
532532
);
533533
while( db_step(&q)==SQLITE_ROW ){
534534
const char *zName = db_column_text(&q,0);
535535
int mperm = db_column_int(&q, 1);
@@ -1790,11 +1790,11 @@
17901790
@ <input type="text" style="width:15;" name="tagname" value="%h(zNewTag)" />
17911791
db_prepare(&q,
17921792
"SELECT tag.tagid, tagname FROM tagxref, tag"
17931793
" WHERE tagxref.rid=%d AND tagtype>0 AND tagxref.tagid=tag.tagid"
17941794
" ORDER BY CASE WHEN tagname GLOB 'sym-*' THEN substr(tagname,5)"
1795
- " ELSE tagname END",
1795
+ " ELSE tagname END /*sort*/",
17961796
rid
17971797
);
17981798
while( db_step(&q)==SQLITE_ROW ){
17991799
int tagid = db_column_int(&q, 0);
18001800
const char *zTagName = db_column_text(&q, 1);
18011801
--- src/info.c
+++ src/info.c
@@ -190,11 +190,11 @@
190 " (SELECT uuid FROM blob WHERE rid=tagxref.srcid AND rid!=%d),"
191 " value, datetime(tagxref.mtime,'localtime'), tagtype,"
192 " (SELECT uuid FROM blob WHERE rid=tagxref.origid AND rid!=%d)"
193 " FROM tagxref JOIN tag ON tagxref.tagid=tag.tagid"
194 " WHERE tagxref.rid=%d AND tagname NOT GLOB '%s'"
195 " ORDER BY tagname", rid, rid, rid, zNotGlob
196 );
197 while( db_step(&q)==SQLITE_ROW ){
198 const char *zTagname = db_column_text(&q, 1);
199 const char *zSrcUuid = db_column_text(&q, 2);
200 const char *zValue = db_column_text(&q, 3);
@@ -525,11 +525,11 @@
525 " (SELECT uuid FROM blob WHERE rid=mlink.pid),"
526 " (SELECT uuid FROM blob WHERE rid=mlink.fid),"
527 " (SELECT name FROM filename WHERE filename.fnid=mlink.pfnid)"
528 " FROM mlink JOIN filename ON filename.fnid=mlink.fnid"
529 " WHERE mlink.mid=%d"
530 " ORDER BY name",
531 rid
532 );
533 while( db_step(&q)==SQLITE_ROW ){
534 const char *zName = db_column_text(&q,0);
535 int mperm = db_column_int(&q, 1);
@@ -1790,11 +1790,11 @@
1790 @ <input type="text" style="width:15;" name="tagname" value="%h(zNewTag)" />
1791 db_prepare(&q,
1792 "SELECT tag.tagid, tagname FROM tagxref, tag"
1793 " WHERE tagxref.rid=%d AND tagtype>0 AND tagxref.tagid=tag.tagid"
1794 " ORDER BY CASE WHEN tagname GLOB 'sym-*' THEN substr(tagname,5)"
1795 " ELSE tagname END",
1796 rid
1797 );
1798 while( db_step(&q)==SQLITE_ROW ){
1799 int tagid = db_column_int(&q, 0);
1800 const char *zTagName = db_column_text(&q, 1);
1801
--- src/info.c
+++ src/info.c
@@ -190,11 +190,11 @@
190 " (SELECT uuid FROM blob WHERE rid=tagxref.srcid AND rid!=%d),"
191 " value, datetime(tagxref.mtime,'localtime'), tagtype,"
192 " (SELECT uuid FROM blob WHERE rid=tagxref.origid AND rid!=%d)"
193 " FROM tagxref JOIN tag ON tagxref.tagid=tag.tagid"
194 " WHERE tagxref.rid=%d AND tagname NOT GLOB '%s'"
195 " ORDER BY tagname /*sort*/", rid, rid, rid, zNotGlob
196 );
197 while( db_step(&q)==SQLITE_ROW ){
198 const char *zTagname = db_column_text(&q, 1);
199 const char *zSrcUuid = db_column_text(&q, 2);
200 const char *zValue = db_column_text(&q, 3);
@@ -525,11 +525,11 @@
525 " (SELECT uuid FROM blob WHERE rid=mlink.pid),"
526 " (SELECT uuid FROM blob WHERE rid=mlink.fid),"
527 " (SELECT name FROM filename WHERE filename.fnid=mlink.pfnid)"
528 " FROM mlink JOIN filename ON filename.fnid=mlink.fnid"
529 " WHERE mlink.mid=%d"
530 " ORDER BY name /*sort*/",
531 rid
532 );
533 while( db_step(&q)==SQLITE_ROW ){
534 const char *zName = db_column_text(&q,0);
535 int mperm = db_column_int(&q, 1);
@@ -1790,11 +1790,11 @@
1790 @ <input type="text" style="width:15;" name="tagname" value="%h(zNewTag)" />
1791 db_prepare(&q,
1792 "SELECT tag.tagid, tagname FROM tagxref, tag"
1793 " WHERE tagxref.rid=%d AND tagtype>0 AND tagxref.tagid=tag.tagid"
1794 " ORDER BY CASE WHEN tagname GLOB 'sym-*' THEN substr(tagname,5)"
1795 " ELSE tagname END /*sort*/",
1796 rid
1797 );
1798 while( db_step(&q)==SQLITE_ROW ){
1799 int tagid = db_column_int(&q, 0);
1800 const char *zTagName = db_column_text(&q, 1);
1801
+2 -2
--- src/main.c
+++ src/main.c
@@ -2,11 +2,11 @@
22
** Copyright (c) 2006 D. Richard Hipp
33
**
44
** This program is free software; you can redistribute it and/or
55
** modify it under the terms of the Simplified BSD License (also
66
** known as the "2-Clause License" or "FreeBSD License".)
7
-
7
+**
88
** This program is distributed in the hope that it will be useful,
99
** but without any warranty; without even the implied warranty of
1010
** merchantability or fitness for a particular purpose.
1111
**
1212
** Author contact information:
@@ -646,11 +646,11 @@
646646
** Usage: %fossil version
647647
**
648648
** Print the source code version number for the fossil executable.
649649
*/
650650
void version_cmd(void){
651
- fossil_print("This is fossil version "
651
+ fossil_print("This is fossil version " RELEASE_VERSION " "
652652
MANIFEST_VERSION " " MANIFEST_DATE " UTC\n");
653653
}
654654
655655
656656
/*
657657
--- src/main.c
+++ src/main.c
@@ -2,11 +2,11 @@
2 ** Copyright (c) 2006 D. Richard Hipp
3 **
4 ** This program is free software; you can redistribute it and/or
5 ** modify it under the terms of the Simplified BSD License (also
6 ** known as the "2-Clause License" or "FreeBSD License".)
7
8 ** This program is distributed in the hope that it will be useful,
9 ** but without any warranty; without even the implied warranty of
10 ** merchantability or fitness for a particular purpose.
11 **
12 ** Author contact information:
@@ -646,11 +646,11 @@
646 ** Usage: %fossil version
647 **
648 ** Print the source code version number for the fossil executable.
649 */
650 void version_cmd(void){
651 fossil_print("This is fossil version "
652 MANIFEST_VERSION " " MANIFEST_DATE " UTC\n");
653 }
654
655
656 /*
657
--- src/main.c
+++ src/main.c
@@ -2,11 +2,11 @@
2 ** Copyright (c) 2006 D. Richard Hipp
3 **
4 ** This program is free software; you can redistribute it and/or
5 ** modify it under the terms of the Simplified BSD License (also
6 ** known as the "2-Clause License" or "FreeBSD License".)
7 **
8 ** This program is distributed in the hope that it will be useful,
9 ** but without any warranty; without even the implied warranty of
10 ** merchantability or fitness for a particular purpose.
11 **
12 ** Author contact information:
@@ -646,11 +646,11 @@
646 ** Usage: %fossil version
647 **
648 ** Print the source code version number for the fossil executable.
649 */
650 void version_cmd(void){
651 fossil_print("This is fossil version " RELEASE_VERSION " "
652 MANIFEST_VERSION " " MANIFEST_DATE " UTC\n");
653 }
654
655
656 /*
657
+2 -2
--- src/main.c
+++ src/main.c
@@ -2,11 +2,11 @@
22
** Copyright (c) 2006 D. Richard Hipp
33
**
44
** This program is free software; you can redistribute it and/or
55
** modify it under the terms of the Simplified BSD License (also
66
** known as the "2-Clause License" or "FreeBSD License".)
7
-
7
+**
88
** This program is distributed in the hope that it will be useful,
99
** but without any warranty; without even the implied warranty of
1010
** merchantability or fitness for a particular purpose.
1111
**
1212
** Author contact information:
@@ -646,11 +646,11 @@
646646
** Usage: %fossil version
647647
**
648648
** Print the source code version number for the fossil executable.
649649
*/
650650
void version_cmd(void){
651
- fossil_print("This is fossil version "
651
+ fossil_print("This is fossil version " RELEASE_VERSION " "
652652
MANIFEST_VERSION " " MANIFEST_DATE " UTC\n");
653653
}
654654
655655
656656
/*
657657
--- src/main.c
+++ src/main.c
@@ -2,11 +2,11 @@
2 ** Copyright (c) 2006 D. Richard Hipp
3 **
4 ** This program is free software; you can redistribute it and/or
5 ** modify it under the terms of the Simplified BSD License (also
6 ** known as the "2-Clause License" or "FreeBSD License".)
7
8 ** This program is distributed in the hope that it will be useful,
9 ** but without any warranty; without even the implied warranty of
10 ** merchantability or fitness for a particular purpose.
11 **
12 ** Author contact information:
@@ -646,11 +646,11 @@
646 ** Usage: %fossil version
647 **
648 ** Print the source code version number for the fossil executable.
649 */
650 void version_cmd(void){
651 fossil_print("This is fossil version "
652 MANIFEST_VERSION " " MANIFEST_DATE " UTC\n");
653 }
654
655
656 /*
657
--- src/main.c
+++ src/main.c
@@ -2,11 +2,11 @@
2 ** Copyright (c) 2006 D. Richard Hipp
3 **
4 ** This program is free software; you can redistribute it and/or
5 ** modify it under the terms of the Simplified BSD License (also
6 ** known as the "2-Clause License" or "FreeBSD License".)
7 **
8 ** This program is distributed in the hope that it will be useful,
9 ** but without any warranty; without even the implied warranty of
10 ** merchantability or fitness for a particular purpose.
11 **
12 ** Author contact information:
@@ -646,11 +646,11 @@
646 ** Usage: %fossil version
647 **
648 ** Print the source code version number for the fossil executable.
649 */
650 void version_cmd(void){
651 fossil_print("This is fossil version " RELEASE_VERSION " "
652 MANIFEST_VERSION " " MANIFEST_DATE " UTC\n");
653 }
654
655
656 /*
657
+5 -4
--- src/main.mk
+++ src/main.mk
@@ -281,20 +281,21 @@
281281
$(BCC) -o $(OBJDIR)/makeheaders $(SRCDIR)/makeheaders.c
282282
283283
$(OBJDIR)/mkindex: $(SRCDIR)/mkindex.c
284284
$(BCC) -o $(OBJDIR)/mkindex $(SRCDIR)/mkindex.c
285285
286
+$(OBJDIR)/mkversion: $(SRCDIR)/mkversion.c
287
+ $(BCC) -o $(OBJDIR)/mkversion $(SRCDIR)/mkversion.c
288
+
286289
# WARNING. DANGER. Running the testsuite modifies the repository the
287290
# build is done from, i.e. the checkout belongs to. Do not sync/push
288291
# the repository after running the tests.
289292
test: $(APPNAME)
290293
$(TCLSH) test/tester.tcl $(APPNAME)
291294
292
-$(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest
293
- awk '{ printf "#define MANIFEST_UUID \"%s\"\n", $$1}' $(SRCDIR)/../manifest.uuid >$(OBJDIR)/VERSION.h
294
- awk '{ printf "#define MANIFEST_VERSION \"[%.10s]\"\n", $$1}' $(SRCDIR)/../manifest.uuid >>$(OBJDIR)/VERSION.h
295
- awk '$$1=="D"{printf "#define MANIFEST_DATE \"%s %s\"\n", substr($$2,1,10),substr($$2,12,8)}' $(SRCDIR)/../manifest >>$(OBJDIR)/VERSION.h
295
+$(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION $(OBJDIR)/mkversion
296
+ $(OBJDIR)/mkversion $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION >$(OBJDIR)/VERSION.h
296297
297298
EXTRAOBJ = $(OBJDIR)/sqlite3.o $(OBJDIR)/shell.o $(OBJDIR)/th.o $(OBJDIR)/th_lang.o
298299
299300
$(APPNAME): $(OBJDIR)/headers $(OBJ) $(EXTRAOBJ)
300301
$(TCC) -o $(APPNAME) $(OBJ) $(EXTRAOBJ) $(LIB)
301302
--- src/main.mk
+++ src/main.mk
@@ -281,20 +281,21 @@
281 $(BCC) -o $(OBJDIR)/makeheaders $(SRCDIR)/makeheaders.c
282
283 $(OBJDIR)/mkindex: $(SRCDIR)/mkindex.c
284 $(BCC) -o $(OBJDIR)/mkindex $(SRCDIR)/mkindex.c
285
 
 
 
286 # WARNING. DANGER. Running the testsuite modifies the repository the
287 # build is done from, i.e. the checkout belongs to. Do not sync/push
288 # the repository after running the tests.
289 test: $(APPNAME)
290 $(TCLSH) test/tester.tcl $(APPNAME)
291
292 $(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest
293 awk '{ printf "#define MANIFEST_UUID \"%s\"\n", $$1}' $(SRCDIR)/../manifest.uuid >$(OBJDIR)/VERSION.h
294 awk '{ printf "#define MANIFEST_VERSION \"[%.10s]\"\n", $$1}' $(SRCDIR)/../manifest.uuid >>$(OBJDIR)/VERSION.h
295 awk '$$1=="D"{printf "#define MANIFEST_DATE \"%s %s\"\n", substr($$2,1,10),substr($$2,12,8)}' $(SRCDIR)/../manifest >>$(OBJDIR)/VERSION.h
296
297 EXTRAOBJ = $(OBJDIR)/sqlite3.o $(OBJDIR)/shell.o $(OBJDIR)/th.o $(OBJDIR)/th_lang.o
298
299 $(APPNAME): $(OBJDIR)/headers $(OBJ) $(EXTRAOBJ)
300 $(TCC) -o $(APPNAME) $(OBJ) $(EXTRAOBJ) $(LIB)
301
--- src/main.mk
+++ src/main.mk
@@ -281,20 +281,21 @@
281 $(BCC) -o $(OBJDIR)/makeheaders $(SRCDIR)/makeheaders.c
282
283 $(OBJDIR)/mkindex: $(SRCDIR)/mkindex.c
284 $(BCC) -o $(OBJDIR)/mkindex $(SRCDIR)/mkindex.c
285
286 $(OBJDIR)/mkversion: $(SRCDIR)/mkversion.c
287 $(BCC) -o $(OBJDIR)/mkversion $(SRCDIR)/mkversion.c
288
289 # WARNING. DANGER. Running the testsuite modifies the repository the
290 # build is done from, i.e. the checkout belongs to. Do not sync/push
291 # the repository after running the tests.
292 test: $(APPNAME)
293 $(TCLSH) test/tester.tcl $(APPNAME)
294
295 $(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION $(OBJDIR)/mkversion
296 $(OBJDIR)/mkversion $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION >$(OBJDIR)/VERSION.h
 
 
297
298 EXTRAOBJ = $(OBJDIR)/sqlite3.o $(OBJDIR)/shell.o $(OBJDIR)/th.o $(OBJDIR)/th_lang.o
299
300 $(APPNAME): $(OBJDIR)/headers $(OBJ) $(EXTRAOBJ)
301 $(TCC) -o $(APPNAME) $(OBJ) $(EXTRAOBJ) $(LIB)
302
--- src/makeheaders.c
+++ src/makeheaders.c
@@ -3066,11 +3066,11 @@
30663066
*/
30673067
if( zSrc[nSrc]==':' ){
30683068
int nHdr;
30693069
char *zHdr;
30703070
zHdr = &zSrc[nSrc+1];
3071
- for(nHdr=0; zHdr[nHdr] && zHdr[nHdr]!=':'; nHdr++){}
3071
+ for(nHdr=0; zHdr[nHdr]; nHdr++){}
30723072
pFile->zHdr = StrDup(zHdr,nHdr);
30733073
}
30743074
30753075
/* Look for any 'c' or 'C' in the suffix of the file name and change
30763076
** that character to 'h' or 'H' respectively. If no 'c' or 'C' is found,
30773077
--- src/makeheaders.c
+++ src/makeheaders.c
@@ -3066,11 +3066,11 @@
3066 */
3067 if( zSrc[nSrc]==':' ){
3068 int nHdr;
3069 char *zHdr;
3070 zHdr = &zSrc[nSrc+1];
3071 for(nHdr=0; zHdr[nHdr] && zHdr[nHdr]!=':'; nHdr++){}
3072 pFile->zHdr = StrDup(zHdr,nHdr);
3073 }
3074
3075 /* Look for any 'c' or 'C' in the suffix of the file name and change
3076 ** that character to 'h' or 'H' respectively. If no 'c' or 'C' is found,
3077
--- src/makeheaders.c
+++ src/makeheaders.c
@@ -3066,11 +3066,11 @@
3066 */
3067 if( zSrc[nSrc]==':' ){
3068 int nHdr;
3069 char *zHdr;
3070 zHdr = &zSrc[nSrc+1];
3071 for(nHdr=0; zHdr[nHdr]; nHdr++){}
3072 pFile->zHdr = StrDup(zHdr,nHdr);
3073 }
3074
3075 /* Look for any 'c' or 'C' in the suffix of the file name and change
3076 ** that character to 'h' or 'H' respectively. If no 'c' or 'C' is found,
3077
+18 -19
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -176,24 +176,23 @@
176176
$(BCC) -o $(OBJDIR)/makeheaders $(SRCDIR)/makeheaders.c
177177
178178
$(OBJDIR)/mkindex: $(SRCDIR)/mkindex.c
179179
$(BCC) -o $(OBJDIR)/mkindex $(SRCDIR)/mkindex.c
180180
181
+$(OBJDIR)/mkversion: $(SRCDIR)/mkversion.c
182
+ $(BCC) -o $(OBJDIR)/mkversion $(SRCDIR)/mkversion.c
183
+
181184
# WARNING. DANGER. Running the testsuite modifies the repository the
182185
# build is done from, i.e. the checkout belongs to. Do not sync/push
183186
# the repository after running the tests.
184187
test: $(APPNAME)
185188
$(TCLSH) test/tester.tcl $(APPNAME)
186189
187
-$(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest
188
- awk '{ printf "#define MANIFEST_UUID \"%s\"\n", $$1}' \
189
- $(SRCDIR)/../manifest.uuid >$(OBJDIR)/VERSION.h
190
- awk '{ printf "#define MANIFEST_VERSION \"[%.10s]\"\n", $$1}' \
191
- $(SRCDIR)/../manifest.uuid >>$(OBJDIR)/VERSION.h
192
- awk '$$1=="D"{printf "#define MANIFEST_DATE \"%s %s\"\n",\
193
- substr($$2,1,10),substr($$2,12,8)}' \
194
- $(SRCDIR)/../manifest >>$(OBJDIR)/VERSION.h
190
+$(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION $(OBJDIR)/mkversion
191
+ $(OBJDIR)/mkversion $(SRCDIR)/../manifest.uuid \
192
+ $(SRCDIR)/../manifest \
193
+ $(SRCDIR)/../VERSION >$(OBJDIR)/VERSION.h
195194
196195
EXTRAOBJ = \
197196
$(OBJDIR)/sqlite3.o \
198197
$(OBJDIR)/shell.o \
199198
$(OBJDIR)/th.o \
@@ -389,12 +388,12 @@
389388
$(BCC) -o $(OBJDIR)/makeheaders $(SRCDIR)/makeheaders.c
390389
391390
$(OBJDIR)/mkindex: $(SRCDIR)/mkindex.c
392391
$(BCC) -o $(OBJDIR)/mkindex $(SRCDIR)/mkindex.c
393392
394
-$(VERSION): $(SRCDIR)/../win/version.c
395
- $(BCC) -o $(OBJDIR)/version $(SRCDIR)/../win/version.c
393
+$(VERSION): $(SRCDIR)/mkversion.c
394
+ $(BCC) -o $(OBJDIR)/version $(SRCDIR)/mkversion.c
396395
397396
# WARNING. DANGER. Running the testsuite modifies the repository the
398397
# build is done from, i.e. the checkout belongs to. Do not sync/push
399398
# the repository after running the tests.
400399
test: $(APPNAME)
@@ -556,11 +555,11 @@
556555
$(BCC) -o$@ $**
557556
558557
mkindex$E: $(SRCDIR)\mkindex.c
559558
$(BCC) -o$@ $**
560559
561
-version$E: $B\win\version.c
560
+version$E: $B\src\mkversion.c
562561
$(BCC) -o$@ $**
563562
564563
$(OBJDIR)\shell$O : $(SRCDIR)\shell.c
565564
$(TCC) -o$@ -c -Dmain=sqlite3_shell $(SQLITE_OPTIONS) $**
566565
@@ -669,18 +668,18 @@
669668
670669
all: $(OX) $(APPNAME)
671670
672671
$(APPNAME) : translate$E mkindex$E headers $(OBJ) $(OX)\linkopts
673672
cd $(OX)
674
- link -LINK -OUT:$@ $(LIBDIR) @linkopts
673
+ link /NODEFAULTLIB:msvcrt -OUT:$@ $(LIBDIR) @linkopts
675674
676675
$(OX)\linkopts: $B\win\Makefile.msc}
677
-writeln -nonewline "\techo "
678
-foreach s [lsort $src] {
679
- writeln -nonewline "$s "
676
+set redir {>}
677
+foreach s [lsort [concat $src {shell sqlite3 th th_lang}]] {
678
+ writeln "\techo \$(OX)\\$s.obj $redir \$@"
679
+ set redir {>>}
680680
}
681
-writeln "sqlite3 th th_lang > \$@"
682681
writeln "\techo \$(LIBS) >> \$@\n\n"
683682
684683
writeln {
685684
686685
$(OX):
@@ -693,15 +692,15 @@
693692
$(BCC) $**
694693
695694
mkindex$E: $(SRCDIR)\mkindex.c
696695
$(BCC) $**
697696
698
-version$E: $B\win\version.c
697
+version$E: $B\src\mkversion.c
699698
$(BCC) $**
700699
701700
$(OX)\shell$O : $(SRCDIR)\shell.c
702
- $(TCC) /Fo$@ /Dmain=sqlite3_shell $(SQLITE_OPTIONS) -c shell_.c
701
+ $(TCC) /Fo$@ /Dmain=sqlite3_shell $(SQLITE_OPTIONS) -c $(SRCDIR)\shell.c
703702
704703
$(OX)\sqlite3$O : $(SRCDIR)\sqlite3.c
705704
$(TCC) /Fo$@ -c $(SQLITE_OPTIONS) $**
706705
707706
$(OX)\th$O : $(SRCDIR)\th.c
@@ -880,11 +879,11 @@
880879
# compiling standard fossil utils
881880
$(UTILS_OBJ): %.obj: $(SRCDIR)%.c
882881
$(CC) $(CCFLAGS) $(INCLUDE) "$<" -Fo"$@"
883882
884883
# compile special windows utils
885
-version.obj: $(WINDIR)version.c
884
+version.obj: $(SRCDIR)mkversion.c
886885
$(CC) $(CCFLAGS) $(INCLUDE) "$<" -Fo"$@"
887886
888887
# generate the translated c-source files
889888
$(TRANSLATEDSRC): %_.c: $(SRCDIR)%.c translate.exe
890889
translate.exe $< >$@
891890
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -176,24 +176,23 @@
176 $(BCC) -o $(OBJDIR)/makeheaders $(SRCDIR)/makeheaders.c
177
178 $(OBJDIR)/mkindex: $(SRCDIR)/mkindex.c
179 $(BCC) -o $(OBJDIR)/mkindex $(SRCDIR)/mkindex.c
180
 
 
 
181 # WARNING. DANGER. Running the testsuite modifies the repository the
182 # build is done from, i.e. the checkout belongs to. Do not sync/push
183 # the repository after running the tests.
184 test: $(APPNAME)
185 $(TCLSH) test/tester.tcl $(APPNAME)
186
187 $(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest
188 awk '{ printf "#define MANIFEST_UUID \"%s\"\n", $$1}' \
189 $(SRCDIR)/../manifest.uuid >$(OBJDIR)/VERSION.h
190 awk '{ printf "#define MANIFEST_VERSION \"[%.10s]\"\n", $$1}' \
191 $(SRCDIR)/../manifest.uuid >>$(OBJDIR)/VERSION.h
192 awk '$$1=="D"{printf "#define MANIFEST_DATE \"%s %s\"\n",\
193 substr($$2,1,10),substr($$2,12,8)}' \
194 $(SRCDIR)/../manifest >>$(OBJDIR)/VERSION.h
195
196 EXTRAOBJ = \
197 $(OBJDIR)/sqlite3.o \
198 $(OBJDIR)/shell.o \
199 $(OBJDIR)/th.o \
@@ -389,12 +388,12 @@
389 $(BCC) -o $(OBJDIR)/makeheaders $(SRCDIR)/makeheaders.c
390
391 $(OBJDIR)/mkindex: $(SRCDIR)/mkindex.c
392 $(BCC) -o $(OBJDIR)/mkindex $(SRCDIR)/mkindex.c
393
394 $(VERSION): $(SRCDIR)/../win/version.c
395 $(BCC) -o $(OBJDIR)/version $(SRCDIR)/../win/version.c
396
397 # WARNING. DANGER. Running the testsuite modifies the repository the
398 # build is done from, i.e. the checkout belongs to. Do not sync/push
399 # the repository after running the tests.
400 test: $(APPNAME)
@@ -556,11 +555,11 @@
556 $(BCC) -o$@ $**
557
558 mkindex$E: $(SRCDIR)\mkindex.c
559 $(BCC) -o$@ $**
560
561 version$E: $B\win\version.c
562 $(BCC) -o$@ $**
563
564 $(OBJDIR)\shell$O : $(SRCDIR)\shell.c
565 $(TCC) -o$@ -c -Dmain=sqlite3_shell $(SQLITE_OPTIONS) $**
566
@@ -669,18 +668,18 @@
669
670 all: $(OX) $(APPNAME)
671
672 $(APPNAME) : translate$E mkindex$E headers $(OBJ) $(OX)\linkopts
673 cd $(OX)
674 link -LINK -OUT:$@ $(LIBDIR) @linkopts
675
676 $(OX)\linkopts: $B\win\Makefile.msc}
677 writeln -nonewline "\techo "
678 foreach s [lsort $src] {
679 writeln -nonewline "$s "
 
680 }
681 writeln "sqlite3 th th_lang > \$@"
682 writeln "\techo \$(LIBS) >> \$@\n\n"
683
684 writeln {
685
686 $(OX):
@@ -693,15 +692,15 @@
693 $(BCC) $**
694
695 mkindex$E: $(SRCDIR)\mkindex.c
696 $(BCC) $**
697
698 version$E: $B\win\version.c
699 $(BCC) $**
700
701 $(OX)\shell$O : $(SRCDIR)\shell.c
702 $(TCC) /Fo$@ /Dmain=sqlite3_shell $(SQLITE_OPTIONS) -c shell_.c
703
704 $(OX)\sqlite3$O : $(SRCDIR)\sqlite3.c
705 $(TCC) /Fo$@ -c $(SQLITE_OPTIONS) $**
706
707 $(OX)\th$O : $(SRCDIR)\th.c
@@ -880,11 +879,11 @@
880 # compiling standard fossil utils
881 $(UTILS_OBJ): %.obj: $(SRCDIR)%.c
882 $(CC) $(CCFLAGS) $(INCLUDE) "$<" -Fo"$@"
883
884 # compile special windows utils
885 version.obj: $(WINDIR)version.c
886 $(CC) $(CCFLAGS) $(INCLUDE) "$<" -Fo"$@"
887
888 # generate the translated c-source files
889 $(TRANSLATEDSRC): %_.c: $(SRCDIR)%.c translate.exe
890 translate.exe $< >$@
891
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -176,24 +176,23 @@
176 $(BCC) -o $(OBJDIR)/makeheaders $(SRCDIR)/makeheaders.c
177
178 $(OBJDIR)/mkindex: $(SRCDIR)/mkindex.c
179 $(BCC) -o $(OBJDIR)/mkindex $(SRCDIR)/mkindex.c
180
181 $(OBJDIR)/mkversion: $(SRCDIR)/mkversion.c
182 $(BCC) -o $(OBJDIR)/mkversion $(SRCDIR)/mkversion.c
183
184 # WARNING. DANGER. Running the testsuite modifies the repository the
185 # build is done from, i.e. the checkout belongs to. Do not sync/push
186 # the repository after running the tests.
187 test: $(APPNAME)
188 $(TCLSH) test/tester.tcl $(APPNAME)
189
190 $(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION $(OBJDIR)/mkversion
191 $(OBJDIR)/mkversion $(SRCDIR)/../manifest.uuid \
192 $(SRCDIR)/../manifest \
193 $(SRCDIR)/../VERSION >$(OBJDIR)/VERSION.h
 
 
 
 
194
195 EXTRAOBJ = \
196 $(OBJDIR)/sqlite3.o \
197 $(OBJDIR)/shell.o \
198 $(OBJDIR)/th.o \
@@ -389,12 +388,12 @@
388 $(BCC) -o $(OBJDIR)/makeheaders $(SRCDIR)/makeheaders.c
389
390 $(OBJDIR)/mkindex: $(SRCDIR)/mkindex.c
391 $(BCC) -o $(OBJDIR)/mkindex $(SRCDIR)/mkindex.c
392
393 $(VERSION): $(SRCDIR)/mkversion.c
394 $(BCC) -o $(OBJDIR)/version $(SRCDIR)/mkversion.c
395
396 # WARNING. DANGER. Running the testsuite modifies the repository the
397 # build is done from, i.e. the checkout belongs to. Do not sync/push
398 # the repository after running the tests.
399 test: $(APPNAME)
@@ -556,11 +555,11 @@
555 $(BCC) -o$@ $**
556
557 mkindex$E: $(SRCDIR)\mkindex.c
558 $(BCC) -o$@ $**
559
560 version$E: $B\src\mkversion.c
561 $(BCC) -o$@ $**
562
563 $(OBJDIR)\shell$O : $(SRCDIR)\shell.c
564 $(TCC) -o$@ -c -Dmain=sqlite3_shell $(SQLITE_OPTIONS) $**
565
@@ -669,18 +668,18 @@
668
669 all: $(OX) $(APPNAME)
670
671 $(APPNAME) : translate$E mkindex$E headers $(OBJ) $(OX)\linkopts
672 cd $(OX)
673 link /NODEFAULTLIB:msvcrt -OUT:$@ $(LIBDIR) @linkopts
674
675 $(OX)\linkopts: $B\win\Makefile.msc}
676 set redir {>}
677 foreach s [lsort [concat $src {shell sqlite3 th th_lang}]] {
678 writeln "\techo \$(OX)\\$s.obj $redir \$@"
679 set redir {>>}
680 }
 
681 writeln "\techo \$(LIBS) >> \$@\n\n"
682
683 writeln {
684
685 $(OX):
@@ -693,15 +692,15 @@
692 $(BCC) $**
693
694 mkindex$E: $(SRCDIR)\mkindex.c
695 $(BCC) $**
696
697 version$E: $B\src\mkversion.c
698 $(BCC) $**
699
700 $(OX)\shell$O : $(SRCDIR)\shell.c
701 $(TCC) /Fo$@ /Dmain=sqlite3_shell $(SQLITE_OPTIONS) -c $(SRCDIR)\shell.c
702
703 $(OX)\sqlite3$O : $(SRCDIR)\sqlite3.c
704 $(TCC) /Fo$@ -c $(SQLITE_OPTIONS) $**
705
706 $(OX)\th$O : $(SRCDIR)\th.c
@@ -880,11 +879,11 @@
879 # compiling standard fossil utils
880 $(UTILS_OBJ): %.obj: $(SRCDIR)%.c
881 $(CC) $(CCFLAGS) $(INCLUDE) "$<" -Fo"$@"
882
883 # compile special windows utils
884 version.obj: $(SRCDIR)mkversion.c
885 $(CC) $(CCFLAGS) $(INCLUDE) "$<" -Fo"$@"
886
887 # generate the translated c-source files
888 $(TRANSLATEDSRC): %_.c: $(SRCDIR)%.c translate.exe
889 translate.exe $< >$@
890
+1 -1
--- src/manifest.c
+++ src/manifest.c
@@ -342,11 +342,11 @@
342342
int sz = 0;
343343
344344
/* Every control artifact ends with a '\n' character. Exit early
345345
** if that is not the case for this artifact.
346346
*/
347
- z = blob_buffer(pContent);
347
+ z = blob_materialize(pContent);
348348
n = blob_size(pContent);
349349
if( n<=0 || z[n-1]!='\n' ){
350350
blob_reset(pContent);
351351
return 0;
352352
}
353353
354354
ADDED src/mkversion.c
--- src/manifest.c
+++ src/manifest.c
@@ -342,11 +342,11 @@
342 int sz = 0;
343
344 /* Every control artifact ends with a '\n' character. Exit early
345 ** if that is not the case for this artifact.
346 */
347 z = blob_buffer(pContent);
348 n = blob_size(pContent);
349 if( n<=0 || z[n-1]!='\n' ){
350 blob_reset(pContent);
351 return 0;
352 }
353
354 DDED src/mkversion.c
--- src/manifest.c
+++ src/manifest.c
@@ -342,11 +342,11 @@
342 int sz = 0;
343
344 /* Every control artifact ends with a '\n' character. Exit early
345 ** if that is not the case for this artifact.
346 */
347 z = blob_materialize(pContent);
348 n = blob_size(pContent);
349 if( n<=0 || z[n-1]!='\n' ){
350 blob_reset(pContent);
351 return 0;
352 }
353
354 DDED src/mkversion.c
+1 -6
--- a/src/mkversion.c
+++ b/src/mkversion.c
@@ -1,10 +1,5 @@
1
-fopen(argv[1],"gv[1],exists to do the job that AWK would do for the unix
2
-** makefile - to extract information from the "mainfest" and "manifest.uuid"
3
-** files for this p)
1
+fopen(argv[1],"gv[1],"fMSC_VER)
42
d = _MSC_VER / 1 return 0;
53
}
64
b2b2,0,sizeof(b2)strcpy(b2b2b2vx[1000]return 0;
75
}
8
-;
9
- char b[1024b[strlen(b)-1] =0; return 0"gv[1],"fMSC_VER)
10
- fopen(argv[1
--- a/src/mkversion.c
+++ b/src/mkversion.c
@@ -1,10 +1,5 @@
1 fopen(argv[1],"gv[1],exists to do the job that AWK would do for the unix
2 ** makefile - to extract information from the "mainfest" and "manifest.uuid"
3 ** files for this p)
4 d = _MSC_VER / 1 return 0;
5 }
6 b2b2,0,sizeof(b2)strcpy(b2b2b2vx[1000]return 0;
7 }
8 ;
9 char b[1024b[strlen(b)-1] =0; return 0"gv[1],"fMSC_VER)
10 fopen(argv[1
--- a/src/mkversion.c
+++ b/src/mkversion.c
@@ -1,10 +1,5 @@
1 fopen(argv[1],"gv[1],"fMSC_VER)
 
 
2 d = _MSC_VER / 1 return 0;
3 }
4 b2b2,0,sizeof(b2)strcpy(b2b2b2vx[1000]return 0;
5 }
 
 
 
--- a/src/mkversion.c
+++ b/src/mkversion.c
@@ -0,0 +1,5 @@
1
+fopen(argv[1],"gv[1],"fMSC_VER)
2
+ d = _MSC_VER / 1 return 0;
3
+}
4
+b2b2,0,sizeof(b2)strcpy(b2b2b2vx[1000]return 0;
5
+}
--- a/src/mkversion.c
+++ b/src/mkversion.c
@@ -0,0 +1,5 @@
 
 
 
 
 
--- a/src/mkversion.c
+++ b/src/mkversion.c
@@ -0,0 +1,5 @@
1 fopen(argv[1],"gv[1],"fMSC_VER)
2 d = _MSC_VER / 1 return 0;
3 }
4 b2b2,0,sizeof(b2)strcpy(b2b2b2vx[1000]return 0;
5 }
+1 -1
--- src/path.c
+++ src/path.c
@@ -366,11 +366,11 @@
366366
367367
*pnChng = 0;
368368
*aiChng = 0;
369369
if( iFrom==iTo ) return;
370370
path_reset();
371
- p = path_shortest(iFrom, iTo, 0);
371
+ p = path_shortest(iFrom, iTo, 1);
372372
if( p==0 ) return;
373373
path_reverse_path();
374374
db_prepare(&q1,
375375
"SELECT pfnid, fnid FROM mlink WHERE mid=:mid AND pfnid>0"
376376
);
377377
--- src/path.c
+++ src/path.c
@@ -366,11 +366,11 @@
366
367 *pnChng = 0;
368 *aiChng = 0;
369 if( iFrom==iTo ) return;
370 path_reset();
371 p = path_shortest(iFrom, iTo, 0);
372 if( p==0 ) return;
373 path_reverse_path();
374 db_prepare(&q1,
375 "SELECT pfnid, fnid FROM mlink WHERE mid=:mid AND pfnid>0"
376 );
377
--- src/path.c
+++ src/path.c
@@ -366,11 +366,11 @@
366
367 *pnChng = 0;
368 *aiChng = 0;
369 if( iFrom==iTo ) return;
370 path_reset();
371 p = path_shortest(iFrom, iTo, 1);
372 if( p==0 ) return;
373 path_reverse_path();
374 db_prepare(&q1,
375 "SELECT pfnid, fnid FROM mlink WHERE mid=:mid AND pfnid>0"
376 );
377
--- src/rebuild.c
+++ src/rebuild.c
@@ -748,10 +748,14 @@
748748
}
749749
if( !privateOnly ){
750750
db_multi_exec(
751751
"UPDATE user SET pw='';"
752752
"DELETE FROM config WHERE name GLOB 'last-sync-*';"
753
+ "DELETE FROM config WHERE name GLOB 'peer-*';"
754
+ "DELETE FROM config WHERE name GLOB 'login-group-*';"
755
+ "DELETE FROM config WHERE name GLOB 'skin:*';"
756
+ "DELETE FROM config WHERE name GLOB 'subrepo:*';"
753757
);
754758
if( bVerily ){
755759
db_multi_exec(
756760
"DELETE FROM concealed;"
757761
"UPDATE rcvfrom SET ipaddr='unknown';"
758762
--- src/rebuild.c
+++ src/rebuild.c
@@ -748,10 +748,14 @@
748 }
749 if( !privateOnly ){
750 db_multi_exec(
751 "UPDATE user SET pw='';"
752 "DELETE FROM config WHERE name GLOB 'last-sync-*';"
 
 
 
 
753 );
754 if( bVerily ){
755 db_multi_exec(
756 "DELETE FROM concealed;"
757 "UPDATE rcvfrom SET ipaddr='unknown';"
758
--- src/rebuild.c
+++ src/rebuild.c
@@ -748,10 +748,14 @@
748 }
749 if( !privateOnly ){
750 db_multi_exec(
751 "UPDATE user SET pw='';"
752 "DELETE FROM config WHERE name GLOB 'last-sync-*';"
753 "DELETE FROM config WHERE name GLOB 'peer-*';"
754 "DELETE FROM config WHERE name GLOB 'login-group-*';"
755 "DELETE FROM config WHERE name GLOB 'skin:*';"
756 "DELETE FROM config WHERE name GLOB 'subrepo:*';"
757 );
758 if( bVerily ){
759 db_multi_exec(
760 "DELETE FROM concealed;"
761 "UPDATE rcvfrom SET ipaddr='unknown';"
762
+2822 -1836
--- src/sqlite3.c
+++ src/sqlite3.c
@@ -650,11 +650,11 @@
650650
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
651651
** [sqlite_version()] and [sqlite_source_id()].
652652
*/
653653
#define SQLITE_VERSION "3.7.7"
654654
#define SQLITE_VERSION_NUMBER 3007007
655
-#define SQLITE_SOURCE_ID "2011-06-03 14:19:10 0206bc6f87bb9393218a380fc5b18039d334a8d8"
655
+#define SQLITE_SOURCE_ID "2011-06-15 13:11:06 f9750870ee04935f338e4d808900fee5a8b2b389"
656656
657657
/*
658658
** CAPI3REF: Run-Time Library Version Numbers
659659
** KEYWORDS: sqlite3_version, sqlite3_sourceid
660660
**
@@ -8483,10 +8483,11 @@
84838483
SQLITE_PRIVATE int sqlite3VdbeAddOp2(Vdbe*,int,int,int);
84848484
SQLITE_PRIVATE int sqlite3VdbeAddOp3(Vdbe*,int,int,int,int);
84858485
SQLITE_PRIVATE int sqlite3VdbeAddOp4(Vdbe*,int,int,int,int,const char *zP4,int);
84868486
SQLITE_PRIVATE int sqlite3VdbeAddOp4Int(Vdbe*,int,int,int,int,int);
84878487
SQLITE_PRIVATE int sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp);
8488
+SQLITE_PRIVATE void sqlite3VdbeAddParseSchemaOp(Vdbe*,int,char*);
84888489
SQLITE_PRIVATE void sqlite3VdbeChangeP1(Vdbe*, int addr, int P1);
84898490
SQLITE_PRIVATE void sqlite3VdbeChangeP2(Vdbe*, int addr, int P2);
84908491
SQLITE_PRIVATE void sqlite3VdbeChangeP3(Vdbe*, int addr, int P3);
84918492
SQLITE_PRIVATE void sqlite3VdbeChangeP5(Vdbe*, u8 P5);
84928493
SQLITE_PRIVATE void sqlite3VdbeJumpHere(Vdbe*, int addr);
@@ -9282,11 +9283,11 @@
92829283
** sqlite3_close().
92839284
*
92849285
** A thread must be holding a mutex on the corresponding Btree in order
92859286
** to access Schema content. This implies that the thread must also be
92869287
** holding a mutex on the sqlite3 connection pointer that owns the Btree.
9287
-** For a TEMP Schema, on the connection mutex is required.
9288
+** For a TEMP Schema, only the connection mutex is required.
92889289
*/
92899290
struct Schema {
92909291
int schema_cookie; /* Database schema version number for this file */
92919292
int iGeneration; /* Generation counter. Incremented with each change */
92929293
Hash tblHash; /* All tables indexed by name */
@@ -11479,11 +11480,11 @@
1147911480
SQLITE_PRIVATE int sqlite3AtoF(const char *z, double*, int, u8);
1148011481
SQLITE_PRIVATE int sqlite3GetInt32(const char *, int*);
1148111482
SQLITE_PRIVATE int sqlite3Atoi(const char*);
1148211483
SQLITE_PRIVATE int sqlite3Utf16ByteLen(const void *pData, int nChar);
1148311484
SQLITE_PRIVATE int sqlite3Utf8CharLen(const char *pData, int nByte);
11484
-SQLITE_PRIVATE int sqlite3Utf8Read(const u8*, const u8**);
11485
+SQLITE_PRIVATE u32 sqlite3Utf8Read(const u8*, const u8**);
1148511486
1148611487
/*
1148711488
** Routines to read and write variable-length integers. These used to
1148811489
** be defined locally, but now we use the varint routines in the util.c
1148911490
** file. Code should use the MACRO forms below, as the Varint32 versions
@@ -20086,11 +20087,11 @@
2008620087
} \
2008720088
if( c<0x80 \
2008820089
|| (c&0xFFFFF800)==0xD800 \
2008920090
|| (c&0xFFFFFFFE)==0xFFFE ){ c = 0xFFFD; } \
2009020091
}
20091
-SQLITE_PRIVATE int sqlite3Utf8Read(
20092
+SQLITE_PRIVATE u32 sqlite3Utf8Read(
2009220093
const unsigned char *zIn, /* First byte of UTF-8 character */
2009320094
const unsigned char **pzNext /* Write first byte past UTF-8 char here */
2009420095
){
2009520096
unsigned int c;
2009620097
@@ -35805,11 +35806,11 @@
3580535806
memset(pCache, 0, sz);
3580635807
if( separateCache ){
3580735808
pGroup = (PGroup*)&pCache[1];
3580835809
pGroup->mxPinned = 10;
3580935810
}else{
35810
- pGroup = &pcache1_g.grp;
35811
+ pGroup = &pcache1.grp;
3581135812
}
3581235813
pCache->pGroup = pGroup;
3581335814
pCache->szPage = szPage;
3581435815
pCache->bPurgeable = (bPurgeable ? 1 : 0);
3581535816
if( bPurgeable ){
@@ -48324,10 +48325,12 @@
4832448325
**
4832548326
** This routine works only for pages that do not contain overflow cells.
4832648327
*/
4832748328
#define findCell(P,I) \
4832848329
((P)->aData + ((P)->maskPage & get2byte(&(P)->aData[(P)->cellOffset+2*(I)])))
48330
+#define findCellv2(D,M,O,I) (D+(M&get2byte(D+(O+2*(I)))))
48331
+
4832948332
4833048333
/*
4833148334
** This a more complex version of findCell() that works for
4833248335
** pages that do contain overflow cells.
4833348336
*/
@@ -51918,11 +51921,11 @@
5191851921
assert( pCur->apPage[pCur->iPage]->nCell==0 );
5191951922
return SQLITE_OK;
5192051923
}
5192151924
assert( pCur->apPage[0]->intKey || pIdxKey );
5192251925
for(;;){
51923
- int lwr, upr;
51926
+ int lwr, upr, idx;
5192451927
Pgno chldPg;
5192551928
MemPage *pPage = pCur->apPage[pCur->iPage];
5192651929
int c;
5192751930
5192851931
/* pPage->nCell must be greater than zero. If this is the root-page
@@ -51934,18 +51937,18 @@
5193451937
assert( pPage->nCell>0 );
5193551938
assert( pPage->intKey==(pIdxKey==0) );
5193651939
lwr = 0;
5193751940
upr = pPage->nCell-1;
5193851941
if( biasRight ){
51939
- pCur->aiIdx[pCur->iPage] = (u16)upr;
51942
+ pCur->aiIdx[pCur->iPage] = (u16)(idx = upr);
5194051943
}else{
51941
- pCur->aiIdx[pCur->iPage] = (u16)((upr+lwr)/2);
51944
+ pCur->aiIdx[pCur->iPage] = (u16)(idx = (upr+lwr)/2);
5194251945
}
5194351946
for(;;){
51944
- int idx = pCur->aiIdx[pCur->iPage]; /* Index of current cell in pPage */
5194551947
u8 *pCell; /* Pointer to current cell in pPage */
5194651948
51949
+ assert( idx==pCur->aiIdx[pCur->iPage] );
5194751950
pCur->info.nSize = 0;
5194851951
pCell = findCell(pPage, idx) + pPage->childPtrSize;
5194951952
if( pPage->intKey ){
5195051953
i64 nCellKey;
5195151954
if( pPage->hasData ){
@@ -52024,11 +52027,11 @@
5202452027
upr = idx-1;
5202552028
}
5202652029
if( lwr>upr ){
5202752030
break;
5202852031
}
52029
- pCur->aiIdx[pCur->iPage] = (u16)((lwr+upr)/2);
52032
+ pCur->aiIdx[pCur->iPage] = (u16)(idx = (lwr+upr)/2);
5203052033
}
5203152034
assert( lwr==upr+1 );
5203252035
assert( pPage->isInit );
5203352036
if( pPage->leaf ){
5203452037
chldPg = 0;
@@ -52886,13 +52889,13 @@
5288652889
if( rc ){
5288752890
*pRC = rc;
5288852891
return;
5288952892
}
5289052893
endPtr = &data[pPage->cellOffset + 2*pPage->nCell - 2];
52894
+ assert( (SQLITE_PTR_TO_INT(ptr)&1)==0 ); /* ptr is always 2-byte aligned */
5289152895
while( ptr<endPtr ){
52892
- ptr[0] = ptr[2];
52893
- ptr[1] = ptr[3];
52896
+ *(u16*)ptr = *(u16*)&ptr[2];
5289452897
ptr += 2;
5289552898
}
5289652899
pPage->nCell--;
5289752900
put2byte(&data[hdr+3], pPage->nCell);
5289852901
pPage->nFree += 2;
@@ -52929,10 +52932,11 @@
5292952932
int end; /* First byte past the last cell pointer in data[] */
5293052933
int ins; /* Index in data[] where new cell pointer is inserted */
5293152934
int cellOffset; /* Address of first cell pointer in data[] */
5293252935
u8 *data; /* The content of the whole page */
5293352936
u8 *ptr; /* Used for moving information around in data[] */
52937
+ u8 *endPtr; /* End of the loop */
5293452938
5293552939
int nSkip = (iChild ? 4 : 0);
5293652940
5293752941
if( *pRC ) return;
5293852942
@@ -52979,13 +52983,16 @@
5297952983
pPage->nFree -= (u16)(2 + sz);
5298052984
memcpy(&data[idx+nSkip], pCell+nSkip, sz-nSkip);
5298152985
if( iChild ){
5298252986
put4byte(&data[idx], iChild);
5298352987
}
52984
- for(j=end, ptr=&data[j]; j>ins; j-=2, ptr-=2){
52985
- ptr[0] = ptr[-2];
52986
- ptr[1] = ptr[-1];
52988
+ ptr = &data[end];
52989
+ endPtr = &data[ins];
52990
+ assert( (SQLITE_PTR_TO_INT(ptr)&1)==0 ); /* ptr is always 2-byte aligned */
52991
+ while( ptr>endPtr ){
52992
+ *(u16*)ptr = *(u16*)&ptr[-2];
52993
+ ptr -= 2;
5298752994
}
5298852995
put2byte(&data[ins], idx);
5298952996
put2byte(&data[pPage->hdrOffset+3], pPage->nCell);
5299052997
#ifndef SQLITE_OMIT_AUTOVACUUM
5299152998
if( pPage->pBt->autoVacuum ){
@@ -53026,14 +53033,15 @@
5302653033
assert( get2byteNotZero(&data[hdr+5])==nUsable );
5302753034
5302853035
pCellptr = &data[pPage->cellOffset + nCell*2];
5302953036
cellbody = nUsable;
5303053037
for(i=nCell-1; i>=0; i--){
53038
+ u16 sz = aSize[i];
5303153039
pCellptr -= 2;
53032
- cellbody -= aSize[i];
53040
+ cellbody -= sz;
5303353041
put2byte(pCellptr, cellbody);
53034
- memcpy(&data[cellbody], apCell[i], aSize[i]);
53042
+ memcpy(&data[cellbody], apCell[i], sz);
5303553043
}
5303653044
put2byte(&data[hdr+3], nCell);
5303753045
put2byte(&data[hdr+5], cellbody);
5303853046
pPage->nFree -= (nCell*2 + nUsable - cellbody);
5303953047
pPage->nCell = (u16)nCell;
@@ -53483,16 +53491,28 @@
5348353491
memcpy(pOld, apOld[i], sizeof(MemPage));
5348453492
pOld->aData = (void*)&pOld[1];
5348553493
memcpy(pOld->aData, apOld[i]->aData, pBt->pageSize);
5348653494
5348753495
limit = pOld->nCell+pOld->nOverflow;
53488
- for(j=0; j<limit; j++){
53489
- assert( nCell<nMaxCells );
53490
- apCell[nCell] = findOverflowCell(pOld, j);
53491
- szCell[nCell] = cellSizePtr(pOld, apCell[nCell]);
53492
- nCell++;
53493
- }
53496
+ if( pOld->nOverflow>0 ){
53497
+ for(j=0; j<limit; j++){
53498
+ assert( nCell<nMaxCells );
53499
+ apCell[nCell] = findOverflowCell(pOld, j);
53500
+ szCell[nCell] = cellSizePtr(pOld, apCell[nCell]);
53501
+ nCell++;
53502
+ }
53503
+ }else{
53504
+ u8 *aData = pOld->aData;
53505
+ u16 maskPage = pOld->maskPage;
53506
+ u16 cellOffset = pOld->cellOffset;
53507
+ for(j=0; j<limit; j++){
53508
+ assert( nCell<nMaxCells );
53509
+ apCell[nCell] = findCellv2(aData, maskPage, cellOffset, j);
53510
+ szCell[nCell] = cellSizePtr(pOld, apCell[nCell]);
53511
+ nCell++;
53512
+ }
53513
+ }
5349453514
if( i<nOld-1 && !leafData){
5349553515
u16 sz = (u16)szNew[i];
5349653516
u8 *pTemp;
5349753517
assert( nCell<nMaxCells );
5349853518
szCell[nCell] = sz;
@@ -57637,17 +57657,10 @@
5763757657
pOp->p1 = p1;
5763857658
pOp->p2 = p2;
5763957659
pOp->p3 = p3;
5764057660
pOp->p4.p = 0;
5764157661
pOp->p4type = P4_NOTUSED;
57642
- p->expired = 0;
57643
- if( op==OP_ParseSchema ){
57644
- /* Any program that uses the OP_ParseSchema opcode needs to lock
57645
- ** all btrees. */
57646
- int j;
57647
- for(j=0; j<p->db->nDb; j++) sqlite3VdbeUsesBtree(p, j);
57648
- }
5764957662
#ifdef SQLITE_DEBUG
5765057663
pOp->zComment = 0;
5765157664
if( sqlite3VdbeAddopTrace ) sqlite3VdbePrintOp(0, i, &p->aOp[i]);
5765257665
#endif
5765357666
#ifdef VDBE_PROFILE
@@ -57681,10 +57694,24 @@
5768157694
){
5768257695
int addr = sqlite3VdbeAddOp3(p, op, p1, p2, p3);
5768357696
sqlite3VdbeChangeP4(p, addr, zP4, p4type);
5768457697
return addr;
5768557698
}
57699
+
57700
+/*
57701
+** Add an OP_ParseSchema opcode. This routine is broken out from
57702
+** sqlite3VdbeAddOp4() since it needs to also local all btrees.
57703
+**
57704
+** The zWhere string must have been obtained from sqlite3_malloc().
57705
+** This routine will take ownership of the allocated memory.
57706
+*/
57707
+SQLITE_PRIVATE void sqlite3VdbeAddParseSchemaOp(Vdbe *p, int iDb, char *zWhere){
57708
+ int j;
57709
+ int addr = sqlite3VdbeAddOp3(p, OP_ParseSchema, iDb, 0, 0);
57710
+ sqlite3VdbeChangeP4(p, addr, zWhere, P4_DYNAMIC);
57711
+ for(j=0; j<p->db->nDb; j++) sqlite3VdbeUsesBtree(p, j);
57712
+}
5768657713
5768757714
/*
5768857715
** Add an opcode that includes the p4 value as an integer.
5768957716
*/
5769057717
SQLITE_PRIVATE int sqlite3VdbeAddOp4Int(
@@ -64083,10 +64110,20 @@
6408364110
u.ag.ctx.pColl = pOp[-1].p4.pColl;
6408464111
}
6408564112
db->lastRowid = lastRowid;
6408664113
(*u.ag.ctx.pFunc->xFunc)(&u.ag.ctx, u.ag.n, u.ag.apVal); /* IMP: R-24505-23230 */
6408764114
lastRowid = db->lastRowid;
64115
+
64116
+ /* If any auxiliary data functions have been called by this user function,
64117
+ ** immediately call the destructor for any non-static values.
64118
+ */
64119
+ if( u.ag.ctx.pVdbeFunc ){
64120
+ sqlite3VdbeDeleteAuxData(u.ag.ctx.pVdbeFunc, pOp->p1);
64121
+ pOp->p4.pVdbeFunc = u.ag.ctx.pVdbeFunc;
64122
+ pOp->p4type = P4_VDBEFUNC;
64123
+ }
64124
+
6408864125
if( db->mallocFailed ){
6408964126
/* Even though a malloc() has failed, the implementation of the
6409064127
** user function may have called an sqlite3_result_XXX() function
6409164128
** to return a value. The following call releases any resources
6409264129
** associated with such a value.
@@ -64093,19 +64130,10 @@
6409364130
*/
6409464131
sqlite3VdbeMemRelease(&u.ag.ctx.s);
6409564132
goto no_mem;
6409664133
}
6409764134
64098
- /* If any auxiliary data functions have been called by this user function,
64099
- ** immediately call the destructor for any non-static values.
64100
- */
64101
- if( u.ag.ctx.pVdbeFunc ){
64102
- sqlite3VdbeDeleteAuxData(u.ag.ctx.pVdbeFunc, pOp->p1);
64103
- pOp->p4.pVdbeFunc = u.ag.ctx.pVdbeFunc;
64104
- pOp->p4type = P4_VDBEFUNC;
64105
- }
64106
-
6410764135
/* If the function returned an error, throw an exception */
6410864136
if( u.ag.ctx.isError ){
6410964137
sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(&u.ag.ctx.s));
6411064138
rc = u.ag.ctx.isError;
6411164139
}
@@ -75255,18 +75283,18 @@
7525575283
sqlite3VdbeAddOp4(v, OP_DropTable, iDb, 0, 0, pTab->zName, 0);
7525675284
7525775285
/* Reload the table, index and permanent trigger schemas. */
7525875286
zWhere = sqlite3MPrintf(pParse->db, "tbl_name=%Q", zName);
7525975287
if( !zWhere ) return;
75260
- sqlite3VdbeAddOp4(v, OP_ParseSchema, iDb, 0, 0, zWhere, P4_DYNAMIC);
75288
+ sqlite3VdbeAddParseSchemaOp(v, iDb, zWhere);
7526175289
7526275290
#ifndef SQLITE_OMIT_TRIGGER
7526375291
/* Now, if the table is not stored in the temp database, reload any temp
7526475292
** triggers. Don't use IN(...) in case SQLITE_OMIT_SUBQUERY is defined.
7526575293
*/
7526675294
if( (zWhere=whereTempTriggers(pParse, pTab))!=0 ){
75267
- sqlite3VdbeAddOp4(v, OP_ParseSchema, 1, 0, 0, zWhere, P4_DYNAMIC);
75295
+ sqlite3VdbeAddParseSchemaOp(v, 1, zWhere);
7526875296
}
7526975297
#endif
7527075298
}
7527175299
7527275300
/*
@@ -78875,12 +78903,12 @@
7887578903
}
7887678904
}
7887778905
#endif
7887878906
7887978907
/* Reparse everything to update our internal data structures */
78880
- sqlite3VdbeAddOp4(v, OP_ParseSchema, iDb, 0, 0,
78881
- sqlite3MPrintf(db, "tbl_name='%q'",p->zName), P4_DYNAMIC);
78908
+ sqlite3VdbeAddParseSchemaOp(v, iDb,
78909
+ sqlite3MPrintf(db, "tbl_name='%q'", p->zName));
7888278910
}
7888378911
7888478912
7888578913
/* Add the table to the in-memory representation of the database.
7888678914
*/
@@ -80073,13 +80101,12 @@
8007380101
** to invalidate all pre-compiled statements.
8007480102
*/
8007580103
if( pTblName ){
8007680104
sqlite3RefillIndex(pParse, pIndex, iMem);
8007780105
sqlite3ChangeCookie(pParse, iDb);
80078
- sqlite3VdbeAddOp4(v, OP_ParseSchema, iDb, 0, 0,
80079
- sqlite3MPrintf(db, "name='%q' AND type='index'", pIndex->zName),
80080
- P4_DYNAMIC);
80106
+ sqlite3VdbeAddParseSchemaOp(v, iDb,
80107
+ sqlite3MPrintf(db, "name='%q' AND type='index'", pIndex->zName));
8008180108
sqlite3VdbeAddOp1(v, OP_Expire, 0);
8008280109
}
8008380110
}
8008480111
8008580112
/* When adding an index to the list of indices for a table, make
@@ -82621,14 +82648,14 @@
8262182648
** character is exactly one byte in size. Also, all characters are
8262282649
** able to participate in upper-case-to-lower-case mappings in EBCDIC
8262382650
** whereas only characters less than 0x80 do in ASCII.
8262482651
*/
8262582652
#if defined(SQLITE_EBCDIC)
82626
-# define sqlite3Utf8Read(A,C) (*(A++))
82627
-# define GlogUpperToLower(A) A = sqlite3UpperToLower[A]
82653
+# define sqlite3Utf8Read(A,C) (*(A++))
82654
+# define GlogUpperToLower(A) A = sqlite3UpperToLower[A]
8262882655
#else
82629
-# define GlogUpperToLower(A) if( A<0x80 ){ A = sqlite3UpperToLower[A]; }
82656
+# define GlogUpperToLower(A) if( !((A)&~0x7f) ){ A = sqlite3UpperToLower[A]; }
8263082657
#endif
8263182658
8263282659
static const struct compareInfo globInfo = { '*', '?', '[', 0 };
8263382660
/* The correct SQL-92 behavior is for the LIKE operator to ignore
8263482661
** case. Thus 'a' LIKE 'A' would be true. */
@@ -82667,13 +82694,13 @@
8266782694
*/
8266882695
static int patternCompare(
8266982696
const u8 *zPattern, /* The glob pattern */
8267082697
const u8 *zString, /* The string to compare against the glob */
8267182698
const struct compareInfo *pInfo, /* Information about how to do the compare */
82672
- const int esc /* The escape character */
82699
+ u32 esc /* The escape character */
8267382700
){
82674
- int c, c2;
82701
+ u32 c, c2;
8267582702
int invert;
8267682703
int seen;
8267782704
u8 matchOne = pInfo->matchOne;
8267882705
u8 matchAll = pInfo->matchAll;
8267982706
u8 matchSet = pInfo->matchSet;
@@ -82723,11 +82750,11 @@
8272382750
}else if( !prevEscape && c==matchOne ){
8272482751
if( sqlite3Utf8Read(zString, &zString)==0 ){
8272582752
return 0;
8272682753
}
8272782754
}else if( c==matchSet ){
82728
- int prior_c = 0;
82755
+ u32 prior_c = 0;
8272982756
assert( esc==0 ); /* This only occurs for GLOB, not LIKE */
8273082757
seen = 0;
8273182758
invert = 0;
8273282759
c = sqlite3Utf8Read(zString, &zString);
8273382760
if( c==0 ) return 0;
@@ -82799,11 +82826,11 @@
8279982826
sqlite3_context *context,
8280082827
int argc,
8280182828
sqlite3_value **argv
8280282829
){
8280382830
const unsigned char *zA, *zB;
82804
- int escape = 0;
82831
+ u32 escape = 0;
8280582832
int nPat;
8280682833
sqlite3 *db = sqlite3_context_db_handle(context);
8280782834
8280882835
zB = sqlite3_value_text(argv[0]);
8280982836
zA = sqlite3_value_text(argv[1]);
@@ -84110,17 +84137,29 @@
8411084137
}
8411184138
8411284139
/* If the parent table is the same as the child table, and we are about
8411384140
** to increment the constraint-counter (i.e. this is an INSERT operation),
8411484141
** then check if the row being inserted matches itself. If so, do not
84115
- ** increment the constraint-counter. */
84142
+ ** increment the constraint-counter.
84143
+ **
84144
+ ** If any of the parent-key values are NULL, then the row cannot match
84145
+ ** itself. So set JUMPIFNULL to make sure we do the OP_Found if any
84146
+ ** of the parent-key values are NULL (at this point it is known that
84147
+ ** none of the child key values are).
84148
+ */
8411684149
if( pTab==pFKey->pFrom && nIncr==1 ){
8411784150
int iJump = sqlite3VdbeCurrentAddr(v) + nCol + 1;
8411884151
for(i=0; i<nCol; i++){
8411984152
int iChild = aiCol[i]+1+regData;
8412084153
int iParent = pIdx->aiColumn[i]+1+regData;
84154
+ assert( aiCol[i]!=pTab->iPKey );
84155
+ if( pIdx->aiColumn[i]==pTab->iPKey ){
84156
+ /* The parent key is a composite key that includes the IPK column */
84157
+ iParent = regData;
84158
+ }
8412184159
sqlite3VdbeAddOp3(v, OP_Ne, iChild, iJump, iParent);
84160
+ sqlite3VdbeChangeP5(v, SQLITE_JUMPIFNULL);
8412284161
}
8412384162
sqlite3VdbeAddOp2(v, OP_Goto, 0, iOk);
8412484163
}
8412584164
8412684165
sqlite3VdbeAddOp3(v, OP_MakeRecord, regTemp, nCol, regRec);
@@ -95336,13 +95375,12 @@
9533695375
"INSERT INTO %Q.%s VALUES('trigger',%Q,%Q,0,'CREATE TRIGGER %q')",
9533795376
db->aDb[iDb].zName, SCHEMA_TABLE(iDb), zName,
9533895377
pTrig->table, z);
9533995378
sqlite3DbFree(db, z);
9534095379
sqlite3ChangeCookie(pParse, iDb);
95341
- sqlite3VdbeAddOp4(v, OP_ParseSchema, iDb, 0, 0, sqlite3MPrintf(
95342
- db, "type='trigger' AND name='%q'", zName), P4_DYNAMIC
95343
- );
95380
+ sqlite3VdbeAddParseSchemaOp(v, iDb,
95381
+ sqlite3MPrintf(db, "type='trigger' AND name='%q'", zName));
9534495382
}
9534595383
9534695384
if( db->init.busy ){
9534795385
Trigger *pLink = pTrig;
9534895386
Hash *pHash = &db->aDb[iDb].pSchema->trigHash;
@@ -96392,11 +96430,11 @@
9639296430
aRegIdx = sqlite3DbMallocRaw(db, sizeof(Index*) * nIdx );
9639396431
if( aRegIdx==0 ) goto update_cleanup;
9639496432
}
9639596433
for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
9639696434
int reg;
96397
- if( chngRowid ){
96435
+ if( hasFK || chngRowid ){
9639896436
reg = ++pParse->nMem;
9639996437
}else{
9640096438
reg = 0;
9640196439
for(i=0; i<pIdx->nColumn; i++){
9640296440
if( aXRef[pIdx->aiColumn[i]]>=0 ){
@@ -97547,11 +97585,11 @@
9754797585
v = sqlite3GetVdbe(pParse);
9754897586
sqlite3ChangeCookie(pParse, iDb);
9754997587
9755097588
sqlite3VdbeAddOp2(v, OP_Expire, 0, 0);
9755197589
zWhere = sqlite3MPrintf(db, "name='%q' AND type='table'", pTab->zName);
97552
- sqlite3VdbeAddOp4(v, OP_ParseSchema, iDb, 0, 0, zWhere, P4_DYNAMIC);
97590
+ sqlite3VdbeAddParseSchemaOp(v, iDb, zWhere);
9755397591
sqlite3VdbeAddOp4(v, OP_VCreate, iDb, 0, 0,
9755497592
pTab->zName, sqlite3Strlen30(pTab->zName) + 1);
9755597593
}
9755697594
9755797595
/* If we are rereading the sqlite_master table create the in-memory
@@ -107274,17 +107312,16 @@
107274107312
#ifndef SQLITE_OMIT_BLOB_LITERAL
107275107313
case 'x': case 'X': {
107276107314
testcase( z[0]=='x' ); testcase( z[0]=='X' );
107277107315
if( z[1]=='\'' ){
107278107316
*tokenType = TK_BLOB;
107279
- for(i=2; (c=z[i])!=0 && c!='\''; i++){
107280
- if( !sqlite3Isxdigit(c) ){
107281
- *tokenType = TK_ILLEGAL;
107282
- }
107317
+ for(i=2; sqlite3Isxdigit(z[i]); i++){}
107318
+ if( z[i]!='\'' || i%2 ){
107319
+ *tokenType = TK_ILLEGAL;
107320
+ while( z[i] && z[i]!='\'' ){ i++; }
107283107321
}
107284
- if( i%2 || !c ) *tokenType = TK_ILLEGAL;
107285
- if( c ) i++;
107322
+ if( z[i] ) i++;
107286107323
return i;
107287107324
}
107288107325
/* Otherwise fall through to the next case */
107289107326
}
107290107327
#endif
@@ -111710,16 +111747,39 @@
111710111747
** similar macro called ArraySize(). Use a different name to avoid
111711111748
** a collision when building an amalgamation with built-in FTS3.
111712111749
*/
111713111750
#define SizeofArray(X) ((int)(sizeof(X)/sizeof(X[0])))
111714111751
111752
+
111753
+#ifndef MIN
111754
+# define MIN(x,y) ((x)<(y)?(x):(y))
111755
+#endif
111756
+
111715111757
/*
111716111758
** Maximum length of a varint encoded integer. The varint format is different
111717111759
** from that used by SQLite, so the maximum length is 10, not 9.
111718111760
*/
111719111761
#define FTS3_VARINT_MAX 10
111720111762
111763
+/*
111764
+** FTS4 virtual tables may maintain multiple indexes - one index of all terms
111765
+** in the document set and zero or more prefix indexes. All indexes are stored
111766
+** as one or more b+-trees in the %_segments and %_segdir tables.
111767
+**
111768
+** It is possible to determine which index a b+-tree belongs to based on the
111769
+** value stored in the "%_segdir.level" column. Given this value L, the index
111770
+** that the b+-tree belongs to is (L<<10). In other words, all b+-trees with
111771
+** level values between 0 and 1023 (inclusive) belong to index 0, all levels
111772
+** between 1024 and 2047 to index 1, and so on.
111773
+**
111774
+** It is considered impossible for an index to use more than 1024 levels. In
111775
+** theory though this may happen, but only after at least
111776
+** (FTS3_MERGE_COUNT^1024) separate flushes of the pending-terms tables.
111777
+*/
111778
+#define FTS3_SEGDIR_MAXLEVEL 1024
111779
+#define FTS3_SEGDIR_MAXLEVEL_STR "1024"
111780
+
111721111781
/*
111722111782
** The testcase() macro is only used by the amalgamation. If undefined,
111723111783
** make it a no-op.
111724111784
*/
111725111785
#ifndef testcase
@@ -111787,14 +111847,15 @@
111787111847
typedef struct Fts3Cursor Fts3Cursor;
111788111848
typedef struct Fts3Expr Fts3Expr;
111789111849
typedef struct Fts3Phrase Fts3Phrase;
111790111850
typedef struct Fts3PhraseToken Fts3PhraseToken;
111791111851
111852
+typedef struct Fts3Doclist Fts3Doclist;
111792111853
typedef struct Fts3SegFilter Fts3SegFilter;
111793111854
typedef struct Fts3DeferredToken Fts3DeferredToken;
111794111855
typedef struct Fts3SegReader Fts3SegReader;
111795
-typedef struct Fts3SegReaderCursor Fts3SegReaderCursor;
111856
+typedef struct Fts3MultiSegReader Fts3MultiSegReader;
111796111857
111797111858
/*
111798111859
** A connection to a fulltext index is an instance of the following
111799111860
** structure. The xCreate and xConnect methods create an instance
111800111861
** of this structure and xDestroy and xDisconnect free that instance.
@@ -111811,33 +111872,45 @@
111811111872
sqlite3_tokenizer *pTokenizer; /* tokenizer for inserts and queries */
111812111873
111813111874
/* Precompiled statements used by the implementation. Each of these
111814111875
** statements is run and reset within a single virtual table API call.
111815111876
*/
111816
- sqlite3_stmt *aStmt[24];
111877
+ sqlite3_stmt *aStmt[27];
111817111878
111818111879
char *zReadExprlist;
111819111880
char *zWriteExprlist;
111820111881
111821111882
int nNodeSize; /* Soft limit for node size */
111822111883
u8 bHasStat; /* True if %_stat table exists */
111823111884
u8 bHasDocsize; /* True if %_docsize table exists */
111885
+ u8 bDescIdx; /* True if doclists are in reverse order */
111824111886
int nPgsz; /* Page size for host database */
111825111887
char *zSegmentsTbl; /* Name of %_segments table */
111826111888
sqlite3_blob *pSegments; /* Blob handle open on %_segments table */
111827111889
111828
- /* The following hash table is used to buffer pending index updates during
111890
+ /* TODO: Fix the first paragraph of this comment.
111891
+ **
111892
+ ** The following hash table is used to buffer pending index updates during
111829111893
** transactions. Variable nPendingData estimates the memory size of the
111830111894
** pending data, including hash table overhead, but not malloc overhead.
111831111895
** When nPendingData exceeds nMaxPendingData, the buffer is flushed
111832111896
** automatically. Variable iPrevDocid is the docid of the most recently
111833111897
** inserted record.
111898
+ **
111899
+ ** A single FTS4 table may have multiple full-text indexes. For each index
111900
+ ** there is an entry in the aIndex[] array. Index 0 is an index of all the
111901
+ ** terms that appear in the document set. Each subsequent index in aIndex[]
111902
+ ** is an index of prefixes of a specific length.
111834111903
*/
111835
- int nMaxPendingData;
111836
- int nPendingData;
111837
- sqlite_int64 iPrevDocid;
111838
- Fts3Hash pendingTerms;
111904
+ int nIndex; /* Size of aIndex[] */
111905
+ struct Fts3Index {
111906
+ int nPrefix; /* Prefix length (0 for main terms index) */
111907
+ Fts3Hash hPending; /* Pending terms table for this index */
111908
+ } *aIndex;
111909
+ int nMaxPendingData; /* Max pending data before flush to disk */
111910
+ int nPendingData; /* Current bytes of pending data */
111911
+ sqlite_int64 iPrevDocid; /* Docid of most recently inserted document */
111839111912
111840111913
#if defined(SQLITE_DEBUG)
111841111914
/* State variables used for validating that the transaction control
111842111915
** methods of the virtual table are called at appropriate times. These
111843111916
** values do not contribution to the FTS computation; they are used for
@@ -111864,13 +111937,14 @@
111864111937
Fts3DeferredToken *pDeferred; /* Deferred search tokens, if any */
111865111938
sqlite3_int64 iPrevId; /* Previous id read from aDoclist */
111866111939
char *pNextId; /* Pointer into the body of aDoclist */
111867111940
char *aDoclist; /* List of docids for full-text queries */
111868111941
int nDoclist; /* Size of buffer at aDoclist */
111869
- int desc; /* True to sort in descending order */
111942
+ u8 bDesc; /* True to sort in descending order */
111870111943
int eEvalmode; /* An FTS3_EVAL_XX constant */
111871111944
int nRowAvg; /* Average size of database rows, in pages */
111945
+ int nDoc; /* Documents in table */
111872111946
111873111947
int isMatchinfoNeeded; /* True when aMatchinfo[] needs filling in */
111874111948
u32 *aMatchinfo; /* Information about most recent match */
111875111949
int nMatchinfo; /* Number of elements in aMatchinfo[] */
111876111950
char *zMatchinfo; /* Matchinfo specification */
@@ -111897,66 +111971,90 @@
111897111971
*/
111898111972
#define FTS3_FULLSCAN_SEARCH 0 /* Linear scan of %_content table */
111899111973
#define FTS3_DOCID_SEARCH 1 /* Lookup by rowid on %_content table */
111900111974
#define FTS3_FULLTEXT_SEARCH 2 /* Full-text index search */
111901111975
111976
+
111977
+struct Fts3Doclist {
111978
+ char *aAll; /* Array containing doclist (or NULL) */
111979
+ int nAll; /* Size of a[] in bytes */
111980
+ char *pNextDocid; /* Pointer to next docid */
111981
+
111982
+ sqlite3_int64 iDocid; /* Current docid (if pList!=0) */
111983
+ int bFreeList; /* True if pList should be sqlite3_free()d */
111984
+ char *pList; /* Pointer to position list following iDocid */
111985
+ int nList; /* Length of position list */
111986
+} doclist;
111987
+
111902111988
/*
111903111989
** A "phrase" is a sequence of one or more tokens that must match in
111904111990
** sequence. A single token is the base case and the most common case.
111905111991
** For a sequence of tokens contained in double-quotes (i.e. "one two three")
111906111992
** nToken will be the number of tokens in the string.
111907
-**
111908
-** The nDocMatch and nMatch variables contain data that may be used by the
111909
-** matchinfo() function. They are populated when the full-text index is
111910
-** queried for hits on the phrase. If one or more tokens in the phrase
111911
-** are deferred, the nDocMatch and nMatch variables are populated based
111912
-** on the assumption that the
111913111993
*/
111914111994
struct Fts3PhraseToken {
111915111995
char *z; /* Text of the token */
111916111996
int n; /* Number of bytes in buffer z */
111917111997
int isPrefix; /* True if token ends with a "*" character */
111998
+
111999
+ /* Variables above this point are populated when the expression is
112000
+ ** parsed (by code in fts3_expr.c). Below this point the variables are
112001
+ ** used when evaluating the expression. */
111918112002
int bFulltext; /* True if full-text index was used */
111919
- Fts3SegReaderCursor *pSegcsr; /* Segment-reader for this token */
111920112003
Fts3DeferredToken *pDeferred; /* Deferred token object for this token */
112004
+ Fts3MultiSegReader *pSegcsr; /* Segment-reader for this token */
111921112005
};
111922112006
111923112007
struct Fts3Phrase {
111924
- /* Variables populated by fts3_expr.c when parsing a MATCH expression */
112008
+ /* Cache of doclist for this phrase. */
112009
+ Fts3Doclist doclist;
112010
+ int bIncr; /* True if doclist is loaded incrementally */
112011
+
112012
+ /* Variables below this point are populated by fts3_expr.c when parsing
112013
+ ** a MATCH expression. Everything above is part of the evaluation phase.
112014
+ */
111925112015
int nToken; /* Number of tokens in the phrase */
111926112016
int iColumn; /* Index of column this phrase must match */
111927
- int isNot; /* Phrase prefixed by unary not (-) operator */
111928112017
Fts3PhraseToken aToken[1]; /* One entry for each token in the phrase */
111929112018
};
111930112019
111931112020
/*
111932112021
** A tree of these objects forms the RHS of a MATCH operator.
111933112022
**
111934
-** If Fts3Expr.eType is either FTSQUERY_NEAR or FTSQUERY_PHRASE and isLoaded
111935
-** is true, then aDoclist points to a malloced buffer, size nDoclist bytes,
111936
-** containing the results of the NEAR or phrase query in FTS3 doclist
111937
-** format. As usual, the initial "Length" field found in doclists stored
111938
-** on disk is omitted from this buffer.
112023
+** If Fts3Expr.eType is FTSQUERY_PHRASE and isLoaded is true, then aDoclist
112024
+** points to a malloced buffer, size nDoclist bytes, containing the results
112025
+** of this phrase query in FTS3 doclist format. As usual, the initial
112026
+** "Length" field found in doclists stored on disk is omitted from this
112027
+** buffer.
111939112028
**
111940
-** Variable pCurrent always points to the start of a docid field within
111941
-** aDoclist. Since the doclist is usually scanned in docid order, this can
111942
-** be used to accelerate seeking to the required docid within the doclist.
112029
+** Variable aMI is used only for FTSQUERY_NEAR nodes to store the global
112030
+** matchinfo data. If it is not NULL, it points to an array of size nCol*3,
112031
+** where nCol is the number of columns in the queried FTS table. The array
112032
+** is populated as follows:
112033
+**
112034
+** aMI[iCol*3 + 0] = Undefined
112035
+** aMI[iCol*3 + 1] = Number of occurrences
112036
+** aMI[iCol*3 + 2] = Number of rows containing at least one instance
112037
+**
112038
+** The aMI array is allocated using sqlite3_malloc(). It should be freed
112039
+** when the expression node is.
111943112040
*/
111944112041
struct Fts3Expr {
111945112042
int eType; /* One of the FTSQUERY_XXX values defined below */
111946112043
int nNear; /* Valid if eType==FTSQUERY_NEAR */
111947112044
Fts3Expr *pParent; /* pParent->pLeft==this or pParent->pRight==this */
111948112045
Fts3Expr *pLeft; /* Left operand */
111949112046
Fts3Expr *pRight; /* Right operand */
111950112047
Fts3Phrase *pPhrase; /* Valid if eType==FTSQUERY_PHRASE */
111951112048
111952
- int isLoaded; /* True if aDoclist/nDoclist are initialized. */
111953
- char *aDoclist; /* Buffer containing doclist */
111954
- int nDoclist; /* Size of aDoclist in bytes */
112049
+ /* The following are used by the fts3_eval.c module. */
112050
+ sqlite3_int64 iDocid; /* Current docid */
112051
+ u8 bEof; /* True this expression is at EOF already */
112052
+ u8 bStart; /* True if iDocid is valid */
112053
+ u8 bDeferred; /* True if this expression is entirely deferred */
111955112054
111956
- sqlite3_int64 iCurrent;
111957
- char *pCurrent;
112055
+ u32 *aMI;
111958112056
};
111959112057
111960112058
/*
111961112059
** Candidate values for Fts3Query.eType. Note that the order of the first
111962112060
** four values is in order of precedence when parsing expressions. For
@@ -111980,35 +112078,36 @@
111980112078
SQLITE_PRIVATE int sqlite3Fts3PendingTermsFlush(Fts3Table *);
111981112079
SQLITE_PRIVATE void sqlite3Fts3PendingTermsClear(Fts3Table *);
111982112080
SQLITE_PRIVATE int sqlite3Fts3Optimize(Fts3Table *);
111983112081
SQLITE_PRIVATE int sqlite3Fts3SegReaderNew(int, sqlite3_int64,
111984112082
sqlite3_int64, sqlite3_int64, const char *, int, Fts3SegReader**);
111985
-SQLITE_PRIVATE int sqlite3Fts3SegReaderPending(Fts3Table*,const char*,int,int,Fts3SegReader**);
112083
+SQLITE_PRIVATE int sqlite3Fts3SegReaderPending(
112084
+ Fts3Table*,int,const char*,int,int,Fts3SegReader**);
111986112085
SQLITE_PRIVATE void sqlite3Fts3SegReaderFree(Fts3SegReader *);
111987
-SQLITE_PRIVATE int sqlite3Fts3SegReaderCost(Fts3Cursor *, Fts3SegReader *, int *);
111988
-SQLITE_PRIVATE int sqlite3Fts3AllSegdirs(Fts3Table*, int, sqlite3_stmt **);
112086
+SQLITE_PRIVATE int sqlite3Fts3AllSegdirs(Fts3Table*, int, int, sqlite3_stmt **);
111989112087
SQLITE_PRIVATE int sqlite3Fts3ReadLock(Fts3Table *);
111990
-SQLITE_PRIVATE int sqlite3Fts3ReadBlock(Fts3Table*, sqlite3_int64, char **, int*);
112088
+SQLITE_PRIVATE int sqlite3Fts3ReadBlock(Fts3Table*, sqlite3_int64, char **, int*, int*);
111991112089
111992112090
SQLITE_PRIVATE int sqlite3Fts3SelectDoctotal(Fts3Table *, sqlite3_stmt **);
111993112091
SQLITE_PRIVATE int sqlite3Fts3SelectDocsize(Fts3Table *, sqlite3_int64, sqlite3_stmt **);
111994112092
111995112093
SQLITE_PRIVATE void sqlite3Fts3FreeDeferredTokens(Fts3Cursor *);
111996112094
SQLITE_PRIVATE int sqlite3Fts3DeferToken(Fts3Cursor *, Fts3PhraseToken *, int);
111997112095
SQLITE_PRIVATE int sqlite3Fts3CacheDeferredDoclists(Fts3Cursor *);
111998112096
SQLITE_PRIVATE void sqlite3Fts3FreeDeferredDoclists(Fts3Cursor *);
111999
-SQLITE_PRIVATE char *sqlite3Fts3DeferredDoclist(Fts3DeferredToken *, int *);
112000112097
SQLITE_PRIVATE void sqlite3Fts3SegmentsClose(Fts3Table *);
112001112098
112002
-#define FTS3_SEGCURSOR_PENDING -1
112003
-#define FTS3_SEGCURSOR_ALL -2
112099
+/* Special values interpreted by sqlite3SegReaderCursor() */
112100
+#define FTS3_SEGCURSOR_PENDING -1
112101
+#define FTS3_SEGCURSOR_ALL -2
112004112102
112005
-SQLITE_PRIVATE int sqlite3Fts3SegReaderStart(Fts3Table*, Fts3SegReaderCursor*, Fts3SegFilter*);
112006
-SQLITE_PRIVATE int sqlite3Fts3SegReaderStep(Fts3Table *, Fts3SegReaderCursor *);
112007
-SQLITE_PRIVATE void sqlite3Fts3SegReaderFinish(Fts3SegReaderCursor *);
112103
+SQLITE_PRIVATE int sqlite3Fts3SegReaderStart(Fts3Table*, Fts3MultiSegReader*, Fts3SegFilter*);
112104
+SQLITE_PRIVATE int sqlite3Fts3SegReaderStep(Fts3Table *, Fts3MultiSegReader *);
112105
+SQLITE_PRIVATE void sqlite3Fts3SegReaderFinish(Fts3MultiSegReader *);
112106
+
112008112107
SQLITE_PRIVATE int sqlite3Fts3SegReaderCursor(
112009
- Fts3Table *, int, const char *, int, int, int, Fts3SegReaderCursor *);
112108
+ Fts3Table *, int, int, const char *, int, int, int, Fts3MultiSegReader *);
112010112109
112011112110
/* Flags allowed as part of the 4th argument to SegmentReaderIterate() */
112012112111
#define FTS3_SEGMENT_REQUIRE_POS 0x00000001
112013112112
#define FTS3_SEGMENT_IGNORE_EMPTY 0x00000002
112014112113
#define FTS3_SEGMENT_COLUMN_FILTER 0x00000004
@@ -112021,21 +112120,24 @@
112021112120
int nTerm;
112022112121
int iCol;
112023112122
int flags;
112024112123
};
112025112124
112026
-struct Fts3SegReaderCursor {
112125
+struct Fts3MultiSegReader {
112027112126
/* Used internally by sqlite3Fts3SegReaderXXX() calls */
112028112127
Fts3SegReader **apSegment; /* Array of Fts3SegReader objects */
112029112128
int nSegment; /* Size of apSegment array */
112030112129
int nAdvance; /* How many seg-readers to advance */
112031112130
Fts3SegFilter *pFilter; /* Pointer to filter object */
112032112131
char *aBuffer; /* Buffer to merge doclists in */
112033112132
int nBuffer; /* Allocated size of aBuffer[] in bytes */
112034112133
112035
- /* Cost of running this iterator. Used by fts3.c only. */
112036
- int nCost;
112134
+ int iColFilter; /* If >=0, filter for this column */
112135
+
112136
+ /* Used by fts3.c only. */
112137
+ int nCost; /* Cost of running iterator */
112138
+ int bLookup; /* True if a lookup of a single entry. */
112037112139
112038112140
/* Output values. Valid only after Fts3SegReaderStep() returns SQLITE_ROW. */
112039112141
char *zTerm; /* Pointer to term buffer */
112040112142
int nTerm; /* Size of zTerm in bytes */
112041112143
char *aDoclist; /* Pointer to doclist buffer */
@@ -112046,15 +112148,13 @@
112046112148
SQLITE_PRIVATE int sqlite3Fts3PutVarint(char *, sqlite3_int64);
112047112149
SQLITE_PRIVATE int sqlite3Fts3GetVarint(const char *, sqlite_int64 *);
112048112150
SQLITE_PRIVATE int sqlite3Fts3GetVarint32(const char *, int *);
112049112151
SQLITE_PRIVATE int sqlite3Fts3VarintLen(sqlite3_uint64);
112050112152
SQLITE_PRIVATE void sqlite3Fts3Dequote(char *);
112153
+SQLITE_PRIVATE void sqlite3Fts3DoclistPrev(int,char*,int,char**,sqlite3_int64*,int*,u8*);
112051112154
112052
-SQLITE_PRIVATE char *sqlite3Fts3FindPositions(Fts3Cursor *, Fts3Expr *, sqlite3_int64, int);
112053
-SQLITE_PRIVATE int sqlite3Fts3ExprLoadDoclist(Fts3Cursor *, Fts3Expr *);
112054
-SQLITE_PRIVATE int sqlite3Fts3ExprLoadFtDoclist(Fts3Cursor *, Fts3Expr *, char **, int *);
112055
-SQLITE_PRIVATE int sqlite3Fts3ExprNearTrim(Fts3Expr *, Fts3Expr *, int);
112155
+SQLITE_PRIVATE int sqlite3Fts3EvalPhraseStats(Fts3Cursor *, Fts3Expr *, u32 *);
112056112156
112057112157
/* fts3_tokenizer.c */
112058112158
SQLITE_PRIVATE const char *sqlite3Fts3NextToken(const char *, int *);
112059112159
SQLITE_PRIVATE int sqlite3Fts3InitHashTable(sqlite3 *, Fts3Hash *, const char *);
112060112160
SQLITE_PRIVATE int sqlite3Fts3InitTokenizer(Fts3Hash *pHash, const char *,
@@ -112079,10 +112179,33 @@
112079112179
SQLITE_PRIVATE int sqlite3Fts3InitTerm(sqlite3 *db);
112080112180
#endif
112081112181
112082112182
/* fts3_aux.c */
112083112183
SQLITE_PRIVATE int sqlite3Fts3InitAux(sqlite3 *db);
112184
+
112185
+SQLITE_PRIVATE int sqlite3Fts3TermSegReaderCursor(
112186
+ Fts3Cursor *pCsr, /* Virtual table cursor handle */
112187
+ const char *zTerm, /* Term to query for */
112188
+ int nTerm, /* Size of zTerm in bytes */
112189
+ int isPrefix, /* True for a prefix search */
112190
+ Fts3MultiSegReader **ppSegcsr /* OUT: Allocated seg-reader cursor */
112191
+);
112192
+
112193
+SQLITE_PRIVATE void sqlite3Fts3EvalPhraseCleanup(Fts3Phrase *);
112194
+
112195
+SQLITE_PRIVATE int sqlite3Fts3EvalStart(Fts3Cursor *, Fts3Expr *, int);
112196
+SQLITE_PRIVATE int sqlite3Fts3EvalNext(Fts3Cursor *pCsr);
112197
+
112198
+SQLITE_PRIVATE int sqlite3Fts3MsrIncrStart(
112199
+ Fts3Table*, Fts3MultiSegReader*, int, const char*, int);
112200
+SQLITE_PRIVATE int sqlite3Fts3MsrIncrNext(
112201
+ Fts3Table *, Fts3MultiSegReader *, sqlite3_int64 *, char **, int *);
112202
+SQLITE_PRIVATE char *sqlite3Fts3EvalPhrasePoslist(Fts3Cursor *, Fts3Expr *, int iCol);
112203
+SQLITE_PRIVATE int sqlite3Fts3MsrOvfl(Fts3Cursor *, Fts3MultiSegReader *, int *);
112204
+
112205
+SQLITE_PRIVATE int sqlite3Fts3DeferredTokenList(Fts3DeferredToken *, char **, int *);
112206
+
112084112207
112085112208
#endif /* _FTSINT_H */
112086112209
112087112210
/************** End of fts3Int.h *********************************************/
112088112211
/************** Continuing where we left off in fts3.c ***********************/
@@ -112200,16 +112323,16 @@
112200112323
112201112324
/*
112202112325
** When this function is called, *pp points to the first byte following a
112203112326
** varint that is part of a doclist (or position-list, or any other list
112204112327
** of varints). This function moves *pp to point to the start of that varint,
112205
-** and decrements the value stored in *pVal by the varint value.
112328
+** and sets *pVal by the varint value.
112206112329
**
112207112330
** Argument pStart points to the first byte of the doclist that the
112208112331
** varint is part of.
112209112332
*/
112210
-static void fts3GetReverseDeltaVarint(
112333
+static void fts3GetReverseVarint(
112211112334
char **pp,
112212112335
char *pStart,
112213112336
sqlite3_int64 *pVal
112214112337
){
112215112338
sqlite3_int64 iVal;
@@ -112221,25 +112344,11 @@
112221112344
for(p = (*pp)-2; p>=pStart && *p&0x80; p--);
112222112345
p++;
112223112346
*pp = p;
112224112347
112225112348
sqlite3Fts3GetVarint(p, &iVal);
112226
- *pVal -= iVal;
112227
-}
112228
-
112229
-/*
112230
-** As long as *pp has not reached its end (pEnd), then do the same
112231
-** as fts3GetDeltaVarint(): read a single varint and add it to *pVal.
112232
-** But if we have reached the end of the varint, just set *pp=0 and
112233
-** leave *pVal unchanged.
112234
-*/
112235
-static void fts3GetDeltaVarint2(char **pp, char *pEnd, sqlite3_int64 *pVal){
112236
- if( *pp>=pEnd ){
112237
- *pp = 0;
112238
- }else{
112239
- fts3GetDeltaVarint(pp, pVal);
112240
- }
112349
+ *pVal = iVal;
112241112350
}
112242112351
112243112352
/*
112244112353
** The xDisconnect() virtual table method.
112245112354
*/
@@ -112608,10 +112717,62 @@
112608112717
fts3Appendf(pRc, &zRet, ",%s(?)", zFunction);
112609112718
}
112610112719
sqlite3_free(zFree);
112611112720
return zRet;
112612112721
}
112722
+
112723
+static int fts3GobbleInt(const char **pp, int *pnOut){
112724
+ const char *p = *pp;
112725
+ int nInt = 0;
112726
+ for(p=*pp; p[0]>='0' && p[0]<='9'; p++){
112727
+ nInt = nInt * 10 + (p[0] - '0');
112728
+ }
112729
+ if( p==*pp ) return SQLITE_ERROR;
112730
+ *pnOut = nInt;
112731
+ *pp = p;
112732
+ return SQLITE_OK;
112733
+}
112734
+
112735
+
112736
+static int fts3PrefixParameter(
112737
+ const char *zParam, /* ABC in prefix=ABC parameter to parse */
112738
+ int *pnIndex, /* OUT: size of *apIndex[] array */
112739
+ struct Fts3Index **apIndex, /* OUT: Array of indexes for this table */
112740
+ struct Fts3Index **apFree /* OUT: Free this with sqlite3_free() */
112741
+){
112742
+ struct Fts3Index *aIndex;
112743
+ int nIndex = 1;
112744
+
112745
+ if( zParam && zParam[0] ){
112746
+ const char *p;
112747
+ nIndex++;
112748
+ for(p=zParam; *p; p++){
112749
+ if( *p==',' ) nIndex++;
112750
+ }
112751
+ }
112752
+
112753
+ aIndex = sqlite3_malloc(sizeof(struct Fts3Index) * nIndex);
112754
+ *apIndex = *apFree = aIndex;
112755
+ *pnIndex = nIndex;
112756
+ if( !aIndex ){
112757
+ return SQLITE_NOMEM;
112758
+ }
112759
+
112760
+ memset(aIndex, 0, sizeof(struct Fts3Index) * nIndex);
112761
+ if( zParam ){
112762
+ const char *p = zParam;
112763
+ int i;
112764
+ for(i=1; i<nIndex; i++){
112765
+ int nPrefix;
112766
+ if( fts3GobbleInt(&p, &nPrefix) ) return SQLITE_ERROR;
112767
+ aIndex[i].nPrefix = nPrefix;
112768
+ p++;
112769
+ }
112770
+ }
112771
+
112772
+ return SQLITE_OK;
112773
+}
112613112774
112614112775
/*
112615112776
** This function is the implementation of both the xConnect and xCreate
112616112777
** methods of the FTS3 virtual table.
112617112778
**
@@ -112641,16 +112802,23 @@
112641112802
int nCol = 0; /* Number of columns in the FTS table */
112642112803
char *zCsr; /* Space for holding column names */
112643112804
int nDb; /* Bytes required to hold database name */
112644112805
int nName; /* Bytes required to hold table name */
112645112806
int isFts4 = (argv[0][3]=='4'); /* True for FTS4, false for FTS3 */
112646
- int bNoDocsize = 0; /* True to omit %_docsize table */
112647112807
const char **aCol; /* Array of column names */
112648112808
sqlite3_tokenizer *pTokenizer = 0; /* Tokenizer for this table */
112649112809
112650
- char *zCompress = 0;
112651
- char *zUncompress = 0;
112810
+ int nIndex; /* Size of aIndex[] array */
112811
+ struct Fts3Index *aIndex; /* Array of indexes for this table */
112812
+ struct Fts3Index *aFree = 0; /* Free this before returning */
112813
+
112814
+ /* The results of parsing supported FTS4 key=value options: */
112815
+ int bNoDocsize = 0; /* True to omit %_docsize table */
112816
+ int bDescIdx = 0; /* True to store descending indexes */
112817
+ char *zPrefix = 0; /* Prefix parameter value (or NULL) */
112818
+ char *zCompress = 0; /* compress=? parameter (or NULL) */
112819
+ char *zUncompress = 0; /* uncompress=? parameter (or NULL) */
112652112820
112653112821
assert( strlen(argv[0])==4 );
112654112822
assert( (sqlite3_strnicmp(argv[0], "fts4", 4)==0 && isFts4)
112655112823
|| (sqlite3_strnicmp(argv[0], "fts3", 4)==0 && !isFts4)
112656112824
);
@@ -112687,32 +112855,76 @@
112687112855
rc = sqlite3Fts3InitTokenizer(pHash, &z[9], &pTokenizer, pzErr);
112688112856
}
112689112857
112690112858
/* Check if it is an FTS4 special argument. */
112691112859
else if( isFts4 && fts3IsSpecialColumn(z, &nKey, &zVal) ){
112860
+ struct Fts4Option {
112861
+ const char *zOpt;
112862
+ int nOpt;
112863
+ char **pzVar;
112864
+ } aFts4Opt[] = {
112865
+ { "matchinfo", 9, 0 }, /* 0 -> MATCHINFO */
112866
+ { "prefix", 6, 0 }, /* 1 -> PREFIX */
112867
+ { "compress", 8, 0 }, /* 2 -> COMPRESS */
112868
+ { "uncompress", 10, 0 }, /* 3 -> UNCOMPRESS */
112869
+ { "order", 5, 0 } /* 4 -> ORDER */
112870
+ };
112871
+
112872
+ int iOpt;
112692112873
if( !zVal ){
112693112874
rc = SQLITE_NOMEM;
112694
- goto fts3_init_out;
112695
- }
112696
- if( nKey==9 && 0==sqlite3_strnicmp(z, "matchinfo", 9) ){
112697
- if( strlen(zVal)==4 && 0==sqlite3_strnicmp(zVal, "fts3", 4) ){
112698
- bNoDocsize = 1;
112699
- }else{
112700
- *pzErr = sqlite3_mprintf("unrecognized matchinfo: %s", zVal);
112701
- rc = SQLITE_ERROR;
112702
- }
112703
- }else if( nKey==8 && 0==sqlite3_strnicmp(z, "compress", 8) ){
112704
- zCompress = zVal;
112705
- zVal = 0;
112706
- }else if( nKey==10 && 0==sqlite3_strnicmp(z, "uncompress", 10) ){
112707
- zUncompress = zVal;
112708
- zVal = 0;
112709
- }else{
112710
- *pzErr = sqlite3_mprintf("unrecognized parameter: %s", z);
112711
- rc = SQLITE_ERROR;
112712
- }
112713
- sqlite3_free(zVal);
112875
+ }else{
112876
+ for(iOpt=0; iOpt<SizeofArray(aFts4Opt); iOpt++){
112877
+ struct Fts4Option *pOp = &aFts4Opt[iOpt];
112878
+ if( nKey==pOp->nOpt && !sqlite3_strnicmp(z, pOp->zOpt, pOp->nOpt) ){
112879
+ break;
112880
+ }
112881
+ }
112882
+ if( iOpt==SizeofArray(aFts4Opt) ){
112883
+ *pzErr = sqlite3_mprintf("unrecognized parameter: %s", z);
112884
+ rc = SQLITE_ERROR;
112885
+ }else{
112886
+ switch( iOpt ){
112887
+ case 0: /* MATCHINFO */
112888
+ if( strlen(zVal)!=4 || sqlite3_strnicmp(zVal, "fts3", 4) ){
112889
+ *pzErr = sqlite3_mprintf("unrecognized matchinfo: %s", zVal);
112890
+ rc = SQLITE_ERROR;
112891
+ }
112892
+ bNoDocsize = 1;
112893
+ break;
112894
+
112895
+ case 1: /* PREFIX */
112896
+ sqlite3_free(zPrefix);
112897
+ zPrefix = zVal;
112898
+ zVal = 0;
112899
+ break;
112900
+
112901
+ case 2: /* COMPRESS */
112902
+ sqlite3_free(zCompress);
112903
+ zCompress = zVal;
112904
+ zVal = 0;
112905
+ break;
112906
+
112907
+ case 3: /* UNCOMPRESS */
112908
+ sqlite3_free(zUncompress);
112909
+ zUncompress = zVal;
112910
+ zVal = 0;
112911
+ break;
112912
+
112913
+ case 4: /* ORDER */
112914
+ if( (strlen(zVal)!=3 || sqlite3_strnicmp(zVal, "asc", 3))
112915
+ && (strlen(zVal)!=4 || sqlite3_strnicmp(zVal, "desc", 3))
112916
+ ){
112917
+ *pzErr = sqlite3_mprintf("unrecognized order: %s", zVal);
112918
+ rc = SQLITE_ERROR;
112919
+ }
112920
+ bDescIdx = (zVal[0]=='d' || zVal[0]=='D');
112921
+ break;
112922
+ }
112923
+ }
112924
+ sqlite3_free(zVal);
112925
+ }
112714112926
}
112715112927
112716112928
/* Otherwise, the argument is a column name. */
112717112929
else {
112718112930
nString += (int)(strlen(z) + 1);
@@ -112732,14 +112944,21 @@
112732112944
rc = sqlite3Fts3InitTokenizer(pHash, "simple", &pTokenizer, pzErr);
112733112945
if( rc!=SQLITE_OK ) goto fts3_init_out;
112734112946
}
112735112947
assert( pTokenizer );
112736112948
112949
+ rc = fts3PrefixParameter(zPrefix, &nIndex, &aIndex, &aFree);
112950
+ if( rc==SQLITE_ERROR ){
112951
+ assert( zPrefix );
112952
+ *pzErr = sqlite3_mprintf("error parsing prefix parameter: %s", zPrefix);
112953
+ }
112954
+ if( rc!=SQLITE_OK ) goto fts3_init_out;
112737112955
112738112956
/* Allocate and populate the Fts3Table structure. */
112739
- nByte = sizeof(Fts3Table) + /* Fts3Table */
112957
+ nByte = sizeof(Fts3Table) + /* Fts3Table */
112740112958
nCol * sizeof(char *) + /* azColumn */
112959
+ nIndex * sizeof(struct Fts3Index) + /* aIndex */
112741112960
nName + /* zName */
112742112961
nDb + /* zDb */
112743112962
nString; /* Space for azColumn strings */
112744112963
p = (Fts3Table*)sqlite3_malloc(nByte);
112745112964
if( p==0 ){
@@ -112750,20 +112969,26 @@
112750112969
p->db = db;
112751112970
p->nColumn = nCol;
112752112971
p->nPendingData = 0;
112753112972
p->azColumn = (char **)&p[1];
112754112973
p->pTokenizer = pTokenizer;
112755
- p->nNodeSize = 1000;
112756112974
p->nMaxPendingData = FTS3_MAX_PENDING_DATA;
112757112975
p->bHasDocsize = (isFts4 && bNoDocsize==0);
112758112976
p->bHasStat = isFts4;
112977
+ p->bDescIdx = bDescIdx;
112759112978
TESTONLY( p->inTransaction = -1 );
112760112979
TESTONLY( p->mxSavepoint = -1 );
112761
- fts3HashInit(&p->pendingTerms, FTS3_HASH_STRING, 1);
112980
+
112981
+ p->aIndex = (struct Fts3Index *)&p->azColumn[nCol];
112982
+ memcpy(p->aIndex, aIndex, sizeof(struct Fts3Index) * nIndex);
112983
+ p->nIndex = nIndex;
112984
+ for(i=0; i<nIndex; i++){
112985
+ fts3HashInit(&p->aIndex[i].hPending, FTS3_HASH_STRING, 1);
112986
+ }
112762112987
112763112988
/* Fill in the zName and zDb fields of the vtab structure. */
112764
- zCsr = (char *)&p->azColumn[nCol];
112989
+ zCsr = (char *)&p->aIndex[nIndex];
112765112990
p->zName = zCsr;
112766112991
memcpy(zCsr, argv[2], nName);
112767112992
zCsr += nName;
112768112993
p->zDb = zCsr;
112769112994
memcpy(zCsr, argv[1], nDb);
@@ -112797,19 +113022,20 @@
112797113022
if( isCreate ){
112798113023
rc = fts3CreateTables(p);
112799113024
}
112800113025
112801113026
/* Figure out the page-size for the database. This is required in order to
112802
- ** estimate the cost of loading large doclists from the database (see
112803
- ** function sqlite3Fts3SegReaderCost() for details).
112804
- */
113027
+ ** estimate the cost of loading large doclists from the database. */
112805113028
fts3DatabasePageSize(&rc, p);
113029
+ p->nNodeSize = p->nPgsz-35;
112806113030
112807113031
/* Declare the table schema to SQLite. */
112808113032
fts3DeclareVtab(&rc, p);
112809113033
112810113034
fts3_init_out:
113035
+ sqlite3_free(zPrefix);
113036
+ sqlite3_free(aFree);
112811113037
sqlite3_free(zCompress);
112812113038
sqlite3_free(zUncompress);
112813113039
sqlite3_free((void *)aCol);
112814113040
if( rc!=SQLITE_OK ){
112815113041
if( p ){
@@ -112816,10 +113042,11 @@
112816113042
fts3DisconnectMethod((sqlite3_vtab *)p);
112817113043
}else if( pTokenizer ){
112818113044
pTokenizer->pModule->xDestroy(pTokenizer);
112819113045
}
112820113046
}else{
113047
+ assert( p->pSegments==0 );
112821113048
*ppVTab = &p->base;
112822113049
}
112823113050
return rc;
112824113051
}
112825113052
@@ -112913,14 +113140,15 @@
112913113140
if( pOrder->desc ){
112914113141
pInfo->idxStr = "DESC";
112915113142
}else{
112916113143
pInfo->idxStr = "ASC";
112917113144
}
113145
+ pInfo->orderByConsumed = 1;
112918113146
}
112919
- pInfo->orderByConsumed = 1;
112920113147
}
112921113148
113149
+ assert( p->pSegments==0 );
112922113150
return SQLITE_OK;
112923113151
}
112924113152
112925113153
/*
112926113154
** Implementation of xOpen method.
@@ -112952,10 +113180,11 @@
112952113180
sqlite3_finalize(pCsr->pStmt);
112953113181
sqlite3Fts3ExprFree(pCsr->pExpr);
112954113182
sqlite3Fts3FreeDeferredTokens(pCsr);
112955113183
sqlite3_free(pCsr->aDoclist);
112956113184
sqlite3_free(pCsr->aMatchinfo);
113185
+ assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 );
112957113186
sqlite3_free(pCsr);
112958113187
return SQLITE_OK;
112959113188
}
112960113189
112961113190
/*
@@ -112963,12 +113192,12 @@
112963113192
** of the %_content table that contains the last match. Return
112964113193
** SQLITE_OK on success.
112965113194
*/
112966113195
static int fts3CursorSeek(sqlite3_context *pContext, Fts3Cursor *pCsr){
112967113196
if( pCsr->isRequireSeek ){
112968
- pCsr->isRequireSeek = 0;
112969113197
sqlite3_bind_int64(pCsr->pStmt, 1, pCsr->iPrevId);
113198
+ pCsr->isRequireSeek = 0;
112970113199
if( SQLITE_ROW==sqlite3_step(pCsr->pStmt) ){
112971113200
return SQLITE_OK;
112972113201
}else{
112973113202
int rc = sqlite3_reset(pCsr->pStmt);
112974113203
if( rc==SQLITE_OK ){
@@ -113145,21 +113374,21 @@
113145113374
if( rc==SQLITE_OK && iHeight>1 ){
113146113375
char *zBlob = 0; /* Blob read from %_segments table */
113147113376
int nBlob; /* Size of zBlob in bytes */
113148113377
113149113378
if( piLeaf && piLeaf2 && (*piLeaf!=*piLeaf2) ){
113150
- rc = sqlite3Fts3ReadBlock(p, *piLeaf, &zBlob, &nBlob);
113379
+ rc = sqlite3Fts3ReadBlock(p, *piLeaf, &zBlob, &nBlob, 0);
113151113380
if( rc==SQLITE_OK ){
113152113381
rc = fts3SelectLeaf(p, zTerm, nTerm, zBlob, nBlob, piLeaf, 0);
113153113382
}
113154113383
sqlite3_free(zBlob);
113155113384
piLeaf = 0;
113156113385
zBlob = 0;
113157113386
}
113158113387
113159113388
if( rc==SQLITE_OK ){
113160
- rc = sqlite3Fts3ReadBlock(p, piLeaf ? *piLeaf : *piLeaf2, &zBlob, &nBlob);
113389
+ rc = sqlite3Fts3ReadBlock(p, piLeaf?*piLeaf:*piLeaf2, &zBlob, &nBlob, 0);
113161113390
}
113162113391
if( rc==SQLITE_OK ){
113163113392
rc = fts3SelectLeaf(p, zTerm, nTerm, zBlob, nBlob, piLeaf, piLeaf2);
113164113393
}
113165113394
sqlite3_free(zBlob);
@@ -113531,11 +113760,23 @@
113531113760
*pp = p;
113532113761
return 1;
113533113762
}
113534113763
113535113764
/*
113536
-** Merge two position-lists as required by the NEAR operator.
113765
+** Merge two position-lists as required by the NEAR operator. The argument
113766
+** position lists correspond to the left and right phrases of an expression
113767
+** like:
113768
+**
113769
+** "phrase 1" NEAR "phrase number 2"
113770
+**
113771
+** Position list *pp1 corresponds to the left-hand side of the NEAR
113772
+** expression and *pp2 to the right. As usual, the indexes in the position
113773
+** lists are the offsets of the last token in each phrase (tokens "1" and "2"
113774
+** in the example above).
113775
+**
113776
+** The output position list - written to *pp - is a copy of *pp2 with those
113777
+** entries that are not sufficiently NEAR entries in *pp1 removed.
113537113778
*/
113538113779
static int fts3PoslistNearMerge(
113539113780
char **pp, /* Output buffer */
113540113781
char *aTmp, /* Temporary buffer space */
113541113782
int nRight, /* Maximum difference in token positions */
@@ -113544,218 +113785,31 @@
113544113785
char **pp2 /* IN/OUT: Right input list */
113545113786
){
113546113787
char *p1 = *pp1;
113547113788
char *p2 = *pp2;
113548113789
113549
- if( !pp ){
113550
- if( fts3PoslistPhraseMerge(0, nRight, 0, 0, pp1, pp2) ) return 1;
113551
- *pp1 = p1;
113552
- *pp2 = p2;
113553
- return fts3PoslistPhraseMerge(0, nLeft, 0, 0, pp2, pp1);
113554
- }else{
113555
- char *pTmp1 = aTmp;
113556
- char *pTmp2;
113557
- char *aTmp2;
113558
- int res = 1;
113559
-
113560
- fts3PoslistPhraseMerge(&pTmp1, nRight, 0, 0, pp1, pp2);
113561
- aTmp2 = pTmp2 = pTmp1;
113562
- *pp1 = p1;
113563
- *pp2 = p2;
113564
- fts3PoslistPhraseMerge(&pTmp2, nLeft, 1, 0, pp2, pp1);
113565
- if( pTmp1!=aTmp && pTmp2!=aTmp2 ){
113566
- fts3PoslistMerge(pp, &aTmp, &aTmp2);
113567
- }else if( pTmp1!=aTmp ){
113568
- fts3PoslistCopy(pp, &aTmp);
113569
- }else if( pTmp2!=aTmp2 ){
113570
- fts3PoslistCopy(pp, &aTmp2);
113571
- }else{
113572
- res = 0;
113573
- }
113574
-
113575
- return res;
113576
- }
113577
-}
113578
-
113579
-/*
113580
-** Values that may be used as the first parameter to fts3DoclistMerge().
113581
-*/
113582
-#define MERGE_NOT 2 /* D + D -> D */
113583
-#define MERGE_AND 3 /* D + D -> D */
113584
-#define MERGE_OR 4 /* D + D -> D */
113585
-#define MERGE_POS_OR 5 /* P + P -> P */
113586
-#define MERGE_PHRASE 6 /* P + P -> D */
113587
-#define MERGE_POS_PHRASE 7 /* P + P -> P */
113588
-#define MERGE_NEAR 8 /* P + P -> D */
113589
-#define MERGE_POS_NEAR 9 /* P + P -> P */
113590
-
113591
-/*
113592
-** Merge the two doclists passed in buffer a1 (size n1 bytes) and a2
113593
-** (size n2 bytes). The output is written to pre-allocated buffer aBuffer,
113594
-** which is guaranteed to be large enough to hold the results. The number
113595
-** of bytes written to aBuffer is stored in *pnBuffer before returning.
113596
-**
113597
-** If successful, SQLITE_OK is returned. Otherwise, if a malloc error
113598
-** occurs while allocating a temporary buffer as part of the merge operation,
113599
-** SQLITE_NOMEM is returned.
113600
-*/
113601
-static int fts3DoclistMerge(
113602
- int mergetype, /* One of the MERGE_XXX constants */
113603
- int nParam1, /* Used by MERGE_NEAR and MERGE_POS_NEAR */
113604
- int nParam2, /* Used by MERGE_NEAR and MERGE_POS_NEAR */
113605
- char *aBuffer, /* Pre-allocated output buffer */
113606
- int *pnBuffer, /* OUT: Bytes written to aBuffer */
113607
- char *a1, /* Buffer containing first doclist */
113608
- int n1, /* Size of buffer a1 */
113609
- char *a2, /* Buffer containing second doclist */
113610
- int n2, /* Size of buffer a2 */
113611
- int *pnDoc /* OUT: Number of docids in output */
113612
-){
113613
- sqlite3_int64 i1 = 0;
113614
- sqlite3_int64 i2 = 0;
113615
- sqlite3_int64 iPrev = 0;
113616
-
113617
- char *p = aBuffer;
113618
- char *p1 = a1;
113619
- char *p2 = a2;
113620
- char *pEnd1 = &a1[n1];
113621
- char *pEnd2 = &a2[n2];
113622
- int nDoc = 0;
113623
-
113624
- assert( mergetype==MERGE_OR || mergetype==MERGE_POS_OR
113625
- || mergetype==MERGE_AND || mergetype==MERGE_NOT
113626
- || mergetype==MERGE_PHRASE || mergetype==MERGE_POS_PHRASE
113627
- || mergetype==MERGE_NEAR || mergetype==MERGE_POS_NEAR
113628
- );
113629
-
113630
- if( !aBuffer ){
113631
- *pnBuffer = 0;
113632
- return SQLITE_NOMEM;
113633
- }
113634
-
113635
- /* Read the first docid from each doclist */
113636
- fts3GetDeltaVarint2(&p1, pEnd1, &i1);
113637
- fts3GetDeltaVarint2(&p2, pEnd2, &i2);
113638
-
113639
- switch( mergetype ){
113640
- case MERGE_OR:
113641
- case MERGE_POS_OR:
113642
- while( p1 || p2 ){
113643
- if( p2 && p1 && i1==i2 ){
113644
- fts3PutDeltaVarint(&p, &iPrev, i1);
113645
- if( mergetype==MERGE_POS_OR ) fts3PoslistMerge(&p, &p1, &p2);
113646
- fts3GetDeltaVarint2(&p1, pEnd1, &i1);
113647
- fts3GetDeltaVarint2(&p2, pEnd2, &i2);
113648
- }else if( !p2 || (p1 && i1<i2) ){
113649
- fts3PutDeltaVarint(&p, &iPrev, i1);
113650
- if( mergetype==MERGE_POS_OR ) fts3PoslistCopy(&p, &p1);
113651
- fts3GetDeltaVarint2(&p1, pEnd1, &i1);
113652
- }else{
113653
- fts3PutDeltaVarint(&p, &iPrev, i2);
113654
- if( mergetype==MERGE_POS_OR ) fts3PoslistCopy(&p, &p2);
113655
- fts3GetDeltaVarint2(&p2, pEnd2, &i2);
113656
- }
113657
- }
113658
- break;
113659
-
113660
- case MERGE_AND:
113661
- while( p1 && p2 ){
113662
- if( i1==i2 ){
113663
- fts3PutDeltaVarint(&p, &iPrev, i1);
113664
- fts3GetDeltaVarint2(&p1, pEnd1, &i1);
113665
- fts3GetDeltaVarint2(&p2, pEnd2, &i2);
113666
- nDoc++;
113667
- }else if( i1<i2 ){
113668
- fts3GetDeltaVarint2(&p1, pEnd1, &i1);
113669
- }else{
113670
- fts3GetDeltaVarint2(&p2, pEnd2, &i2);
113671
- }
113672
- }
113673
- break;
113674
-
113675
- case MERGE_NOT:
113676
- while( p1 ){
113677
- if( p2 && i1==i2 ){
113678
- fts3GetDeltaVarint2(&p1, pEnd1, &i1);
113679
- fts3GetDeltaVarint2(&p2, pEnd2, &i2);
113680
- }else if( !p2 || i1<i2 ){
113681
- fts3PutDeltaVarint(&p, &iPrev, i1);
113682
- fts3GetDeltaVarint2(&p1, pEnd1, &i1);
113683
- }else{
113684
- fts3GetDeltaVarint2(&p2, pEnd2, &i2);
113685
- }
113686
- }
113687
- break;
113688
-
113689
- case MERGE_POS_PHRASE:
113690
- case MERGE_PHRASE: {
113691
- char **ppPos = (mergetype==MERGE_PHRASE ? 0 : &p);
113692
- while( p1 && p2 ){
113693
- if( i1==i2 ){
113694
- char *pSave = p;
113695
- sqlite3_int64 iPrevSave = iPrev;
113696
- fts3PutDeltaVarint(&p, &iPrev, i1);
113697
- if( 0==fts3PoslistPhraseMerge(ppPos, nParam1, 0, 1, &p1, &p2) ){
113698
- p = pSave;
113699
- iPrev = iPrevSave;
113700
- }else{
113701
- nDoc++;
113702
- }
113703
- fts3GetDeltaVarint2(&p1, pEnd1, &i1);
113704
- fts3GetDeltaVarint2(&p2, pEnd2, &i2);
113705
- }else if( i1<i2 ){
113706
- fts3PoslistCopy(0, &p1);
113707
- fts3GetDeltaVarint2(&p1, pEnd1, &i1);
113708
- }else{
113709
- fts3PoslistCopy(0, &p2);
113710
- fts3GetDeltaVarint2(&p2, pEnd2, &i2);
113711
- }
113712
- }
113713
- break;
113714
- }
113715
-
113716
- default: assert( mergetype==MERGE_POS_NEAR || mergetype==MERGE_NEAR ); {
113717
- char *aTmp = 0;
113718
- char **ppPos = 0;
113719
-
113720
- if( mergetype==MERGE_POS_NEAR ){
113721
- ppPos = &p;
113722
- aTmp = sqlite3_malloc(2*(n1+n2+1));
113723
- if( !aTmp ){
113724
- return SQLITE_NOMEM;
113725
- }
113726
- }
113727
-
113728
- while( p1 && p2 ){
113729
- if( i1==i2 ){
113730
- char *pSave = p;
113731
- sqlite3_int64 iPrevSave = iPrev;
113732
- fts3PutDeltaVarint(&p, &iPrev, i1);
113733
-
113734
- if( !fts3PoslistNearMerge(ppPos, aTmp, nParam1, nParam2, &p1, &p2) ){
113735
- iPrev = iPrevSave;
113736
- p = pSave;
113737
- }
113738
-
113739
- fts3GetDeltaVarint2(&p1, pEnd1, &i1);
113740
- fts3GetDeltaVarint2(&p2, pEnd2, &i2);
113741
- }else if( i1<i2 ){
113742
- fts3PoslistCopy(0, &p1);
113743
- fts3GetDeltaVarint2(&p1, pEnd1, &i1);
113744
- }else{
113745
- fts3PoslistCopy(0, &p2);
113746
- fts3GetDeltaVarint2(&p2, pEnd2, &i2);
113747
- }
113748
- }
113749
- sqlite3_free(aTmp);
113750
- break;
113751
- }
113752
- }
113753
-
113754
- if( pnDoc ) *pnDoc = nDoc;
113755
- *pnBuffer = (int)(p-aBuffer);
113756
- return SQLITE_OK;
113790
+ char *pTmp1 = aTmp;
113791
+ char *pTmp2;
113792
+ char *aTmp2;
113793
+ int res = 1;
113794
+
113795
+ fts3PoslistPhraseMerge(&pTmp1, nRight, 0, 0, pp1, pp2);
113796
+ aTmp2 = pTmp2 = pTmp1;
113797
+ *pp1 = p1;
113798
+ *pp2 = p2;
113799
+ fts3PoslistPhraseMerge(&pTmp2, nLeft, 1, 0, pp2, pp1);
113800
+ if( pTmp1!=aTmp && pTmp2!=aTmp2 ){
113801
+ fts3PoslistMerge(pp, &aTmp, &aTmp2);
113802
+ }else if( pTmp1!=aTmp ){
113803
+ fts3PoslistCopy(pp, &aTmp);
113804
+ }else if( pTmp2!=aTmp2 ){
113805
+ fts3PoslistCopy(pp, &aTmp2);
113806
+ }else{
113807
+ res = 0;
113808
+ }
113809
+
113810
+ return res;
113757113811
}
113758113812
113759113813
/*
113760113814
** A pointer to an instance of this structure is used as the context
113761113815
** argument to sqlite3Fts3SegReaderIterate()
@@ -113764,10 +113818,152 @@
113764113818
struct TermSelect {
113765113819
int isReqPos;
113766113820
char *aaOutput[16]; /* Malloc'd output buffer */
113767113821
int anOutput[16]; /* Size of output in bytes */
113768113822
};
113823
+
113824
+
113825
+static void fts3GetDeltaVarint3(
113826
+ char **pp,
113827
+ char *pEnd,
113828
+ int bDescIdx,
113829
+ sqlite3_int64 *pVal
113830
+){
113831
+ if( *pp>=pEnd ){
113832
+ *pp = 0;
113833
+ }else{
113834
+ sqlite3_int64 iVal;
113835
+ *pp += sqlite3Fts3GetVarint(*pp, &iVal);
113836
+ if( bDescIdx ){
113837
+ *pVal -= iVal;
113838
+ }else{
113839
+ *pVal += iVal;
113840
+ }
113841
+ }
113842
+}
113843
+
113844
+static void fts3PutDeltaVarint3(
113845
+ char **pp, /* IN/OUT: Output pointer */
113846
+ int bDescIdx, /* True for descending docids */
113847
+ sqlite3_int64 *piPrev, /* IN/OUT: Previous value written to list */
113848
+ int *pbFirst, /* IN/OUT: True after first int written */
113849
+ sqlite3_int64 iVal /* Write this value to the list */
113850
+){
113851
+ sqlite3_int64 iWrite;
113852
+ if( bDescIdx==0 || *pbFirst==0 ){
113853
+ iWrite = iVal - *piPrev;
113854
+ }else{
113855
+ iWrite = *piPrev - iVal;
113856
+ }
113857
+ assert( *pbFirst || *piPrev==0 );
113858
+ assert( *pbFirst==0 || iWrite>0 );
113859
+ *pp += sqlite3Fts3PutVarint(*pp, iWrite);
113860
+ *piPrev = iVal;
113861
+ *pbFirst = 1;
113862
+}
113863
+
113864
+#define COMPARE_DOCID(i1, i2) ((bDescIdx?-1:1) * (i1-i2))
113865
+
113866
+static int fts3DoclistOrMerge(
113867
+ int bDescIdx, /* True if arguments are desc */
113868
+ char *a1, int n1, /* First doclist */
113869
+ char *a2, int n2, /* Second doclist */
113870
+ char **paOut, int *pnOut /* OUT: Malloc'd doclist */
113871
+){
113872
+ sqlite3_int64 i1 = 0;
113873
+ sqlite3_int64 i2 = 0;
113874
+ sqlite3_int64 iPrev = 0;
113875
+ char *pEnd1 = &a1[n1];
113876
+ char *pEnd2 = &a2[n2];
113877
+ char *p1 = a1;
113878
+ char *p2 = a2;
113879
+ char *p;
113880
+ char *aOut;
113881
+ int bFirstOut = 0;
113882
+
113883
+ *paOut = 0;
113884
+ *pnOut = 0;
113885
+ aOut = sqlite3_malloc(n1+n2);
113886
+ if( !aOut ) return SQLITE_NOMEM;
113887
+
113888
+ p = aOut;
113889
+ fts3GetDeltaVarint3(&p1, pEnd1, 0, &i1);
113890
+ fts3GetDeltaVarint3(&p2, pEnd2, 0, &i2);
113891
+ while( p1 || p2 ){
113892
+ sqlite3_int64 iDiff = COMPARE_DOCID(i1, i2);
113893
+
113894
+ if( p2 && p1 && iDiff==0 ){
113895
+ fts3PutDeltaVarint3(&p, bDescIdx, &iPrev, &bFirstOut, i1);
113896
+ fts3PoslistMerge(&p, &p1, &p2);
113897
+ fts3GetDeltaVarint3(&p1, pEnd1, bDescIdx, &i1);
113898
+ fts3GetDeltaVarint3(&p2, pEnd2, bDescIdx, &i2);
113899
+ }else if( !p2 || (p1 && iDiff<0) ){
113900
+ fts3PutDeltaVarint3(&p, bDescIdx, &iPrev, &bFirstOut, i1);
113901
+ fts3PoslistCopy(&p, &p1);
113902
+ fts3GetDeltaVarint3(&p1, pEnd1, bDescIdx, &i1);
113903
+ }else{
113904
+ fts3PutDeltaVarint3(&p, bDescIdx, &iPrev, &bFirstOut, i2);
113905
+ fts3PoslistCopy(&p, &p2);
113906
+ fts3GetDeltaVarint3(&p2, pEnd2, bDescIdx, &i2);
113907
+ }
113908
+ }
113909
+
113910
+ *paOut = aOut;
113911
+ *pnOut = (p-aOut);
113912
+ return SQLITE_OK;
113913
+}
113914
+
113915
+static void fts3DoclistPhraseMerge(
113916
+ int bDescIdx, /* True if arguments are desc */
113917
+ int nDist, /* Distance from left to right (1=adjacent) */
113918
+ char *aLeft, int nLeft, /* Left doclist */
113919
+ char *aRight, int *pnRight /* IN/OUT: Right/output doclist */
113920
+){
113921
+ sqlite3_int64 i1 = 0;
113922
+ sqlite3_int64 i2 = 0;
113923
+ sqlite3_int64 iPrev = 0;
113924
+ char *pEnd1 = &aLeft[nLeft];
113925
+ char *pEnd2 = &aRight[*pnRight];
113926
+ char *p1 = aLeft;
113927
+ char *p2 = aRight;
113928
+ char *p;
113929
+ int bFirstOut = 0;
113930
+ char *aOut = aRight;
113931
+
113932
+ assert( nDist>0 );
113933
+
113934
+ p = aOut;
113935
+ fts3GetDeltaVarint3(&p1, pEnd1, 0, &i1);
113936
+ fts3GetDeltaVarint3(&p2, pEnd2, 0, &i2);
113937
+
113938
+ while( p1 && p2 ){
113939
+ sqlite3_int64 iDiff = COMPARE_DOCID(i1, i2);
113940
+ if( iDiff==0 ){
113941
+ char *pSave = p;
113942
+ sqlite3_int64 iPrevSave = iPrev;
113943
+ int bFirstOutSave = bFirstOut;
113944
+
113945
+ fts3PutDeltaVarint3(&p, bDescIdx, &iPrev, &bFirstOut, i1);
113946
+ if( 0==fts3PoslistPhraseMerge(&p, nDist, 0, 1, &p1, &p2) ){
113947
+ p = pSave;
113948
+ iPrev = iPrevSave;
113949
+ bFirstOut = bFirstOutSave;
113950
+ }
113951
+ fts3GetDeltaVarint3(&p1, pEnd1, bDescIdx, &i1);
113952
+ fts3GetDeltaVarint3(&p2, pEnd2, bDescIdx, &i2);
113953
+ }else if( iDiff<0 ){
113954
+ fts3PoslistCopy(0, &p1);
113955
+ fts3GetDeltaVarint3(&p1, pEnd1, bDescIdx, &i1);
113956
+ }else{
113957
+ fts3PoslistCopy(0, &p2);
113958
+ fts3GetDeltaVarint3(&p2, pEnd2, bDescIdx, &i2);
113959
+ }
113960
+ }
113961
+
113962
+ *pnRight = p - aOut;
113963
+}
113964
+
113769113965
113770113966
/*
113771113967
** Merge all doclists in the TermSelect.aaOutput[] array into a single
113772113968
** doclist stored in TermSelect.aaOutput[0]. If successful, delete all
113773113969
** other doclists (except the aaOutput[0] one) and return SQLITE_OK.
@@ -113774,12 +113970,11 @@
113774113970
**
113775113971
** If an OOM error occurs, return SQLITE_NOMEM. In this case it is
113776113972
** the responsibility of the caller to free any doclists left in the
113777113973
** TermSelect.aaOutput[] array.
113778113974
*/
113779
-static int fts3TermSelectMerge(TermSelect *pTS){
113780
- int mergetype = (pTS->isReqPos ? MERGE_POS_OR : MERGE_OR);
113975
+static int fts3TermSelectMerge(Fts3Table *p, TermSelect *pTS){
113781113976
char *aOut = 0;
113782113977
int nOut = 0;
113783113978
int i;
113784113979
113785113980
/* Loop through the doclists in the aaOutput[] array. Merge them all
@@ -113790,19 +113985,21 @@
113790113985
if( !aOut ){
113791113986
aOut = pTS->aaOutput[i];
113792113987
nOut = pTS->anOutput[i];
113793113988
pTS->aaOutput[i] = 0;
113794113989
}else{
113795
- int nNew = nOut + pTS->anOutput[i];
113796
- char *aNew = sqlite3_malloc(nNew);
113797
- if( !aNew ){
113990
+ int nNew;
113991
+ char *aNew;
113992
+
113993
+ int rc = fts3DoclistOrMerge(p->bDescIdx,
113994
+ pTS->aaOutput[i], pTS->anOutput[i], aOut, nOut, &aNew, &nNew
113995
+ );
113996
+ if( rc!=SQLITE_OK ){
113798113997
sqlite3_free(aOut);
113799
- return SQLITE_NOMEM;
113998
+ return rc;
113800113999
}
113801
- fts3DoclistMerge(mergetype, 0, 0,
113802
- aNew, &nNew, pTS->aaOutput[i], pTS->anOutput[i], aOut, nOut, 0
113803
- );
114000
+
113804114001
sqlite3_free(pTS->aaOutput[i]);
113805114002
sqlite3_free(aOut);
113806114003
pTS->aaOutput[i] = 0;
113807114004
aOut = aNew;
113808114005
nOut = nNew;
@@ -113834,217 +114031,241 @@
113834114031
UNUSED_PARAMETER(zTerm);
113835114032
UNUSED_PARAMETER(nTerm);
113836114033
113837114034
if( pTS->aaOutput[0]==0 ){
113838114035
/* If this is the first term selected, copy the doclist to the output
113839
- ** buffer using memcpy(). TODO: Add a way to transfer control of the
113840
- ** aDoclist buffer from the caller so as to avoid the memcpy().
113841
- */
114036
+ ** buffer using memcpy(). */
113842114037
pTS->aaOutput[0] = sqlite3_malloc(nDoclist);
113843114038
pTS->anOutput[0] = nDoclist;
113844114039
if( pTS->aaOutput[0] ){
113845114040
memcpy(pTS->aaOutput[0], aDoclist, nDoclist);
113846114041
}else{
113847114042
return SQLITE_NOMEM;
113848114043
}
113849114044
}else{
113850
- int mergetype = (pTS->isReqPos ? MERGE_POS_OR : MERGE_OR);
113851114045
char *aMerge = aDoclist;
113852114046
int nMerge = nDoclist;
113853114047
int iOut;
113854114048
113855114049
for(iOut=0; iOut<SizeofArray(pTS->aaOutput); iOut++){
113856
- char *aNew;
113857
- int nNew;
113858114050
if( pTS->aaOutput[iOut]==0 ){
113859114051
assert( iOut>0 );
113860114052
pTS->aaOutput[iOut] = aMerge;
113861114053
pTS->anOutput[iOut] = nMerge;
113862114054
break;
113863
- }
113864
-
113865
- nNew = nMerge + pTS->anOutput[iOut];
113866
- aNew = sqlite3_malloc(nNew);
113867
- if( !aNew ){
113868
- if( aMerge!=aDoclist ){
113869
- sqlite3_free(aMerge);
113870
- }
113871
- return SQLITE_NOMEM;
113872
- }
113873
- fts3DoclistMerge(mergetype, 0, 0, aNew, &nNew,
113874
- pTS->aaOutput[iOut], pTS->anOutput[iOut], aMerge, nMerge, 0
113875
- );
113876
-
113877
- if( iOut>0 ) sqlite3_free(aMerge);
113878
- sqlite3_free(pTS->aaOutput[iOut]);
113879
- pTS->aaOutput[iOut] = 0;
113880
-
113881
- aMerge = aNew;
113882
- nMerge = nNew;
113883
- if( (iOut+1)==SizeofArray(pTS->aaOutput) ){
113884
- pTS->aaOutput[iOut] = aMerge;
113885
- pTS->anOutput[iOut] = nMerge;
113886
- }
113887
- }
113888
- }
113889
- return SQLITE_OK;
113890
-}
113891
-
113892
-static int fts3DeferredTermSelect(
113893
- Fts3DeferredToken *pToken, /* Phrase token */
113894
- int isTermPos, /* True to include positions */
113895
- int *pnOut, /* OUT: Size of list */
113896
- char **ppOut /* OUT: Body of list */
113897
-){
113898
- char *aSource;
113899
- int nSource;
113900
-
113901
- aSource = sqlite3Fts3DeferredDoclist(pToken, &nSource);
113902
- if( !aSource ){
113903
- *pnOut = 0;
113904
- *ppOut = 0;
113905
- }else if( isTermPos ){
113906
- *ppOut = sqlite3_malloc(nSource);
113907
- if( !*ppOut ) return SQLITE_NOMEM;
113908
- memcpy(*ppOut, aSource, nSource);
113909
- *pnOut = nSource;
113910
- }else{
113911
- sqlite3_int64 docid;
113912
- *pnOut = sqlite3Fts3GetVarint(aSource, &docid);
113913
- *ppOut = sqlite3_malloc(*pnOut);
113914
- if( !*ppOut ) return SQLITE_NOMEM;
113915
- sqlite3Fts3PutVarint(*ppOut, docid);
113916
- }
113917
-
113918
- return SQLITE_OK;
113919
-}
113920
-
113921
-SQLITE_PRIVATE int sqlite3Fts3SegReaderCursor(
114055
+ }else{
114056
+ char *aNew;
114057
+ int nNew;
114058
+
114059
+ int rc = fts3DoclistOrMerge(p->bDescIdx, aMerge, nMerge,
114060
+ pTS->aaOutput[iOut], pTS->anOutput[iOut], &aNew, &nNew
114061
+ );
114062
+ if( rc!=SQLITE_OK ){
114063
+ if( aMerge!=aDoclist ) sqlite3_free(aMerge);
114064
+ return rc;
114065
+ }
114066
+
114067
+ if( aMerge!=aDoclist ) sqlite3_free(aMerge);
114068
+ sqlite3_free(pTS->aaOutput[iOut]);
114069
+ pTS->aaOutput[iOut] = 0;
114070
+
114071
+ aMerge = aNew;
114072
+ nMerge = nNew;
114073
+ if( (iOut+1)==SizeofArray(pTS->aaOutput) ){
114074
+ pTS->aaOutput[iOut] = aMerge;
114075
+ pTS->anOutput[iOut] = nMerge;
114076
+ }
114077
+ }
114078
+ }
114079
+ }
114080
+ return SQLITE_OK;
114081
+}
114082
+
114083
+/*
114084
+** Append SegReader object pNew to the end of the pCsr->apSegment[] array.
114085
+*/
114086
+static int fts3SegReaderCursorAppend(
114087
+ Fts3MultiSegReader *pCsr,
114088
+ Fts3SegReader *pNew
114089
+){
114090
+ if( (pCsr->nSegment%16)==0 ){
114091
+ Fts3SegReader **apNew;
114092
+ int nByte = (pCsr->nSegment + 16)*sizeof(Fts3SegReader*);
114093
+ apNew = (Fts3SegReader **)sqlite3_realloc(pCsr->apSegment, nByte);
114094
+ if( !apNew ){
114095
+ sqlite3Fts3SegReaderFree(pNew);
114096
+ return SQLITE_NOMEM;
114097
+ }
114098
+ pCsr->apSegment = apNew;
114099
+ }
114100
+ pCsr->apSegment[pCsr->nSegment++] = pNew;
114101
+ return SQLITE_OK;
114102
+}
114103
+
114104
+static int fts3SegReaderCursor(
113922114105
Fts3Table *p, /* FTS3 table handle */
114106
+ int iIndex, /* Index to search (from 0 to p->nIndex-1) */
113923114107
int iLevel, /* Level of segments to scan */
113924114108
const char *zTerm, /* Term to query for */
113925114109
int nTerm, /* Size of zTerm in bytes */
113926114110
int isPrefix, /* True for a prefix search */
113927114111
int isScan, /* True to scan from zTerm to EOF */
113928
- Fts3SegReaderCursor *pCsr /* Cursor object to populate */
114112
+ Fts3MultiSegReader *pCsr /* Cursor object to populate */
113929114113
){
113930114114
int rc = SQLITE_OK;
113931114115
int rc2;
113932
- int iAge = 0;
113933114116
sqlite3_stmt *pStmt = 0;
113934
- Fts3SegReader *pPending = 0;
113935
-
113936
- assert( iLevel==FTS3_SEGCURSOR_ALL
113937
- || iLevel==FTS3_SEGCURSOR_PENDING
113938
- || iLevel>=0
113939
- );
113940
- assert( FTS3_SEGCURSOR_PENDING<0 );
113941
- assert( FTS3_SEGCURSOR_ALL<0 );
113942
- assert( iLevel==FTS3_SEGCURSOR_ALL || (zTerm==0 && isPrefix==1) );
113943
- assert( isPrefix==0 || isScan==0 );
113944
-
113945
-
113946
- memset(pCsr, 0, sizeof(Fts3SegReaderCursor));
113947
-
113948
- /* If iLevel is less than 0, include a seg-reader for the pending-terms. */
113949
- assert( isScan==0 || fts3HashCount(&p->pendingTerms)==0 );
113950
- if( iLevel<0 && isScan==0 ){
113951
- rc = sqlite3Fts3SegReaderPending(p, zTerm, nTerm, isPrefix, &pPending);
113952
- if( rc==SQLITE_OK && pPending ){
113953
- int nByte = (sizeof(Fts3SegReader *) * 16);
113954
- pCsr->apSegment = (Fts3SegReader **)sqlite3_malloc(nByte);
113955
- if( pCsr->apSegment==0 ){
113956
- rc = SQLITE_NOMEM;
113957
- }else{
113958
- pCsr->apSegment[0] = pPending;
113959
- pCsr->nSegment = 1;
113960
- pPending = 0;
113961
- }
114117
+
114118
+ /* If iLevel is less than 0 and this is not a scan, include a seg-reader
114119
+ ** for the pending-terms. If this is a scan, then this call must be being
114120
+ ** made by an fts4aux module, not an FTS table. In this case calling
114121
+ ** Fts3SegReaderPending might segfault, as the data structures used by
114122
+ ** fts4aux are not completely populated. So it's easiest to filter these
114123
+ ** calls out here. */
114124
+ if( iLevel<0 && p->aIndex ){
114125
+ Fts3SegReader *pSeg = 0;
114126
+ rc = sqlite3Fts3SegReaderPending(p, iIndex, zTerm, nTerm, isPrefix, &pSeg);
114127
+ if( rc==SQLITE_OK && pSeg ){
114128
+ rc = fts3SegReaderCursorAppend(pCsr, pSeg);
113962114129
}
113963114130
}
113964114131
113965114132
if( iLevel!=FTS3_SEGCURSOR_PENDING ){
113966114133
if( rc==SQLITE_OK ){
113967
- rc = sqlite3Fts3AllSegdirs(p, iLevel, &pStmt);
114134
+ rc = sqlite3Fts3AllSegdirs(p, iIndex, iLevel, &pStmt);
113968114135
}
114136
+
113969114137
while( rc==SQLITE_OK && SQLITE_ROW==(rc = sqlite3_step(pStmt)) ){
114138
+ Fts3SegReader *pSeg = 0;
113970114139
113971114140
/* Read the values returned by the SELECT into local variables. */
113972114141
sqlite3_int64 iStartBlock = sqlite3_column_int64(pStmt, 1);
113973114142
sqlite3_int64 iLeavesEndBlock = sqlite3_column_int64(pStmt, 2);
113974114143
sqlite3_int64 iEndBlock = sqlite3_column_int64(pStmt, 3);
113975114144
int nRoot = sqlite3_column_bytes(pStmt, 4);
113976114145
char const *zRoot = sqlite3_column_blob(pStmt, 4);
113977114146
113978
- /* If nSegment is a multiple of 16 the array needs to be extended. */
113979
- if( (pCsr->nSegment%16)==0 ){
113980
- Fts3SegReader **apNew;
113981
- int nByte = (pCsr->nSegment + 16)*sizeof(Fts3SegReader*);
113982
- apNew = (Fts3SegReader **)sqlite3_realloc(pCsr->apSegment, nByte);
113983
- if( !apNew ){
113984
- rc = SQLITE_NOMEM;
113985
- goto finished;
113986
- }
113987
- pCsr->apSegment = apNew;
113988
- }
113989
-
113990114147
/* If zTerm is not NULL, and this segment is not stored entirely on its
113991114148
** root node, the range of leaves scanned can be reduced. Do this. */
113992114149
if( iStartBlock && zTerm ){
113993114150
sqlite3_int64 *pi = (isPrefix ? &iLeavesEndBlock : 0);
113994114151
rc = fts3SelectLeaf(p, zTerm, nTerm, zRoot, nRoot, &iStartBlock, pi);
113995114152
if( rc!=SQLITE_OK ) goto finished;
113996114153
if( isPrefix==0 && isScan==0 ) iLeavesEndBlock = iStartBlock;
113997114154
}
113998114155
113999
- rc = sqlite3Fts3SegReaderNew(iAge, iStartBlock, iLeavesEndBlock,
114000
- iEndBlock, zRoot, nRoot, &pCsr->apSegment[pCsr->nSegment]
114156
+ rc = sqlite3Fts3SegReaderNew(pCsr->nSegment+1,
114157
+ iStartBlock, iLeavesEndBlock, iEndBlock, zRoot, nRoot, &pSeg
114001114158
);
114002114159
if( rc!=SQLITE_OK ) goto finished;
114003
- pCsr->nSegment++;
114004
- iAge++;
114160
+ rc = fts3SegReaderCursorAppend(pCsr, pSeg);
114005114161
}
114006114162
}
114007114163
114008114164
finished:
114009114165
rc2 = sqlite3_reset(pStmt);
114010114166
if( rc==SQLITE_DONE ) rc = rc2;
114011
- sqlite3Fts3SegReaderFree(pPending);
114012114167
114013114168
return rc;
114014114169
}
114015114170
114171
+/*
114172
+** Set up a cursor object for iterating through a full-text index or a
114173
+** single level therein.
114174
+*/
114175
+SQLITE_PRIVATE int sqlite3Fts3SegReaderCursor(
114176
+ Fts3Table *p, /* FTS3 table handle */
114177
+ int iIndex, /* Index to search (from 0 to p->nIndex-1) */
114178
+ int iLevel, /* Level of segments to scan */
114179
+ const char *zTerm, /* Term to query for */
114180
+ int nTerm, /* Size of zTerm in bytes */
114181
+ int isPrefix, /* True for a prefix search */
114182
+ int isScan, /* True to scan from zTerm to EOF */
114183
+ Fts3MultiSegReader *pCsr /* Cursor object to populate */
114184
+){
114185
+ assert( iIndex>=0 && iIndex<p->nIndex );
114186
+ assert( iLevel==FTS3_SEGCURSOR_ALL
114187
+ || iLevel==FTS3_SEGCURSOR_PENDING
114188
+ || iLevel>=0
114189
+ );
114190
+ assert( iLevel<FTS3_SEGDIR_MAXLEVEL );
114191
+ assert( FTS3_SEGCURSOR_ALL<0 && FTS3_SEGCURSOR_PENDING<0 );
114192
+ assert( isPrefix==0 || isScan==0 );
114016114193
114017
-static int fts3TermSegReaderCursor(
114194
+ /* "isScan" is only set to true by the ft4aux module, an ordinary
114195
+ ** full-text tables. */
114196
+ assert( isScan==0 || p->aIndex==0 );
114197
+
114198
+ memset(pCsr, 0, sizeof(Fts3MultiSegReader));
114199
+
114200
+ return fts3SegReaderCursor(
114201
+ p, iIndex, iLevel, zTerm, nTerm, isPrefix, isScan, pCsr
114202
+ );
114203
+}
114204
+
114205
+static int fts3SegReaderCursorAddZero(
114206
+ Fts3Table *p,
114207
+ const char *zTerm,
114208
+ int nTerm,
114209
+ Fts3MultiSegReader *pCsr
114210
+){
114211
+ return fts3SegReaderCursor(p, 0, FTS3_SEGCURSOR_ALL, zTerm, nTerm, 0, 0,pCsr);
114212
+}
114213
+
114214
+
114215
+SQLITE_PRIVATE int sqlite3Fts3TermSegReaderCursor(
114018114216
Fts3Cursor *pCsr, /* Virtual table cursor handle */
114019114217
const char *zTerm, /* Term to query for */
114020114218
int nTerm, /* Size of zTerm in bytes */
114021114219
int isPrefix, /* True for a prefix search */
114022
- Fts3SegReaderCursor **ppSegcsr /* OUT: Allocated seg-reader cursor */
114220
+ Fts3MultiSegReader **ppSegcsr /* OUT: Allocated seg-reader cursor */
114023114221
){
114024
- Fts3SegReaderCursor *pSegcsr; /* Object to allocate and return */
114222
+ Fts3MultiSegReader *pSegcsr; /* Object to allocate and return */
114025114223
int rc = SQLITE_NOMEM; /* Return code */
114026114224
114027
- pSegcsr = sqlite3_malloc(sizeof(Fts3SegReaderCursor));
114225
+ pSegcsr = sqlite3_malloc(sizeof(Fts3MultiSegReader));
114028114226
if( pSegcsr ){
114227
+ int i;
114228
+ int bFound = 0; /* True once an index has been found */
114029114229
Fts3Table *p = (Fts3Table *)pCsr->base.pVtab;
114030
- int i;
114031
- int nCost = 0;
114032
- rc = sqlite3Fts3SegReaderCursor(
114033
- p, FTS3_SEGCURSOR_ALL, zTerm, nTerm, isPrefix, 0, pSegcsr);
114034
-
114035
- for(i=0; rc==SQLITE_OK && i<pSegcsr->nSegment; i++){
114036
- rc = sqlite3Fts3SegReaderCost(pCsr, pSegcsr->apSegment[i], &nCost);
114037
- }
114038
- pSegcsr->nCost = nCost;
114230
+
114231
+ if( isPrefix ){
114232
+ for(i=1; bFound==0 && i<p->nIndex; i++){
114233
+ if( p->aIndex[i].nPrefix==nTerm ){
114234
+ bFound = 1;
114235
+ rc = sqlite3Fts3SegReaderCursor(
114236
+ p, i, FTS3_SEGCURSOR_ALL, zTerm, nTerm, 0, 0, pSegcsr);
114237
+ pSegcsr->bLookup = 1;
114238
+ }
114239
+ }
114240
+
114241
+ for(i=1; bFound==0 && i<p->nIndex; i++){
114242
+ if( p->aIndex[i].nPrefix==nTerm+1 ){
114243
+ bFound = 1;
114244
+ rc = sqlite3Fts3SegReaderCursor(
114245
+ p, i, FTS3_SEGCURSOR_ALL, zTerm, nTerm, 1, 0, pSegcsr
114246
+ );
114247
+ if( rc==SQLITE_OK ){
114248
+ rc = fts3SegReaderCursorAddZero(p, zTerm, nTerm, pSegcsr);
114249
+ }
114250
+ }
114251
+ }
114252
+ }
114253
+
114254
+ if( bFound==0 ){
114255
+ rc = sqlite3Fts3SegReaderCursor(
114256
+ p, 0, FTS3_SEGCURSOR_ALL, zTerm, nTerm, isPrefix, 0, pSegcsr
114257
+ );
114258
+ pSegcsr->bLookup = !isPrefix;
114259
+ }
114039114260
}
114040114261
114041114262
*ppSegcsr = pSegcsr;
114042114263
return rc;
114043114264
}
114044114265
114045
-static void fts3SegReaderCursorFree(Fts3SegReaderCursor *pSegcsr){
114266
+static void fts3SegReaderCursorFree(Fts3MultiSegReader *pSegcsr){
114046114267
sqlite3Fts3SegReaderFinish(pSegcsr);
114047114268
sqlite3_free(pSegcsr);
114048114269
}
114049114270
114050114271
/*
@@ -114065,11 +114286,11 @@
114065114286
int isReqPos, /* True to include position lists in output */
114066114287
int *pnOut, /* OUT: Size of buffer at *ppOut */
114067114288
char **ppOut /* OUT: Malloced result buffer */
114068114289
){
114069114290
int rc; /* Return code */
114070
- Fts3SegReaderCursor *pSegcsr; /* Seg-reader cursor for this term */
114291
+ Fts3MultiSegReader *pSegcsr; /* Seg-reader cursor for this term */
114071114292
TermSelect tsc; /* Context object for fts3TermSelectCb() */
114072114293
Fts3SegFilter filter; /* Segment term filter configuration */
114073114294
114074114295
pSegcsr = pTok->pSegcsr;
114075114296
memset(&tsc, 0, sizeof(TermSelect));
@@ -114091,11 +114312,11 @@
114091114312
pSegcsr->zTerm, pSegcsr->nTerm, pSegcsr->aDoclist, pSegcsr->nDoclist
114092114313
);
114093114314
}
114094114315
114095114316
if( rc==SQLITE_OK ){
114096
- rc = fts3TermSelectMerge(&tsc);
114317
+ rc = fts3TermSelectMerge(p, &tsc);
114097114318
}
114098114319
if( rc==SQLITE_OK ){
114099114320
*ppOut = tsc.aaOutput[0];
114100114321
*pnOut = tsc.anOutput[0];
114101114322
}else{
@@ -114141,664 +114362,10 @@
114141114362
}
114142114363
114143114364
return nDoc;
114144114365
}
114145114366
114146
-/*
114147
-** Call sqlite3Fts3DeferToken() for each token in the expression pExpr.
114148
-*/
114149
-static int fts3DeferExpression(Fts3Cursor *pCsr, Fts3Expr *pExpr){
114150
- int rc = SQLITE_OK;
114151
- if( pExpr ){
114152
- rc = fts3DeferExpression(pCsr, pExpr->pLeft);
114153
- if( rc==SQLITE_OK ){
114154
- rc = fts3DeferExpression(pCsr, pExpr->pRight);
114155
- }
114156
- if( pExpr->eType==FTSQUERY_PHRASE ){
114157
- int iCol = pExpr->pPhrase->iColumn;
114158
- int i;
114159
- for(i=0; rc==SQLITE_OK && i<pExpr->pPhrase->nToken; i++){
114160
- Fts3PhraseToken *pToken = &pExpr->pPhrase->aToken[i];
114161
- if( pToken->pDeferred==0 ){
114162
- rc = sqlite3Fts3DeferToken(pCsr, pToken, iCol);
114163
- }
114164
- }
114165
- }
114166
- }
114167
- return rc;
114168
-}
114169
-
114170
-/*
114171
-** This function removes the position information from a doclist. When
114172
-** called, buffer aList (size *pnList bytes) contains a doclist that includes
114173
-** position information. This function removes the position information so
114174
-** that aList contains only docids, and adjusts *pnList to reflect the new
114175
-** (possibly reduced) size of the doclist.
114176
-*/
114177
-static void fts3DoclistStripPositions(
114178
- char *aList, /* IN/OUT: Buffer containing doclist */
114179
- int *pnList /* IN/OUT: Size of doclist in bytes */
114180
-){
114181
- if( aList ){
114182
- char *aEnd = &aList[*pnList]; /* Pointer to one byte after EOF */
114183
- char *p = aList; /* Input cursor */
114184
- char *pOut = aList; /* Output cursor */
114185
-
114186
- while( p<aEnd ){
114187
- sqlite3_int64 delta;
114188
- p += sqlite3Fts3GetVarint(p, &delta);
114189
- fts3PoslistCopy(0, &p);
114190
- pOut += sqlite3Fts3PutVarint(pOut, delta);
114191
- }
114192
-
114193
- *pnList = (int)(pOut - aList);
114194
- }
114195
-}
114196
-
114197
-/*
114198
-** Return a DocList corresponding to the phrase *pPhrase.
114199
-**
114200
-** If this function returns SQLITE_OK, but *pnOut is set to a negative value,
114201
-** then no tokens in the phrase were looked up in the full-text index. This
114202
-** is only possible when this function is called from within xFilter(). The
114203
-** caller should assume that all documents match the phrase. The actual
114204
-** filtering will take place in xNext().
114205
-*/
114206
-static int fts3PhraseSelect(
114207
- Fts3Cursor *pCsr, /* Virtual table cursor handle */
114208
- Fts3Phrase *pPhrase, /* Phrase to return a doclist for */
114209
- int isReqPos, /* True if output should contain positions */
114210
- char **paOut, /* OUT: Pointer to malloc'd result buffer */
114211
- int *pnOut /* OUT: Size of buffer at *paOut */
114212
-){
114213
- char *pOut = 0;
114214
- int nOut = 0;
114215
- int rc = SQLITE_OK;
114216
- int ii;
114217
- int iCol = pPhrase->iColumn;
114218
- int isTermPos = (pPhrase->nToken>1 || isReqPos);
114219
- Fts3Table *p = (Fts3Table *)pCsr->base.pVtab;
114220
- int isFirst = 1;
114221
-
114222
- int iPrevTok = 0;
114223
- int nDoc = 0;
114224
-
114225
- /* If this is an xFilter() evaluation, create a segment-reader for each
114226
- ** phrase token. Or, if this is an xNext() or snippet/offsets/matchinfo
114227
- ** evaluation, only create segment-readers if there are no Fts3DeferredToken
114228
- ** objects attached to the phrase-tokens.
114229
- */
114230
- for(ii=0; ii<pPhrase->nToken; ii++){
114231
- Fts3PhraseToken *pTok = &pPhrase->aToken[ii];
114232
- if( pTok->pSegcsr==0 ){
114233
- if( (pCsr->eEvalmode==FTS3_EVAL_FILTER)
114234
- || (pCsr->eEvalmode==FTS3_EVAL_NEXT && pCsr->pDeferred==0)
114235
- || (pCsr->eEvalmode==FTS3_EVAL_MATCHINFO && pTok->bFulltext)
114236
- ){
114237
- rc = fts3TermSegReaderCursor(
114238
- pCsr, pTok->z, pTok->n, pTok->isPrefix, &pTok->pSegcsr
114239
- );
114240
- if( rc!=SQLITE_OK ) return rc;
114241
- }
114242
- }
114243
- }
114244
-
114245
- for(ii=0; ii<pPhrase->nToken; ii++){
114246
- Fts3PhraseToken *pTok; /* Token to find doclist for */
114247
- int iTok = 0; /* The token being queried this iteration */
114248
- char *pList = 0; /* Pointer to token doclist */
114249
- int nList = 0; /* Size of buffer at pList */
114250
-
114251
- /* Select a token to process. If this is an xFilter() call, then tokens
114252
- ** are processed in order from least to most costly. Otherwise, tokens
114253
- ** are processed in the order in which they occur in the phrase.
114254
- */
114255
- if( pCsr->eEvalmode==FTS3_EVAL_MATCHINFO ){
114256
- assert( isReqPos );
114257
- iTok = ii;
114258
- pTok = &pPhrase->aToken[iTok];
114259
- if( pTok->bFulltext==0 ) continue;
114260
- }else if( pCsr->eEvalmode==FTS3_EVAL_NEXT || isReqPos ){
114261
- iTok = ii;
114262
- pTok = &pPhrase->aToken[iTok];
114263
- }else{
114264
- int nMinCost = 0x7FFFFFFF;
114265
- int jj;
114266
-
114267
- /* Find the remaining token with the lowest cost. */
114268
- for(jj=0; jj<pPhrase->nToken; jj++){
114269
- Fts3SegReaderCursor *pSegcsr = pPhrase->aToken[jj].pSegcsr;
114270
- if( pSegcsr && pSegcsr->nCost<nMinCost ){
114271
- iTok = jj;
114272
- nMinCost = pSegcsr->nCost;
114273
- }
114274
- }
114275
- pTok = &pPhrase->aToken[iTok];
114276
-
114277
- /* This branch is taken if it is determined that loading the doclist
114278
- ** for the next token would require more IO than loading all documents
114279
- ** currently identified by doclist pOut/nOut. No further doclists will
114280
- ** be loaded from the full-text index for this phrase.
114281
- */
114282
- if( nMinCost>nDoc && ii>0 ){
114283
- rc = fts3DeferExpression(pCsr, pCsr->pExpr);
114284
- break;
114285
- }
114286
- }
114287
-
114288
- if( pCsr->eEvalmode==FTS3_EVAL_NEXT && pTok->pDeferred ){
114289
- rc = fts3DeferredTermSelect(pTok->pDeferred, isTermPos, &nList, &pList);
114290
- }else{
114291
- if( pTok->pSegcsr ){
114292
- rc = fts3TermSelect(p, pTok, iCol, isTermPos, &nList, &pList);
114293
- }
114294
- pTok->bFulltext = 1;
114295
- }
114296
- assert( rc!=SQLITE_OK || pCsr->eEvalmode || pTok->pSegcsr==0 );
114297
- if( rc!=SQLITE_OK ) break;
114298
-
114299
- if( isFirst ){
114300
- pOut = pList;
114301
- nOut = nList;
114302
- if( pCsr->eEvalmode==FTS3_EVAL_FILTER && pPhrase->nToken>1 ){
114303
- nDoc = fts3DoclistCountDocids(1, pOut, nOut);
114304
- }
114305
- isFirst = 0;
114306
- iPrevTok = iTok;
114307
- }else{
114308
- /* Merge the new term list and the current output. */
114309
- char *aLeft, *aRight;
114310
- int nLeft, nRight;
114311
- int nDist;
114312
- int mt;
114313
-
114314
- /* If this is the final token of the phrase, and positions were not
114315
- ** requested by the caller, use MERGE_PHRASE instead of POS_PHRASE.
114316
- ** This drops the position information from the output list.
114317
- */
114318
- mt = MERGE_POS_PHRASE;
114319
- if( ii==pPhrase->nToken-1 && !isReqPos ) mt = MERGE_PHRASE;
114320
-
114321
- assert( iPrevTok!=iTok );
114322
- if( iPrevTok<iTok ){
114323
- aLeft = pOut;
114324
- nLeft = nOut;
114325
- aRight = pList;
114326
- nRight = nList;
114327
- nDist = iTok-iPrevTok;
114328
- iPrevTok = iTok;
114329
- }else{
114330
- aRight = pOut;
114331
- nRight = nOut;
114332
- aLeft = pList;
114333
- nLeft = nList;
114334
- nDist = iPrevTok-iTok;
114335
- }
114336
- pOut = aRight;
114337
- fts3DoclistMerge(
114338
- mt, nDist, 0, pOut, &nOut, aLeft, nLeft, aRight, nRight, &nDoc
114339
- );
114340
- sqlite3_free(aLeft);
114341
- }
114342
- assert( nOut==0 || pOut!=0 );
114343
- }
114344
-
114345
- if( rc==SQLITE_OK ){
114346
- if( ii!=pPhrase->nToken ){
114347
- assert( pCsr->eEvalmode==FTS3_EVAL_FILTER && isReqPos==0 );
114348
- fts3DoclistStripPositions(pOut, &nOut);
114349
- }
114350
- *paOut = pOut;
114351
- *pnOut = nOut;
114352
- }else{
114353
- sqlite3_free(pOut);
114354
- }
114355
- return rc;
114356
-}
114357
-
114358
-/*
114359
-** This function merges two doclists according to the requirements of a
114360
-** NEAR operator.
114361
-**
114362
-** Both input doclists must include position information. The output doclist
114363
-** includes position information if the first argument to this function
114364
-** is MERGE_POS_NEAR, or does not if it is MERGE_NEAR.
114365
-*/
114366
-static int fts3NearMerge(
114367
- int mergetype, /* MERGE_POS_NEAR or MERGE_NEAR */
114368
- int nNear, /* Parameter to NEAR operator */
114369
- int nTokenLeft, /* Number of tokens in LHS phrase arg */
114370
- char *aLeft, /* Doclist for LHS (incl. positions) */
114371
- int nLeft, /* Size of LHS doclist in bytes */
114372
- int nTokenRight, /* As nTokenLeft */
114373
- char *aRight, /* As aLeft */
114374
- int nRight, /* As nRight */
114375
- char **paOut, /* OUT: Results of merge (malloced) */
114376
- int *pnOut /* OUT: Sized of output buffer */
114377
-){
114378
- char *aOut; /* Buffer to write output doclist to */
114379
- int rc; /* Return code */
114380
-
114381
- assert( mergetype==MERGE_POS_NEAR || MERGE_NEAR );
114382
-
114383
- aOut = sqlite3_malloc(nLeft+nRight+1);
114384
- if( aOut==0 ){
114385
- rc = SQLITE_NOMEM;
114386
- }else{
114387
- rc = fts3DoclistMerge(mergetype, nNear+nTokenRight, nNear+nTokenLeft,
114388
- aOut, pnOut, aLeft, nLeft, aRight, nRight, 0
114389
- );
114390
- if( rc!=SQLITE_OK ){
114391
- sqlite3_free(aOut);
114392
- aOut = 0;
114393
- }
114394
- }
114395
-
114396
- *paOut = aOut;
114397
- return rc;
114398
-}
114399
-
114400
-/*
114401
-** This function is used as part of the processing for the snippet() and
114402
-** offsets() functions.
114403
-**
114404
-** Both pLeft and pRight are expression nodes of type FTSQUERY_PHRASE. Both
114405
-** have their respective doclists (including position information) loaded
114406
-** in Fts3Expr.aDoclist/nDoclist. This function removes all entries from
114407
-** each doclist that are not within nNear tokens of a corresponding entry
114408
-** in the other doclist.
114409
-*/
114410
-SQLITE_PRIVATE int sqlite3Fts3ExprNearTrim(Fts3Expr *pLeft, Fts3Expr *pRight, int nNear){
114411
- int rc; /* Return code */
114412
-
114413
- assert( pLeft->eType==FTSQUERY_PHRASE );
114414
- assert( pRight->eType==FTSQUERY_PHRASE );
114415
- assert( pLeft->isLoaded && pRight->isLoaded );
114416
-
114417
- if( pLeft->aDoclist==0 || pRight->aDoclist==0 ){
114418
- sqlite3_free(pLeft->aDoclist);
114419
- sqlite3_free(pRight->aDoclist);
114420
- pRight->aDoclist = 0;
114421
- pLeft->aDoclist = 0;
114422
- rc = SQLITE_OK;
114423
- }else{
114424
- char *aOut; /* Buffer in which to assemble new doclist */
114425
- int nOut; /* Size of buffer aOut in bytes */
114426
-
114427
- rc = fts3NearMerge(MERGE_POS_NEAR, nNear,
114428
- pLeft->pPhrase->nToken, pLeft->aDoclist, pLeft->nDoclist,
114429
- pRight->pPhrase->nToken, pRight->aDoclist, pRight->nDoclist,
114430
- &aOut, &nOut
114431
- );
114432
- if( rc!=SQLITE_OK ) return rc;
114433
- sqlite3_free(pRight->aDoclist);
114434
- pRight->aDoclist = aOut;
114435
- pRight->nDoclist = nOut;
114436
-
114437
- rc = fts3NearMerge(MERGE_POS_NEAR, nNear,
114438
- pRight->pPhrase->nToken, pRight->aDoclist, pRight->nDoclist,
114439
- pLeft->pPhrase->nToken, pLeft->aDoclist, pLeft->nDoclist,
114440
- &aOut, &nOut
114441
- );
114442
- sqlite3_free(pLeft->aDoclist);
114443
- pLeft->aDoclist = aOut;
114444
- pLeft->nDoclist = nOut;
114445
- }
114446
- return rc;
114447
-}
114448
-
114449
-
114450
-/*
114451
-** Allocate an Fts3SegReaderArray for each token in the expression pExpr.
114452
-** The allocated objects are stored in the Fts3PhraseToken.pArray member
114453
-** variables of each token structure.
114454
-*/
114455
-static int fts3ExprAllocateSegReaders(
114456
- Fts3Cursor *pCsr, /* FTS3 table */
114457
- Fts3Expr *pExpr, /* Expression to create seg-readers for */
114458
- int *pnExpr /* OUT: Number of AND'd expressions */
114459
-){
114460
- int rc = SQLITE_OK; /* Return code */
114461
-
114462
- assert( pCsr->eEvalmode==FTS3_EVAL_FILTER );
114463
- if( pnExpr && pExpr->eType!=FTSQUERY_AND ){
114464
- (*pnExpr)++;
114465
- pnExpr = 0;
114466
- }
114467
-
114468
- if( pExpr->eType==FTSQUERY_PHRASE ){
114469
- Fts3Phrase *pPhrase = pExpr->pPhrase;
114470
- int ii;
114471
-
114472
- for(ii=0; rc==SQLITE_OK && ii<pPhrase->nToken; ii++){
114473
- Fts3PhraseToken *pTok = &pPhrase->aToken[ii];
114474
- if( pTok->pSegcsr==0 ){
114475
- rc = fts3TermSegReaderCursor(
114476
- pCsr, pTok->z, pTok->n, pTok->isPrefix, &pTok->pSegcsr
114477
- );
114478
- }
114479
- }
114480
- }else{
114481
- rc = fts3ExprAllocateSegReaders(pCsr, pExpr->pLeft, pnExpr);
114482
- if( rc==SQLITE_OK ){
114483
- rc = fts3ExprAllocateSegReaders(pCsr, pExpr->pRight, pnExpr);
114484
- }
114485
- }
114486
- return rc;
114487
-}
114488
-
114489
-/*
114490
-** Free the Fts3SegReaderArray objects associated with each token in the
114491
-** expression pExpr. In other words, this function frees the resources
114492
-** allocated by fts3ExprAllocateSegReaders().
114493
-*/
114494
-static void fts3ExprFreeSegReaders(Fts3Expr *pExpr){
114495
- if( pExpr ){
114496
- Fts3Phrase *pPhrase = pExpr->pPhrase;
114497
- if( pPhrase ){
114498
- int kk;
114499
- for(kk=0; kk<pPhrase->nToken; kk++){
114500
- fts3SegReaderCursorFree(pPhrase->aToken[kk].pSegcsr);
114501
- pPhrase->aToken[kk].pSegcsr = 0;
114502
- }
114503
- }
114504
- fts3ExprFreeSegReaders(pExpr->pLeft);
114505
- fts3ExprFreeSegReaders(pExpr->pRight);
114506
- }
114507
-}
114508
-
114509
-/*
114510
-** Return the sum of the costs of all tokens in the expression pExpr. This
114511
-** function must be called after Fts3SegReaderArrays have been allocated
114512
-** for all tokens using fts3ExprAllocateSegReaders().
114513
-*/
114514
-static int fts3ExprCost(Fts3Expr *pExpr){
114515
- int nCost; /* Return value */
114516
- if( pExpr->eType==FTSQUERY_PHRASE ){
114517
- Fts3Phrase *pPhrase = pExpr->pPhrase;
114518
- int ii;
114519
- nCost = 0;
114520
- for(ii=0; ii<pPhrase->nToken; ii++){
114521
- Fts3SegReaderCursor *pSegcsr = pPhrase->aToken[ii].pSegcsr;
114522
- if( pSegcsr ) nCost += pSegcsr->nCost;
114523
- }
114524
- }else{
114525
- nCost = fts3ExprCost(pExpr->pLeft) + fts3ExprCost(pExpr->pRight);
114526
- }
114527
- return nCost;
114528
-}
114529
-
114530
-/*
114531
-** The following is a helper function (and type) for fts3EvalExpr(). It
114532
-** must be called after Fts3SegReaders have been allocated for every token
114533
-** in the expression. See the context it is called from in fts3EvalExpr()
114534
-** for further explanation.
114535
-*/
114536
-typedef struct ExprAndCost ExprAndCost;
114537
-struct ExprAndCost {
114538
- Fts3Expr *pExpr;
114539
- int nCost;
114540
-};
114541
-static void fts3ExprAssignCosts(
114542
- Fts3Expr *pExpr, /* Expression to create seg-readers for */
114543
- ExprAndCost **ppExprCost /* OUT: Write to *ppExprCost */
114544
-){
114545
- if( pExpr->eType==FTSQUERY_AND ){
114546
- fts3ExprAssignCosts(pExpr->pLeft, ppExprCost);
114547
- fts3ExprAssignCosts(pExpr->pRight, ppExprCost);
114548
- }else{
114549
- (*ppExprCost)->pExpr = pExpr;
114550
- (*ppExprCost)->nCost = fts3ExprCost(pExpr);
114551
- (*ppExprCost)++;
114552
- }
114553
-}
114554
-
114555
-/*
114556
-** Evaluate the full-text expression pExpr against FTS3 table pTab. Store
114557
-** the resulting doclist in *paOut and *pnOut. This routine mallocs for
114558
-** the space needed to store the output. The caller is responsible for
114559
-** freeing the space when it has finished.
114560
-**
114561
-** This function is called in two distinct contexts:
114562
-**
114563
-** * From within the virtual table xFilter() method. In this case, the
114564
-** output doclist contains entries for all rows in the table, based on
114565
-** data read from the full-text index.
114566
-**
114567
-** In this case, if the query expression contains one or more tokens that
114568
-** are very common, then the returned doclist may contain a superset of
114569
-** the documents that actually match the expression.
114570
-**
114571
-** * From within the virtual table xNext() method. This call is only made
114572
-** if the call from within xFilter() found that there were very common
114573
-** tokens in the query expression and did return a superset of the
114574
-** matching documents. In this case the returned doclist contains only
114575
-** entries that correspond to the current row of the table. Instead of
114576
-** reading the data for each token from the full-text index, the data is
114577
-** already available in-memory in the Fts3PhraseToken.pDeferred structures.
114578
-** See fts3EvalDeferred() for how it gets there.
114579
-**
114580
-** In the first case above, Fts3Cursor.doDeferred==0. In the second (if it is
114581
-** required) Fts3Cursor.doDeferred==1.
114582
-**
114583
-** If the SQLite invokes the snippet(), offsets() or matchinfo() function
114584
-** as part of a SELECT on an FTS3 table, this function is called on each
114585
-** individual phrase expression in the query. If there were very common tokens
114586
-** found in the xFilter() call, then this function is called once for phrase
114587
-** for each row visited, and the returned doclist contains entries for the
114588
-** current row only. Otherwise, if there were no very common tokens, then this
114589
-** function is called once only for each phrase in the query and the returned
114590
-** doclist contains entries for all rows of the table.
114591
-**
114592
-** Fts3Cursor.doDeferred==1 when this function is called on phrases as a
114593
-** result of a snippet(), offsets() or matchinfo() invocation.
114594
-*/
114595
-static int fts3EvalExpr(
114596
- Fts3Cursor *p, /* Virtual table cursor handle */
114597
- Fts3Expr *pExpr, /* Parsed fts3 expression */
114598
- char **paOut, /* OUT: Pointer to malloc'd result buffer */
114599
- int *pnOut, /* OUT: Size of buffer at *paOut */
114600
- int isReqPos /* Require positions in output buffer */
114601
-){
114602
- int rc = SQLITE_OK; /* Return code */
114603
-
114604
- /* Zero the output parameters. */
114605
- *paOut = 0;
114606
- *pnOut = 0;
114607
-
114608
- if( pExpr ){
114609
- assert( pExpr->eType==FTSQUERY_NEAR || pExpr->eType==FTSQUERY_OR
114610
- || pExpr->eType==FTSQUERY_AND || pExpr->eType==FTSQUERY_NOT
114611
- || pExpr->eType==FTSQUERY_PHRASE
114612
- );
114613
- assert( pExpr->eType==FTSQUERY_PHRASE || isReqPos==0 );
114614
-
114615
- if( pExpr->eType==FTSQUERY_PHRASE ){
114616
- rc = fts3PhraseSelect(p, pExpr->pPhrase,
114617
- isReqPos || (pExpr->pParent && pExpr->pParent->eType==FTSQUERY_NEAR),
114618
- paOut, pnOut
114619
- );
114620
- fts3ExprFreeSegReaders(pExpr);
114621
- }else if( p->eEvalmode==FTS3_EVAL_FILTER && pExpr->eType==FTSQUERY_AND ){
114622
- ExprAndCost *aExpr = 0; /* Array of AND'd expressions and costs */
114623
- int nExpr = 0; /* Size of aExpr[] */
114624
- char *aRet = 0; /* Doclist to return to caller */
114625
- int nRet = 0; /* Length of aRet[] in bytes */
114626
- int nDoc = 0x7FFFFFFF;
114627
-
114628
- assert( !isReqPos );
114629
-
114630
- rc = fts3ExprAllocateSegReaders(p, pExpr, &nExpr);
114631
- if( rc==SQLITE_OK ){
114632
- assert( nExpr>1 );
114633
- aExpr = sqlite3_malloc(sizeof(ExprAndCost) * nExpr);
114634
- if( !aExpr ) rc = SQLITE_NOMEM;
114635
- }
114636
- if( rc==SQLITE_OK ){
114637
- int ii; /* Used to iterate through expressions */
114638
-
114639
- fts3ExprAssignCosts(pExpr, &aExpr);
114640
- aExpr -= nExpr;
114641
- for(ii=0; ii<nExpr; ii++){
114642
- char *aNew;
114643
- int nNew;
114644
- int jj;
114645
- ExprAndCost *pBest = 0;
114646
-
114647
- for(jj=0; jj<nExpr; jj++){
114648
- ExprAndCost *pCand = &aExpr[jj];
114649
- if( pCand->pExpr && (pBest==0 || pCand->nCost<pBest->nCost) ){
114650
- pBest = pCand;
114651
- }
114652
- }
114653
-
114654
- if( pBest->nCost>nDoc ){
114655
- rc = fts3DeferExpression(p, p->pExpr);
114656
- break;
114657
- }else{
114658
- rc = fts3EvalExpr(p, pBest->pExpr, &aNew, &nNew, 0);
114659
- if( rc!=SQLITE_OK ) break;
114660
- pBest->pExpr = 0;
114661
- if( ii==0 ){
114662
- aRet = aNew;
114663
- nRet = nNew;
114664
- nDoc = fts3DoclistCountDocids(0, aRet, nRet);
114665
- }else{
114666
- fts3DoclistMerge(
114667
- MERGE_AND, 0, 0, aRet, &nRet, aRet, nRet, aNew, nNew, &nDoc
114668
- );
114669
- sqlite3_free(aNew);
114670
- }
114671
- }
114672
- }
114673
- }
114674
-
114675
- if( rc==SQLITE_OK ){
114676
- *paOut = aRet;
114677
- *pnOut = nRet;
114678
- }else{
114679
- assert( *paOut==0 );
114680
- sqlite3_free(aRet);
114681
- }
114682
- sqlite3_free(aExpr);
114683
- fts3ExprFreeSegReaders(pExpr);
114684
-
114685
- }else{
114686
- char *aLeft;
114687
- char *aRight;
114688
- int nLeft;
114689
- int nRight;
114690
-
114691
- assert( pExpr->eType==FTSQUERY_NEAR
114692
- || pExpr->eType==FTSQUERY_OR
114693
- || pExpr->eType==FTSQUERY_NOT
114694
- || (pExpr->eType==FTSQUERY_AND && p->eEvalmode==FTS3_EVAL_NEXT)
114695
- );
114696
-
114697
- if( 0==(rc = fts3EvalExpr(p, pExpr->pRight, &aRight, &nRight, isReqPos))
114698
- && 0==(rc = fts3EvalExpr(p, pExpr->pLeft, &aLeft, &nLeft, isReqPos))
114699
- ){
114700
- switch( pExpr->eType ){
114701
- case FTSQUERY_NEAR: {
114702
- Fts3Expr *pLeft;
114703
- Fts3Expr *pRight;
114704
- int mergetype = MERGE_NEAR;
114705
- if( pExpr->pParent && pExpr->pParent->eType==FTSQUERY_NEAR ){
114706
- mergetype = MERGE_POS_NEAR;
114707
- }
114708
- pLeft = pExpr->pLeft;
114709
- while( pLeft->eType==FTSQUERY_NEAR ){
114710
- pLeft=pLeft->pRight;
114711
- }
114712
- pRight = pExpr->pRight;
114713
- assert( pRight->eType==FTSQUERY_PHRASE );
114714
- assert( pLeft->eType==FTSQUERY_PHRASE );
114715
-
114716
- rc = fts3NearMerge(mergetype, pExpr->nNear,
114717
- pLeft->pPhrase->nToken, aLeft, nLeft,
114718
- pRight->pPhrase->nToken, aRight, nRight,
114719
- paOut, pnOut
114720
- );
114721
- sqlite3_free(aLeft);
114722
- break;
114723
- }
114724
-
114725
- case FTSQUERY_OR: {
114726
- /* Allocate a buffer for the output. The maximum size is the
114727
- ** sum of the sizes of the two input buffers. The +1 term is
114728
- ** so that a buffer of zero bytes is never allocated - this can
114729
- ** cause fts3DoclistMerge() to incorrectly return SQLITE_NOMEM.
114730
- */
114731
- char *aBuffer = sqlite3_malloc(nRight+nLeft+1);
114732
- rc = fts3DoclistMerge(MERGE_OR, 0, 0, aBuffer, pnOut,
114733
- aLeft, nLeft, aRight, nRight, 0
114734
- );
114735
- *paOut = aBuffer;
114736
- sqlite3_free(aLeft);
114737
- break;
114738
- }
114739
-
114740
- default: {
114741
- assert( FTSQUERY_NOT==MERGE_NOT && FTSQUERY_AND==MERGE_AND );
114742
- fts3DoclistMerge(pExpr->eType, 0, 0, aLeft, pnOut,
114743
- aLeft, nLeft, aRight, nRight, 0
114744
- );
114745
- *paOut = aLeft;
114746
- break;
114747
- }
114748
- }
114749
- }
114750
- sqlite3_free(aRight);
114751
- }
114752
- }
114753
-
114754
- assert( rc==SQLITE_OK || *paOut==0 );
114755
- return rc;
114756
-}
114757
-
114758
-/*
114759
-** This function is called from within xNext() for each row visited by
114760
-** an FTS3 query. If evaluating the FTS3 query expression within xFilter()
114761
-** was able to determine the exact set of matching rows, this function sets
114762
-** *pbRes to true and returns SQLITE_IO immediately.
114763
-**
114764
-** Otherwise, if evaluating the query expression within xFilter() returned a
114765
-** superset of the matching documents instead of an exact set (this happens
114766
-** when the query includes very common tokens and it is deemed too expensive to
114767
-** load their doclists from disk), this function tests if the current row
114768
-** really does match the FTS3 query.
114769
-**
114770
-** If an error occurs, an SQLite error code is returned. Otherwise, SQLITE_OK
114771
-** is returned and *pbRes is set to true if the current row matches the
114772
-** FTS3 query (and should be included in the results returned to SQLite), or
114773
-** false otherwise.
114774
-*/
114775
-static int fts3EvalDeferred(
114776
- Fts3Cursor *pCsr, /* FTS3 cursor pointing at row to test */
114777
- int *pbRes /* OUT: Set to true if row is a match */
114778
-){
114779
- int rc = SQLITE_OK;
114780
- if( pCsr->pDeferred==0 ){
114781
- *pbRes = 1;
114782
- }else{
114783
- rc = fts3CursorSeek(0, pCsr);
114784
- if( rc==SQLITE_OK ){
114785
- sqlite3Fts3FreeDeferredDoclists(pCsr);
114786
- rc = sqlite3Fts3CacheDeferredDoclists(pCsr);
114787
- }
114788
- if( rc==SQLITE_OK ){
114789
- char *a = 0;
114790
- int n = 0;
114791
- rc = fts3EvalExpr(pCsr, pCsr->pExpr, &a, &n, 0);
114792
- assert( n>=0 );
114793
- *pbRes = (n>0);
114794
- sqlite3_free(a);
114795
- }
114796
- }
114797
- return rc;
114798
-}
114799
-
114800114367
/*
114801114368
** Advance the cursor to the next row in the %_content table that
114802114369
** matches the search criteria. For a MATCH search, this will be
114803114370
** the next row that matches. For a full-table scan, this will be
114804114371
** simply the next row in the %_content table. For a docid lookup,
@@ -114807,43 +114374,24 @@
114807114374
** Return SQLITE_OK if nothing goes wrong. SQLITE_OK is returned
114808114375
** even if we reach end-of-file. The fts3EofMethod() will be called
114809114376
** subsequently to determine whether or not an EOF was hit.
114810114377
*/
114811114378
static int fts3NextMethod(sqlite3_vtab_cursor *pCursor){
114812
- int res;
114813
- int rc = SQLITE_OK; /* Return code */
114379
+ int rc;
114814114380
Fts3Cursor *pCsr = (Fts3Cursor *)pCursor;
114815
-
114816
- pCsr->eEvalmode = FTS3_EVAL_NEXT;
114817
- do {
114818
- if( pCsr->aDoclist==0 ){
114819
- if( SQLITE_ROW!=sqlite3_step(pCsr->pStmt) ){
114820
- pCsr->isEof = 1;
114821
- rc = sqlite3_reset(pCsr->pStmt);
114822
- break;
114823
- }
114381
+ if( pCsr->eSearch==FTS3_DOCID_SEARCH || pCsr->eSearch==FTS3_FULLSCAN_SEARCH ){
114382
+ if( SQLITE_ROW!=sqlite3_step(pCsr->pStmt) ){
114383
+ pCsr->isEof = 1;
114384
+ rc = sqlite3_reset(pCsr->pStmt);
114385
+ }else{
114824114386
pCsr->iPrevId = sqlite3_column_int64(pCsr->pStmt, 0);
114825
- }else{
114826
- if( pCsr->desc==0 ){
114827
- if( pCsr->pNextId>=&pCsr->aDoclist[pCsr->nDoclist] ){
114828
- pCsr->isEof = 1;
114829
- break;
114830
- }
114831
- fts3GetDeltaVarint(&pCsr->pNextId, &pCsr->iPrevId);
114832
- }else{
114833
- fts3GetReverseDeltaVarint(&pCsr->pNextId,pCsr->aDoclist,&pCsr->iPrevId);
114834
- if( pCsr->pNextId<=pCsr->aDoclist ){
114835
- pCsr->isEof = 1;
114836
- break;
114837
- }
114838
- }
114839
- sqlite3_reset(pCsr->pStmt);
114840
- pCsr->isRequireSeek = 1;
114841
- pCsr->isMatchinfoNeeded = 1;
114842
- }
114843
- }while( SQLITE_OK==(rc = fts3EvalDeferred(pCsr, &res)) && res==0 );
114844
-
114387
+ rc = SQLITE_OK;
114388
+ }
114389
+ }else{
114390
+ rc = sqlite3Fts3EvalNext((Fts3Cursor *)pCursor);
114391
+ }
114392
+ assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 );
114845114393
return rc;
114846114394
}
114847114395
114848114396
/*
114849114397
** This is the xFilter interface for the virtual table. See
@@ -114866,15 +114414,11 @@
114866114414
int idxNum, /* Strategy index */
114867114415
const char *idxStr, /* Unused */
114868114416
int nVal, /* Number of elements in apVal */
114869114417
sqlite3_value **apVal /* Arguments for the indexing scheme */
114870114418
){
114871
- const char *azSql[] = {
114872
- "SELECT %s FROM %Q.'%q_content' AS x WHERE docid = ?", /* non-full-scan */
114873
- "SELECT %s FROM %Q.'%q_content' AS x ORDER BY docid %s", /* full-scan */
114874
- };
114875
- int rc; /* Return code */
114419
+ int rc;
114876114420
char *zSql; /* SQL statement used to access %_content */
114877114421
Fts3Table *p = (Fts3Table *)pCursor->pVtab;
114878114422
Fts3Cursor *pCsr = (Fts3Cursor *)pCursor;
114879114423
114880114424
UNUSED_PARAMETER(idxStr);
@@ -114889,10 +114433,17 @@
114889114433
sqlite3_finalize(pCsr->pStmt);
114890114434
sqlite3_free(pCsr->aDoclist);
114891114435
sqlite3Fts3ExprFree(pCsr->pExpr);
114892114436
memset(&pCursor[1], 0, sizeof(Fts3Cursor)-sizeof(sqlite3_vtab_cursor));
114893114437
114438
+ if( idxStr ){
114439
+ pCsr->bDesc = (idxStr[0]=='D');
114440
+ }else{
114441
+ pCsr->bDesc = p->bDescIdx;
114442
+ }
114443
+ pCsr->eSearch = (i16)idxNum;
114444
+
114894114445
if( idxNum!=FTS3_DOCID_SEARCH && idxNum!=FTS3_FULLSCAN_SEARCH ){
114895114446
int iCol = idxNum-FTS3_FULLTEXT_SEARCH;
114896114447
const char *zQuery = (const char *)sqlite3_value_text(apVal[0]);
114897114448
114898114449
if( zQuery==0 && sqlite3_value_type(apVal[0])!=SQLITE_NULL ){
@@ -114902,20 +114453,21 @@
114902114453
rc = sqlite3Fts3ExprParse(p->pTokenizer, p->azColumn, p->nColumn,
114903114454
iCol, zQuery, -1, &pCsr->pExpr
114904114455
);
114905114456
if( rc!=SQLITE_OK ){
114906114457
if( rc==SQLITE_ERROR ){
114907
- p->base.zErrMsg = sqlite3_mprintf("malformed MATCH expression: [%s]",
114908
- zQuery);
114458
+ static const char *zErr = "malformed MATCH expression: [%s]";
114459
+ p->base.zErrMsg = sqlite3_mprintf(zErr, zQuery);
114909114460
}
114910114461
return rc;
114911114462
}
114912114463
114913114464
rc = sqlite3Fts3ReadLock(p);
114914114465
if( rc!=SQLITE_OK ) return rc;
114915114466
114916
- rc = fts3EvalExpr(pCsr, pCsr->pExpr, &pCsr->aDoclist, &pCsr->nDoclist, 0);
114467
+ rc = sqlite3Fts3EvalStart(pCsr, pCsr->pExpr, 1);
114468
+
114917114469
sqlite3Fts3SegmentsClose(p);
114918114470
if( rc!=SQLITE_OK ) return rc;
114919114471
pCsr->pNextId = pCsr->aDoclist;
114920114472
pCsr->iPrevId = 0;
114921114473
}
@@ -114923,41 +114475,28 @@
114923114475
/* Compile a SELECT statement for this cursor. For a full-table-scan, the
114924114476
** statement loops through all rows of the %_content table. For a
114925114477
** full-text query or docid lookup, the statement retrieves a single
114926114478
** row by docid.
114927114479
*/
114928
- zSql = (char *)azSql[idxNum==FTS3_FULLSCAN_SEARCH];
114929
- zSql = sqlite3_mprintf(
114930
- zSql, p->zReadExprlist, p->zDb, p->zName, (idxStr ? idxStr : "ASC")
114931
- );
114932
- if( !zSql ){
114933
- rc = SQLITE_NOMEM;
114480
+ if( idxNum==FTS3_FULLSCAN_SEARCH ){
114481
+ const char *zSort = (pCsr->bDesc ? "DESC" : "ASC");
114482
+ const char *zTmpl = "SELECT %s FROM %Q.'%q_content' AS x ORDER BY docid %s";
114483
+ zSql = sqlite3_mprintf(zTmpl, p->zReadExprlist, p->zDb, p->zName, zSort);
114934114484
}else{
114935
- rc = sqlite3_prepare_v2(p->db, zSql, -1, &pCsr->pStmt, 0);
114936
- sqlite3_free(zSql);
114485
+ const char *zTmpl = "SELECT %s FROM %Q.'%q_content' AS x WHERE docid = ?";
114486
+ zSql = sqlite3_mprintf(zTmpl, p->zReadExprlist, p->zDb, p->zName);
114937114487
}
114938
- if( rc==SQLITE_OK && idxNum==FTS3_DOCID_SEARCH ){
114488
+ if( !zSql ) return SQLITE_NOMEM;
114489
+ rc = sqlite3_prepare_v2(p->db, zSql, -1, &pCsr->pStmt, 0);
114490
+ sqlite3_free(zSql);
114491
+ if( rc!=SQLITE_OK ) return rc;
114492
+
114493
+ if( idxNum==FTS3_DOCID_SEARCH ){
114939114494
rc = sqlite3_bind_value(pCsr->pStmt, 1, apVal[0]);
114940
- }
114941
- pCsr->eSearch = (i16)idxNum;
114942
-
114943
- assert( pCsr->desc==0 );
114944
- if( rc!=SQLITE_OK ) return rc;
114945
- if( rc==SQLITE_OK && pCsr->nDoclist>0 && idxStr && idxStr[0]=='D' ){
114946
- sqlite3_int64 iDocid = 0;
114947
- char *csr = pCsr->aDoclist;
114948
- while( csr<&pCsr->aDoclist[pCsr->nDoclist] ){
114949
- fts3GetDeltaVarint(&csr, &iDocid);
114950
- }
114951
- pCsr->pNextId = csr;
114952
- pCsr->iPrevId = iDocid;
114953
- pCsr->desc = 1;
114954
- pCsr->isRequireSeek = 1;
114955
- pCsr->isMatchinfoNeeded = 1;
114956
- pCsr->eEvalmode = FTS3_EVAL_NEXT;
114957
- return SQLITE_OK;
114958
- }
114495
+ if( rc!=SQLITE_OK ) return rc;
114496
+ }
114497
+
114959114498
return fts3NextMethod(pCursor);
114960114499
}
114961114500
114962114501
/*
114963114502
** This is the xEof method of the virtual table. SQLite calls this
@@ -114973,20 +114512,11 @@
114973114512
** exposes %_content.docid as the rowid for the virtual table. The
114974114513
** rowid should be written to *pRowid.
114975114514
*/
114976114515
static int fts3RowidMethod(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){
114977114516
Fts3Cursor *pCsr = (Fts3Cursor *) pCursor;
114978
- if( pCsr->aDoclist ){
114979
- *pRowid = pCsr->iPrevId;
114980
- }else{
114981
- /* This branch runs if the query is implemented using a full-table scan
114982
- ** (not using the full-text index). In this case grab the rowid from the
114983
- ** SELECT statement.
114984
- */
114985
- assert( pCsr->isRequireSeek==0 );
114986
- *pRowid = sqlite3_column_int64(pCsr->pStmt, 0);
114987
- }
114517
+ *pRowid = pCsr->iPrevId;
114988114518
return SQLITE_OK;
114989114519
}
114990114520
114991114521
/*
114992114522
** This is the xColumn method, called by SQLite to request a value from
@@ -114995,11 +114525,11 @@
114995114525
static int fts3ColumnMethod(
114996114526
sqlite3_vtab_cursor *pCursor, /* Cursor to retrieve value from */
114997114527
sqlite3_context *pContext, /* Context for sqlite3_result_xxx() calls */
114998114528
int iCol /* Index of column to read value from */
114999114529
){
115000
- int rc; /* Return Code */
114530
+ int rc = SQLITE_OK; /* Return Code */
115001114531
Fts3Cursor *pCsr = (Fts3Cursor *) pCursor;
115002114532
Fts3Table *p = (Fts3Table *)pCursor->pVtab;
115003114533
115004114534
/* The column value supplied by SQLite must be in range. */
115005114535
assert( iCol>=0 && iCol<=p->nColumn+1 );
@@ -115006,25 +114536,24 @@
115006114536
115007114537
if( iCol==p->nColumn+1 ){
115008114538
/* This call is a request for the "docid" column. Since "docid" is an
115009114539
** alias for "rowid", use the xRowid() method to obtain the value.
115010114540
*/
115011
- sqlite3_int64 iRowid;
115012
- rc = fts3RowidMethod(pCursor, &iRowid);
115013
- sqlite3_result_int64(pContext, iRowid);
114541
+ sqlite3_result_int64(pContext, pCsr->iPrevId);
115014114542
}else if( iCol==p->nColumn ){
115015114543
/* The extra column whose name is the same as the table.
115016114544
** Return a blob which is a pointer to the cursor.
115017114545
*/
115018114546
sqlite3_result_blob(pContext, &pCsr, sizeof(pCsr), SQLITE_TRANSIENT);
115019
- rc = SQLITE_OK;
115020114547
}else{
115021114548
rc = fts3CursorSeek(0, pCsr);
115022114549
if( rc==SQLITE_OK ){
115023114550
sqlite3_result_value(pContext, sqlite3_column_value(pCsr->pStmt, iCol+1));
115024114551
}
115025114552
}
114553
+
114554
+ assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 );
115026114555
return rc;
115027114556
}
115028114557
115029114558
/*
115030114559
** This function is the implementation of the xUpdate callback used by
@@ -115054,10 +114583,11 @@
115054114583
** Implementation of xBegin() method. This is a no-op.
115055114584
*/
115056114585
static int fts3BeginMethod(sqlite3_vtab *pVtab){
115057114586
UNUSED_PARAMETER(pVtab);
115058114587
TESTONLY( Fts3Table *p = (Fts3Table*)pVtab );
114588
+ assert( p->pSegments==0 );
115059114589
assert( p->nPendingData==0 );
115060114590
assert( p->inTransaction!=1 );
115061114591
TESTONLY( p->inTransaction = 1 );
115062114592
TESTONLY( p->mxSavepoint = -1; );
115063114593
return SQLITE_OK;
@@ -115071,10 +114601,11 @@
115071114601
static int fts3CommitMethod(sqlite3_vtab *pVtab){
115072114602
UNUSED_PARAMETER(pVtab);
115073114603
TESTONLY( Fts3Table *p = (Fts3Table*)pVtab );
115074114604
assert( p->nPendingData==0 );
115075114605
assert( p->inTransaction!=0 );
114606
+ assert( p->pSegments==0 );
115076114607
TESTONLY( p->inTransaction = 0 );
115077114608
TESTONLY( p->mxSavepoint = -1; );
115078114609
return SQLITE_OK;
115079114610
}
115080114611
@@ -115088,132 +114619,30 @@
115088114619
assert( p->inTransaction!=0 );
115089114620
TESTONLY( p->inTransaction = 0 );
115090114621
TESTONLY( p->mxSavepoint = -1; );
115091114622
return SQLITE_OK;
115092114623
}
115093
-
115094
-/*
115095
-** Load the doclist associated with expression pExpr to pExpr->aDoclist.
115096
-** The loaded doclist contains positions as well as the document ids.
115097
-** This is used by the matchinfo(), snippet() and offsets() auxillary
115098
-** functions.
115099
-*/
115100
-SQLITE_PRIVATE int sqlite3Fts3ExprLoadDoclist(Fts3Cursor *pCsr, Fts3Expr *pExpr){
115101
- int rc;
115102
- assert( pExpr->eType==FTSQUERY_PHRASE && pExpr->pPhrase );
115103
- assert( pCsr->eEvalmode==FTS3_EVAL_NEXT );
115104
- rc = fts3EvalExpr(pCsr, pExpr, &pExpr->aDoclist, &pExpr->nDoclist, 1);
115105
- return rc;
115106
-}
115107
-
115108
-SQLITE_PRIVATE int sqlite3Fts3ExprLoadFtDoclist(
115109
- Fts3Cursor *pCsr,
115110
- Fts3Expr *pExpr,
115111
- char **paDoclist,
115112
- int *pnDoclist
115113
-){
115114
- int rc;
115115
- assert( pCsr->eEvalmode==FTS3_EVAL_NEXT );
115116
- assert( pExpr->eType==FTSQUERY_PHRASE && pExpr->pPhrase );
115117
- pCsr->eEvalmode = FTS3_EVAL_MATCHINFO;
115118
- rc = fts3EvalExpr(pCsr, pExpr, paDoclist, pnDoclist, 1);
115119
- pCsr->eEvalmode = FTS3_EVAL_NEXT;
115120
- return rc;
115121
-}
115122
-
115123114624
115124114625
/*
115125114626
** When called, *ppPoslist must point to the byte immediately following the
115126114627
** end of a position-list. i.e. ( (*ppPoslist)[-1]==POS_END ). This function
115127114628
** moves *ppPoslist so that it instead points to the first byte of the
115128114629
** same position list.
115129114630
*/
115130114631
static void fts3ReversePoslist(char *pStart, char **ppPoslist){
115131
- char *p = &(*ppPoslist)[-3];
115132
- char c = p[1];
114632
+ char *p = &(*ppPoslist)[-2];
114633
+ char c;
114634
+
114635
+ while( p>pStart && (c=*p--)==0 );
115133114636
while( p>pStart && (*p & 0x80) | c ){
115134114637
c = *p--;
115135114638
}
115136114639
if( p>pStart ){ p = &p[2]; }
115137114640
while( *p++&0x80 );
115138114641
*ppPoslist = p;
115139114642
}
115140114643
115141
-
115142
-/*
115143
-** After ExprLoadDoclist() (see above) has been called, this function is
115144
-** used to iterate/search through the position lists that make up the doclist
115145
-** stored in pExpr->aDoclist.
115146
-*/
115147
-SQLITE_PRIVATE char *sqlite3Fts3FindPositions(
115148
- Fts3Cursor *pCursor, /* Associate FTS3 cursor */
115149
- Fts3Expr *pExpr, /* Access this expressions doclist */
115150
- sqlite3_int64 iDocid, /* Docid associated with requested pos-list */
115151
- int iCol /* Column of requested pos-list */
115152
-){
115153
- assert( pExpr->isLoaded );
115154
- if( pExpr->aDoclist ){
115155
- char *pEnd = &pExpr->aDoclist[pExpr->nDoclist];
115156
- char *pCsr;
115157
-
115158
- if( pExpr->pCurrent==0 ){
115159
- if( pCursor->desc==0 ){
115160
- pExpr->pCurrent = pExpr->aDoclist;
115161
- pExpr->iCurrent = 0;
115162
- fts3GetDeltaVarint(&pExpr->pCurrent, &pExpr->iCurrent);
115163
- }else{
115164
- pCsr = pExpr->aDoclist;
115165
- while( pCsr<pEnd ){
115166
- fts3GetDeltaVarint(&pCsr, &pExpr->iCurrent);
115167
- fts3PoslistCopy(0, &pCsr);
115168
- }
115169
- fts3ReversePoslist(pExpr->aDoclist, &pCsr);
115170
- pExpr->pCurrent = pCsr;
115171
- }
115172
- }
115173
- pCsr = pExpr->pCurrent;
115174
- assert( pCsr );
115175
-
115176
- while( (pCursor->desc==0 && pCsr<pEnd)
115177
- || (pCursor->desc && pCsr>pExpr->aDoclist)
115178
- ){
115179
- if( pCursor->desc==0 && pExpr->iCurrent<iDocid ){
115180
- fts3PoslistCopy(0, &pCsr);
115181
- if( pCsr<pEnd ){
115182
- fts3GetDeltaVarint(&pCsr, &pExpr->iCurrent);
115183
- }
115184
- pExpr->pCurrent = pCsr;
115185
- }else if( pCursor->desc && pExpr->iCurrent>iDocid ){
115186
- fts3GetReverseDeltaVarint(&pCsr, pExpr->aDoclist, &pExpr->iCurrent);
115187
- fts3ReversePoslist(pExpr->aDoclist, &pCsr);
115188
- pExpr->pCurrent = pCsr;
115189
- }else{
115190
- if( pExpr->iCurrent==iDocid ){
115191
- int iThis = 0;
115192
- if( iCol<0 ){
115193
- /* If iCol is negative, return a pointer to the start of the
115194
- ** position-list (instead of a pointer to the start of a list
115195
- ** of offsets associated with a specific column).
115196
- */
115197
- return pCsr;
115198
- }
115199
- while( iThis<iCol ){
115200
- fts3ColumnlistCopy(0, &pCsr);
115201
- if( *pCsr==0x00 ) return 0;
115202
- pCsr++;
115203
- pCsr += sqlite3Fts3GetVarint32(pCsr, &iThis);
115204
- }
115205
- if( iCol==iThis && (*pCsr&0xFE) ) return pCsr;
115206
- }
115207
- return 0;
115208
- }
115209
- }
115210
- }
115211
-
115212
- return 0;
115213
-}
115214
-
115215114644
/*
115216114645
** Helper function used by the implementation of the overloaded snippet(),
115217114646
** offsets() and optimize() SQL functions.
115218114647
**
115219114648
** If the value passed as the third argument is a blob of size
@@ -115441,16 +114870,15 @@
115441114870
);
115442114871
return rc;
115443114872
}
115444114873
115445114874
static int fts3SavepointMethod(sqlite3_vtab *pVtab, int iSavepoint){
115446
- Fts3Table *p = (Fts3Table*)pVtab;
115447114875
UNUSED_PARAMETER(iSavepoint);
115448
- assert( p->inTransaction );
115449
- assert( p->mxSavepoint < iSavepoint );
115450
- TESTONLY( p->mxSavepoint = iSavepoint );
115451
- return sqlite3Fts3PendingTermsFlush(p);
114876
+ assert( ((Fts3Table *)pVtab)->inTransaction );
114877
+ assert( ((Fts3Table *)pVtab)->mxSavepoint < iSavepoint );
114878
+ TESTONLY( ((Fts3Table *)pVtab)->mxSavepoint = iSavepoint );
114879
+ return fts3SyncMethod(pVtab);
115452114880
}
115453114881
static int fts3ReleaseMethod(sqlite3_vtab *pVtab, int iSavepoint){
115454114882
TESTONLY( Fts3Table *p = (Fts3Table*)pVtab );
115455114883
UNUSED_PARAMETER(iSavepoint);
115456114884
UNUSED_PARAMETER(pVtab);
@@ -115617,10 +115045,1282 @@
115617115045
SQLITE_EXTENSION_INIT2(pApi)
115618115046
return sqlite3Fts3Init(db);
115619115047
}
115620115048
#endif
115621115049
115050
+
115051
+/*
115052
+** Allocate an Fts3MultiSegReader for each token in the expression headed
115053
+** by pExpr.
115054
+**
115055
+** An Fts3SegReader object is a cursor that can seek or scan a range of
115056
+** entries within a single segment b-tree. An Fts3MultiSegReader uses multiple
115057
+** Fts3SegReader objects internally to provide an interface to seek or scan
115058
+** within the union of all segments of a b-tree. Hence the name.
115059
+**
115060
+** If the allocated Fts3MultiSegReader just seeks to a single entry in a
115061
+** segment b-tree (if the term is not a prefix or it is a prefix for which
115062
+** there exists prefix b-tree of the right length) then it may be traversed
115063
+** and merged incrementally. Otherwise, it has to be merged into an in-memory
115064
+** doclist and then traversed.
115065
+*/
115066
+static void fts3EvalAllocateReaders(
115067
+ Fts3Cursor *pCsr,
115068
+ Fts3Expr *pExpr,
115069
+ int *pnToken, /* OUT: Total number of tokens in phrase. */
115070
+ int *pnOr, /* OUT: Total number of OR nodes in expr. */
115071
+ int *pRc
115072
+){
115073
+ if( pExpr && SQLITE_OK==*pRc ){
115074
+ if( pExpr->eType==FTSQUERY_PHRASE ){
115075
+ int i;
115076
+ int nToken = pExpr->pPhrase->nToken;
115077
+ *pnToken += nToken;
115078
+ for(i=0; i<nToken; i++){
115079
+ Fts3PhraseToken *pToken = &pExpr->pPhrase->aToken[i];
115080
+ int rc = sqlite3Fts3TermSegReaderCursor(pCsr,
115081
+ pToken->z, pToken->n, pToken->isPrefix, &pToken->pSegcsr
115082
+ );
115083
+ if( rc!=SQLITE_OK ){
115084
+ *pRc = rc;
115085
+ return;
115086
+ }
115087
+ }
115088
+ }else{
115089
+ *pnOr += (pExpr->eType==FTSQUERY_OR);
115090
+ fts3EvalAllocateReaders(pCsr, pExpr->pLeft, pnToken, pnOr, pRc);
115091
+ fts3EvalAllocateReaders(pCsr, pExpr->pRight, pnToken, pnOr, pRc);
115092
+ }
115093
+ }
115094
+}
115095
+
115096
+static int fts3EvalPhraseLoad(
115097
+ Fts3Cursor *pCsr,
115098
+ Fts3Phrase *p
115099
+){
115100
+ Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
115101
+ int iToken;
115102
+ int rc = SQLITE_OK;
115103
+
115104
+ char *aDoclist = 0;
115105
+ int nDoclist = 0;
115106
+ int iPrev = -1;
115107
+
115108
+ for(iToken=0; rc==SQLITE_OK && iToken<p->nToken; iToken++){
115109
+ Fts3PhraseToken *pToken = &p->aToken[iToken];
115110
+ assert( pToken->pSegcsr || pToken->pDeferred );
115111
+
115112
+ if( pToken->pDeferred==0 ){
115113
+ int nThis = 0;
115114
+ char *pThis = 0;
115115
+ rc = fts3TermSelect(pTab, pToken, p->iColumn, 1, &nThis, &pThis);
115116
+ if( rc==SQLITE_OK ){
115117
+ if( pThis==0 ){
115118
+ sqlite3_free(aDoclist);
115119
+ aDoclist = 0;
115120
+ nDoclist = 0;
115121
+ break;
115122
+ }else if( aDoclist==0 ){
115123
+ aDoclist = pThis;
115124
+ nDoclist = nThis;
115125
+ }else{
115126
+ assert( iPrev>=0 );
115127
+ fts3DoclistPhraseMerge(pTab->bDescIdx,
115128
+ iToken-iPrev, aDoclist, nDoclist, pThis, &nThis
115129
+ );
115130
+ sqlite3_free(aDoclist);
115131
+ aDoclist = pThis;
115132
+ nDoclist = nThis;
115133
+ }
115134
+ iPrev = iToken;
115135
+ }
115136
+ }
115137
+ }
115138
+
115139
+ if( rc==SQLITE_OK ){
115140
+ p->doclist.aAll = aDoclist;
115141
+ p->doclist.nAll = nDoclist;
115142
+ }else{
115143
+ sqlite3_free(aDoclist);
115144
+ }
115145
+ return rc;
115146
+}
115147
+
115148
+static int fts3EvalDeferredPhrase(Fts3Cursor *pCsr, Fts3Phrase *pPhrase){
115149
+ int iToken;
115150
+ int rc = SQLITE_OK;
115151
+
115152
+ int nMaxUndeferred = -1;
115153
+ char *aPoslist = 0;
115154
+ int nPoslist = 0;
115155
+ int iPrev = -1;
115156
+
115157
+ assert( pPhrase->doclist.bFreeList==0 );
115158
+
115159
+ for(iToken=0; rc==SQLITE_OK && iToken<pPhrase->nToken; iToken++){
115160
+ Fts3PhraseToken *pToken = &pPhrase->aToken[iToken];
115161
+ Fts3DeferredToken *pDeferred = pToken->pDeferred;
115162
+
115163
+ if( pDeferred ){
115164
+ char *pList;
115165
+ int nList;
115166
+ rc = sqlite3Fts3DeferredTokenList(pDeferred, &pList, &nList);
115167
+ if( rc!=SQLITE_OK ) return rc;
115168
+
115169
+ if( pList==0 ){
115170
+ sqlite3_free(aPoslist);
115171
+ pPhrase->doclist.pList = 0;
115172
+ pPhrase->doclist.nList = 0;
115173
+ return SQLITE_OK;
115174
+
115175
+ }else if( aPoslist==0 ){
115176
+ aPoslist = pList;
115177
+ nPoslist = nList;
115178
+
115179
+ }else{
115180
+ char *aOut = pList;
115181
+ char *p1 = aPoslist;
115182
+ char *p2 = aOut;
115183
+
115184
+ assert( iPrev>=0 );
115185
+ fts3PoslistPhraseMerge(&aOut, iToken-iPrev, 0, 1, &p1, &p2);
115186
+ sqlite3_free(aPoslist);
115187
+ aPoslist = pList;
115188
+ nPoslist = aOut - aPoslist;
115189
+ if( nPoslist==0 ){
115190
+ sqlite3_free(aPoslist);
115191
+ pPhrase->doclist.pList = 0;
115192
+ pPhrase->doclist.nList = 0;
115193
+ return SQLITE_OK;
115194
+ }
115195
+ }
115196
+ iPrev = iToken;
115197
+ }else{
115198
+ nMaxUndeferred = iToken;
115199
+ }
115200
+ }
115201
+
115202
+ if( iPrev>=0 ){
115203
+ if( nMaxUndeferred<0 ){
115204
+ pPhrase->doclist.pList = aPoslist;
115205
+ pPhrase->doclist.nList = nPoslist;
115206
+ pPhrase->doclist.iDocid = pCsr->iPrevId;
115207
+ pPhrase->doclist.bFreeList = 1;
115208
+ }else{
115209
+ int nDistance;
115210
+ char *p1;
115211
+ char *p2;
115212
+ char *aOut;
115213
+
115214
+ if( nMaxUndeferred>iPrev ){
115215
+ p1 = aPoslist;
115216
+ p2 = pPhrase->doclist.pList;
115217
+ nDistance = nMaxUndeferred - iPrev;
115218
+ }else{
115219
+ p1 = pPhrase->doclist.pList;
115220
+ p2 = aPoslist;
115221
+ nDistance = iPrev - nMaxUndeferred;
115222
+ }
115223
+
115224
+ aOut = (char *)sqlite3_malloc(nPoslist+8);
115225
+ if( !aOut ){
115226
+ sqlite3_free(aPoslist);
115227
+ return SQLITE_NOMEM;
115228
+ }
115229
+
115230
+ pPhrase->doclist.pList = aOut;
115231
+ if( fts3PoslistPhraseMerge(&aOut, nDistance, 0, 1, &p1, &p2) ){
115232
+ pPhrase->doclist.bFreeList = 1;
115233
+ pPhrase->doclist.nList = (aOut - pPhrase->doclist.pList);
115234
+ }else{
115235
+ sqlite3_free(aOut);
115236
+ pPhrase->doclist.pList = 0;
115237
+ pPhrase->doclist.nList = 0;
115238
+ }
115239
+ sqlite3_free(aPoslist);
115240
+ }
115241
+ }
115242
+
115243
+ return SQLITE_OK;
115244
+}
115245
+
115246
+/*
115247
+** This function is called for each Fts3Phrase in a full-text query
115248
+** expression to initialize the mechanism for returning rows. Once this
115249
+** function has been called successfully on an Fts3Phrase, it may be
115250
+** used with fts3EvalPhraseNext() to iterate through the matching docids.
115251
+*/
115252
+static int fts3EvalPhraseStart(Fts3Cursor *pCsr, int bOptOk, Fts3Phrase *p){
115253
+ int rc;
115254
+ Fts3PhraseToken *pFirst = &p->aToken[0];
115255
+ Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
115256
+
115257
+ assert( p->doclist.aAll==0 );
115258
+ if( pCsr->bDesc==pTab->bDescIdx && bOptOk==1 && p->nToken==1
115259
+ && pFirst->pSegcsr && pFirst->pSegcsr->bLookup
115260
+ ){
115261
+ /* Use the incremental approach. */
115262
+ int iCol = (p->iColumn >= pTab->nColumn ? -1 : p->iColumn);
115263
+ rc = sqlite3Fts3MsrIncrStart(
115264
+ pTab, pFirst->pSegcsr, iCol, pFirst->z, pFirst->n);
115265
+ p->bIncr = 1;
115266
+
115267
+ }else{
115268
+ /* Load the full doclist for the phrase into memory. */
115269
+ rc = fts3EvalPhraseLoad(pCsr, p);
115270
+ p->bIncr = 0;
115271
+ }
115272
+
115273
+ assert( rc!=SQLITE_OK || p->nToken<1 || p->aToken[0].pSegcsr==0 || p->bIncr );
115274
+ return rc;
115275
+}
115276
+
115277
+/*
115278
+** This function is used to iterate backwards (from the end to start)
115279
+** through doclists.
115280
+*/
115281
+SQLITE_PRIVATE void sqlite3Fts3DoclistPrev(
115282
+ int bDescIdx, /* True if the doclist is desc */
115283
+ char *aDoclist, /* Pointer to entire doclist */
115284
+ int nDoclist, /* Length of aDoclist in bytes */
115285
+ char **ppIter, /* IN/OUT: Iterator pointer */
115286
+ sqlite3_int64 *piDocid, /* IN/OUT: Docid pointer */
115287
+ int *pnList, /* IN/OUT: List length pointer */
115288
+ u8 *pbEof /* OUT: End-of-file flag */
115289
+){
115290
+ char *p = *ppIter;
115291
+
115292
+ assert( nDoclist>0 );
115293
+ assert( *pbEof==0 );
115294
+ assert( p || *piDocid==0 );
115295
+ assert( !p || (p>aDoclist && p<&aDoclist[nDoclist]) );
115296
+
115297
+ if( p==0 ){
115298
+ sqlite3_int64 iDocid = 0;
115299
+ char *pNext = 0;
115300
+ char *pDocid = aDoclist;
115301
+ char *pEnd = &aDoclist[nDoclist];
115302
+ int iMul = 1;
115303
+
115304
+ while( pDocid<pEnd ){
115305
+ sqlite3_int64 iDelta;
115306
+ pDocid += sqlite3Fts3GetVarint(pDocid, &iDelta);
115307
+ iDocid += (iMul * iDelta);
115308
+ pNext = pDocid;
115309
+ fts3PoslistCopy(0, &pDocid);
115310
+ while( pDocid<pEnd && *pDocid==0 ) pDocid++;
115311
+ iMul = (bDescIdx ? -1 : 1);
115312
+ }
115313
+
115314
+ *pnList = pEnd - pNext;
115315
+ *ppIter = pNext;
115316
+ *piDocid = iDocid;
115317
+ }else{
115318
+ int iMul = (bDescIdx ? -1 : 1);
115319
+ sqlite3_int64 iDelta;
115320
+ fts3GetReverseVarint(&p, aDoclist, &iDelta);
115321
+ *piDocid -= (iMul * iDelta);
115322
+
115323
+ if( p==aDoclist ){
115324
+ *pbEof = 1;
115325
+ }else{
115326
+ char *pSave = p;
115327
+ fts3ReversePoslist(aDoclist, &p);
115328
+ *pnList = (pSave - p);
115329
+ }
115330
+ *ppIter = p;
115331
+ }
115332
+}
115333
+
115334
+/*
115335
+** Attempt to move the phrase iterator to point to the next matching docid.
115336
+** If an error occurs, return an SQLite error code. Otherwise, return
115337
+** SQLITE_OK.
115338
+**
115339
+** If there is no "next" entry and no error occurs, then *pbEof is set to
115340
+** 1 before returning. Otherwise, if no error occurs and the iterator is
115341
+** successfully advanced, *pbEof is set to 0.
115342
+*/
115343
+static int fts3EvalPhraseNext(
115344
+ Fts3Cursor *pCsr,
115345
+ Fts3Phrase *p,
115346
+ u8 *pbEof
115347
+){
115348
+ int rc = SQLITE_OK;
115349
+ Fts3Doclist *pDL = &p->doclist;
115350
+ Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
115351
+
115352
+ if( p->bIncr ){
115353
+ assert( p->nToken==1 );
115354
+ assert( pDL->pNextDocid==0 );
115355
+ rc = sqlite3Fts3MsrIncrNext(pTab, p->aToken[0].pSegcsr,
115356
+ &pDL->iDocid, &pDL->pList, &pDL->nList
115357
+ );
115358
+ if( rc==SQLITE_OK && !pDL->pList ){
115359
+ *pbEof = 1;
115360
+ }
115361
+ }else if( pCsr->bDesc!=pTab->bDescIdx && pDL->nAll ){
115362
+ sqlite3Fts3DoclistPrev(pTab->bDescIdx, pDL->aAll, pDL->nAll,
115363
+ &pDL->pNextDocid, &pDL->iDocid, &pDL->nList, pbEof
115364
+ );
115365
+ pDL->pList = pDL->pNextDocid;
115366
+ }else{
115367
+ char *pIter; /* Used to iterate through aAll */
115368
+ char *pEnd = &pDL->aAll[pDL->nAll]; /* 1 byte past end of aAll */
115369
+ if( pDL->pNextDocid ){
115370
+ pIter = pDL->pNextDocid;
115371
+ }else{
115372
+ pIter = pDL->aAll;
115373
+ }
115374
+
115375
+ if( pIter>=pEnd ){
115376
+ /* We have already reached the end of this doclist. EOF. */
115377
+ *pbEof = 1;
115378
+ }else{
115379
+ sqlite3_int64 iDelta;
115380
+ pIter += sqlite3Fts3GetVarint(pIter, &iDelta);
115381
+ if( pTab->bDescIdx==0 || pDL->pNextDocid==0 ){
115382
+ pDL->iDocid += iDelta;
115383
+ }else{
115384
+ pDL->iDocid -= iDelta;
115385
+ }
115386
+ pDL->pList = pIter;
115387
+ fts3PoslistCopy(0, &pIter);
115388
+ pDL->nList = (pIter - pDL->pList);
115389
+
115390
+ /* pIter now points just past the 0x00 that terminates the position-
115391
+ ** list for document pDL->iDocid. However, if this position-list was
115392
+ ** edited in place by fts3EvalNearTrim2(), then pIter may not actually
115393
+ ** point to the start of the next docid value. The following line deals
115394
+ ** with this case by advancing pIter past the zero-padding added by
115395
+ ** fts3EvalNearTrim2(). */
115396
+ while( pIter<pEnd && *pIter==0 ) pIter++;
115397
+
115398
+ pDL->pNextDocid = pIter;
115399
+ assert( *pIter || pIter>=&pDL->aAll[pDL->nAll] );
115400
+ *pbEof = 0;
115401
+ }
115402
+ }
115403
+
115404
+ return rc;
115405
+}
115406
+
115407
+static void fts3EvalStartReaders(
115408
+ Fts3Cursor *pCsr,
115409
+ Fts3Expr *pExpr,
115410
+ int bOptOk,
115411
+ int *pRc
115412
+){
115413
+ if( pExpr && SQLITE_OK==*pRc ){
115414
+ if( pExpr->eType==FTSQUERY_PHRASE ){
115415
+ int i;
115416
+ int nToken = pExpr->pPhrase->nToken;
115417
+ for(i=0; i<nToken; i++){
115418
+ if( pExpr->pPhrase->aToken[i].pDeferred==0 ) break;
115419
+ }
115420
+ pExpr->bDeferred = (i==nToken);
115421
+ *pRc = fts3EvalPhraseStart(pCsr, bOptOk, pExpr->pPhrase);
115422
+ }else{
115423
+ fts3EvalStartReaders(pCsr, pExpr->pLeft, bOptOk, pRc);
115424
+ fts3EvalStartReaders(pCsr, pExpr->pRight, bOptOk, pRc);
115425
+ pExpr->bDeferred = (pExpr->pLeft->bDeferred && pExpr->pRight->bDeferred);
115426
+ }
115427
+ }
115428
+}
115429
+
115430
+
115431
+typedef struct Fts3TokenAndCost Fts3TokenAndCost;
115432
+struct Fts3TokenAndCost {
115433
+ Fts3PhraseToken *pToken;
115434
+ Fts3Expr *pRoot;
115435
+ int nOvfl;
115436
+ int iCol;
115437
+};
115438
+
115439
+static void fts3EvalTokenCosts(
115440
+ Fts3Cursor *pCsr,
115441
+ Fts3Expr *pRoot,
115442
+ Fts3Expr *pExpr,
115443
+ Fts3TokenAndCost **ppTC,
115444
+ Fts3Expr ***ppOr,
115445
+ int *pRc
115446
+){
115447
+ if( *pRc==SQLITE_OK && pExpr ){
115448
+ if( pExpr->eType==FTSQUERY_PHRASE ){
115449
+ Fts3Phrase *pPhrase = pExpr->pPhrase;
115450
+ int i;
115451
+ for(i=0; *pRc==SQLITE_OK && i<pPhrase->nToken; i++){
115452
+ Fts3TokenAndCost *pTC = (*ppTC)++;
115453
+ pTC->pRoot = pRoot;
115454
+ pTC->pToken = &pPhrase->aToken[i];
115455
+ pTC->iCol = pPhrase->iColumn;
115456
+ *pRc = sqlite3Fts3MsrOvfl(pCsr, pTC->pToken->pSegcsr, &pTC->nOvfl);
115457
+ }
115458
+ }else if( pExpr->eType!=FTSQUERY_NOT ){
115459
+ if( pExpr->eType==FTSQUERY_OR ){
115460
+ pRoot = pExpr->pLeft;
115461
+ **ppOr = pRoot;
115462
+ (*ppOr)++;
115463
+ }
115464
+ fts3EvalTokenCosts(pCsr, pRoot, pExpr->pLeft, ppTC, ppOr, pRc);
115465
+ if( pExpr->eType==FTSQUERY_OR ){
115466
+ pRoot = pExpr->pRight;
115467
+ **ppOr = pRoot;
115468
+ (*ppOr)++;
115469
+ }
115470
+ fts3EvalTokenCosts(pCsr, pRoot, pExpr->pRight, ppTC, ppOr, pRc);
115471
+ }
115472
+ }
115473
+}
115474
+
115475
+static int fts3EvalAverageDocsize(Fts3Cursor *pCsr, int *pnPage){
115476
+ if( pCsr->nRowAvg==0 ){
115477
+ /* The average document size, which is required to calculate the cost
115478
+ ** of each doclist, has not yet been determined. Read the required
115479
+ ** data from the %_stat table to calculate it.
115480
+ **
115481
+ ** Entry 0 of the %_stat table is a blob containing (nCol+1) FTS3
115482
+ ** varints, where nCol is the number of columns in the FTS3 table.
115483
+ ** The first varint is the number of documents currently stored in
115484
+ ** the table. The following nCol varints contain the total amount of
115485
+ ** data stored in all rows of each column of the table, from left
115486
+ ** to right.
115487
+ */
115488
+ int rc;
115489
+ Fts3Table *p = (Fts3Table*)pCsr->base.pVtab;
115490
+ sqlite3_stmt *pStmt;
115491
+ sqlite3_int64 nDoc = 0;
115492
+ sqlite3_int64 nByte = 0;
115493
+ const char *pEnd;
115494
+ const char *a;
115495
+
115496
+ rc = sqlite3Fts3SelectDoctotal(p, &pStmt);
115497
+ if( rc!=SQLITE_OK ) return rc;
115498
+ a = sqlite3_column_blob(pStmt, 0);
115499
+ assert( a );
115500
+
115501
+ pEnd = &a[sqlite3_column_bytes(pStmt, 0)];
115502
+ a += sqlite3Fts3GetVarint(a, &nDoc);
115503
+ while( a<pEnd ){
115504
+ a += sqlite3Fts3GetVarint(a, &nByte);
115505
+ }
115506
+ if( nDoc==0 || nByte==0 ){
115507
+ sqlite3_reset(pStmt);
115508
+ return SQLITE_CORRUPT_VTAB;
115509
+ }
115510
+
115511
+ pCsr->nDoc = nDoc;
115512
+ pCsr->nRowAvg = (int)(((nByte / nDoc) + p->nPgsz) / p->nPgsz);
115513
+ assert( pCsr->nRowAvg>0 );
115514
+ rc = sqlite3_reset(pStmt);
115515
+ if( rc!=SQLITE_OK ) return rc;
115516
+ }
115517
+
115518
+ *pnPage = pCsr->nRowAvg;
115519
+ return SQLITE_OK;
115520
+}
115521
+
115522
+static int fts3EvalSelectDeferred(
115523
+ Fts3Cursor *pCsr,
115524
+ Fts3Expr *pRoot,
115525
+ Fts3TokenAndCost *aTC,
115526
+ int nTC
115527
+){
115528
+ int nDocSize = 0;
115529
+ int nDocEst = 0;
115530
+ int rc = SQLITE_OK;
115531
+ Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
115532
+ int ii;
115533
+
115534
+ int nOvfl = 0;
115535
+ int nTerm = 0;
115536
+
115537
+ for(ii=0; ii<nTC; ii++){
115538
+ if( aTC[ii].pRoot==pRoot ){
115539
+ nOvfl += aTC[ii].nOvfl;
115540
+ nTerm++;
115541
+ }
115542
+ }
115543
+ if( nOvfl==0 || nTerm<2 ) return SQLITE_OK;
115544
+
115545
+ rc = fts3EvalAverageDocsize(pCsr, &nDocSize);
115546
+
115547
+ for(ii=0; ii<nTerm && rc==SQLITE_OK; ii++){
115548
+ int jj;
115549
+ Fts3TokenAndCost *pTC = 0;
115550
+
115551
+ for(jj=0; jj<nTC; jj++){
115552
+ if( aTC[jj].pToken && aTC[jj].pRoot==pRoot
115553
+ && (!pTC || aTC[jj].nOvfl<pTC->nOvfl)
115554
+ ){
115555
+ pTC = &aTC[jj];
115556
+ }
115557
+ }
115558
+ assert( pTC );
115559
+
115560
+ /* At this point pTC points to the cheapest remaining token. */
115561
+ if( ii==0 ){
115562
+ if( pTC->nOvfl ){
115563
+ nDocEst = (pTC->nOvfl * pTab->nPgsz + pTab->nPgsz) / 10;
115564
+ }else{
115565
+ /* TODO: Fix this so that the doclist need not be read twice. */
115566
+ Fts3PhraseToken *pToken = pTC->pToken;
115567
+ int nList = 0;
115568
+ char *pList = 0;
115569
+ rc = fts3TermSelect(pTab, pToken, pTC->iCol, 1, &nList, &pList);
115570
+ if( rc==SQLITE_OK ){
115571
+ nDocEst = fts3DoclistCountDocids(1, pList, nList);
115572
+ }
115573
+ sqlite3_free(pList);
115574
+ if( rc==SQLITE_OK ){
115575
+ rc = sqlite3Fts3TermSegReaderCursor(pCsr,
115576
+ pToken->z, pToken->n, pToken->isPrefix, &pToken->pSegcsr
115577
+ );
115578
+ }
115579
+ }
115580
+ }else{
115581
+ if( pTC->nOvfl>=(nDocEst*nDocSize) ){
115582
+ Fts3PhraseToken *pToken = pTC->pToken;
115583
+ rc = sqlite3Fts3DeferToken(pCsr, pToken, pTC->iCol);
115584
+ fts3SegReaderCursorFree(pToken->pSegcsr);
115585
+ pToken->pSegcsr = 0;
115586
+ }
115587
+ nDocEst = 1 + (nDocEst/4);
115588
+ }
115589
+ pTC->pToken = 0;
115590
+ }
115591
+
115592
+ return rc;
115593
+}
115594
+
115595
+SQLITE_PRIVATE int sqlite3Fts3EvalStart(Fts3Cursor *pCsr, Fts3Expr *pExpr, int bOptOk){
115596
+ Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
115597
+ int rc = SQLITE_OK;
115598
+ int nToken = 0;
115599
+ int nOr = 0;
115600
+
115601
+ /* Allocate a MultiSegReader for each token in the expression. */
115602
+ fts3EvalAllocateReaders(pCsr, pExpr, &nToken, &nOr, &rc);
115603
+
115604
+ /* Call fts3EvalPhraseStart() on all phrases in the expression. TODO:
115605
+ ** This call will eventually also be responsible for determining which
115606
+ ** tokens are 'deferred' until the document text is loaded into memory.
115607
+ **
115608
+ ** Each token in each phrase is dealt with using one of the following
115609
+ ** three strategies:
115610
+ **
115611
+ ** 1. Entire doclist loaded into memory as part of the
115612
+ ** fts3EvalStartReaders() call.
115613
+ **
115614
+ ** 2. Doclist loaded into memory incrementally, as part of each
115615
+ ** sqlite3Fts3EvalNext() call.
115616
+ **
115617
+ ** 3. Token doclist is never loaded. Instead, documents are loaded into
115618
+ ** memory and scanned for the token as part of the sqlite3Fts3EvalNext()
115619
+ ** call. This is known as a "deferred" token.
115620
+ */
115621
+
115622
+ /* If bOptOk is true, check if there are any tokens that should be deferred.
115623
+ */
115624
+ if( rc==SQLITE_OK && bOptOk && nToken>1 && pTab->bHasStat ){
115625
+ Fts3TokenAndCost *aTC;
115626
+ Fts3Expr **apOr;
115627
+ aTC = (Fts3TokenAndCost *)sqlite3_malloc(
115628
+ sizeof(Fts3TokenAndCost) * nToken
115629
+ + sizeof(Fts3Expr *) * nOr * 2
115630
+ );
115631
+ apOr = (Fts3Expr **)&aTC[nToken];
115632
+
115633
+ if( !aTC ){
115634
+ rc = SQLITE_NOMEM;
115635
+ }else{
115636
+ int ii;
115637
+ Fts3TokenAndCost *pTC = aTC;
115638
+ Fts3Expr **ppOr = apOr;
115639
+
115640
+ fts3EvalTokenCosts(pCsr, 0, pExpr, &pTC, &ppOr, &rc);
115641
+ nToken = pTC-aTC;
115642
+ nOr = ppOr-apOr;
115643
+
115644
+ if( rc==SQLITE_OK ){
115645
+ rc = fts3EvalSelectDeferred(pCsr, 0, aTC, nToken);
115646
+ for(ii=0; rc==SQLITE_OK && ii<nOr; ii++){
115647
+ rc = fts3EvalSelectDeferred(pCsr, apOr[ii], aTC, nToken);
115648
+ }
115649
+ }
115650
+
115651
+ sqlite3_free(aTC);
115652
+ }
115653
+ }
115654
+
115655
+ fts3EvalStartReaders(pCsr, pExpr, bOptOk, &rc);
115656
+ return rc;
115657
+}
115658
+
115659
+static void fts3EvalZeroPoslist(Fts3Phrase *pPhrase){
115660
+ if( pPhrase->doclist.bFreeList ){
115661
+ sqlite3_free(pPhrase->doclist.pList);
115662
+ }
115663
+ pPhrase->doclist.pList = 0;
115664
+ pPhrase->doclist.nList = 0;
115665
+ pPhrase->doclist.bFreeList = 0;
115666
+}
115667
+
115668
+static int fts3EvalNearTrim2(
115669
+ int nNear,
115670
+ char *aTmp, /* Temporary space to use */
115671
+ char **paPoslist, /* IN/OUT: Position list */
115672
+ int *pnToken, /* IN/OUT: Tokens in phrase of *paPoslist */
115673
+ Fts3Phrase *pPhrase /* The phrase object to trim the doclist of */
115674
+){
115675
+ int nParam1 = nNear + pPhrase->nToken;
115676
+ int nParam2 = nNear + *pnToken;
115677
+ int nNew;
115678
+ char *p2;
115679
+ char *pOut;
115680
+ int res;
115681
+
115682
+ assert( pPhrase->doclist.pList );
115683
+
115684
+ p2 = pOut = pPhrase->doclist.pList;
115685
+ res = fts3PoslistNearMerge(
115686
+ &pOut, aTmp, nParam1, nParam2, paPoslist, &p2
115687
+ );
115688
+ if( res ){
115689
+ nNew = (pOut - pPhrase->doclist.pList) - 1;
115690
+ assert( pPhrase->doclist.pList[nNew]=='\0' );
115691
+ assert( nNew<=pPhrase->doclist.nList && nNew>0 );
115692
+ memset(&pPhrase->doclist.pList[nNew], 0, pPhrase->doclist.nList - nNew);
115693
+ pPhrase->doclist.nList = nNew;
115694
+ *paPoslist = pPhrase->doclist.pList;
115695
+ *pnToken = pPhrase->nToken;
115696
+ }
115697
+
115698
+ return res;
115699
+}
115700
+
115701
+static int fts3EvalNearTest(Fts3Expr *pExpr, int *pRc){
115702
+ int res = 1;
115703
+
115704
+ /* The following block runs if pExpr is the root of a NEAR query.
115705
+ ** For example, the query:
115706
+ **
115707
+ ** "w" NEAR "x" NEAR "y" NEAR "z"
115708
+ **
115709
+ ** which is represented in tree form as:
115710
+ **
115711
+ ** |
115712
+ ** +--NEAR--+ <-- root of NEAR query
115713
+ ** | |
115714
+ ** +--NEAR--+ "z"
115715
+ ** | |
115716
+ ** +--NEAR--+ "y"
115717
+ ** | |
115718
+ ** "w" "x"
115719
+ **
115720
+ ** The right-hand child of a NEAR node is always a phrase. The
115721
+ ** left-hand child may be either a phrase or a NEAR node. There are
115722
+ ** no exceptions to this.
115723
+ */
115724
+ if( *pRc==SQLITE_OK
115725
+ && pExpr->eType==FTSQUERY_NEAR
115726
+ && pExpr->bEof==0
115727
+ && (pExpr->pParent==0 || pExpr->pParent->eType!=FTSQUERY_NEAR)
115728
+ ){
115729
+ Fts3Expr *p;
115730
+ int nTmp = 0; /* Bytes of temp space */
115731
+ char *aTmp; /* Temp space for PoslistNearMerge() */
115732
+
115733
+ /* Allocate temporary working space. */
115734
+ for(p=pExpr; p->pLeft; p=p->pLeft){
115735
+ nTmp += p->pRight->pPhrase->doclist.nList;
115736
+ }
115737
+ nTmp += p->pPhrase->doclist.nList;
115738
+ aTmp = sqlite3_malloc(nTmp*2);
115739
+ if( !aTmp ){
115740
+ *pRc = SQLITE_NOMEM;
115741
+ res = 0;
115742
+ }else{
115743
+ char *aPoslist = p->pPhrase->doclist.pList;
115744
+ int nToken = p->pPhrase->nToken;
115745
+
115746
+ for(p=p->pParent;res && p && p->eType==FTSQUERY_NEAR; p=p->pParent){
115747
+ Fts3Phrase *pPhrase = p->pRight->pPhrase;
115748
+ int nNear = p->nNear;
115749
+ res = fts3EvalNearTrim2(nNear, aTmp, &aPoslist, &nToken, pPhrase);
115750
+ }
115751
+
115752
+ aPoslist = pExpr->pRight->pPhrase->doclist.pList;
115753
+ nToken = pExpr->pRight->pPhrase->nToken;
115754
+ for(p=pExpr->pLeft; p && res; p=p->pLeft){
115755
+ int nNear = p->pParent->nNear;
115756
+ Fts3Phrase *pPhrase = (
115757
+ p->eType==FTSQUERY_NEAR ? p->pRight->pPhrase : p->pPhrase
115758
+ );
115759
+ res = fts3EvalNearTrim2(nNear, aTmp, &aPoslist, &nToken, pPhrase);
115760
+ }
115761
+ }
115762
+
115763
+ sqlite3_free(aTmp);
115764
+ }
115765
+
115766
+ return res;
115767
+}
115768
+
115769
+/*
115770
+** This macro is used by the fts3EvalNext() function. The two arguments are
115771
+** 64-bit docid values. If the current query is "ORDER BY docid ASC", then
115772
+** the macro returns (i1 - i2). Or if it is "ORDER BY docid DESC", then
115773
+** it returns (i2 - i1). This allows the same code to be used for merging
115774
+** doclists in ascending or descending order.
115775
+*/
115776
+#define DOCID_CMP(i1, i2) ((pCsr->bDesc?-1:1) * (i1-i2))
115777
+
115778
+static void fts3EvalNext(
115779
+ Fts3Cursor *pCsr,
115780
+ Fts3Expr *pExpr,
115781
+ int *pRc
115782
+){
115783
+ if( *pRc==SQLITE_OK ){
115784
+ assert( pExpr->bEof==0 );
115785
+ pExpr->bStart = 1;
115786
+
115787
+ switch( pExpr->eType ){
115788
+ case FTSQUERY_NEAR:
115789
+ case FTSQUERY_AND: {
115790
+ Fts3Expr *pLeft = pExpr->pLeft;
115791
+ Fts3Expr *pRight = pExpr->pRight;
115792
+ assert( !pLeft->bDeferred || !pRight->bDeferred );
115793
+ if( pLeft->bDeferred ){
115794
+ fts3EvalNext(pCsr, pRight, pRc);
115795
+ pExpr->iDocid = pRight->iDocid;
115796
+ pExpr->bEof = pRight->bEof;
115797
+ }else if( pRight->bDeferred ){
115798
+ fts3EvalNext(pCsr, pLeft, pRc);
115799
+ pExpr->iDocid = pLeft->iDocid;
115800
+ pExpr->bEof = pLeft->bEof;
115801
+ }else{
115802
+ fts3EvalNext(pCsr, pLeft, pRc);
115803
+ fts3EvalNext(pCsr, pRight, pRc);
115804
+
115805
+ while( !pLeft->bEof && !pRight->bEof && *pRc==SQLITE_OK ){
115806
+ sqlite3_int64 iDiff = DOCID_CMP(pLeft->iDocid, pRight->iDocid);
115807
+ if( iDiff==0 ) break;
115808
+ if( iDiff<0 ){
115809
+ fts3EvalNext(pCsr, pLeft, pRc);
115810
+ }else{
115811
+ fts3EvalNext(pCsr, pRight, pRc);
115812
+ }
115813
+ }
115814
+
115815
+ pExpr->iDocid = pLeft->iDocid;
115816
+ pExpr->bEof = (pLeft->bEof || pRight->bEof);
115817
+ }
115818
+ break;
115819
+ }
115820
+
115821
+ case FTSQUERY_OR: {
115822
+ Fts3Expr *pLeft = pExpr->pLeft;
115823
+ Fts3Expr *pRight = pExpr->pRight;
115824
+ sqlite3_int64 iCmp = DOCID_CMP(pLeft->iDocid, pRight->iDocid);
115825
+
115826
+ assert( pLeft->bStart || pLeft->iDocid==pRight->iDocid );
115827
+ assert( pRight->bStart || pLeft->iDocid==pRight->iDocid );
115828
+
115829
+ if( pRight->bEof || (pLeft->bEof==0 && iCmp<0) ){
115830
+ fts3EvalNext(pCsr, pLeft, pRc);
115831
+ }else if( pLeft->bEof || (pRight->bEof==0 && iCmp>0) ){
115832
+ fts3EvalNext(pCsr, pRight, pRc);
115833
+ }else{
115834
+ fts3EvalNext(pCsr, pLeft, pRc);
115835
+ fts3EvalNext(pCsr, pRight, pRc);
115836
+ }
115837
+
115838
+ pExpr->bEof = (pLeft->bEof && pRight->bEof);
115839
+ iCmp = DOCID_CMP(pLeft->iDocid, pRight->iDocid);
115840
+ if( pRight->bEof || (pLeft->bEof==0 && iCmp<0) ){
115841
+ pExpr->iDocid = pLeft->iDocid;
115842
+ }else{
115843
+ pExpr->iDocid = pRight->iDocid;
115844
+ }
115845
+
115846
+ break;
115847
+ }
115848
+
115849
+ case FTSQUERY_NOT: {
115850
+ Fts3Expr *pLeft = pExpr->pLeft;
115851
+ Fts3Expr *pRight = pExpr->pRight;
115852
+
115853
+ if( pRight->bStart==0 ){
115854
+ fts3EvalNext(pCsr, pRight, pRc);
115855
+ assert( *pRc!=SQLITE_OK || pRight->bStart );
115856
+ }
115857
+
115858
+ fts3EvalNext(pCsr, pLeft, pRc);
115859
+ if( pLeft->bEof==0 ){
115860
+ while( !*pRc
115861
+ && !pRight->bEof
115862
+ && DOCID_CMP(pLeft->iDocid, pRight->iDocid)>0
115863
+ ){
115864
+ fts3EvalNext(pCsr, pRight, pRc);
115865
+ }
115866
+ }
115867
+ pExpr->iDocid = pLeft->iDocid;
115868
+ pExpr->bEof = pLeft->bEof;
115869
+ break;
115870
+ }
115871
+
115872
+ default: {
115873
+ Fts3Phrase *pPhrase = pExpr->pPhrase;
115874
+ fts3EvalZeroPoslist(pPhrase);
115875
+ *pRc = fts3EvalPhraseNext(pCsr, pPhrase, &pExpr->bEof);
115876
+ pExpr->iDocid = pPhrase->doclist.iDocid;
115877
+ break;
115878
+ }
115879
+ }
115880
+ }
115881
+}
115882
+
115883
+static int fts3EvalDeferredTest(Fts3Cursor *pCsr, Fts3Expr *pExpr, int *pRc){
115884
+ int bHit = 1;
115885
+ if( *pRc==SQLITE_OK ){
115886
+ switch( pExpr->eType ){
115887
+ case FTSQUERY_NEAR:
115888
+ case FTSQUERY_AND:
115889
+ bHit = (
115890
+ fts3EvalDeferredTest(pCsr, pExpr->pLeft, pRc)
115891
+ && fts3EvalDeferredTest(pCsr, pExpr->pRight, pRc)
115892
+ && fts3EvalNearTest(pExpr, pRc)
115893
+ );
115894
+
115895
+ /* If the NEAR expression does not match any rows, zero the doclist for
115896
+ ** all phrases involved in the NEAR. This is because the snippet(),
115897
+ ** offsets() and matchinfo() functions are not supposed to recognize
115898
+ ** any instances of phrases that are part of unmatched NEAR queries.
115899
+ ** For example if this expression:
115900
+ **
115901
+ ** ... MATCH 'a OR (b NEAR c)'
115902
+ **
115903
+ ** is matched against a row containing:
115904
+ **
115905
+ ** 'a b d e'
115906
+ **
115907
+ ** then any snippet() should ony highlight the "a" term, not the "b"
115908
+ ** (as "b" is part of a non-matching NEAR clause).
115909
+ */
115910
+ if( bHit==0
115911
+ && pExpr->eType==FTSQUERY_NEAR
115912
+ && (pExpr->pParent==0 || pExpr->pParent->eType!=FTSQUERY_NEAR)
115913
+ ){
115914
+ Fts3Expr *p;
115915
+ for(p=pExpr; p->pPhrase==0; p=p->pLeft){
115916
+ if( p->pRight->iDocid==pCsr->iPrevId ){
115917
+ fts3EvalZeroPoslist(p->pRight->pPhrase);
115918
+ }
115919
+ }
115920
+ if( p->iDocid==pCsr->iPrevId ){
115921
+ fts3EvalZeroPoslist(p->pPhrase);
115922
+ }
115923
+ }
115924
+
115925
+ break;
115926
+
115927
+ case FTSQUERY_OR: {
115928
+ int bHit1 = fts3EvalDeferredTest(pCsr, pExpr->pLeft, pRc);
115929
+ int bHit2 = fts3EvalDeferredTest(pCsr, pExpr->pRight, pRc);
115930
+ bHit = bHit1 || bHit2;
115931
+ break;
115932
+ }
115933
+
115934
+ case FTSQUERY_NOT:
115935
+ bHit = (
115936
+ fts3EvalDeferredTest(pCsr, pExpr->pLeft, pRc)
115937
+ && !fts3EvalDeferredTest(pCsr, pExpr->pRight, pRc)
115938
+ );
115939
+ break;
115940
+
115941
+ default: {
115942
+ if( pCsr->pDeferred
115943
+ && (pExpr->iDocid==pCsr->iPrevId || pExpr->bDeferred)
115944
+ ){
115945
+ Fts3Phrase *pPhrase = pExpr->pPhrase;
115946
+ assert( pExpr->bDeferred || pPhrase->doclist.bFreeList==0 );
115947
+ if( pExpr->bDeferred ){
115948
+ fts3EvalZeroPoslist(pPhrase);
115949
+ }
115950
+ *pRc = fts3EvalDeferredPhrase(pCsr, pPhrase);
115951
+ bHit = (pPhrase->doclist.pList!=0);
115952
+ pExpr->iDocid = pCsr->iPrevId;
115953
+ }else{
115954
+ bHit = (pExpr->bEof==0 && pExpr->iDocid==pCsr->iPrevId);
115955
+ }
115956
+ break;
115957
+ }
115958
+ }
115959
+ }
115960
+ return bHit;
115961
+}
115962
+
115963
+/*
115964
+** Return 1 if both of the following are true:
115965
+**
115966
+** 1. *pRc is SQLITE_OK when this function returns, and
115967
+**
115968
+** 2. After scanning the current FTS table row for the deferred tokens,
115969
+** it is determined that the row does not match the query.
115970
+**
115971
+** Or, if no error occurs and it seems the current row does match the FTS
115972
+** query, return 0.
115973
+*/
115974
+static int fts3EvalLoadDeferred(Fts3Cursor *pCsr, int *pRc){
115975
+ int rc = *pRc;
115976
+ int bMiss = 0;
115977
+ if( rc==SQLITE_OK ){
115978
+ if( pCsr->pDeferred ){
115979
+ rc = fts3CursorSeek(0, pCsr);
115980
+ if( rc==SQLITE_OK ){
115981
+ rc = sqlite3Fts3CacheDeferredDoclists(pCsr);
115982
+ }
115983
+ }
115984
+ bMiss = (0==fts3EvalDeferredTest(pCsr, pCsr->pExpr, &rc));
115985
+ sqlite3Fts3FreeDeferredDoclists(pCsr);
115986
+ *pRc = rc;
115987
+ }
115988
+ return (rc==SQLITE_OK && bMiss);
115989
+}
115990
+
115991
+/*
115992
+** Advance to the next document that matches the FTS expression in
115993
+** Fts3Cursor.pExpr.
115994
+*/
115995
+SQLITE_PRIVATE int sqlite3Fts3EvalNext(Fts3Cursor *pCsr){
115996
+ int rc = SQLITE_OK; /* Return Code */
115997
+ Fts3Expr *pExpr = pCsr->pExpr;
115998
+ assert( pCsr->isEof==0 );
115999
+ if( pExpr==0 ){
116000
+ pCsr->isEof = 1;
116001
+ }else{
116002
+ do {
116003
+ if( pCsr->isRequireSeek==0 ){
116004
+ sqlite3_reset(pCsr->pStmt);
116005
+ }
116006
+ assert( sqlite3_data_count(pCsr->pStmt)==0 );
116007
+ fts3EvalNext(pCsr, pExpr, &rc);
116008
+ pCsr->isEof = pExpr->bEof;
116009
+ pCsr->isRequireSeek = 1;
116010
+ pCsr->isMatchinfoNeeded = 1;
116011
+ pCsr->iPrevId = pExpr->iDocid;
116012
+ }while( pCsr->isEof==0 && fts3EvalLoadDeferred(pCsr, &rc) );
116013
+ }
116014
+ return rc;
116015
+}
116016
+
116017
+/*
116018
+** Restart interation for expression pExpr so that the next call to
116019
+** sqlite3Fts3EvalNext() visits the first row. Do not allow incremental
116020
+** loading or merging of phrase doclists for this iteration.
116021
+**
116022
+** If *pRc is other than SQLITE_OK when this function is called, it is
116023
+** a no-op. If an error occurs within this function, *pRc is set to an
116024
+** SQLite error code before returning.
116025
+*/
116026
+static void fts3EvalRestart(
116027
+ Fts3Cursor *pCsr,
116028
+ Fts3Expr *pExpr,
116029
+ int *pRc
116030
+){
116031
+ if( pExpr && *pRc==SQLITE_OK ){
116032
+ Fts3Phrase *pPhrase = pExpr->pPhrase;
116033
+
116034
+ if( pPhrase ){
116035
+ fts3EvalZeroPoslist(pPhrase);
116036
+ if( pPhrase->bIncr ){
116037
+ sqlite3Fts3EvalPhraseCleanup(pPhrase);
116038
+ memset(&pPhrase->doclist, 0, sizeof(Fts3Doclist));
116039
+ *pRc = sqlite3Fts3EvalStart(pCsr, pExpr, 0);
116040
+ }else{
116041
+ pPhrase->doclist.pNextDocid = 0;
116042
+ pPhrase->doclist.iDocid = 0;
116043
+ }
116044
+ }
116045
+
116046
+ pExpr->iDocid = 0;
116047
+ pExpr->bEof = 0;
116048
+ pExpr->bStart = 0;
116049
+
116050
+ fts3EvalRestart(pCsr, pExpr->pLeft, pRc);
116051
+ fts3EvalRestart(pCsr, pExpr->pRight, pRc);
116052
+ }
116053
+}
116054
+
116055
+/*
116056
+** After allocating the Fts3Expr.aMI[] array for each phrase in the
116057
+** expression rooted at pExpr, the cursor iterates through all rows matched
116058
+** by pExpr, calling this function for each row. This function increments
116059
+** the values in Fts3Expr.aMI[] according to the position-list currently
116060
+** found in Fts3Expr.pPhrase->doclist.pList for each of the phrase
116061
+** expression nodes.
116062
+*/
116063
+static void fts3EvalUpdateCounts(Fts3Expr *pExpr){
116064
+ if( pExpr ){
116065
+ Fts3Phrase *pPhrase = pExpr->pPhrase;
116066
+ if( pPhrase && pPhrase->doclist.pList ){
116067
+ int iCol = 0;
116068
+ char *p = pPhrase->doclist.pList;
116069
+
116070
+ assert( *p );
116071
+ while( 1 ){
116072
+ u8 c = 0;
116073
+ int iCnt = 0;
116074
+ while( 0xFE & (*p | c) ){
116075
+ if( (c&0x80)==0 ) iCnt++;
116076
+ c = *p++ & 0x80;
116077
+ }
116078
+
116079
+ /* aMI[iCol*3 + 1] = Number of occurrences
116080
+ ** aMI[iCol*3 + 2] = Number of rows containing at least one instance
116081
+ */
116082
+ pExpr->aMI[iCol*3 + 1] += iCnt;
116083
+ pExpr->aMI[iCol*3 + 2] += (iCnt>0);
116084
+ if( *p==0x00 ) break;
116085
+ p++;
116086
+ p += sqlite3Fts3GetVarint32(p, &iCol);
116087
+ }
116088
+ }
116089
+
116090
+ fts3EvalUpdateCounts(pExpr->pLeft);
116091
+ fts3EvalUpdateCounts(pExpr->pRight);
116092
+ }
116093
+}
116094
+
116095
+/*
116096
+** Expression pExpr must be of type FTSQUERY_PHRASE.
116097
+**
116098
+** If it is not already allocated and populated, this function allocates and
116099
+** populates the Fts3Expr.aMI[] array for expression pExpr. If pExpr is part
116100
+** of a NEAR expression, then it also allocates and populates the same array
116101
+** for all other phrases that are part of the NEAR expression.
116102
+**
116103
+** SQLITE_OK is returned if the aMI[] array is successfully allocated and
116104
+** populated. Otherwise, if an error occurs, an SQLite error code is returned.
116105
+*/
116106
+static int fts3EvalGatherStats(
116107
+ Fts3Cursor *pCsr, /* Cursor object */
116108
+ Fts3Expr *pExpr /* FTSQUERY_PHRASE expression */
116109
+){
116110
+ int rc = SQLITE_OK; /* Return code */
116111
+
116112
+ assert( pExpr->eType==FTSQUERY_PHRASE );
116113
+ if( pExpr->aMI==0 ){
116114
+ Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
116115
+ Fts3Expr *pRoot; /* Root of NEAR expression */
116116
+ Fts3Expr *p; /* Iterator used for several purposes */
116117
+
116118
+ sqlite3_int64 iPrevId = pCsr->iPrevId;
116119
+ sqlite3_int64 iDocid;
116120
+ u8 bEof;
116121
+
116122
+ /* Find the root of the NEAR expression */
116123
+ pRoot = pExpr;
116124
+ while( pRoot->pParent && pRoot->pParent->eType==FTSQUERY_NEAR ){
116125
+ pRoot = pRoot->pParent;
116126
+ }
116127
+ iDocid = pRoot->iDocid;
116128
+ bEof = pRoot->bEof;
116129
+ assert( pRoot->bStart );
116130
+
116131
+ /* Allocate space for the aMSI[] array of each FTSQUERY_PHRASE node */
116132
+ for(p=pRoot; p; p=p->pLeft){
116133
+ Fts3Expr *pE = (p->eType==FTSQUERY_PHRASE?p:p->pRight);
116134
+ assert( pE->aMI==0 );
116135
+ pE->aMI = (u32 *)sqlite3_malloc(pTab->nColumn * 3 * sizeof(u32));
116136
+ if( !pE->aMI ) return SQLITE_NOMEM;
116137
+ memset(pE->aMI, 0, pTab->nColumn * 3 * sizeof(u32));
116138
+ }
116139
+
116140
+ fts3EvalRestart(pCsr, pRoot, &rc);
116141
+
116142
+ while( pCsr->isEof==0 && rc==SQLITE_OK ){
116143
+
116144
+ do {
116145
+ /* Ensure the %_content statement is reset. */
116146
+ if( pCsr->isRequireSeek==0 ) sqlite3_reset(pCsr->pStmt);
116147
+ assert( sqlite3_data_count(pCsr->pStmt)==0 );
116148
+
116149
+ /* Advance to the next document */
116150
+ fts3EvalNext(pCsr, pRoot, &rc);
116151
+ pCsr->isEof = pRoot->bEof;
116152
+ pCsr->isRequireSeek = 1;
116153
+ pCsr->isMatchinfoNeeded = 1;
116154
+ pCsr->iPrevId = pRoot->iDocid;
116155
+ }while( pCsr->isEof==0
116156
+ && pRoot->eType==FTSQUERY_NEAR
116157
+ && fts3EvalLoadDeferred(pCsr, &rc)
116158
+ );
116159
+
116160
+ if( rc==SQLITE_OK && pCsr->isEof==0 ){
116161
+ fts3EvalUpdateCounts(pRoot);
116162
+ }
116163
+ }
116164
+
116165
+ pCsr->isEof = 0;
116166
+ pCsr->iPrevId = iPrevId;
116167
+
116168
+ if( bEof ){
116169
+ pRoot->bEof = bEof;
116170
+ }else{
116171
+ /* Caution: pRoot may iterate through docids in ascending or descending
116172
+ ** order. For this reason, even though it seems more defensive, the
116173
+ ** do loop can not be written:
116174
+ **
116175
+ ** do {...} while( pRoot->iDocid<iDocid && rc==SQLITE_OK );
116176
+ */
116177
+ fts3EvalRestart(pCsr, pRoot, &rc);
116178
+ do {
116179
+ fts3EvalNext(pCsr, pRoot, &rc);
116180
+ assert( pRoot->bEof==0 );
116181
+ }while( pRoot->iDocid!=iDocid && rc==SQLITE_OK );
116182
+ fts3EvalLoadDeferred(pCsr, &rc);
116183
+ }
116184
+ }
116185
+ return rc;
116186
+}
116187
+
116188
+/*
116189
+** This function is used by the matchinfo() module to query a phrase
116190
+** expression node for the following information:
116191
+**
116192
+** 1. The total number of occurrences of the phrase in each column of
116193
+** the FTS table (considering all rows), and
116194
+**
116195
+** 2. For each column, the number of rows in the table for which the
116196
+** column contains at least one instance of the phrase.
116197
+**
116198
+** If no error occurs, SQLITE_OK is returned and the values for each column
116199
+** written into the array aiOut as follows:
116200
+**
116201
+** aiOut[iCol*3 + 1] = Number of occurrences
116202
+** aiOut[iCol*3 + 2] = Number of rows containing at least one instance
116203
+**
116204
+** Caveats:
116205
+**
116206
+** * If a phrase consists entirely of deferred tokens, then all output
116207
+** values are set to the number of documents in the table. In other
116208
+** words we assume that very common tokens occur exactly once in each
116209
+** column of each row of the table.
116210
+**
116211
+** * If a phrase contains some deferred tokens (and some non-deferred
116212
+** tokens), count the potential occurrence identified by considering
116213
+** the non-deferred tokens instead of actual phrase occurrences.
116214
+**
116215
+** * If the phrase is part of a NEAR expression, then only phrase instances
116216
+** that meet the NEAR constraint are included in the counts.
116217
+*/
116218
+SQLITE_PRIVATE int sqlite3Fts3EvalPhraseStats(
116219
+ Fts3Cursor *pCsr, /* FTS cursor handle */
116220
+ Fts3Expr *pExpr, /* Phrase expression */
116221
+ u32 *aiOut /* Array to write results into (see above) */
116222
+){
116223
+ Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
116224
+ int rc = SQLITE_OK;
116225
+ int iCol;
116226
+
116227
+ if( pExpr->bDeferred && pExpr->pParent->eType!=FTSQUERY_NEAR ){
116228
+ assert( pCsr->nDoc>0 );
116229
+ for(iCol=0; iCol<pTab->nColumn; iCol++){
116230
+ aiOut[iCol*3 + 1] = pCsr->nDoc;
116231
+ aiOut[iCol*3 + 2] = pCsr->nDoc;
116232
+ }
116233
+ }else{
116234
+ rc = fts3EvalGatherStats(pCsr, pExpr);
116235
+ if( rc==SQLITE_OK ){
116236
+ assert( pExpr->aMI );
116237
+ for(iCol=0; iCol<pTab->nColumn; iCol++){
116238
+ aiOut[iCol*3 + 1] = pExpr->aMI[iCol*3 + 1];
116239
+ aiOut[iCol*3 + 2] = pExpr->aMI[iCol*3 + 2];
116240
+ }
116241
+ }
116242
+ }
116243
+
116244
+ return rc;
116245
+}
116246
+
116247
+/*
116248
+** The expression pExpr passed as the second argument to this function
116249
+** must be of type FTSQUERY_PHRASE.
116250
+**
116251
+** The returned value is either NULL or a pointer to a buffer containing
116252
+** a position-list indicating the occurrences of the phrase in column iCol
116253
+** of the current row.
116254
+**
116255
+** More specifically, the returned buffer contains 1 varint for each
116256
+** occurence of the phrase in the column, stored using the normal (delta+2)
116257
+** compression and is terminated by either an 0x01 or 0x00 byte. For example,
116258
+** if the requested column contains "a b X c d X X" and the position-list
116259
+** for 'X' is requested, the buffer returned may contain:
116260
+**
116261
+** 0x04 0x05 0x03 0x01 or 0x04 0x05 0x03 0x00
116262
+**
116263
+** This function works regardless of whether or not the phrase is deferred,
116264
+** incremental, or neither.
116265
+*/
116266
+SQLITE_PRIVATE char *sqlite3Fts3EvalPhrasePoslist(
116267
+ Fts3Cursor *pCsr, /* FTS3 cursor object */
116268
+ Fts3Expr *pExpr, /* Phrase to return doclist for */
116269
+ int iCol /* Column to return position list for */
116270
+){
116271
+ Fts3Phrase *pPhrase = pExpr->pPhrase;
116272
+ Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
116273
+ char *pIter = pPhrase->doclist.pList;
116274
+ int iThis;
116275
+
116276
+ assert( iCol>=0 && iCol<pTab->nColumn );
116277
+ if( !pIter
116278
+ || pExpr->bEof
116279
+ || pExpr->iDocid!=pCsr->iPrevId
116280
+ || (pPhrase->iColumn<pTab->nColumn && pPhrase->iColumn!=iCol)
116281
+ ){
116282
+ return 0;
116283
+ }
116284
+
116285
+ assert( pPhrase->doclist.nList>0 );
116286
+ if( *pIter==0x01 ){
116287
+ pIter++;
116288
+ pIter += sqlite3Fts3GetVarint32(pIter, &iThis);
116289
+ }else{
116290
+ iThis = 0;
116291
+ }
116292
+ while( iThis<iCol ){
116293
+ fts3ColumnlistCopy(0, &pIter);
116294
+ if( *pIter==0x00 ) return 0;
116295
+ pIter++;
116296
+ pIter += sqlite3Fts3GetVarint32(pIter, &iThis);
116297
+ }
116298
+
116299
+ return ((iCol==iThis)?pIter:0);
116300
+}
116301
+
116302
+/*
116303
+** Free all components of the Fts3Phrase structure that were allocated by
116304
+** the eval module. Specifically, this means to free:
116305
+**
116306
+** * the contents of pPhrase->doclist, and
116307
+** * any Fts3MultiSegReader objects held by phrase tokens.
116308
+*/
116309
+SQLITE_PRIVATE void sqlite3Fts3EvalPhraseCleanup(Fts3Phrase *pPhrase){
116310
+ if( pPhrase ){
116311
+ int i;
116312
+ sqlite3_free(pPhrase->doclist.aAll);
116313
+ fts3EvalZeroPoslist(pPhrase);
116314
+ memset(&pPhrase->doclist, 0, sizeof(Fts3Doclist));
116315
+ for(i=0; i<pPhrase->nToken; i++){
116316
+ fts3SegReaderCursorFree(pPhrase->aToken[i].pSegcsr);
116317
+ pPhrase->aToken[i].pSegcsr = 0;
116318
+ }
116319
+ }
116320
+}
116321
+
115622116322
#endif
115623116323
115624116324
/************** End of fts3.c ************************************************/
115625116325
/************** Begin file fts3_aux.c ****************************************/
115626116326
/*
@@ -115648,11 +116348,11 @@
115648116348
Fts3Table *pFts3Tab;
115649116349
};
115650116350
115651116351
struct Fts3auxCursor {
115652116352
sqlite3_vtab_cursor base; /* Base class used by SQLite core */
115653
- Fts3SegReaderCursor csr; /* Must be right after "base" */
116353
+ Fts3MultiSegReader csr; /* Must be right after "base" */
115654116354
Fts3SegFilter filter;
115655116355
char *zStop;
115656116356
int nStop; /* Byte-length of string zStop */
115657116357
int isEof; /* True if cursor is at EOF */
115658116358
sqlite3_int64 iRowid; /* Current rowid */
@@ -115716,10 +116416,11 @@
115716116416
115717116417
p->pFts3Tab = (Fts3Table *)&p[1];
115718116418
p->pFts3Tab->zDb = (char *)&p->pFts3Tab[1];
115719116419
p->pFts3Tab->zName = &p->pFts3Tab->zDb[nDb+1];
115720116420
p->pFts3Tab->db = db;
116421
+ p->pFts3Tab->nIndex = 1;
115721116422
115722116423
memcpy((char *)p->pFts3Tab->zDb, zDb, nDb);
115723116424
memcpy((char *)p->pFts3Tab->zName, zFts3, nFts3);
115724116425
sqlite3Fts3Dequote((char *)p->pFts3Tab->zName);
115725116426
@@ -115996,11 +116697,11 @@
115996116697
pCsr->zStop = sqlite3_mprintf("%s", sqlite3_value_text(apVal[iIdx]));
115997116698
pCsr->nStop = sqlite3_value_bytes(apVal[iIdx]);
115998116699
if( pCsr->zStop==0 ) return SQLITE_NOMEM;
115999116700
}
116000116701
116001
- rc = sqlite3Fts3SegReaderCursor(pFts3, FTS3_SEGCURSOR_ALL,
116702
+ rc = sqlite3Fts3SegReaderCursor(pFts3, 0, FTS3_SEGCURSOR_ALL,
116002116703
pCsr->filter.zTerm, pCsr->filter.nTerm, 0, isScan, &pCsr->csr
116003116704
);
116004116705
if( rc==SQLITE_OK ){
116005116706
rc = sqlite3Fts3SegReaderStart(pFts3, &pCsr->csr, &pCsr->filter);
116006116707
}
@@ -116175,16 +116876,25 @@
116175116876
** Default span for NEAR operators.
116176116877
*/
116177116878
#define SQLITE_FTS3_DEFAULT_NEAR_PARAM 10
116178116879
116179116880
116881
+/*
116882
+** isNot:
116883
+** This variable is used by function getNextNode(). When getNextNode() is
116884
+** called, it sets ParseContext.isNot to true if the 'next node' is a
116885
+** FTSQUERY_PHRASE with a unary "-" attached to it. i.e. "mysql" in the
116886
+** FTS3 query "sqlite -mysql". Otherwise, ParseContext.isNot is set to
116887
+** zero.
116888
+*/
116180116889
typedef struct ParseContext ParseContext;
116181116890
struct ParseContext {
116182116891
sqlite3_tokenizer *pTokenizer; /* Tokenizer module */
116183116892
const char **azCol; /* Array of column names for fts3 table */
116184116893
int nCol; /* Number of entries in azCol[] */
116185116894
int iDefaultCol; /* Default column to query */
116895
+ int isNot; /* True if getNextNode() sees a unary - */
116186116896
sqlite3_context *pCtx; /* Write error message here */
116187116897
int nNest; /* Number of nested brackets */
116188116898
};
116189116899
116190116900
/*
@@ -116266,11 +116976,11 @@
116266116976
if( iEnd<n && z[iEnd]=='*' ){
116267116977
pRet->pPhrase->aToken[0].isPrefix = 1;
116268116978
iEnd++;
116269116979
}
116270116980
if( !sqlite3_fts3_enable_parentheses && iStart>0 && z[iStart-1]=='-' ){
116271
- pRet->pPhrase->isNot = 1;
116981
+ pParse->isNot = 1;
116272116982
}
116273116983
}
116274116984
nConsumed = iEnd;
116275116985
}
116276116986
@@ -116318,71 +117028,86 @@
116318117028
Fts3Expr *p = 0;
116319117029
sqlite3_tokenizer_cursor *pCursor = 0;
116320117030
char *zTemp = 0;
116321117031
int nTemp = 0;
116322117032
117033
+ const int nSpace = sizeof(Fts3Expr) + sizeof(Fts3Phrase);
117034
+ int nToken = 0;
117035
+
117036
+ /* The final Fts3Expr data structure, including the Fts3Phrase,
117037
+ ** Fts3PhraseToken structures token buffers are all stored as a single
117038
+ ** allocation so that the expression can be freed with a single call to
117039
+ ** sqlite3_free(). Setting this up requires a two pass approach.
117040
+ **
117041
+ ** The first pass, in the block below, uses a tokenizer cursor to iterate
117042
+ ** through the tokens in the expression. This pass uses fts3ReallocOrFree()
117043
+ ** to assemble data in two dynamic buffers:
117044
+ **
117045
+ ** Buffer p: Points to the Fts3Expr structure, followed by the Fts3Phrase
117046
+ ** structure, followed by the array of Fts3PhraseToken
117047
+ ** structures. This pass only populates the Fts3PhraseToken array.
117048
+ **
117049
+ ** Buffer zTemp: Contains copies of all tokens.
117050
+ **
117051
+ ** The second pass, in the block that begins "if( rc==SQLITE_DONE )" below,
117052
+ ** appends buffer zTemp to buffer p, and fills in the Fts3Expr and Fts3Phrase
117053
+ ** structures.
117054
+ */
116323117055
rc = pModule->xOpen(pTokenizer, zInput, nInput, &pCursor);
116324117056
if( rc==SQLITE_OK ){
116325117057
int ii;
116326117058
pCursor->pTokenizer = pTokenizer;
116327117059
for(ii=0; rc==SQLITE_OK; ii++){
116328
- const char *zToken;
116329
- int nToken, iBegin, iEnd, iPos;
116330
- rc = pModule->xNext(pCursor, &zToken, &nToken, &iBegin, &iEnd, &iPos);
117060
+ const char *zByte;
117061
+ int nByte, iBegin, iEnd, iPos;
117062
+ rc = pModule->xNext(pCursor, &zByte, &nByte, &iBegin, &iEnd, &iPos);
116331117063
if( rc==SQLITE_OK ){
116332
- int nByte = sizeof(Fts3Expr) + sizeof(Fts3Phrase);
116333
- p = fts3ReallocOrFree(p, nByte+ii*sizeof(Fts3PhraseToken));
116334
- zTemp = fts3ReallocOrFree(zTemp, nTemp + nToken);
116335
- if( !p || !zTemp ){
116336
- goto no_mem;
116337
- }
116338
- if( ii==0 ){
116339
- memset(p, 0, nByte);
116340
- p->pPhrase = (Fts3Phrase *)&p[1];
116341
- }
116342
- p->pPhrase = (Fts3Phrase *)&p[1];
116343
- memset(&p->pPhrase->aToken[ii], 0, sizeof(Fts3PhraseToken));
116344
- p->pPhrase->nToken = ii+1;
116345
- p->pPhrase->aToken[ii].n = nToken;
116346
- memcpy(&zTemp[nTemp], zToken, nToken);
116347
- nTemp += nToken;
116348
- if( iEnd<nInput && zInput[iEnd]=='*' ){
116349
- p->pPhrase->aToken[ii].isPrefix = 1;
116350
- }else{
116351
- p->pPhrase->aToken[ii].isPrefix = 0;
116352
- }
117064
+ Fts3PhraseToken *pToken;
117065
+
117066
+ p = fts3ReallocOrFree(p, nSpace + ii*sizeof(Fts3PhraseToken));
117067
+ if( !p ) goto no_mem;
117068
+
117069
+ zTemp = fts3ReallocOrFree(zTemp, nTemp + nByte);
117070
+ if( !zTemp ) goto no_mem;
117071
+
117072
+ assert( nToken==ii );
117073
+ pToken = &((Fts3Phrase *)(&p[1]))->aToken[ii];
117074
+ memset(pToken, 0, sizeof(Fts3PhraseToken));
117075
+
117076
+ memcpy(&zTemp[nTemp], zByte, nByte);
117077
+ nTemp += nByte;
117078
+
117079
+ pToken->n = nByte;
117080
+ pToken->isPrefix = (iEnd<nInput && zInput[iEnd]=='*');
117081
+ nToken = ii+1;
116353117082
}
116354117083
}
116355117084
116356117085
pModule->xClose(pCursor);
116357117086
pCursor = 0;
116358117087
}
116359117088
116360117089
if( rc==SQLITE_DONE ){
116361117090
int jj;
116362
- char *zNew = NULL;
116363
- int nNew = 0;
116364
- int nByte = sizeof(Fts3Expr) + sizeof(Fts3Phrase);
116365
- nByte += (p?(p->pPhrase->nToken-1):0) * sizeof(Fts3PhraseToken);
116366
- p = fts3ReallocOrFree(p, nByte + nTemp);
116367
- if( !p ){
116368
- goto no_mem;
116369
- }
116370
- if( zTemp ){
116371
- zNew = &(((char *)p)[nByte]);
116372
- memcpy(zNew, zTemp, nTemp);
116373
- }else{
116374
- memset(p, 0, nByte+nTemp);
116375
- }
117091
+ char *zBuf = 0;
117092
+
117093
+ p = fts3ReallocOrFree(p, nSpace + nToken*sizeof(Fts3PhraseToken) + nTemp);
117094
+ if( !p ) goto no_mem;
117095
+ memset(p, 0, (char *)&(((Fts3Phrase *)&p[1])->aToken[0])-(char *)p);
117096
+ p->eType = FTSQUERY_PHRASE;
116376117097
p->pPhrase = (Fts3Phrase *)&p[1];
117098
+ p->pPhrase->iColumn = pParse->iDefaultCol;
117099
+ p->pPhrase->nToken = nToken;
117100
+
117101
+ zBuf = (char *)&p->pPhrase->aToken[nToken];
117102
+ memcpy(zBuf, zTemp, nTemp);
117103
+ sqlite3_free(zTemp);
117104
+
116377117105
for(jj=0; jj<p->pPhrase->nToken; jj++){
116378
- p->pPhrase->aToken[jj].z = &zNew[nNew];
116379
- nNew += p->pPhrase->aToken[jj].n;
117106
+ p->pPhrase->aToken[jj].z = zBuf;
117107
+ zBuf += p->pPhrase->aToken[jj].n;
116380117108
}
116381
- sqlite3_free(zTemp);
116382
- p->eType = FTSQUERY_PHRASE;
116383
- p->pPhrase->iColumn = pParse->iDefaultCol;
116384117109
rc = SQLITE_OK;
116385117110
}
116386117111
116387117112
*ppExpr = p;
116388117113
return rc;
@@ -116434,10 +117159,12 @@
116434117159
int rc;
116435117160
Fts3Expr *pRet = 0;
116436117161
116437117162
const char *zInput = z;
116438117163
int nInput = n;
117164
+
117165
+ pParse->isNot = 0;
116439117166
116440117167
/* Skip over any whitespace before checking for a keyword, an open or
116441117168
** close bracket, or a quoted string.
116442117169
*/
116443117170
while( nInput>0 && fts3isspace(*zInput) ){
@@ -116653,11 +117380,11 @@
116653117380
rc = getNextNode(pParse, zIn, nIn, &p, &nByte);
116654117381
if( rc==SQLITE_OK ){
116655117382
int isPhrase;
116656117383
116657117384
if( !sqlite3_fts3_enable_parentheses
116658
- && p->eType==FTSQUERY_PHRASE && p->pPhrase->isNot
117385
+ && p->eType==FTSQUERY_PHRASE && pParse->isNot
116659117386
){
116660117387
/* Create an implicit NOT operator. */
116661117388
Fts3Expr *pNot = fts3MallocZero(sizeof(Fts3Expr));
116662117389
if( !pNot ){
116663117390
sqlite3Fts3ExprFree(p);
@@ -116671,11 +117398,10 @@
116671117398
}
116672117399
pNotBranch = pNot;
116673117400
p = pPrev;
116674117401
}else{
116675117402
int eType = p->eType;
116676
- assert( eType!=FTSQUERY_PHRASE || !p->pPhrase->isNot );
116677117403
isPhrase = (eType==FTSQUERY_PHRASE || p->pLeft);
116678117404
116679117405
/* The isRequirePhrase variable is set to true if a phrase or
116680117406
** an expression contained in parenthesis is required. If a
116681117407
** binary operator (AND, OR, NOT or NEAR) is encounted when
@@ -116834,13 +117560,15 @@
116834117560
/*
116835117561
** Free a parsed fts3 query expression allocated by sqlite3Fts3ExprParse().
116836117562
*/
116837117563
SQLITE_PRIVATE void sqlite3Fts3ExprFree(Fts3Expr *p){
116838117564
if( p ){
117565
+ assert( p->eType==FTSQUERY_PHRASE || p->pPhrase==0 );
116839117566
sqlite3Fts3ExprFree(p->pLeft);
116840117567
sqlite3Fts3ExprFree(p->pRight);
116841
- sqlite3_free(p->aDoclist);
117568
+ sqlite3Fts3EvalPhraseCleanup(p->pPhrase);
117569
+ sqlite3_free(p->aMI);
116842117570
sqlite3_free(p);
116843117571
}
116844117572
}
116845117573
116846117574
/****************************************************************************
@@ -116893,11 +117621,11 @@
116893117621
switch( pExpr->eType ){
116894117622
case FTSQUERY_PHRASE: {
116895117623
Fts3Phrase *pPhrase = pExpr->pPhrase;
116896117624
int i;
116897117625
zBuf = sqlite3_mprintf(
116898
- "%zPHRASE %d %d", zBuf, pPhrase->iColumn, pPhrase->isNot);
117626
+ "%zPHRASE %d 0", zBuf, pPhrase->iColumn);
116899117627
for(i=0; zBuf && i<pPhrase->nToken; i++){
116900117628
zBuf = sqlite3_mprintf("%z %.*s%s", zBuf,
116901117629
pPhrase->aToken[i].n, pPhrase->aToken[i].z,
116902117630
(pPhrase->aToken[i].isPrefix?"+":"")
116903117631
);
@@ -118811,18 +119539,44 @@
118811119539
** it is always safe to read up to two varints from it without risking an
118812119540
** overread, even if the node data is corrupted.
118813119541
*/
118814119542
#define FTS3_NODE_PADDING (FTS3_VARINT_MAX*2)
118815119543
119544
+/*
119545
+** Under certain circumstances, b-tree nodes (doclists) can be loaded into
119546
+** memory incrementally instead of all at once. This can be a big performance
119547
+** win (reduced IO and CPU) if SQLite stops calling the virtual table xNext()
119548
+** method before retrieving all query results (as may happen, for example,
119549
+** if a query has a LIMIT clause).
119550
+**
119551
+** Incremental loading is used for b-tree nodes FTS3_NODE_CHUNK_THRESHOLD
119552
+** bytes and larger. Nodes are loaded in chunks of FTS3_NODE_CHUNKSIZE bytes.
119553
+** The code is written so that the hard lower-limit for each of these values
119554
+** is 1. Clearly such small values would be inefficient, but can be useful
119555
+** for testing purposes.
119556
+**
119557
+** If this module is built with SQLITE_TEST defined, these constants may
119558
+** be overridden at runtime for testing purposes. File fts3_test.c contains
119559
+** a Tcl interface to read and write the values.
119560
+*/
119561
+#ifdef SQLITE_TEST
119562
+int test_fts3_node_chunksize = (4*1024);
119563
+int test_fts3_node_chunk_threshold = (4*1024)*4;
119564
+# define FTS3_NODE_CHUNKSIZE test_fts3_node_chunksize
119565
+# define FTS3_NODE_CHUNK_THRESHOLD test_fts3_node_chunk_threshold
119566
+#else
119567
+# define FTS3_NODE_CHUNKSIZE (4*1024)
119568
+# define FTS3_NODE_CHUNK_THRESHOLD (FTS3_NODE_CHUNKSIZE*4)
119569
+#endif
119570
+
118816119571
typedef struct PendingList PendingList;
118817119572
typedef struct SegmentNode SegmentNode;
118818119573
typedef struct SegmentWriter SegmentWriter;
118819119574
118820119575
/*
118821
-** Data structure used while accumulating terms in the pending-terms hash
118822
-** table. The hash table entry maps from term (a string) to a malloc'd
118823
-** instance of this structure.
119576
+** An instance of the following data structure is used to build doclists
119577
+** incrementally. See function fts3PendingListAppend() for details.
118824119578
*/
118825119579
struct PendingList {
118826119580
int nData;
118827119581
char *aData;
118828119582
int nSpace;
@@ -118849,11 +119603,10 @@
118849119603
** of type Fts3SegReader* are also used by code in fts3.c to iterate through
118850119604
** terms when querying the full-text index. See functions:
118851119605
**
118852119606
** sqlite3Fts3SegReaderNew()
118853119607
** sqlite3Fts3SegReaderFree()
118854
-** sqlite3Fts3SegReaderCost()
118855119608
** sqlite3Fts3SegReaderIterate()
118856119609
**
118857119610
** Methods used to manipulate Fts3SegReader structures:
118858119611
**
118859119612
** fts3SegReaderNext()
@@ -118868,10 +119621,13 @@
118868119621
sqlite3_int64 iEndBlock; /* Rowid of final block in segment (or 0) */
118869119622
sqlite3_int64 iCurrentBlock; /* Current leaf block (or 0) */
118870119623
118871119624
char *aNode; /* Pointer to node data (or NULL) */
118872119625
int nNode; /* Size of buffer at aNode (or 0) */
119626
+ int nPopulate; /* If >0, bytes of buffer aNode[] loaded */
119627
+ sqlite3_blob *pBlob; /* If not NULL, blob handle to read node */
119628
+
118873119629
Fts3HashElem **ppNextElem;
118874119630
118875119631
/* Variables set by fts3SegReaderNext(). These may be read directly
118876119632
** by the caller. They are valid from the time SegmentReaderNew() returns
118877119633
** until SegmentReaderNext() returns something other than SQLITE_OK
@@ -118881,12 +119637,15 @@
118881119637
char *zTerm; /* Pointer to current term */
118882119638
int nTermAlloc; /* Allocated size of zTerm buffer */
118883119639
char *aDoclist; /* Pointer to doclist of current entry */
118884119640
int nDoclist; /* Size of doclist in current entry */
118885119641
118886
- /* The following variables are used to iterate through the current doclist */
119642
+ /* The following variables are used by fts3SegReaderNextDocid() to iterate
119643
+ ** through the current doclist (aDoclist/nDoclist).
119644
+ */
118887119645
char *pOffsetList;
119646
+ int nOffsetList; /* For descending pending seg-readers only */
118888119647
sqlite3_int64 iDocid;
118889119648
};
118890119649
118891119650
#define fts3SegReaderIsPending(p) ((p)->ppNextElem!=0)
118892119651
#define fts3SegReaderIsRootOnly(p) ((p)->aNode==(char *)&(p)[1])
@@ -118920,10 +119679,18 @@
118920119679
** within the fts3SegWriterXXX() family of functions described above.
118921119680
**
118922119681
** fts3NodeAddTerm()
118923119682
** fts3NodeWrite()
118924119683
** fts3NodeFree()
119684
+**
119685
+** When a b+tree is written to the database (either as a result of a merge
119686
+** or the pending-terms table being flushed), leaves are written into the
119687
+** database file as soon as they are completely populated. The interior of
119688
+** the tree is assembled in memory and written out only once all leaves have
119689
+** been populated and stored. This is Ok, as the b+-tree fanout is usually
119690
+** very large, meaning that the interior of the tree consumes relatively
119691
+** little memory.
118925119692
*/
118926119693
struct SegmentNode {
118927119694
SegmentNode *pParent; /* Parent node (or NULL for root node) */
118928119695
SegmentNode *pRight; /* Pointer to right-sibling */
118929119696
SegmentNode *pLeftmost; /* Pointer to left-most node of this depth */
@@ -118950,21 +119717,26 @@
118950119717
#define SQL_NEXT_SEGMENT_INDEX 8
118951119718
#define SQL_INSERT_SEGMENTS 9
118952119719
#define SQL_NEXT_SEGMENTS_ID 10
118953119720
#define SQL_INSERT_SEGDIR 11
118954119721
#define SQL_SELECT_LEVEL 12
118955
-#define SQL_SELECT_ALL_LEVEL 13
119722
+#define SQL_SELECT_LEVEL_RANGE 13
118956119723
#define SQL_SELECT_LEVEL_COUNT 14
118957
-#define SQL_SELECT_SEGDIR_COUNT_MAX 15
118958
-#define SQL_DELETE_SEGDIR_BY_LEVEL 16
119724
+#define SQL_SELECT_SEGDIR_MAX_LEVEL 15
119725
+#define SQL_DELETE_SEGDIR_LEVEL 16
118959119726
#define SQL_DELETE_SEGMENTS_RANGE 17
118960119727
#define SQL_CONTENT_INSERT 18
118961119728
#define SQL_DELETE_DOCSIZE 19
118962119729
#define SQL_REPLACE_DOCSIZE 20
118963119730
#define SQL_SELECT_DOCSIZE 21
118964119731
#define SQL_SELECT_DOCTOTAL 22
118965119732
#define SQL_REPLACE_DOCTOTAL 23
119733
+
119734
+#define SQL_SELECT_ALL_PREFIX_LEVEL 24
119735
+#define SQL_DELETE_ALL_TERMS_SEGDIR 25
119736
+
119737
+#define SQL_DELETE_SEGDIR_RANGE 26
118966119738
118967119739
/*
118968119740
** This function is used to obtain an SQLite prepared statement handle
118969119741
** for the statement identified by the second argument. If successful,
118970119742
** *pp is set to the requested statement handle and SQLITE_OK returned.
@@ -118997,23 +119769,29 @@
118997119769
118998119770
/* Return segments in order from oldest to newest.*/
118999119771
/* 12 */ "SELECT idx, start_block, leaves_end_block, end_block, root "
119000119772
"FROM %Q.'%q_segdir' WHERE level = ? ORDER BY idx ASC",
119001119773
/* 13 */ "SELECT idx, start_block, leaves_end_block, end_block, root "
119002
- "FROM %Q.'%q_segdir' ORDER BY level DESC, idx ASC",
119774
+ "FROM %Q.'%q_segdir' WHERE level BETWEEN ? AND ?"
119775
+ "ORDER BY level DESC, idx ASC",
119003119776
119004119777
/* 14 */ "SELECT count(*) FROM %Q.'%q_segdir' WHERE level = ?",
119005
-/* 15 */ "SELECT count(*), max(level) FROM %Q.'%q_segdir'",
119778
+/* 15 */ "SELECT max(level) FROM %Q.'%q_segdir' WHERE level BETWEEN ? AND ?",
119006119779
119007119780
/* 16 */ "DELETE FROM %Q.'%q_segdir' WHERE level = ?",
119008119781
/* 17 */ "DELETE FROM %Q.'%q_segments' WHERE blockid BETWEEN ? AND ?",
119009119782
/* 18 */ "INSERT INTO %Q.'%q_content' VALUES(%s)",
119010119783
/* 19 */ "DELETE FROM %Q.'%q_docsize' WHERE docid = ?",
119011119784
/* 20 */ "REPLACE INTO %Q.'%q_docsize' VALUES(?,?)",
119012119785
/* 21 */ "SELECT size FROM %Q.'%q_docsize' WHERE docid=?",
119013119786
/* 22 */ "SELECT value FROM %Q.'%q_stat' WHERE id=0",
119014119787
/* 23 */ "REPLACE INTO %Q.'%q_stat' VALUES(0,?)",
119788
+/* 24 */ "",
119789
+/* 25 */ "",
119790
+
119791
+/* 26 */ "DELETE FROM %Q.'%q_segdir' WHERE level BETWEEN ? AND ?",
119792
+
119015119793
};
119016119794
int rc = SQLITE_OK;
119017119795
sqlite3_stmt *pStmt;
119018119796
119019119797
assert( SizeofArray(azSql)==SizeofArray(p->aStmt) );
@@ -119165,18 +119943,36 @@
119165119943
** 1: start_block
119166119944
** 2: leaves_end_block
119167119945
** 3: end_block
119168119946
** 4: root
119169119947
*/
119170
-SQLITE_PRIVATE int sqlite3Fts3AllSegdirs(Fts3Table *p, int iLevel, sqlite3_stmt **ppStmt){
119948
+SQLITE_PRIVATE int sqlite3Fts3AllSegdirs(
119949
+ Fts3Table *p, /* FTS3 table */
119950
+ int iIndex, /* Index for p->aIndex[] */
119951
+ int iLevel, /* Level to select */
119952
+ sqlite3_stmt **ppStmt /* OUT: Compiled statement */
119953
+){
119171119954
int rc;
119172119955
sqlite3_stmt *pStmt = 0;
119956
+
119957
+ assert( iLevel==FTS3_SEGCURSOR_ALL || iLevel>=0 );
119958
+ assert( iLevel<FTS3_SEGDIR_MAXLEVEL );
119959
+ assert( iIndex>=0 && iIndex<p->nIndex );
119960
+
119173119961
if( iLevel<0 ){
119174
- rc = fts3SqlStmt(p, SQL_SELECT_ALL_LEVEL, &pStmt, 0);
119962
+ /* "SELECT * FROM %_segdir WHERE level BETWEEN ? AND ? ORDER BY ..." */
119963
+ rc = fts3SqlStmt(p, SQL_SELECT_LEVEL_RANGE, &pStmt, 0);
119964
+ if( rc==SQLITE_OK ){
119965
+ sqlite3_bind_int(pStmt, 1, iIndex*FTS3_SEGDIR_MAXLEVEL);
119966
+ sqlite3_bind_int(pStmt, 2, (iIndex+1)*FTS3_SEGDIR_MAXLEVEL-1);
119967
+ }
119175119968
}else{
119969
+ /* "SELECT * FROM %_segdir WHERE level = ? ORDER BY ..." */
119176119970
rc = fts3SqlStmt(p, SQL_SELECT_LEVEL, &pStmt, 0);
119177
- if( rc==SQLITE_OK ) sqlite3_bind_int(pStmt, 1, iLevel);
119971
+ if( rc==SQLITE_OK ){
119972
+ sqlite3_bind_int(pStmt, 1, iLevel+iIndex*FTS3_SEGDIR_MAXLEVEL);
119973
+ }
119178119974
}
119179119975
*ppStmt = pStmt;
119180119976
return rc;
119181119977
}
119182119978
@@ -119286,10 +120082,51 @@
119286120082
*pp = p;
119287120083
return 1;
119288120084
}
119289120085
return 0;
119290120086
}
120087
+
120088
+/*
120089
+** Free a PendingList object allocated by fts3PendingListAppend().
120090
+*/
120091
+static void fts3PendingListDelete(PendingList *pList){
120092
+ sqlite3_free(pList);
120093
+}
120094
+
120095
+/*
120096
+** Add an entry to one of the pending-terms hash tables.
120097
+*/
120098
+static int fts3PendingTermsAddOne(
120099
+ Fts3Table *p,
120100
+ int iCol,
120101
+ int iPos,
120102
+ Fts3Hash *pHash, /* Pending terms hash table to add entry to */
120103
+ const char *zToken,
120104
+ int nToken
120105
+){
120106
+ PendingList *pList;
120107
+ int rc = SQLITE_OK;
120108
+
120109
+ pList = (PendingList *)fts3HashFind(pHash, zToken, nToken);
120110
+ if( pList ){
120111
+ p->nPendingData -= (pList->nData + nToken + sizeof(Fts3HashElem));
120112
+ }
120113
+ if( fts3PendingListAppend(&pList, p->iPrevDocid, iCol, iPos, &rc) ){
120114
+ if( pList==fts3HashInsert(pHash, zToken, nToken, pList) ){
120115
+ /* Malloc failed while inserting the new entry. This can only
120116
+ ** happen if there was no previous entry for this token.
120117
+ */
120118
+ assert( 0==fts3HashFind(pHash, zToken, nToken) );
120119
+ sqlite3_free(pList);
120120
+ rc = SQLITE_NOMEM;
120121
+ }
120122
+ }
120123
+ if( rc==SQLITE_OK ){
120124
+ p->nPendingData += (pList->nData + nToken + sizeof(Fts3HashElem));
120125
+ }
120126
+ return rc;
120127
+}
119291120128
119292120129
/*
119293120130
** Tokenize the nul-terminated string zText and add all tokens to the
119294120131
** pending-terms hash-table. The docid used is that currently stored in
119295120132
** p->iPrevDocid, and the column is specified by argument iCol.
@@ -119335,12 +120172,11 @@
119335120172
119336120173
xNext = pModule->xNext;
119337120174
while( SQLITE_OK==rc
119338120175
&& SQLITE_OK==(rc = xNext(pCsr, &zToken, &nToken, &iStart, &iEnd, &iPos))
119339120176
){
119340
- PendingList *pList;
119341
-
120177
+ int i;
119342120178
if( iPos>=nWord ) nWord = iPos+1;
119343120179
119344120180
/* Positions cannot be negative; we use -1 as a terminator internally.
119345120181
** Tokens must have a non-zero length.
119346120182
*/
@@ -119347,26 +120183,23 @@
119347120183
if( iPos<0 || !zToken || nToken<=0 ){
119348120184
rc = SQLITE_ERROR;
119349120185
break;
119350120186
}
119351120187
119352
- pList = (PendingList *)fts3HashFind(&p->pendingTerms, zToken, nToken);
119353
- if( pList ){
119354
- p->nPendingData -= (pList->nData + nToken + sizeof(Fts3HashElem));
119355
- }
119356
- if( fts3PendingListAppend(&pList, p->iPrevDocid, iCol, iPos, &rc) ){
119357
- if( pList==fts3HashInsert(&p->pendingTerms, zToken, nToken, pList) ){
119358
- /* Malloc failed while inserting the new entry. This can only
119359
- ** happen if there was no previous entry for this token.
119360
- */
119361
- assert( 0==fts3HashFind(&p->pendingTerms, zToken, nToken) );
119362
- sqlite3_free(pList);
119363
- rc = SQLITE_NOMEM;
119364
- }
119365
- }
119366
- if( rc==SQLITE_OK ){
119367
- p->nPendingData += (pList->nData + nToken + sizeof(Fts3HashElem));
120188
+ /* Add the term to the terms index */
120189
+ rc = fts3PendingTermsAddOne(
120190
+ p, iCol, iPos, &p->aIndex[0].hPending, zToken, nToken
120191
+ );
120192
+
120193
+ /* Add the term to each of the prefix indexes that it is not too
120194
+ ** short for. */
120195
+ for(i=1; rc==SQLITE_OK && i<p->nIndex; i++){
120196
+ struct Fts3Index *pIndex = &p->aIndex[i];
120197
+ if( nToken<pIndex->nPrefix ) continue;
120198
+ rc = fts3PendingTermsAddOne(
120199
+ p, iCol, iPos, &pIndex->hPending, zToken, pIndex->nPrefix
120200
+ );
119368120201
}
119369120202
}
119370120203
119371120204
pModule->xClose(pCsr);
119372120205
*pnWord = nWord;
@@ -119392,18 +120225,23 @@
119392120225
p->iPrevDocid = iDocid;
119393120226
return SQLITE_OK;
119394120227
}
119395120228
119396120229
/*
119397
-** Discard the contents of the pending-terms hash table.
120230
+** Discard the contents of the pending-terms hash tables.
119398120231
*/
119399120232
SQLITE_PRIVATE void sqlite3Fts3PendingTermsClear(Fts3Table *p){
119400
- Fts3HashElem *pElem;
119401
- for(pElem=fts3HashFirst(&p->pendingTerms); pElem; pElem=fts3HashNext(pElem)){
119402
- sqlite3_free(fts3HashData(pElem));
120233
+ int i;
120234
+ for(i=0; i<p->nIndex; i++){
120235
+ Fts3HashElem *pElem;
120236
+ Fts3Hash *pHash = &p->aIndex[i].hPending;
120237
+ for(pElem=fts3HashFirst(pHash); pElem; pElem=fts3HashNext(pElem)){
120238
+ PendingList *pList = (PendingList *)fts3HashData(pElem);
120239
+ fts3PendingListDelete(pList);
120240
+ }
120241
+ fts3HashClear(pHash);
119403120242
}
119404
- fts3HashClear(&p->pendingTerms);
119405120243
p->nPendingData = 0;
119406120244
}
119407120245
119408120246
/*
119409120247
** This function is called by the xUpdate() method as part of an INSERT
@@ -119555,11 +120393,11 @@
119555120393
119556120394
/*
119557120395
** Forward declaration to account for the circular dependency between
119558120396
** functions fts3SegmentMerge() and fts3AllocateSegdirIdx().
119559120397
*/
119560
-static int fts3SegmentMerge(Fts3Table *, int);
120398
+static int fts3SegmentMerge(Fts3Table *, int, int);
119561120399
119562120400
/*
119563120401
** This function allocates a new level iLevel index in the segdir table.
119564120402
** Usually, indexes are allocated within a level sequentially starting
119565120403
** with 0, so the allocated index is one greater than the value returned
@@ -119572,19 +120410,24 @@
119572120410
** allocated index is 0.
119573120411
**
119574120412
** If successful, *piIdx is set to the allocated index slot and SQLITE_OK
119575120413
** returned. Otherwise, an SQLite error code is returned.
119576120414
*/
119577
-static int fts3AllocateSegdirIdx(Fts3Table *p, int iLevel, int *piIdx){
120415
+static int fts3AllocateSegdirIdx(
120416
+ Fts3Table *p,
120417
+ int iIndex, /* Index for p->aIndex */
120418
+ int iLevel,
120419
+ int *piIdx
120420
+){
119578120421
int rc; /* Return Code */
119579120422
sqlite3_stmt *pNextIdx; /* Query for next idx at level iLevel */
119580120423
int iNext = 0; /* Result of query pNextIdx */
119581120424
119582120425
/* Set variable iNext to the next available segdir index at level iLevel. */
119583120426
rc = fts3SqlStmt(p, SQL_NEXT_SEGMENT_INDEX, &pNextIdx, 0);
119584120427
if( rc==SQLITE_OK ){
119585
- sqlite3_bind_int(pNextIdx, 1, iLevel);
120428
+ sqlite3_bind_int(pNextIdx, 1, iIndex*FTS3_SEGDIR_MAXLEVEL + iLevel);
119586120429
if( SQLITE_ROW==sqlite3_step(pNextIdx) ){
119587120430
iNext = sqlite3_column_int(pNextIdx, 0);
119588120431
}
119589120432
rc = sqlite3_reset(pNextIdx);
119590120433
}
@@ -119594,11 +120437,11 @@
119594120437
** full, merge all segments in level iLevel into a single iLevel+1
119595120438
** segment and allocate (newly freed) index 0 at level iLevel. Otherwise,
119596120439
** if iNext is less than FTS3_MERGE_COUNT, allocate index iNext.
119597120440
*/
119598120441
if( iNext>=FTS3_MERGE_COUNT ){
119599
- rc = fts3SegmentMerge(p, iLevel);
120442
+ rc = fts3SegmentMerge(p, iIndex, iLevel);
119600120443
*piIdx = 0;
119601120444
}else{
119602120445
*piIdx = iNext;
119603120446
}
119604120447
}
@@ -119635,11 +120478,12 @@
119635120478
*/
119636120479
SQLITE_PRIVATE int sqlite3Fts3ReadBlock(
119637120480
Fts3Table *p, /* FTS3 table handle */
119638120481
sqlite3_int64 iBlockid, /* Access the row with blockid=$iBlockid */
119639120482
char **paBlob, /* OUT: Blob data in malloc'd buffer */
119640
- int *pnBlob /* OUT: Size of blob data */
120483
+ int *pnBlob, /* OUT: Size of blob data */
120484
+ int *pnLoad /* OUT: Bytes actually loaded */
119641120485
){
119642120486
int rc; /* Return code */
119643120487
119644120488
/* pnBlob must be non-NULL. paBlob may be NULL or non-NULL. */
119645120489
assert( pnBlob);
@@ -119656,25 +120500,29 @@
119656120500
);
119657120501
}
119658120502
119659120503
if( rc==SQLITE_OK ){
119660120504
int nByte = sqlite3_blob_bytes(p->pSegments);
120505
+ *pnBlob = nByte;
119661120506
if( paBlob ){
119662120507
char *aByte = sqlite3_malloc(nByte + FTS3_NODE_PADDING);
119663120508
if( !aByte ){
119664120509
rc = SQLITE_NOMEM;
119665120510
}else{
120511
+ if( pnLoad && nByte>(FTS3_NODE_CHUNK_THRESHOLD) ){
120512
+ nByte = FTS3_NODE_CHUNKSIZE;
120513
+ *pnLoad = nByte;
120514
+ }
119666120515
rc = sqlite3_blob_read(p->pSegments, aByte, nByte, 0);
119667120516
memset(&aByte[nByte], 0, FTS3_NODE_PADDING);
119668120517
if( rc!=SQLITE_OK ){
119669120518
sqlite3_free(aByte);
119670120519
aByte = 0;
119671120520
}
119672120521
}
119673120522
*paBlob = aByte;
119674120523
}
119675
- *pnBlob = nByte;
119676120524
}
119677120525
119678120526
return rc;
119679120527
}
119680120528
@@ -119684,17 +120532,59 @@
119684120532
*/
119685120533
SQLITE_PRIVATE void sqlite3Fts3SegmentsClose(Fts3Table *p){
119686120534
sqlite3_blob_close(p->pSegments);
119687120535
p->pSegments = 0;
119688120536
}
120537
+
120538
+static int fts3SegReaderIncrRead(Fts3SegReader *pReader){
120539
+ int nRead; /* Number of bytes to read */
120540
+ int rc; /* Return code */
120541
+
120542
+ nRead = MIN(pReader->nNode - pReader->nPopulate, FTS3_NODE_CHUNKSIZE);
120543
+ rc = sqlite3_blob_read(
120544
+ pReader->pBlob,
120545
+ &pReader->aNode[pReader->nPopulate],
120546
+ nRead,
120547
+ pReader->nPopulate
120548
+ );
120549
+
120550
+ if( rc==SQLITE_OK ){
120551
+ pReader->nPopulate += nRead;
120552
+ memset(&pReader->aNode[pReader->nPopulate], 0, FTS3_NODE_PADDING);
120553
+ if( pReader->nPopulate==pReader->nNode ){
120554
+ sqlite3_blob_close(pReader->pBlob);
120555
+ pReader->pBlob = 0;
120556
+ pReader->nPopulate = 0;
120557
+ }
120558
+ }
120559
+ return rc;
120560
+}
120561
+
120562
+static int fts3SegReaderRequire(Fts3SegReader *pReader, char *pFrom, int nByte){
120563
+ int rc = SQLITE_OK;
120564
+ assert( !pReader->pBlob
120565
+ || (pFrom>=pReader->aNode && pFrom<&pReader->aNode[pReader->nNode])
120566
+ );
120567
+ while( pReader->pBlob && rc==SQLITE_OK
120568
+ && (pFrom - pReader->aNode + nByte)>pReader->nPopulate
120569
+ ){
120570
+ rc = fts3SegReaderIncrRead(pReader);
120571
+ }
120572
+ return rc;
120573
+}
119689120574
119690120575
/*
119691120576
** Move the iterator passed as the first argument to the next term in the
119692120577
** segment. If successful, SQLITE_OK is returned. If there is no next term,
119693120578
** SQLITE_DONE. Otherwise, an SQLite error code.
119694120579
*/
119695
-static int fts3SegReaderNext(Fts3Table *p, Fts3SegReader *pReader){
120580
+static int fts3SegReaderNext(
120581
+ Fts3Table *p,
120582
+ Fts3SegReader *pReader,
120583
+ int bIncr
120584
+){
120585
+ int rc; /* Return code of various sub-routines */
119696120586
char *pNext; /* Cursor variable */
119697120587
int nPrefix; /* Number of bytes in term prefix */
119698120588
int nSuffix; /* Number of bytes in term suffix */
119699120589
119700120590
if( !pReader->aDoclist ){
@@ -119702,11 +120592,10 @@
119702120592
}else{
119703120593
pNext = &pReader->aDoclist[pReader->nDoclist];
119704120594
}
119705120595
119706120596
if( !pNext || pNext>=&pReader->aNode[pReader->nNode] ){
119707
- int rc; /* Return code from Fts3ReadBlock() */
119708120597
119709120598
if( fts3SegReaderIsPending(pReader) ){
119710120599
Fts3HashElem *pElem = *(pReader->ppNextElem);
119711120600
if( pElem==0 ){
119712120601
pReader->aNode = 0;
@@ -119722,10 +120611,12 @@
119722120611
return SQLITE_OK;
119723120612
}
119724120613
119725120614
if( !fts3SegReaderIsRootOnly(pReader) ){
119726120615
sqlite3_free(pReader->aNode);
120616
+ sqlite3_blob_close(pReader->pBlob);
120617
+ pReader->pBlob = 0;
119727120618
}
119728120619
pReader->aNode = 0;
119729120620
119730120621
/* If iCurrentBlock>=iLeafEndBlock, this is an EOF condition. All leaf
119731120622
** blocks have already been traversed. */
@@ -119733,19 +120624,29 @@
119733120624
if( pReader->iCurrentBlock>=pReader->iLeafEndBlock ){
119734120625
return SQLITE_OK;
119735120626
}
119736120627
119737120628
rc = sqlite3Fts3ReadBlock(
119738
- p, ++pReader->iCurrentBlock, &pReader->aNode, &pReader->nNode
120629
+ p, ++pReader->iCurrentBlock, &pReader->aNode, &pReader->nNode,
120630
+ (bIncr ? &pReader->nPopulate : 0)
119739120631
);
119740120632
if( rc!=SQLITE_OK ) return rc;
120633
+ assert( pReader->pBlob==0 );
120634
+ if( bIncr && pReader->nPopulate<pReader->nNode ){
120635
+ pReader->pBlob = p->pSegments;
120636
+ p->pSegments = 0;
120637
+ }
119741120638
pNext = pReader->aNode;
119742120639
}
120640
+
120641
+ assert( !fts3SegReaderIsPending(pReader) );
120642
+
120643
+ rc = fts3SegReaderRequire(pReader, pNext, FTS3_VARINT_MAX*2);
120644
+ if( rc!=SQLITE_OK ) return rc;
119743120645
119744120646
/* Because of the FTS3_NODE_PADDING bytes of padding, the following is
119745
- ** safe (no risk of overread) even if the node data is corrupted.
119746
- */
120647
+ ** safe (no risk of overread) even if the node data is corrupted. */
119747120648
pNext += sqlite3Fts3GetVarint32(pNext, &nPrefix);
119748120649
pNext += sqlite3Fts3GetVarint32(pNext, &nSuffix);
119749120650
if( nPrefix<0 || nSuffix<=0
119750120651
|| &pNext[nSuffix]>&pReader->aNode[pReader->nNode]
119751120652
){
@@ -119759,10 +120660,14 @@
119759120660
return SQLITE_NOMEM;
119760120661
}
119761120662
pReader->zTerm = zNew;
119762120663
pReader->nTermAlloc = nNew;
119763120664
}
120665
+
120666
+ rc = fts3SegReaderRequire(pReader, pNext, nSuffix+FTS3_VARINT_MAX);
120667
+ if( rc!=SQLITE_OK ) return rc;
120668
+
119764120669
memcpy(&pReader->zTerm[nPrefix], pNext, nSuffix);
119765120670
pReader->nTerm = nPrefix+nSuffix;
119766120671
pNext += nSuffix;
119767120672
pNext += sqlite3Fts3GetVarint32(pNext, &pReader->nDoclist);
119768120673
pReader->aDoclist = pNext;
@@ -119771,11 +120676,11 @@
119771120676
/* Check that the doclist does not appear to extend past the end of the
119772120677
** b-tree node. And that the final byte of the doclist is 0x00. If either
119773120678
** of these statements is untrue, then the data structure is corrupt.
119774120679
*/
119775120680
if( &pReader->aDoclist[pReader->nDoclist]>&pReader->aNode[pReader->nNode]
119776
- || pReader->aDoclist[pReader->nDoclist-1]
120681
+ || (pReader->nPopulate==0 && pReader->aDoclist[pReader->nDoclist-1])
119777120682
){
119778120683
return SQLITE_CORRUPT_VTAB;
119779120684
}
119780120685
return SQLITE_OK;
119781120686
}
@@ -119782,16 +120687,30 @@
119782120687
119783120688
/*
119784120689
** Set the SegReader to point to the first docid in the doclist associated
119785120690
** with the current term.
119786120691
*/
119787
-static void fts3SegReaderFirstDocid(Fts3SegReader *pReader){
119788
- int n;
120692
+static int fts3SegReaderFirstDocid(Fts3Table *pTab, Fts3SegReader *pReader){
120693
+ int rc = SQLITE_OK;
119789120694
assert( pReader->aDoclist );
119790120695
assert( !pReader->pOffsetList );
119791
- n = sqlite3Fts3GetVarint(pReader->aDoclist, &pReader->iDocid);
119792
- pReader->pOffsetList = &pReader->aDoclist[n];
120696
+ if( pTab->bDescIdx && fts3SegReaderIsPending(pReader) ){
120697
+ u8 bEof = 0;
120698
+ pReader->iDocid = 0;
120699
+ pReader->nOffsetList = 0;
120700
+ sqlite3Fts3DoclistPrev(0,
120701
+ pReader->aDoclist, pReader->nDoclist, &pReader->pOffsetList,
120702
+ &pReader->iDocid, &pReader->nOffsetList, &bEof
120703
+ );
120704
+ }else{
120705
+ rc = fts3SegReaderRequire(pReader, pReader->aDoclist, FTS3_VARINT_MAX);
120706
+ if( rc==SQLITE_OK ){
120707
+ int n = sqlite3Fts3GetVarint(pReader->aDoclist, &pReader->iDocid);
120708
+ pReader->pOffsetList = &pReader->aDoclist[n];
120709
+ }
120710
+ }
120711
+ return rc;
119793120712
}
119794120713
119795120714
/*
119796120715
** Advance the SegReader to point to the next docid in the doclist
119797120716
** associated with the current term.
@@ -119800,132 +120719,126 @@
119800120719
** *ppOffsetList is set to point to the first column-offset list
119801120720
** in the doclist entry (i.e. immediately past the docid varint).
119802120721
** *pnOffsetList is set to the length of the set of column-offset
119803120722
** lists, not including the nul-terminator byte. For example:
119804120723
*/
119805
-static void fts3SegReaderNextDocid(
119806
- Fts3SegReader *pReader,
119807
- char **ppOffsetList,
119808
- int *pnOffsetList
120724
+static int fts3SegReaderNextDocid(
120725
+ Fts3Table *pTab,
120726
+ Fts3SegReader *pReader, /* Reader to advance to next docid */
120727
+ char **ppOffsetList, /* OUT: Pointer to current position-list */
120728
+ int *pnOffsetList /* OUT: Length of *ppOffsetList in bytes */
119809120729
){
120730
+ int rc = SQLITE_OK;
119810120731
char *p = pReader->pOffsetList;
119811120732
char c = 0;
119812120733
119813
- /* Pointer p currently points at the first byte of an offset list. The
119814
- ** following two lines advance it to point one byte past the end of
119815
- ** the same offset list.
119816
- */
119817
- while( *p | c ) c = *p++ & 0x80;
119818
- p++;
119819
-
119820
- /* If required, populate the output variables with a pointer to and the
119821
- ** size of the previous offset-list.
119822
- */
119823
- if( ppOffsetList ){
119824
- *ppOffsetList = pReader->pOffsetList;
119825
- *pnOffsetList = (int)(p - pReader->pOffsetList - 1);
119826
- }
119827
-
119828
- /* If there are no more entries in the doclist, set pOffsetList to
119829
- ** NULL. Otherwise, set Fts3SegReader.iDocid to the next docid and
119830
- ** Fts3SegReader.pOffsetList to point to the next offset list before
119831
- ** returning.
119832
- */
119833
- if( p>=&pReader->aDoclist[pReader->nDoclist] ){
119834
- pReader->pOffsetList = 0;
120734
+ assert( p );
120735
+
120736
+ if( pTab->bDescIdx && fts3SegReaderIsPending(pReader) ){
120737
+ /* A pending-terms seg-reader for an FTS4 table that uses order=desc.
120738
+ ** Pending-terms doclists are always built up in ascending order, so
120739
+ ** we have to iterate through them backwards here. */
120740
+ u8 bEof = 0;
120741
+ if( ppOffsetList ){
120742
+ *ppOffsetList = pReader->pOffsetList;
120743
+ *pnOffsetList = pReader->nOffsetList - 1;
120744
+ }
120745
+ sqlite3Fts3DoclistPrev(0,
120746
+ pReader->aDoclist, pReader->nDoclist, &p, &pReader->iDocid,
120747
+ &pReader->nOffsetList, &bEof
120748
+ );
120749
+ if( bEof ){
120750
+ pReader->pOffsetList = 0;
120751
+ }else{
120752
+ pReader->pOffsetList = p;
120753
+ }
119835120754
}else{
119836
- sqlite3_int64 iDelta;
119837
- pReader->pOffsetList = p + sqlite3Fts3GetVarint(p, &iDelta);
119838
- pReader->iDocid += iDelta;
119839
- }
119840
-}
119841
-
119842
-/*
119843
-** This function is called to estimate the amount of data that will be
119844
-** loaded from the disk If SegReaderIterate() is called on this seg-reader,
119845
-** in units of average document size.
119846
-**
119847
-** This can be used as follows: If the caller has a small doclist that
119848
-** contains references to N documents, and is considering merging it with
119849
-** a large doclist (size X "average documents"), it may opt not to load
119850
-** the large doclist if X>N.
119851
-*/
119852
-SQLITE_PRIVATE int sqlite3Fts3SegReaderCost(
119853
- Fts3Cursor *pCsr, /* FTS3 cursor handle */
119854
- Fts3SegReader *pReader, /* Segment-reader handle */
119855
- int *pnCost /* IN/OUT: Number of bytes read */
120755
+
120756
+ /* Pointer p currently points at the first byte of an offset list. The
120757
+ ** following block advances it to point one byte past the end of
120758
+ ** the same offset list. */
120759
+ while( 1 ){
120760
+
120761
+ /* The following line of code (and the "p++" below the while() loop) is
120762
+ ** normally all that is required to move pointer p to the desired
120763
+ ** position. The exception is if this node is being loaded from disk
120764
+ ** incrementally and pointer "p" now points to the first byte passed
120765
+ ** the populated part of pReader->aNode[].
120766
+ */
120767
+ while( *p | c ) c = *p++ & 0x80;
120768
+ assert( *p==0 );
120769
+
120770
+ if( pReader->pBlob==0 || p<&pReader->aNode[pReader->nPopulate] ) break;
120771
+ rc = fts3SegReaderIncrRead(pReader);
120772
+ if( rc!=SQLITE_OK ) return rc;
120773
+ }
120774
+ p++;
120775
+
120776
+ /* If required, populate the output variables with a pointer to and the
120777
+ ** size of the previous offset-list.
120778
+ */
120779
+ if( ppOffsetList ){
120780
+ *ppOffsetList = pReader->pOffsetList;
120781
+ *pnOffsetList = (int)(p - pReader->pOffsetList - 1);
120782
+ }
120783
+
120784
+ /* If there are no more entries in the doclist, set pOffsetList to
120785
+ ** NULL. Otherwise, set Fts3SegReader.iDocid to the next docid and
120786
+ ** Fts3SegReader.pOffsetList to point to the next offset list before
120787
+ ** returning.
120788
+ */
120789
+ if( p>=&pReader->aDoclist[pReader->nDoclist] ){
120790
+ pReader->pOffsetList = 0;
120791
+ }else{
120792
+ rc = fts3SegReaderRequire(pReader, p, FTS3_VARINT_MAX);
120793
+ if( rc==SQLITE_OK ){
120794
+ sqlite3_int64 iDelta;
120795
+ pReader->pOffsetList = p + sqlite3Fts3GetVarint(p, &iDelta);
120796
+ if( pTab->bDescIdx ){
120797
+ pReader->iDocid -= iDelta;
120798
+ }else{
120799
+ pReader->iDocid += iDelta;
120800
+ }
120801
+ }
120802
+ }
120803
+ }
120804
+
120805
+ return SQLITE_OK;
120806
+}
120807
+
120808
+
120809
+SQLITE_PRIVATE int sqlite3Fts3MsrOvfl(
120810
+ Fts3Cursor *pCsr,
120811
+ Fts3MultiSegReader *pMsr,
120812
+ int *pnOvfl
119856120813
){
119857120814
Fts3Table *p = (Fts3Table*)pCsr->base.pVtab;
119858
- int rc = SQLITE_OK; /* Return code */
119859
- int nCost = 0; /* Cost in bytes to return */
119860
- int pgsz = p->nPgsz; /* Database page size */
119861
-
119862
- /* If this seg-reader is reading the pending-terms table, or if all data
119863
- ** for the segment is stored on the root page of the b-tree, then the cost
119864
- ** is zero. In this case all required data is already in main memory.
119865
- */
119866
- if( p->bHasStat
119867
- && !fts3SegReaderIsPending(pReader)
119868
- && !fts3SegReaderIsRootOnly(pReader)
119869
- ){
119870
- int nBlob = 0;
119871
- sqlite3_int64 iBlock;
119872
-
119873
- if( pCsr->nRowAvg==0 ){
119874
- /* The average document size, which is required to calculate the cost
119875
- ** of each doclist, has not yet been determined. Read the required
119876
- ** data from the %_stat table to calculate it.
119877
- **
119878
- ** Entry 0 of the %_stat table is a blob containing (nCol+1) FTS3
119879
- ** varints, where nCol is the number of columns in the FTS3 table.
119880
- ** The first varint is the number of documents currently stored in
119881
- ** the table. The following nCol varints contain the total amount of
119882
- ** data stored in all rows of each column of the table, from left
119883
- ** to right.
119884
- */
119885
- sqlite3_stmt *pStmt;
119886
- sqlite3_int64 nDoc = 0;
119887
- sqlite3_int64 nByte = 0;
119888
- const char *pEnd;
119889
- const char *a;
119890
-
119891
- rc = sqlite3Fts3SelectDoctotal(p, &pStmt);
119892
- if( rc!=SQLITE_OK ) return rc;
119893
- a = sqlite3_column_blob(pStmt, 0);
119894
- assert( a );
119895
-
119896
- pEnd = &a[sqlite3_column_bytes(pStmt, 0)];
119897
- a += sqlite3Fts3GetVarint(a, &nDoc);
119898
- while( a<pEnd ){
119899
- a += sqlite3Fts3GetVarint(a, &nByte);
119900
- }
119901
- if( nDoc==0 || nByte==0 ){
119902
- sqlite3_reset(pStmt);
119903
- return SQLITE_CORRUPT_VTAB;
119904
- }
119905
-
119906
- pCsr->nRowAvg = (int)(((nByte / nDoc) + pgsz) / pgsz);
119907
- assert( pCsr->nRowAvg>0 );
119908
- rc = sqlite3_reset(pStmt);
119909
- if( rc!=SQLITE_OK ) return rc;
119910
- }
119911
-
119912
- /* Assume that a blob flows over onto overflow pages if it is larger
119913
- ** than (pgsz-35) bytes in size (the file-format documentation
119914
- ** confirms this).
119915
- */
119916
- for(iBlock=pReader->iStartBlock; iBlock<=pReader->iLeafEndBlock; iBlock++){
119917
- rc = sqlite3Fts3ReadBlock(p, iBlock, 0, &nBlob);
119918
- if( rc!=SQLITE_OK ) break;
119919
- if( (nBlob+35)>pgsz ){
119920
- int nOvfl = (nBlob + 34)/pgsz;
119921
- nCost += ((nOvfl + pCsr->nRowAvg - 1)/pCsr->nRowAvg);
119922
- }
119923
- }
119924
- }
119925
-
119926
- *pnCost += nCost;
120815
+ int nOvfl = 0;
120816
+ int ii;
120817
+ int rc = SQLITE_OK;
120818
+ int pgsz = p->nPgsz;
120819
+
120820
+ assert( p->bHasStat );
120821
+ assert( pgsz>0 );
120822
+
120823
+ for(ii=0; rc==SQLITE_OK && ii<pMsr->nSegment; ii++){
120824
+ Fts3SegReader *pReader = pMsr->apSegment[ii];
120825
+ if( !fts3SegReaderIsPending(pReader)
120826
+ && !fts3SegReaderIsRootOnly(pReader)
120827
+ ){
120828
+ int jj;
120829
+ for(jj=pReader->iStartBlock; jj<=pReader->iLeafEndBlock; jj++){
120830
+ int nBlob;
120831
+ rc = sqlite3Fts3ReadBlock(p, jj, 0, &nBlob, 0);
120832
+ if( rc!=SQLITE_OK ) break;
120833
+ if( (nBlob+35)>pgsz ){
120834
+ nOvfl += (nBlob + 34)/pgsz;
120835
+ }
120836
+ }
120837
+ }
120838
+ }
120839
+ *pnOvfl = nOvfl;
119927120840
return rc;
119928120841
}
119929120842
119930120843
/*
119931120844
** Free all allocations associated with the iterator passed as the
@@ -119934,10 +120847,11 @@
119934120847
SQLITE_PRIVATE void sqlite3Fts3SegReaderFree(Fts3SegReader *pReader){
119935120848
if( pReader && !fts3SegReaderIsPending(pReader) ){
119936120849
sqlite3_free(pReader->zTerm);
119937120850
if( !fts3SegReaderIsRootOnly(pReader) ){
119938120851
sqlite3_free(pReader->aNode);
120852
+ sqlite3_blob_close(pReader->pBlob);
119939120853
}
119940120854
}
119941120855
sqlite3_free(pReader);
119942120856
}
119943120857
@@ -120010,28 +120924,46 @@
120010120924
}
120011120925
120012120926
/*
120013120927
** This function is used to allocate an Fts3SegReader that iterates through
120014120928
** a subset of the terms stored in the Fts3Table.pendingTerms array.
120929
+**
120930
+** If the isPrefixIter parameter is zero, then the returned SegReader iterates
120931
+** through each term in the pending-terms table. Or, if isPrefixIter is
120932
+** non-zero, it iterates through each term and its prefixes. For example, if
120933
+** the pending terms hash table contains the terms "sqlite", "mysql" and
120934
+** "firebird", then the iterator visits the following 'terms' (in the order
120935
+** shown):
120936
+**
120937
+** f fi fir fire fireb firebi firebir firebird
120938
+** m my mys mysq mysql
120939
+** s sq sql sqli sqlit sqlite
120940
+**
120941
+** Whereas if isPrefixIter is zero, the terms visited are:
120942
+**
120943
+** firebird mysql sqlite
120015120944
*/
120016120945
SQLITE_PRIVATE int sqlite3Fts3SegReaderPending(
120017120946
Fts3Table *p, /* Virtual table handle */
120947
+ int iIndex, /* Index for p->aIndex */
120018120948
const char *zTerm, /* Term to search for */
120019120949
int nTerm, /* Size of buffer zTerm */
120020
- int isPrefix, /* True for a term-prefix query */
120950
+ int bPrefix, /* True for a prefix iterator */
120021120951
Fts3SegReader **ppReader /* OUT: SegReader for pending-terms */
120022120952
){
120023120953
Fts3SegReader *pReader = 0; /* Fts3SegReader object to return */
120024120954
Fts3HashElem **aElem = 0; /* Array of term hash entries to scan */
120025120955
int nElem = 0; /* Size of array at aElem */
120026120956
int rc = SQLITE_OK; /* Return Code */
120957
+ Fts3Hash *pHash;
120027120958
120028
- if( isPrefix ){
120959
+ pHash = &p->aIndex[iIndex].hPending;
120960
+ if( bPrefix ){
120029120961
int nAlloc = 0; /* Size of allocated array at aElem */
120030120962
Fts3HashElem *pE = 0; /* Iterator variable */
120031120963
120032
- for(pE=fts3HashFirst(&p->pendingTerms); pE; pE=fts3HashNext(pE)){
120964
+ for(pE=fts3HashFirst(pHash); pE; pE=fts3HashNext(pE)){
120033120965
char *zKey = (char *)fts3HashKey(pE);
120034120966
int nKey = fts3HashKeysize(pE);
120035120967
if( nTerm==0 || (nKey>=nTerm && 0==memcmp(zKey, zTerm, nTerm)) ){
120036120968
if( nElem==nAlloc ){
120037120969
Fts3HashElem **aElem2;
@@ -120044,10 +120976,11 @@
120044120976
nElem = 0;
120045120977
break;
120046120978
}
120047120979
aElem = aElem2;
120048120980
}
120981
+
120049120982
aElem[nElem++] = pE;
120050120983
}
120051120984
}
120052120985
120053120986
/* If more than one term matches the prefix, sort the Fts3HashElem
@@ -120057,11 +120990,13 @@
120057120990
if( nElem>1 ){
120058120991
qsort(aElem, nElem, sizeof(Fts3HashElem *), fts3CompareElemByTerm);
120059120992
}
120060120993
120061120994
}else{
120062
- Fts3HashElem *pE = fts3HashFindElem(&p->pendingTerms, zTerm, nTerm);
120995
+ /* The query is a simple term lookup that matches at most one term in
120996
+ ** the index. All that is required is a straight hash-lookup. */
120997
+ Fts3HashElem *pE = fts3HashFindElem(pHash, zTerm, nTerm);
120063120998
if( pE ){
120064120999
aElem = &pE;
120065121000
nElem = 1;
120066121001
}
120067121002
}
@@ -120077,11 +121012,11 @@
120077121012
pReader->ppNextElem = (Fts3HashElem **)&pReader[1];
120078121013
memcpy(pReader->ppNextElem, aElem, nElem*sizeof(Fts3HashElem *));
120079121014
}
120080121015
}
120081121016
120082
- if( isPrefix ){
121017
+ if( bPrefix ){
120083121018
sqlite3_free(aElem);
120084121019
}
120085121020
*ppReader = pReader;
120086121021
return rc;
120087121022
}
@@ -120137,10 +121072,22 @@
120137121072
if( pLhs->iDocid==pRhs->iDocid ){
120138121073
rc = pRhs->iIdx - pLhs->iIdx;
120139121074
}else{
120140121075
rc = (pLhs->iDocid > pRhs->iDocid) ? 1 : -1;
120141121076
}
121077
+ }
121078
+ assert( pLhs->aNode && pRhs->aNode );
121079
+ return rc;
121080
+}
121081
+static int fts3SegReaderDoclistCmpRev(Fts3SegReader *pLhs, Fts3SegReader *pRhs){
121082
+ int rc = (pLhs->pOffsetList==0)-(pRhs->pOffsetList==0);
121083
+ if( rc==0 ){
121084
+ if( pLhs->iDocid==pRhs->iDocid ){
121085
+ rc = pRhs->iIdx - pLhs->iIdx;
121086
+ }else{
121087
+ rc = (pLhs->iDocid < pRhs->iDocid) ? 1 : -1;
121088
+ }
120142121089
}
120143121090
assert( pLhs->aNode && pRhs->aNode );
120144121091
return rc;
120145121092
}
120146121093
@@ -120689,25 +121636,34 @@
120689121636
}
120690121637
return rc;
120691121638
}
120692121639
120693121640
/*
120694
-** Set *pnSegment to the total number of segments in the database. Set
120695
-** *pnMax to the largest segment level in the database (segment levels
120696
-** are stored in the 'level' column of the %_segdir table).
121641
+** Set *pnMax to the largest segment level in the database for the index
121642
+** iIndex.
121643
+**
121644
+** Segment levels are stored in the 'level' column of the %_segdir table.
120697121645
**
120698121646
** Return SQLITE_OK if successful, or an SQLite error code if not.
120699121647
*/
120700
-static int fts3SegmentCountMax(Fts3Table *p, int *pnSegment, int *pnMax){
121648
+static int fts3SegmentMaxLevel(Fts3Table *p, int iIndex, int *pnMax){
120701121649
sqlite3_stmt *pStmt;
120702121650
int rc;
121651
+ assert( iIndex>=0 && iIndex<p->nIndex );
120703121652
120704
- rc = fts3SqlStmt(p, SQL_SELECT_SEGDIR_COUNT_MAX, &pStmt, 0);
121653
+ /* Set pStmt to the compiled version of:
121654
+ **
121655
+ ** SELECT max(level) FROM %Q.'%q_segdir' WHERE level BETWEEN ? AND ?
121656
+ **
121657
+ ** (1024 is actually the value of macro FTS3_SEGDIR_PREFIXLEVEL_STR).
121658
+ */
121659
+ rc = fts3SqlStmt(p, SQL_SELECT_SEGDIR_MAX_LEVEL, &pStmt, 0);
120705121660
if( rc!=SQLITE_OK ) return rc;
121661
+ sqlite3_bind_int(pStmt, 1, iIndex*FTS3_SEGDIR_MAXLEVEL);
121662
+ sqlite3_bind_int(pStmt, 2, (iIndex+1)*FTS3_SEGDIR_MAXLEVEL - 1);
120706121663
if( SQLITE_ROW==sqlite3_step(pStmt) ){
120707
- *pnSegment = sqlite3_column_int(pStmt, 0);
120708
- *pnMax = sqlite3_column_int(pStmt, 1);
121664
+ *pnMax = sqlite3_column_int(pStmt, 0);
120709121665
}
120710121666
return sqlite3_reset(pStmt);
120711121667
}
120712121668
120713121669
/*
@@ -120724,10 +121680,11 @@
120724121680
**
120725121681
** SQLITE_OK is returned if successful, otherwise an SQLite error code.
120726121682
*/
120727121683
static int fts3DeleteSegdir(
120728121684
Fts3Table *p, /* Virtual table handle */
121685
+ int iIndex, /* Index for p->aIndex */
120729121686
int iLevel, /* Level of %_segdir entries to delete */
120730121687
Fts3SegReader **apSegment, /* Array of SegReader objects */
120731121688
int nReader /* Size of array apSegment */
120732121689
){
120733121690
int rc; /* Return Code */
@@ -120746,23 +121703,28 @@
120746121703
}
120747121704
if( rc!=SQLITE_OK ){
120748121705
return rc;
120749121706
}
120750121707
121708
+ assert( iLevel>=0 || iLevel==FTS3_SEGCURSOR_ALL );
120751121709
if( iLevel==FTS3_SEGCURSOR_ALL ){
120752
- fts3SqlExec(&rc, p, SQL_DELETE_ALL_SEGDIR, 0);
120753
- }else if( iLevel==FTS3_SEGCURSOR_PENDING ){
120754
- sqlite3Fts3PendingTermsClear(p);
121710
+ rc = fts3SqlStmt(p, SQL_DELETE_SEGDIR_RANGE, &pDelete, 0);
121711
+ if( rc==SQLITE_OK ){
121712
+ sqlite3_bind_int(pDelete, 1, iIndex*FTS3_SEGDIR_MAXLEVEL);
121713
+ sqlite3_bind_int(pDelete, 2, (iIndex+1) * FTS3_SEGDIR_MAXLEVEL - 1);
121714
+ }
120755121715
}else{
120756
- assert( iLevel>=0 );
120757
- rc = fts3SqlStmt(p, SQL_DELETE_SEGDIR_BY_LEVEL, &pDelete, 0);
121716
+ rc = fts3SqlStmt(p, SQL_DELETE_SEGDIR_LEVEL, &pDelete, 0);
120758121717
if( rc==SQLITE_OK ){
120759
- sqlite3_bind_int(pDelete, 1, iLevel);
120760
- sqlite3_step(pDelete);
120761
- rc = sqlite3_reset(pDelete);
121718
+ sqlite3_bind_int(pDelete, 1, iIndex*FTS3_SEGDIR_MAXLEVEL + iLevel);
120762121719
}
120763121720
}
121721
+
121722
+ if( rc==SQLITE_OK ){
121723
+ sqlite3_step(pDelete);
121724
+ rc = sqlite3_reset(pDelete);
121725
+ }
120764121726
120765121727
return rc;
120766121728
}
120767121729
120768121730
/*
@@ -120805,14 +121767,124 @@
120805121767
}
120806121768
120807121769
*ppList = pList;
120808121770
*pnList = nList;
120809121771
}
121772
+
121773
+SQLITE_PRIVATE int sqlite3Fts3MsrIncrStart(
121774
+ Fts3Table *p, /* Virtual table handle */
121775
+ Fts3MultiSegReader *pCsr, /* Cursor object */
121776
+ int iCol, /* Column to match on. */
121777
+ const char *zTerm, /* Term to iterate through a doclist for */
121778
+ int nTerm /* Number of bytes in zTerm */
121779
+){
121780
+ int i;
121781
+ int nSegment = pCsr->nSegment;
121782
+ int (*xCmp)(Fts3SegReader *, Fts3SegReader *) = (
121783
+ p->bDescIdx ? fts3SegReaderDoclistCmpRev : fts3SegReaderDoclistCmp
121784
+ );
121785
+
121786
+ assert( pCsr->pFilter==0 );
121787
+ assert( zTerm && nTerm>0 );
121788
+
121789
+ /* Advance each segment iterator until it points to the term zTerm/nTerm. */
121790
+ for(i=0; i<nSegment; i++){
121791
+ Fts3SegReader *pSeg = pCsr->apSegment[i];
121792
+ do {
121793
+ int rc = fts3SegReaderNext(p, pSeg, 1);
121794
+ if( rc!=SQLITE_OK ) return rc;
121795
+ }while( fts3SegReaderTermCmp(pSeg, zTerm, nTerm)<0 );
121796
+ }
121797
+ fts3SegReaderSort(pCsr->apSegment, nSegment, nSegment, fts3SegReaderCmp);
121798
+
121799
+ /* Determine how many of the segments actually point to zTerm/nTerm. */
121800
+ for(i=0; i<nSegment; i++){
121801
+ Fts3SegReader *pSeg = pCsr->apSegment[i];
121802
+ if( !pSeg->aNode || fts3SegReaderTermCmp(pSeg, zTerm, nTerm) ){
121803
+ break;
121804
+ }
121805
+ }
121806
+ pCsr->nAdvance = i;
121807
+
121808
+ /* Advance each of the segments to point to the first docid. */
121809
+ for(i=0; i<pCsr->nAdvance; i++){
121810
+ int rc = fts3SegReaderFirstDocid(p, pCsr->apSegment[i]);
121811
+ if( rc!=SQLITE_OK ) return rc;
121812
+ }
121813
+ fts3SegReaderSort(pCsr->apSegment, i, i, xCmp);
121814
+
121815
+ assert( iCol<0 || iCol<p->nColumn );
121816
+ pCsr->iColFilter = iCol;
121817
+
121818
+ return SQLITE_OK;
121819
+}
121820
+
121821
+SQLITE_PRIVATE int sqlite3Fts3MsrIncrNext(
121822
+ Fts3Table *p, /* Virtual table handle */
121823
+ Fts3MultiSegReader *pMsr, /* Multi-segment-reader handle */
121824
+ sqlite3_int64 *piDocid, /* OUT: Docid value */
121825
+ char **paPoslist, /* OUT: Pointer to position list */
121826
+ int *pnPoslist /* OUT: Size of position list in bytes */
121827
+){
121828
+ int nMerge = pMsr->nAdvance;
121829
+ Fts3SegReader **apSegment = pMsr->apSegment;
121830
+ int (*xCmp)(Fts3SegReader *, Fts3SegReader *) = (
121831
+ p->bDescIdx ? fts3SegReaderDoclistCmpRev : fts3SegReaderDoclistCmp
121832
+ );
121833
+
121834
+ if( nMerge==0 ){
121835
+ *paPoslist = 0;
121836
+ return SQLITE_OK;
121837
+ }
121838
+
121839
+ while( 1 ){
121840
+ Fts3SegReader *pSeg;
121841
+ pSeg = pMsr->apSegment[0];
121842
+
121843
+ if( pSeg->pOffsetList==0 ){
121844
+ *paPoslist = 0;
121845
+ break;
121846
+ }else{
121847
+ int rc;
121848
+ char *pList;
121849
+ int nList;
121850
+ int j;
121851
+ sqlite3_int64 iDocid = apSegment[0]->iDocid;
121852
+
121853
+ rc = fts3SegReaderNextDocid(p, apSegment[0], &pList, &nList);
121854
+ j = 1;
121855
+ while( rc==SQLITE_OK
121856
+ && j<nMerge
121857
+ && apSegment[j]->pOffsetList
121858
+ && apSegment[j]->iDocid==iDocid
121859
+ ){
121860
+ rc = fts3SegReaderNextDocid(p, apSegment[j], 0, 0);
121861
+ j++;
121862
+ }
121863
+ if( rc!=SQLITE_OK ) return rc;
121864
+ fts3SegReaderSort(pMsr->apSegment, nMerge, j, xCmp);
121865
+
121866
+ if( pMsr->iColFilter>=0 ){
121867
+ fts3ColumnFilter(pMsr->iColFilter, &pList, &nList);
121868
+ }
121869
+
121870
+ if( nList>0 ){
121871
+ *piDocid = iDocid;
121872
+ *paPoslist = pList;
121873
+ *pnPoslist = nList;
121874
+ break;
121875
+ }
121876
+ }
121877
+
121878
+ }
121879
+
121880
+ return SQLITE_OK;
121881
+}
120810121882
120811121883
SQLITE_PRIVATE int sqlite3Fts3SegReaderStart(
120812121884
Fts3Table *p, /* Virtual table handle */
120813
- Fts3SegReaderCursor *pCsr, /* Cursor object */
121885
+ Fts3MultiSegReader *pCsr, /* Cursor object */
120814121886
Fts3SegFilter *pFilter /* Restrictions on range of iteration */
120815121887
){
120816121888
int i;
120817121889
120818121890
/* Initialize the cursor object */
@@ -120827,11 +121899,11 @@
120827121899
for(i=0; i<pCsr->nSegment; i++){
120828121900
int nTerm = pFilter->nTerm;
120829121901
const char *zTerm = pFilter->zTerm;
120830121902
Fts3SegReader *pSeg = pCsr->apSegment[i];
120831121903
do {
120832
- int rc = fts3SegReaderNext(p, pSeg);
121904
+ int rc = fts3SegReaderNext(p, pSeg, 0);
120833121905
if( rc!=SQLITE_OK ) return rc;
120834121906
}while( zTerm && fts3SegReaderTermCmp(pSeg, zTerm, nTerm)<0 );
120835121907
}
120836121908
fts3SegReaderSort(
120837121909
pCsr->apSegment, pCsr->nSegment, pCsr->nSegment, fts3SegReaderCmp);
@@ -120839,11 +121911,11 @@
120839121911
return SQLITE_OK;
120840121912
}
120841121913
120842121914
SQLITE_PRIVATE int sqlite3Fts3SegReaderStep(
120843121915
Fts3Table *p, /* Virtual table handle */
120844
- Fts3SegReaderCursor *pCsr /* Cursor object */
121916
+ Fts3MultiSegReader *pCsr /* Cursor object */
120845121917
){
120846121918
int rc = SQLITE_OK;
120847121919
120848121920
int isIgnoreEmpty = (pCsr->pFilter->flags & FTS3_SEGMENT_IGNORE_EMPTY);
120849121921
int isRequirePos = (pCsr->pFilter->flags & FTS3_SEGMENT_REQUIRE_POS);
@@ -120852,10 +121924,13 @@
120852121924
int isScan = (pCsr->pFilter->flags & FTS3_SEGMENT_SCAN);
120853121925
120854121926
Fts3SegReader **apSegment = pCsr->apSegment;
120855121927
int nSegment = pCsr->nSegment;
120856121928
Fts3SegFilter *pFilter = pCsr->pFilter;
121929
+ int (*xCmp)(Fts3SegReader *, Fts3SegReader *) = (
121930
+ p->bDescIdx ? fts3SegReaderDoclistCmpRev : fts3SegReaderDoclistCmp
121931
+ );
120857121932
120858121933
if( pCsr->nSegment==0 ) return SQLITE_OK;
120859121934
120860121935
do {
120861121936
int nMerge;
@@ -120863,11 +121938,11 @@
120863121938
120864121939
/* Advance the first pCsr->nAdvance entries in the apSegment[] array
120865121940
** forward. Then sort the list in order of current term again.
120866121941
*/
120867121942
for(i=0; i<pCsr->nAdvance; i++){
120868
- rc = fts3SegReaderNext(p, apSegment[i]);
121943
+ rc = fts3SegReaderNext(p, apSegment[i], 0);
120869121944
if( rc!=SQLITE_OK ) return rc;
120870121945
}
120871121946
fts3SegReaderSort(apSegment, nSegment, pCsr->nAdvance, fts3SegReaderCmp);
120872121947
pCsr->nAdvance = 0;
120873121948
@@ -120902,11 +121977,14 @@
120902121977
){
120903121978
nMerge++;
120904121979
}
120905121980
120906121981
assert( isIgnoreEmpty || (isRequirePos && !isColFilter) );
120907
- if( nMerge==1 && !isIgnoreEmpty ){
121982
+ if( nMerge==1
121983
+ && !isIgnoreEmpty
121984
+ && (p->bDescIdx==0 || fts3SegReaderIsPending(apSegment[0])==0)
121985
+ ){
120908121986
pCsr->aDoclist = apSegment[0]->aDoclist;
120909121987
pCsr->nDoclist = apSegment[0]->nDoclist;
120910121988
rc = SQLITE_ROW;
120911121989
}else{
120912121990
int nDoclist = 0; /* Size of doclist */
@@ -120915,56 +121993,66 @@
120915121993
/* The current term of the first nMerge entries in the array
120916121994
** of Fts3SegReader objects is the same. The doclists must be merged
120917121995
** and a single term returned with the merged doclist.
120918121996
*/
120919121997
for(i=0; i<nMerge; i++){
120920
- fts3SegReaderFirstDocid(apSegment[i]);
121998
+ fts3SegReaderFirstDocid(p, apSegment[i]);
120921121999
}
120922
- fts3SegReaderSort(apSegment, nMerge, nMerge, fts3SegReaderDoclistCmp);
122000
+ fts3SegReaderSort(apSegment, nMerge, nMerge, xCmp);
120923122001
while( apSegment[0]->pOffsetList ){
120924122002
int j; /* Number of segments that share a docid */
120925122003
char *pList;
120926122004
int nList;
120927122005
int nByte;
120928122006
sqlite3_int64 iDocid = apSegment[0]->iDocid;
120929
- fts3SegReaderNextDocid(apSegment[0], &pList, &nList);
122007
+ fts3SegReaderNextDocid(p, apSegment[0], &pList, &nList);
120930122008
j = 1;
120931122009
while( j<nMerge
120932122010
&& apSegment[j]->pOffsetList
120933122011
&& apSegment[j]->iDocid==iDocid
120934122012
){
120935
- fts3SegReaderNextDocid(apSegment[j], 0, 0);
122013
+ fts3SegReaderNextDocid(p, apSegment[j], 0, 0);
120936122014
j++;
120937122015
}
120938122016
120939122017
if( isColFilter ){
120940122018
fts3ColumnFilter(pFilter->iCol, &pList, &nList);
120941122019
}
120942122020
120943122021
if( !isIgnoreEmpty || nList>0 ){
120944
- nByte = sqlite3Fts3VarintLen(iDocid-iPrev) + (isRequirePos?nList+1:0);
122022
+
122023
+ /* Calculate the 'docid' delta value to write into the merged
122024
+ ** doclist. */
122025
+ sqlite3_int64 iDelta;
122026
+ if( p->bDescIdx && nDoclist>0 ){
122027
+ iDelta = iPrev - iDocid;
122028
+ }else{
122029
+ iDelta = iDocid - iPrev;
122030
+ }
122031
+ assert( iDelta>0 || (nDoclist==0 && iDelta==iDocid) );
122032
+ assert( nDoclist>0 || iDelta==iDocid );
122033
+
122034
+ nByte = sqlite3Fts3VarintLen(iDelta) + (isRequirePos?nList+1:0);
120945122035
if( nDoclist+nByte>pCsr->nBuffer ){
120946122036
char *aNew;
120947122037
pCsr->nBuffer = (nDoclist+nByte)*2;
120948122038
aNew = sqlite3_realloc(pCsr->aBuffer, pCsr->nBuffer);
120949122039
if( !aNew ){
120950122040
return SQLITE_NOMEM;
120951122041
}
120952122042
pCsr->aBuffer = aNew;
120953122043
}
120954
- nDoclist += sqlite3Fts3PutVarint(
120955
- &pCsr->aBuffer[nDoclist], iDocid-iPrev
120956
- );
122044
+ nDoclist += sqlite3Fts3PutVarint(&pCsr->aBuffer[nDoclist], iDelta);
120957122045
iPrev = iDocid;
120958122046
if( isRequirePos ){
120959122047
memcpy(&pCsr->aBuffer[nDoclist], pList, nList);
120960122048
nDoclist += nList;
120961122049
pCsr->aBuffer[nDoclist++] = '\0';
120962122050
}
120963122051
}
120964122052
120965
- fts3SegReaderSort(apSegment, nMerge, j, fts3SegReaderDoclistCmp);
122053
+ fts3SegReaderSort(apSegment, nMerge, j, xCmp);
120966122054
}
120967122055
if( nDoclist>0 ){
120968122056
pCsr->aDoclist = pCsr->aBuffer;
120969122057
pCsr->nDoclist = nDoclist;
120970122058
rc = SQLITE_ROW;
@@ -120973,13 +122061,14 @@
120973122061
pCsr->nAdvance = nMerge;
120974122062
}while( rc==SQLITE_OK );
120975122063
120976122064
return rc;
120977122065
}
122066
+
120978122067
120979122068
SQLITE_PRIVATE void sqlite3Fts3SegReaderFinish(
120980
- Fts3SegReaderCursor *pCsr /* Cursor object */
122069
+ Fts3MultiSegReader *pCsr /* Cursor object */
120981122070
){
120982122071
if( pCsr ){
120983122072
int i;
120984122073
for(i=0; i<pCsr->nSegment; i++){
120985122074
sqlite3Fts3SegReaderFree(pCsr->apSegment[i]);
@@ -121002,47 +122091,60 @@
121002122091
** If this function is called with iLevel<0, but there is only one
121003122092
** segment in the database, SQLITE_DONE is returned immediately.
121004122093
** Otherwise, if successful, SQLITE_OK is returned. If an error occurs,
121005122094
** an SQLite error code is returned.
121006122095
*/
121007
-static int fts3SegmentMerge(Fts3Table *p, int iLevel){
122096
+static int fts3SegmentMerge(Fts3Table *p, int iIndex, int iLevel){
121008122097
int rc; /* Return code */
121009122098
int iIdx = 0; /* Index of new segment */
121010
- int iNewLevel = 0; /* Level to create new segment at */
122099
+ int iNewLevel = 0; /* Level/index to create new segment at */
121011122100
SegmentWriter *pWriter = 0; /* Used to write the new, merged, segment */
121012122101
Fts3SegFilter filter; /* Segment term filter condition */
121013
- Fts3SegReaderCursor csr; /* Cursor to iterate through level(s) */
122102
+ Fts3MultiSegReader csr; /* Cursor to iterate through level(s) */
122103
+ int bIgnoreEmpty = 0; /* True to ignore empty segments */
121014122104
121015
- rc = sqlite3Fts3SegReaderCursor(p, iLevel, 0, 0, 1, 0, &csr);
122105
+ assert( iLevel==FTS3_SEGCURSOR_ALL
122106
+ || iLevel==FTS3_SEGCURSOR_PENDING
122107
+ || iLevel>=0
122108
+ );
122109
+ assert( iLevel<FTS3_SEGDIR_MAXLEVEL );
122110
+ assert( iIndex>=0 && iIndex<p->nIndex );
122111
+
122112
+ rc = sqlite3Fts3SegReaderCursor(p, iIndex, iLevel, 0, 0, 1, 0, &csr);
121016122113
if( rc!=SQLITE_OK || csr.nSegment==0 ) goto finished;
121017122114
121018122115
if( iLevel==FTS3_SEGCURSOR_ALL ){
121019122116
/* This call is to merge all segments in the database to a single
121020122117
** segment. The level of the new segment is equal to the the numerically
121021
- ** greatest segment level currently present in the database. The index
121022
- ** of the new segment is always 0. */
121023
- int nDummy; /* TODO: Remove this */
122118
+ ** greatest segment level currently present in the database for this
122119
+ ** index. The idx of the new segment is always 0. */
121024122120
if( csr.nSegment==1 ){
121025122121
rc = SQLITE_DONE;
121026122122
goto finished;
121027122123
}
121028
- rc = fts3SegmentCountMax(p, &nDummy, &iNewLevel);
122124
+ rc = fts3SegmentMaxLevel(p, iIndex, &iNewLevel);
122125
+ bIgnoreEmpty = 1;
122126
+
122127
+ }else if( iLevel==FTS3_SEGCURSOR_PENDING ){
122128
+ iNewLevel = iIndex * FTS3_SEGDIR_MAXLEVEL;
122129
+ rc = fts3AllocateSegdirIdx(p, iIndex, 0, &iIdx);
121029122130
}else{
121030
- /* This call is to merge all segments at level iLevel. Find the next
122131
+ /* This call is to merge all segments at level iLevel. find the next
121031122132
** available segment index at level iLevel+1. The call to
121032122133
** fts3AllocateSegdirIdx() will merge the segments at level iLevel+1 to
121033122134
** a single iLevel+2 segment if necessary. */
121034
- iNewLevel = iLevel+1;
121035
- rc = fts3AllocateSegdirIdx(p, iNewLevel, &iIdx);
122135
+ rc = fts3AllocateSegdirIdx(p, iIndex, iLevel+1, &iIdx);
122136
+ iNewLevel = iIndex * FTS3_SEGDIR_MAXLEVEL + iLevel+1;
121036122137
}
121037122138
if( rc!=SQLITE_OK ) goto finished;
121038122139
assert( csr.nSegment>0 );
121039
- assert( iNewLevel>=0 );
122140
+ assert( iNewLevel>=(iIndex*FTS3_SEGDIR_MAXLEVEL) );
122141
+ assert( iNewLevel<((iIndex+1)*FTS3_SEGDIR_MAXLEVEL) );
121040122142
121041122143
memset(&filter, 0, sizeof(Fts3SegFilter));
121042122144
filter.flags = FTS3_SEGMENT_REQUIRE_POS;
121043
- filter.flags |= (iLevel==FTS3_SEGCURSOR_ALL ? FTS3_SEGMENT_IGNORE_EMPTY : 0);
122145
+ filter.flags |= (bIgnoreEmpty ? FTS3_SEGMENT_IGNORE_EMPTY : 0);
121044122146
121045122147
rc = sqlite3Fts3SegReaderStart(p, &csr, &filter);
121046122148
while( SQLITE_OK==rc ){
121047122149
rc = sqlite3Fts3SegReaderStep(p, &csr);
121048122150
if( rc!=SQLITE_ROW ) break;
@@ -121050,12 +122152,14 @@
121050122152
csr.zTerm, csr.nTerm, csr.aDoclist, csr.nDoclist);
121051122153
}
121052122154
if( rc!=SQLITE_OK ) goto finished;
121053122155
assert( pWriter );
121054122156
121055
- rc = fts3DeleteSegdir(p, iLevel, csr.apSegment, csr.nSegment);
121056
- if( rc!=SQLITE_OK ) goto finished;
122157
+ if( iLevel!=FTS3_SEGCURSOR_PENDING ){
122158
+ rc = fts3DeleteSegdir(p, iIndex, iLevel, csr.apSegment, csr.nSegment);
122159
+ if( rc!=SQLITE_OK ) goto finished;
122160
+ }
121057122161
rc = fts3SegWriterFlush(p, pWriter, iNewLevel, iIdx);
121058122162
121059122163
finished:
121060122164
fts3SegWriterFree(pWriter);
121061122165
sqlite3Fts3SegReaderFinish(&csr);
@@ -121062,14 +122166,21 @@
121062122166
return rc;
121063122167
}
121064122168
121065122169
121066122170
/*
121067
-** Flush the contents of pendingTerms to a level 0 segment.
122171
+** Flush the contents of pendingTerms to level 0 segments.
121068122172
*/
121069122173
SQLITE_PRIVATE int sqlite3Fts3PendingTermsFlush(Fts3Table *p){
121070
- return fts3SegmentMerge(p, FTS3_SEGCURSOR_PENDING);
122174
+ int rc = SQLITE_OK;
122175
+ int i;
122176
+ for(i=0; rc==SQLITE_OK && i<p->nIndex; i++){
122177
+ rc = fts3SegmentMerge(p, i, FTS3_SEGCURSOR_PENDING);
122178
+ if( rc==SQLITE_DONE ) rc = SQLITE_OK;
122179
+ }
122180
+ sqlite3Fts3PendingTermsClear(p);
122181
+ return rc;
121071122182
}
121072122183
121073122184
/*
121074122185
** Encode N integers as varints into a blob.
121075122186
*/
@@ -121215,10 +122326,27 @@
121215122326
sqlite3_bind_blob(pStmt, 1, pBlob, nBlob, SQLITE_STATIC);
121216122327
sqlite3_step(pStmt);
121217122328
*pRC = sqlite3_reset(pStmt);
121218122329
sqlite3_free(a);
121219122330
}
122331
+
122332
+static int fts3DoOptimize(Fts3Table *p, int bReturnDone){
122333
+ int i;
122334
+ int bSeenDone = 0;
122335
+ int rc = SQLITE_OK;
122336
+ for(i=0; rc==SQLITE_OK && i<p->nIndex; i++){
122337
+ rc = fts3SegmentMerge(p, i, FTS3_SEGCURSOR_ALL);
122338
+ if( rc==SQLITE_DONE ){
122339
+ bSeenDone = 1;
122340
+ rc = SQLITE_OK;
122341
+ }
122342
+ }
122343
+ sqlite3Fts3SegmentsClose(p);
122344
+ sqlite3Fts3PendingTermsClear(p);
122345
+
122346
+ return (rc==SQLITE_OK && bReturnDone && bSeenDone) ? SQLITE_DONE : rc;
122347
+}
121220122348
121221122349
/*
121222122350
** Handle a 'special' INSERT of the form:
121223122351
**
121224122352
** "INSERT INTO tbl(tbl) VALUES(<expr>)"
@@ -121232,16 +122360,11 @@
121232122360
int nVal = sqlite3_value_bytes(pVal);
121233122361
121234122362
if( !zVal ){
121235122363
return SQLITE_NOMEM;
121236122364
}else if( nVal==8 && 0==sqlite3_strnicmp(zVal, "optimize", 8) ){
121237
- rc = fts3SegmentMerge(p, FTS3_SEGCURSOR_ALL);
121238
- if( rc==SQLITE_DONE ){
121239
- rc = SQLITE_OK;
121240
- }else{
121241
- sqlite3Fts3PendingTermsClear(p);
121242
- }
122365
+ rc = fts3DoOptimize(p, 0);
121243122366
#ifdef SQLITE_TEST
121244122367
}else if( nVal>9 && 0==sqlite3_strnicmp(zVal, "nodesize=", 9) ){
121245122368
p->nNodeSize = atoi(&zVal[9]);
121246122369
rc = SQLITE_OK;
121247122370
}else if( nVal>11 && 0==sqlite3_strnicmp(zVal, "maxpending=", 9) ){
@@ -121250,61 +122373,23 @@
121250122373
#endif
121251122374
}else{
121252122375
rc = SQLITE_ERROR;
121253122376
}
121254122377
121255
- sqlite3Fts3SegmentsClose(p);
121256122378
return rc;
121257122379
}
121258122380
121259
-/*
121260
-** Return the deferred doclist associated with deferred token pDeferred.
121261
-** This function assumes that sqlite3Fts3CacheDeferredDoclists() has already
121262
-** been called to allocate and populate the doclist.
121263
-*/
121264
-SQLITE_PRIVATE char *sqlite3Fts3DeferredDoclist(Fts3DeferredToken *pDeferred, int *pnByte){
121265
- if( pDeferred->pList ){
121266
- *pnByte = pDeferred->pList->nData;
121267
- return pDeferred->pList->aData;
121268
- }
121269
- *pnByte = 0;
121270
- return 0;
121271
-}
121272
-
121273
-/*
121274
-** Helper fucntion for FreeDeferredDoclists(). This function removes all
121275
-** references to deferred doclists from within the tree of Fts3Expr
121276
-** structures headed by
121277
-*/
121278
-static void fts3DeferredDoclistClear(Fts3Expr *pExpr){
121279
- if( pExpr ){
121280
- fts3DeferredDoclistClear(pExpr->pLeft);
121281
- fts3DeferredDoclistClear(pExpr->pRight);
121282
- if( pExpr->isLoaded ){
121283
- sqlite3_free(pExpr->aDoclist);
121284
- pExpr->isLoaded = 0;
121285
- pExpr->aDoclist = 0;
121286
- pExpr->nDoclist = 0;
121287
- pExpr->pCurrent = 0;
121288
- pExpr->iCurrent = 0;
121289
- }
121290
- }
121291
-}
121292
-
121293122381
/*
121294122382
** Delete all cached deferred doclists. Deferred doclists are cached
121295122383
** (allocated) by the sqlite3Fts3CacheDeferredDoclists() function.
121296122384
*/
121297122385
SQLITE_PRIVATE void sqlite3Fts3FreeDeferredDoclists(Fts3Cursor *pCsr){
121298122386
Fts3DeferredToken *pDef;
121299122387
for(pDef=pCsr->pDeferred; pDef; pDef=pDef->pNext){
121300
- sqlite3_free(pDef->pList);
122388
+ fts3PendingListDelete(pDef->pList);
121301122389
pDef->pList = 0;
121302122390
}
121303
- if( pCsr->pDeferred ){
121304
- fts3DeferredDoclistClear(pCsr->pExpr);
121305
- }
121306122391
}
121307122392
121308122393
/*
121309122394
** Free all entries in the pCsr->pDeffered list. Entries are added to
121310122395
** this list using sqlite3Fts3DeferToken().
@@ -121312,11 +122397,11 @@
121312122397
SQLITE_PRIVATE void sqlite3Fts3FreeDeferredTokens(Fts3Cursor *pCsr){
121313122398
Fts3DeferredToken *pDef;
121314122399
Fts3DeferredToken *pNext;
121315122400
for(pDef=pCsr->pDeferred; pDef; pDef=pNext){
121316122401
pNext = pDef->pNext;
121317
- sqlite3_free(pDef->pList);
122402
+ fts3PendingListDelete(pDef->pList);
121318122403
sqlite3_free(pDef);
121319122404
}
121320122405
pCsr->pDeferred = 0;
121321122406
}
121322122407
@@ -121376,10 +122461,37 @@
121376122461
}
121377122462
}
121378122463
121379122464
return rc;
121380122465
}
122466
+
122467
+SQLITE_PRIVATE int sqlite3Fts3DeferredTokenList(
122468
+ Fts3DeferredToken *p,
122469
+ char **ppData,
122470
+ int *pnData
122471
+){
122472
+ char *pRet;
122473
+ int nSkip;
122474
+ sqlite3_int64 dummy;
122475
+
122476
+ *ppData = 0;
122477
+ *pnData = 0;
122478
+
122479
+ if( p->pList==0 ){
122480
+ return SQLITE_OK;
122481
+ }
122482
+
122483
+ pRet = (char *)sqlite3_malloc(p->pList->nData);
122484
+ if( !pRet ) return SQLITE_NOMEM;
122485
+
122486
+ nSkip = sqlite3Fts3GetVarint(p->pList->aData, &dummy);
122487
+ *pnData = p->pList->nData - nSkip;
122488
+ *ppData = pRet;
122489
+
122490
+ memcpy(pRet, &p->pList->aData[nSkip], *pnData);
122491
+ return SQLITE_OK;
122492
+}
121381122493
121382122494
/*
121383122495
** Add an entry for token pToken to the pCsr->pDeferred list.
121384122496
*/
121385122497
SQLITE_PRIVATE int sqlite3Fts3DeferToken(
@@ -121451,11 +122563,11 @@
121451122563
){
121452122564
Fts3Table *p = (Fts3Table *)pVtab;
121453122565
int rc = SQLITE_OK; /* Return Code */
121454122566
int isRemove = 0; /* True for an UPDATE or DELETE */
121455122567
sqlite3_int64 iRemove = 0; /* Rowid removed by UPDATE or DELETE */
121456
- u32 *aSzIns; /* Sizes of inserted documents */
122568
+ u32 *aSzIns = 0; /* Sizes of inserted documents */
121457122569
u32 *aSzDel; /* Sizes of deleted documents */
121458122570
int nChng = 0; /* Net change in number of documents */
121459122571
int bInsertDone = 0;
121460122572
121461122573
assert( p->pSegments==0 );
@@ -121466,16 +122578,20 @@
121466122578
*/
121467122579
if( nArg>1
121468122580
&& sqlite3_value_type(apVal[0])==SQLITE_NULL
121469122581
&& sqlite3_value_type(apVal[p->nColumn+2])!=SQLITE_NULL
121470122582
){
121471
- return fts3SpecialInsert(p, apVal[p->nColumn+2]);
122583
+ rc = fts3SpecialInsert(p, apVal[p->nColumn+2]);
122584
+ goto update_out;
121472122585
}
121473122586
121474122587
/* Allocate space to hold the change in document sizes */
121475122588
aSzIns = sqlite3_malloc( sizeof(aSzIns[0])*(p->nColumn+1)*2 );
121476
- if( aSzIns==0 ) return SQLITE_NOMEM;
122589
+ if( aSzIns==0 ){
122590
+ rc = SQLITE_NOMEM;
122591
+ goto update_out;
122592
+ }
121477122593
aSzDel = &aSzIns[p->nColumn+1];
121478122594
memset(aSzIns, 0, sizeof(aSzIns[0])*(p->nColumn+1)*2);
121479122595
121480122596
/* If this is an INSERT operation, or an UPDATE that modifies the rowid
121481122597
** value, then this operation requires constraint handling.
@@ -121521,12 +122637,11 @@
121521122637
bInsertDone = 1;
121522122638
}
121523122639
}
121524122640
}
121525122641
if( rc!=SQLITE_OK ){
121526
- sqlite3_free(aSzIns);
121527
- return rc;
122642
+ goto update_out;
121528122643
}
121529122644
121530122645
/* If this is a DELETE or UPDATE operation, remove the old record. */
121531122646
if( sqlite3_value_type(apVal[0])!=SQLITE_NULL ){
121532122647
assert( sqlite3_value_type(apVal[0])==SQLITE_INTEGER );
@@ -121555,10 +122670,11 @@
121555122670
121556122671
if( p->bHasStat ){
121557122672
fts3UpdateDocTotals(&rc, p, aSzIns, aSzDel, nChng);
121558122673
}
121559122674
122675
+ update_out:
121560122676
sqlite3_free(aSzIns);
121561122677
sqlite3Fts3SegmentsClose(p);
121562122678
return rc;
121563122679
}
121564122680
@@ -121569,16 +122685,14 @@
121569122685
*/
121570122686
SQLITE_PRIVATE int sqlite3Fts3Optimize(Fts3Table *p){
121571122687
int rc;
121572122688
rc = sqlite3_exec(p->db, "SAVEPOINT fts3", 0, 0, 0);
121573122689
if( rc==SQLITE_OK ){
121574
- rc = fts3SegmentMerge(p, FTS3_SEGCURSOR_ALL);
121575
- if( rc==SQLITE_OK ){
121576
- rc = sqlite3_exec(p->db, "RELEASE fts3", 0, 0, 0);
121577
- if( rc==SQLITE_OK ){
121578
- sqlite3Fts3PendingTermsClear(p);
121579
- }
122690
+ rc = fts3DoOptimize(p, 1);
122691
+ if( rc==SQLITE_OK || rc==SQLITE_DONE ){
122692
+ int rc2 = sqlite3_exec(p->db, "RELEASE fts3", 0, 0, 0);
122693
+ if( rc2!=SQLITE_OK ) rc = rc2;
121580122694
}else{
121581122695
sqlite3_exec(p->db, "ROLLBACK TO fts3", 0, 0, 0);
121582122696
sqlite3_exec(p->db, "RELEASE fts3", 0, 0, 0);
121583122697
}
121584122698
}
@@ -121763,76 +122877,24 @@
121763122877
){
121764122878
int iPhrase = 0; /* Variable used as the phrase counter */
121765122879
return fts3ExprIterate2(pExpr, &iPhrase, x, pCtx);
121766122880
}
121767122881
121768
-/*
121769
-** The argument to this function is always a phrase node. Its doclist
121770
-** (Fts3Expr.aDoclist[]) and the doclists associated with all phrase nodes
121771
-** to the left of this one in the query tree have already been loaded.
121772
-**
121773
-** If this phrase node is part of a series of phrase nodes joined by
121774
-** NEAR operators (and is not the left-most of said series), then elements are
121775
-** removed from the phrases doclist consistent with the NEAR restriction. If
121776
-** required, elements may be removed from the doclists of phrases to the
121777
-** left of this one that are part of the same series of NEAR operator
121778
-** connected phrases.
121779
-**
121780
-** If an OOM error occurs, SQLITE_NOMEM is returned. Otherwise, SQLITE_OK.
121781
-*/
121782
-static int fts3ExprNearTrim(Fts3Expr *pExpr){
121783
- int rc = SQLITE_OK;
121784
- Fts3Expr *pParent = pExpr->pParent;
121785
-
121786
- assert( pExpr->eType==FTSQUERY_PHRASE );
121787
- while( rc==SQLITE_OK
121788
- && pParent
121789
- && pParent->eType==FTSQUERY_NEAR
121790
- && pParent->pRight==pExpr
121791
- ){
121792
- /* This expression (pExpr) is the right-hand-side of a NEAR operator.
121793
- ** Find the expression to the left of the same operator.
121794
- */
121795
- int nNear = pParent->nNear;
121796
- Fts3Expr *pLeft = pParent->pLeft;
121797
-
121798
- if( pLeft->eType!=FTSQUERY_PHRASE ){
121799
- assert( pLeft->eType==FTSQUERY_NEAR );
121800
- assert( pLeft->pRight->eType==FTSQUERY_PHRASE );
121801
- pLeft = pLeft->pRight;
121802
- }
121803
-
121804
- rc = sqlite3Fts3ExprNearTrim(pLeft, pExpr, nNear);
121805
-
121806
- pExpr = pLeft;
121807
- pParent = pExpr->pParent;
121808
- }
121809
-
121810
- return rc;
121811
-}
121812
-
121813122882
/*
121814122883
** This is an fts3ExprIterate() callback used while loading the doclists
121815122884
** for each phrase into Fts3Expr.aDoclist[]/nDoclist. See also
121816122885
** fts3ExprLoadDoclists().
121817122886
*/
121818122887
static int fts3ExprLoadDoclistsCb(Fts3Expr *pExpr, int iPhrase, void *ctx){
121819122888
int rc = SQLITE_OK;
122889
+ Fts3Phrase *pPhrase = pExpr->pPhrase;
121820122890
LoadDoclistCtx *p = (LoadDoclistCtx *)ctx;
121821122891
121822122892
UNUSED_PARAMETER(iPhrase);
121823122893
121824122894
p->nPhrase++;
121825
- p->nToken += pExpr->pPhrase->nToken;
121826
-
121827
- if( pExpr->isLoaded==0 ){
121828
- rc = sqlite3Fts3ExprLoadDoclist(p->pCsr, pExpr);
121829
- pExpr->isLoaded = 1;
121830
- if( rc==SQLITE_OK ){
121831
- rc = fts3ExprNearTrim(pExpr);
121832
- }
121833
- }
122895
+ p->nToken += pPhrase->nToken;
121834122896
121835122897
return rc;
121836122898
}
121837122899
121838122900
/*
@@ -122002,11 +123064,11 @@
122002123064
SnippetPhrase *pPhrase = &p->aPhrase[iPhrase];
122003123065
char *pCsr;
122004123066
122005123067
pPhrase->nToken = pExpr->pPhrase->nToken;
122006123068
122007
- pCsr = sqlite3Fts3FindPositions(p->pCsr, pExpr, p->pCsr->iPrevId, p->iCol);
123069
+ pCsr = sqlite3Fts3EvalPhrasePoslist(p->pCsr, pExpr, p->iCol);
122008123070
if( pCsr ){
122009123071
int iFirst = 0;
122010123072
pPhrase->pList = pCsr;
122011123073
fts3GetDeltaPosition(&pCsr, &iFirst);
122012123074
pPhrase->pHead = pCsr;
@@ -122359,30 +123421,10 @@
122359123421
122360123422
*ppCollist = pEnd;
122361123423
return nEntry;
122362123424
}
122363123425
122364
-static void fts3LoadColumnlistCounts(char **pp, u32 *aOut, int isGlobal){
122365
- char *pCsr = *pp;
122366
- while( *pCsr ){
122367
- int nHit;
122368
- sqlite3_int64 iCol = 0;
122369
- if( *pCsr==0x01 ){
122370
- pCsr++;
122371
- pCsr += sqlite3Fts3GetVarint(pCsr, &iCol);
122372
- }
122373
- nHit = fts3ColumnlistCount(&pCsr);
122374
- assert( nHit>0 );
122375
- if( isGlobal ){
122376
- aOut[iCol*3+1]++;
122377
- }
122378
- aOut[iCol*3] += nHit;
122379
- }
122380
- pCsr++;
122381
- *pp = pCsr;
122382
-}
122383
-
122384123426
/*
122385123427
** fts3ExprIterate() callback used to collect the "global" matchinfo stats
122386123428
** for a single query.
122387123429
**
122388123430
** fts3ExprIterate() callback to load the 'global' elements of a
@@ -122412,52 +123454,13 @@
122412123454
Fts3Expr *pExpr, /* Phrase expression node */
122413123455
int iPhrase, /* Phrase number (numbered from zero) */
122414123456
void *pCtx /* Pointer to MatchInfo structure */
122415123457
){
122416123458
MatchInfo *p = (MatchInfo *)pCtx;
122417
- Fts3Cursor *pCsr = p->pCursor;
122418
- char *pIter;
122419
- char *pEnd;
122420
- char *pFree = 0;
122421
- u32 *aOut = &p->aMatchinfo[3*iPhrase*p->nCol];
122422
-
122423
- assert( pExpr->isLoaded );
122424
- assert( pExpr->eType==FTSQUERY_PHRASE );
122425
-
122426
- if( pCsr->pDeferred ){
122427
- Fts3Phrase *pPhrase = pExpr->pPhrase;
122428
- int ii;
122429
- for(ii=0; ii<pPhrase->nToken; ii++){
122430
- if( pPhrase->aToken[ii].bFulltext ) break;
122431
- }
122432
- if( ii<pPhrase->nToken ){
122433
- int nFree = 0;
122434
- int rc = sqlite3Fts3ExprLoadFtDoclist(pCsr, pExpr, &pFree, &nFree);
122435
- if( rc!=SQLITE_OK ) return rc;
122436
- pIter = pFree;
122437
- pEnd = &pFree[nFree];
122438
- }else{
122439
- int iCol; /* Column index */
122440
- for(iCol=0; iCol<p->nCol; iCol++){
122441
- aOut[iCol*3 + 1] = (u32)p->nDoc;
122442
- aOut[iCol*3 + 2] = (u32)p->nDoc;
122443
- }
122444
- return SQLITE_OK;
122445
- }
122446
- }else{
122447
- pIter = pExpr->aDoclist;
122448
- pEnd = &pExpr->aDoclist[pExpr->nDoclist];
122449
- }
122450
-
122451
- /* Fill in the global hit count matrix row for this phrase. */
122452
- while( pIter<pEnd ){
122453
- while( *pIter++ & 0x80 ); /* Skip past docid. */
122454
- fts3LoadColumnlistCounts(&pIter, &aOut[1], 1);
122455
- }
122456
-
122457
- sqlite3_free(pFree);
122458
- return SQLITE_OK;
123459
+ return sqlite3Fts3EvalPhraseStats(
123460
+ p->pCursor, pExpr, &p->aMatchinfo[3*iPhrase*p->nCol]
123461
+ );
122459123462
}
122460123463
122461123464
/*
122462123465
** fts3ExprIterate() callback used to collect the "local" part of the
122463123466
** FTS3_MATCHINFO_HITS array. The local stats are those elements of the
@@ -122470,18 +123473,17 @@
122470123473
){
122471123474
MatchInfo *p = (MatchInfo *)pCtx;
122472123475
int iStart = iPhrase * p->nCol * 3;
122473123476
int i;
122474123477
122475
- for(i=0; i<p->nCol; i++) p->aMatchinfo[iStart+i*3] = 0;
122476
-
122477
- if( pExpr->aDoclist ){
123478
+ for(i=0; i<p->nCol; i++){
122478123479
char *pCsr;
122479
-
122480
- pCsr = sqlite3Fts3FindPositions(p->pCursor, pExpr, p->pCursor->iPrevId, -1);
123480
+ pCsr = sqlite3Fts3EvalPhrasePoslist(p->pCursor, pExpr, i);
122481123481
if( pCsr ){
122482
- fts3LoadColumnlistCounts(&pCsr, &p->aMatchinfo[iStart], 0);
123482
+ p->aMatchinfo[iStart+i*3] = fts3ColumnlistCount(&pCsr);
123483
+ }else{
123484
+ p->aMatchinfo[iStart+i*3] = 0;
122483123485
}
122484123486
}
122485123487
122486123488
return SQLITE_OK;
122487123489
}
@@ -122563,13 +123565,12 @@
122563123565
** values for a matchinfo() FTS3_MATCHINFO_LCS request.
122564123566
*/
122565123567
typedef struct LcsIterator LcsIterator;
122566123568
struct LcsIterator {
122567123569
Fts3Expr *pExpr; /* Pointer to phrase expression */
122568
- char *pRead; /* Cursor used to iterate through aDoclist */
122569123570
int iPosOffset; /* Tokens count up to end of this phrase */
122570
- int iCol; /* Current column number */
123571
+ char *pRead; /* Cursor used to iterate through aDoclist */
122571123572
int iPos; /* Current position */
122572123573
};
122573123574
122574123575
/*
122575123576
** If LcsIterator.iCol is set to the following value, the iterator has
@@ -122596,21 +123597,14 @@
122596123597
char *pRead = pIter->pRead;
122597123598
sqlite3_int64 iRead;
122598123599
int rc = 0;
122599123600
122600123601
pRead += sqlite3Fts3GetVarint(pRead, &iRead);
122601
- if( iRead==0 ){
122602
- pIter->iCol = LCS_ITERATOR_FINISHED;
123602
+ if( iRead==0 || iRead==1 ){
123603
+ pRead = 0;
122603123604
rc = 1;
122604123605
}else{
122605
- if( iRead==1 ){
122606
- pRead += sqlite3Fts3GetVarint(pRead, &iRead);
122607
- pIter->iCol = (int)iRead;
122608
- pIter->iPos = pIter->iPosOffset;
122609
- pRead += sqlite3Fts3GetVarint(pRead, &iRead);
122610
- rc = 1;
122611
- }
122612123606
pIter->iPos += (int)(iRead-2);
122613123607
}
122614123608
122615123609
pIter->pRead = pRead;
122616123610
return rc;
@@ -122638,46 +123632,38 @@
122638123632
**/
122639123633
aIter = sqlite3_malloc(sizeof(LcsIterator) * pCsr->nPhrase);
122640123634
if( !aIter ) return SQLITE_NOMEM;
122641123635
memset(aIter, 0, sizeof(LcsIterator) * pCsr->nPhrase);
122642123636
(void)fts3ExprIterate(pCsr->pExpr, fts3MatchinfoLcsCb, (void*)aIter);
123637
+
122643123638
for(i=0; i<pInfo->nPhrase; i++){
122644123639
LcsIterator *pIter = &aIter[i];
122645123640
nToken -= pIter->pExpr->pPhrase->nToken;
122646123641
pIter->iPosOffset = nToken;
122647
- pIter->pRead = sqlite3Fts3FindPositions(pCsr,pIter->pExpr,pCsr->iPrevId,-1);
122648
- if( pIter->pRead ){
122649
- pIter->iPos = pIter->iPosOffset;
122650
- fts3LcsIteratorAdvance(&aIter[i]);
122651
- }else{
122652
- pIter->iCol = LCS_ITERATOR_FINISHED;
122653
- }
122654123642
}
122655123643
122656123644
for(iCol=0; iCol<pInfo->nCol; iCol++){
122657123645
int nLcs = 0; /* LCS value for this column */
122658123646
int nLive = 0; /* Number of iterators in aIter not at EOF */
122659123647
122660
- /* Loop through the iterators in aIter[]. Set nLive to the number of
122661
- ** iterators that point to a position-list corresponding to column iCol.
122662
- */
122663123648
for(i=0; i<pInfo->nPhrase; i++){
122664
- assert( aIter[i].iCol>=iCol );
122665
- if( aIter[i].iCol==iCol ) nLive++;
123649
+ LcsIterator *pIt = &aIter[i];
123650
+ pIt->pRead = sqlite3Fts3EvalPhrasePoslist(pCsr, pIt->pExpr, iCol);
123651
+ if( pIt->pRead ){
123652
+ pIt->iPos = pIt->iPosOffset;
123653
+ fts3LcsIteratorAdvance(&aIter[i]);
123654
+ nLive++;
123655
+ }
122666123656
}
122667123657
122668
- /* The following loop runs until all iterators in aIter[] have finished
122669
- ** iterating through positions in column iCol. Exactly one of the
122670
- ** iterators is advanced each time the body of the loop is run.
122671
- */
122672123658
while( nLive>0 ){
122673123659
LcsIterator *pAdv = 0; /* The iterator to advance by one position */
122674123660
int nThisLcs = 0; /* LCS for the current iterator positions */
122675123661
122676123662
for(i=0; i<pInfo->nPhrase; i++){
122677123663
LcsIterator *pIter = &aIter[i];
122678
- if( iCol!=pIter->iCol ){
123664
+ if( pIter->pRead==0 ){
122679123665
/* This iterator is already at EOF for this column. */
122680123666
nThisLcs = 0;
122681123667
}else{
122682123668
if( pAdv==0 || pIter->iPos<pAdv->iPos ){
122683123669
pAdv = pIter;
@@ -123013,11 +123999,11 @@
123013123999
int iTerm; /* For looping through nTerm phrase terms */
123014124000
char *pList; /* Pointer to position list for phrase */
123015124001
int iPos = 0; /* First position in position-list */
123016124002
123017124003
UNUSED_PARAMETER(iPhrase);
123018
- pList = sqlite3Fts3FindPositions(p->pCsr, pExpr, p->iDocid, p->iCol);
124004
+ pList = sqlite3Fts3EvalPhrasePoslist(p->pCsr, pExpr, p->iCol);
123019124005
nTerm = pExpr->pPhrase->nToken;
123020124006
if( pList ){
123021124007
fts3GetDeltaPosition(&pList, &iPos);
123022124008
assert( iPos>=0 );
123023124009
}
123024124010
--- src/sqlite3.c
+++ src/sqlite3.c
@@ -650,11 +650,11 @@
650 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
651 ** [sqlite_version()] and [sqlite_source_id()].
652 */
653 #define SQLITE_VERSION "3.7.7"
654 #define SQLITE_VERSION_NUMBER 3007007
655 #define SQLITE_SOURCE_ID "2011-06-03 14:19:10 0206bc6f87bb9393218a380fc5b18039d334a8d8"
656
657 /*
658 ** CAPI3REF: Run-Time Library Version Numbers
659 ** KEYWORDS: sqlite3_version, sqlite3_sourceid
660 **
@@ -8483,10 +8483,11 @@
8483 SQLITE_PRIVATE int sqlite3VdbeAddOp2(Vdbe*,int,int,int);
8484 SQLITE_PRIVATE int sqlite3VdbeAddOp3(Vdbe*,int,int,int,int);
8485 SQLITE_PRIVATE int sqlite3VdbeAddOp4(Vdbe*,int,int,int,int,const char *zP4,int);
8486 SQLITE_PRIVATE int sqlite3VdbeAddOp4Int(Vdbe*,int,int,int,int,int);
8487 SQLITE_PRIVATE int sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp);
 
8488 SQLITE_PRIVATE void sqlite3VdbeChangeP1(Vdbe*, int addr, int P1);
8489 SQLITE_PRIVATE void sqlite3VdbeChangeP2(Vdbe*, int addr, int P2);
8490 SQLITE_PRIVATE void sqlite3VdbeChangeP3(Vdbe*, int addr, int P3);
8491 SQLITE_PRIVATE void sqlite3VdbeChangeP5(Vdbe*, u8 P5);
8492 SQLITE_PRIVATE void sqlite3VdbeJumpHere(Vdbe*, int addr);
@@ -9282,11 +9283,11 @@
9282 ** sqlite3_close().
9283 *
9284 ** A thread must be holding a mutex on the corresponding Btree in order
9285 ** to access Schema content. This implies that the thread must also be
9286 ** holding a mutex on the sqlite3 connection pointer that owns the Btree.
9287 ** For a TEMP Schema, on the connection mutex is required.
9288 */
9289 struct Schema {
9290 int schema_cookie; /* Database schema version number for this file */
9291 int iGeneration; /* Generation counter. Incremented with each change */
9292 Hash tblHash; /* All tables indexed by name */
@@ -11479,11 +11480,11 @@
11479 SQLITE_PRIVATE int sqlite3AtoF(const char *z, double*, int, u8);
11480 SQLITE_PRIVATE int sqlite3GetInt32(const char *, int*);
11481 SQLITE_PRIVATE int sqlite3Atoi(const char*);
11482 SQLITE_PRIVATE int sqlite3Utf16ByteLen(const void *pData, int nChar);
11483 SQLITE_PRIVATE int sqlite3Utf8CharLen(const char *pData, int nByte);
11484 SQLITE_PRIVATE int sqlite3Utf8Read(const u8*, const u8**);
11485
11486 /*
11487 ** Routines to read and write variable-length integers. These used to
11488 ** be defined locally, but now we use the varint routines in the util.c
11489 ** file. Code should use the MACRO forms below, as the Varint32 versions
@@ -20086,11 +20087,11 @@
20086 } \
20087 if( c<0x80 \
20088 || (c&0xFFFFF800)==0xD800 \
20089 || (c&0xFFFFFFFE)==0xFFFE ){ c = 0xFFFD; } \
20090 }
20091 SQLITE_PRIVATE int sqlite3Utf8Read(
20092 const unsigned char *zIn, /* First byte of UTF-8 character */
20093 const unsigned char **pzNext /* Write first byte past UTF-8 char here */
20094 ){
20095 unsigned int c;
20096
@@ -35805,11 +35806,11 @@
35805 memset(pCache, 0, sz);
35806 if( separateCache ){
35807 pGroup = (PGroup*)&pCache[1];
35808 pGroup->mxPinned = 10;
35809 }else{
35810 pGroup = &pcache1_g.grp;
35811 }
35812 pCache->pGroup = pGroup;
35813 pCache->szPage = szPage;
35814 pCache->bPurgeable = (bPurgeable ? 1 : 0);
35815 if( bPurgeable ){
@@ -48324,10 +48325,12 @@
48324 **
48325 ** This routine works only for pages that do not contain overflow cells.
48326 */
48327 #define findCell(P,I) \
48328 ((P)->aData + ((P)->maskPage & get2byte(&(P)->aData[(P)->cellOffset+2*(I)])))
 
 
48329
48330 /*
48331 ** This a more complex version of findCell() that works for
48332 ** pages that do contain overflow cells.
48333 */
@@ -51918,11 +51921,11 @@
51918 assert( pCur->apPage[pCur->iPage]->nCell==0 );
51919 return SQLITE_OK;
51920 }
51921 assert( pCur->apPage[0]->intKey || pIdxKey );
51922 for(;;){
51923 int lwr, upr;
51924 Pgno chldPg;
51925 MemPage *pPage = pCur->apPage[pCur->iPage];
51926 int c;
51927
51928 /* pPage->nCell must be greater than zero. If this is the root-page
@@ -51934,18 +51937,18 @@
51934 assert( pPage->nCell>0 );
51935 assert( pPage->intKey==(pIdxKey==0) );
51936 lwr = 0;
51937 upr = pPage->nCell-1;
51938 if( biasRight ){
51939 pCur->aiIdx[pCur->iPage] = (u16)upr;
51940 }else{
51941 pCur->aiIdx[pCur->iPage] = (u16)((upr+lwr)/2);
51942 }
51943 for(;;){
51944 int idx = pCur->aiIdx[pCur->iPage]; /* Index of current cell in pPage */
51945 u8 *pCell; /* Pointer to current cell in pPage */
51946
 
51947 pCur->info.nSize = 0;
51948 pCell = findCell(pPage, idx) + pPage->childPtrSize;
51949 if( pPage->intKey ){
51950 i64 nCellKey;
51951 if( pPage->hasData ){
@@ -52024,11 +52027,11 @@
52024 upr = idx-1;
52025 }
52026 if( lwr>upr ){
52027 break;
52028 }
52029 pCur->aiIdx[pCur->iPage] = (u16)((lwr+upr)/2);
52030 }
52031 assert( lwr==upr+1 );
52032 assert( pPage->isInit );
52033 if( pPage->leaf ){
52034 chldPg = 0;
@@ -52886,13 +52889,13 @@
52886 if( rc ){
52887 *pRC = rc;
52888 return;
52889 }
52890 endPtr = &data[pPage->cellOffset + 2*pPage->nCell - 2];
 
52891 while( ptr<endPtr ){
52892 ptr[0] = ptr[2];
52893 ptr[1] = ptr[3];
52894 ptr += 2;
52895 }
52896 pPage->nCell--;
52897 put2byte(&data[hdr+3], pPage->nCell);
52898 pPage->nFree += 2;
@@ -52929,10 +52932,11 @@
52929 int end; /* First byte past the last cell pointer in data[] */
52930 int ins; /* Index in data[] where new cell pointer is inserted */
52931 int cellOffset; /* Address of first cell pointer in data[] */
52932 u8 *data; /* The content of the whole page */
52933 u8 *ptr; /* Used for moving information around in data[] */
 
52934
52935 int nSkip = (iChild ? 4 : 0);
52936
52937 if( *pRC ) return;
52938
@@ -52979,13 +52983,16 @@
52979 pPage->nFree -= (u16)(2 + sz);
52980 memcpy(&data[idx+nSkip], pCell+nSkip, sz-nSkip);
52981 if( iChild ){
52982 put4byte(&data[idx], iChild);
52983 }
52984 for(j=end, ptr=&data[j]; j>ins; j-=2, ptr-=2){
52985 ptr[0] = ptr[-2];
52986 ptr[1] = ptr[-1];
 
 
 
52987 }
52988 put2byte(&data[ins], idx);
52989 put2byte(&data[pPage->hdrOffset+3], pPage->nCell);
52990 #ifndef SQLITE_OMIT_AUTOVACUUM
52991 if( pPage->pBt->autoVacuum ){
@@ -53026,14 +53033,15 @@
53026 assert( get2byteNotZero(&data[hdr+5])==nUsable );
53027
53028 pCellptr = &data[pPage->cellOffset + nCell*2];
53029 cellbody = nUsable;
53030 for(i=nCell-1; i>=0; i--){
 
53031 pCellptr -= 2;
53032 cellbody -= aSize[i];
53033 put2byte(pCellptr, cellbody);
53034 memcpy(&data[cellbody], apCell[i], aSize[i]);
53035 }
53036 put2byte(&data[hdr+3], nCell);
53037 put2byte(&data[hdr+5], cellbody);
53038 pPage->nFree -= (nCell*2 + nUsable - cellbody);
53039 pPage->nCell = (u16)nCell;
@@ -53483,16 +53491,28 @@
53483 memcpy(pOld, apOld[i], sizeof(MemPage));
53484 pOld->aData = (void*)&pOld[1];
53485 memcpy(pOld->aData, apOld[i]->aData, pBt->pageSize);
53486
53487 limit = pOld->nCell+pOld->nOverflow;
53488 for(j=0; j<limit; j++){
53489 assert( nCell<nMaxCells );
53490 apCell[nCell] = findOverflowCell(pOld, j);
53491 szCell[nCell] = cellSizePtr(pOld, apCell[nCell]);
53492 nCell++;
53493 }
 
 
 
 
 
 
 
 
 
 
 
 
53494 if( i<nOld-1 && !leafData){
53495 u16 sz = (u16)szNew[i];
53496 u8 *pTemp;
53497 assert( nCell<nMaxCells );
53498 szCell[nCell] = sz;
@@ -57637,17 +57657,10 @@
57637 pOp->p1 = p1;
57638 pOp->p2 = p2;
57639 pOp->p3 = p3;
57640 pOp->p4.p = 0;
57641 pOp->p4type = P4_NOTUSED;
57642 p->expired = 0;
57643 if( op==OP_ParseSchema ){
57644 /* Any program that uses the OP_ParseSchema opcode needs to lock
57645 ** all btrees. */
57646 int j;
57647 for(j=0; j<p->db->nDb; j++) sqlite3VdbeUsesBtree(p, j);
57648 }
57649 #ifdef SQLITE_DEBUG
57650 pOp->zComment = 0;
57651 if( sqlite3VdbeAddopTrace ) sqlite3VdbePrintOp(0, i, &p->aOp[i]);
57652 #endif
57653 #ifdef VDBE_PROFILE
@@ -57681,10 +57694,24 @@
57681 ){
57682 int addr = sqlite3VdbeAddOp3(p, op, p1, p2, p3);
57683 sqlite3VdbeChangeP4(p, addr, zP4, p4type);
57684 return addr;
57685 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
57686
57687 /*
57688 ** Add an opcode that includes the p4 value as an integer.
57689 */
57690 SQLITE_PRIVATE int sqlite3VdbeAddOp4Int(
@@ -64083,10 +64110,20 @@
64083 u.ag.ctx.pColl = pOp[-1].p4.pColl;
64084 }
64085 db->lastRowid = lastRowid;
64086 (*u.ag.ctx.pFunc->xFunc)(&u.ag.ctx, u.ag.n, u.ag.apVal); /* IMP: R-24505-23230 */
64087 lastRowid = db->lastRowid;
 
 
 
 
 
 
 
 
 
 
64088 if( db->mallocFailed ){
64089 /* Even though a malloc() has failed, the implementation of the
64090 ** user function may have called an sqlite3_result_XXX() function
64091 ** to return a value. The following call releases any resources
64092 ** associated with such a value.
@@ -64093,19 +64130,10 @@
64093 */
64094 sqlite3VdbeMemRelease(&u.ag.ctx.s);
64095 goto no_mem;
64096 }
64097
64098 /* If any auxiliary data functions have been called by this user function,
64099 ** immediately call the destructor for any non-static values.
64100 */
64101 if( u.ag.ctx.pVdbeFunc ){
64102 sqlite3VdbeDeleteAuxData(u.ag.ctx.pVdbeFunc, pOp->p1);
64103 pOp->p4.pVdbeFunc = u.ag.ctx.pVdbeFunc;
64104 pOp->p4type = P4_VDBEFUNC;
64105 }
64106
64107 /* If the function returned an error, throw an exception */
64108 if( u.ag.ctx.isError ){
64109 sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(&u.ag.ctx.s));
64110 rc = u.ag.ctx.isError;
64111 }
@@ -75255,18 +75283,18 @@
75255 sqlite3VdbeAddOp4(v, OP_DropTable, iDb, 0, 0, pTab->zName, 0);
75256
75257 /* Reload the table, index and permanent trigger schemas. */
75258 zWhere = sqlite3MPrintf(pParse->db, "tbl_name=%Q", zName);
75259 if( !zWhere ) return;
75260 sqlite3VdbeAddOp4(v, OP_ParseSchema, iDb, 0, 0, zWhere, P4_DYNAMIC);
75261
75262 #ifndef SQLITE_OMIT_TRIGGER
75263 /* Now, if the table is not stored in the temp database, reload any temp
75264 ** triggers. Don't use IN(...) in case SQLITE_OMIT_SUBQUERY is defined.
75265 */
75266 if( (zWhere=whereTempTriggers(pParse, pTab))!=0 ){
75267 sqlite3VdbeAddOp4(v, OP_ParseSchema, 1, 0, 0, zWhere, P4_DYNAMIC);
75268 }
75269 #endif
75270 }
75271
75272 /*
@@ -78875,12 +78903,12 @@
78875 }
78876 }
78877 #endif
78878
78879 /* Reparse everything to update our internal data structures */
78880 sqlite3VdbeAddOp4(v, OP_ParseSchema, iDb, 0, 0,
78881 sqlite3MPrintf(db, "tbl_name='%q'",p->zName), P4_DYNAMIC);
78882 }
78883
78884
78885 /* Add the table to the in-memory representation of the database.
78886 */
@@ -80073,13 +80101,12 @@
80073 ** to invalidate all pre-compiled statements.
80074 */
80075 if( pTblName ){
80076 sqlite3RefillIndex(pParse, pIndex, iMem);
80077 sqlite3ChangeCookie(pParse, iDb);
80078 sqlite3VdbeAddOp4(v, OP_ParseSchema, iDb, 0, 0,
80079 sqlite3MPrintf(db, "name='%q' AND type='index'", pIndex->zName),
80080 P4_DYNAMIC);
80081 sqlite3VdbeAddOp1(v, OP_Expire, 0);
80082 }
80083 }
80084
80085 /* When adding an index to the list of indices for a table, make
@@ -82621,14 +82648,14 @@
82621 ** character is exactly one byte in size. Also, all characters are
82622 ** able to participate in upper-case-to-lower-case mappings in EBCDIC
82623 ** whereas only characters less than 0x80 do in ASCII.
82624 */
82625 #if defined(SQLITE_EBCDIC)
82626 # define sqlite3Utf8Read(A,C) (*(A++))
82627 # define GlogUpperToLower(A) A = sqlite3UpperToLower[A]
82628 #else
82629 # define GlogUpperToLower(A) if( A<0x80 ){ A = sqlite3UpperToLower[A]; }
82630 #endif
82631
82632 static const struct compareInfo globInfo = { '*', '?', '[', 0 };
82633 /* The correct SQL-92 behavior is for the LIKE operator to ignore
82634 ** case. Thus 'a' LIKE 'A' would be true. */
@@ -82667,13 +82694,13 @@
82667 */
82668 static int patternCompare(
82669 const u8 *zPattern, /* The glob pattern */
82670 const u8 *zString, /* The string to compare against the glob */
82671 const struct compareInfo *pInfo, /* Information about how to do the compare */
82672 const int esc /* The escape character */
82673 ){
82674 int c, c2;
82675 int invert;
82676 int seen;
82677 u8 matchOne = pInfo->matchOne;
82678 u8 matchAll = pInfo->matchAll;
82679 u8 matchSet = pInfo->matchSet;
@@ -82723,11 +82750,11 @@
82723 }else if( !prevEscape && c==matchOne ){
82724 if( sqlite3Utf8Read(zString, &zString)==0 ){
82725 return 0;
82726 }
82727 }else if( c==matchSet ){
82728 int prior_c = 0;
82729 assert( esc==0 ); /* This only occurs for GLOB, not LIKE */
82730 seen = 0;
82731 invert = 0;
82732 c = sqlite3Utf8Read(zString, &zString);
82733 if( c==0 ) return 0;
@@ -82799,11 +82826,11 @@
82799 sqlite3_context *context,
82800 int argc,
82801 sqlite3_value **argv
82802 ){
82803 const unsigned char *zA, *zB;
82804 int escape = 0;
82805 int nPat;
82806 sqlite3 *db = sqlite3_context_db_handle(context);
82807
82808 zB = sqlite3_value_text(argv[0]);
82809 zA = sqlite3_value_text(argv[1]);
@@ -84110,17 +84137,29 @@
84110 }
84111
84112 /* If the parent table is the same as the child table, and we are about
84113 ** to increment the constraint-counter (i.e. this is an INSERT operation),
84114 ** then check if the row being inserted matches itself. If so, do not
84115 ** increment the constraint-counter. */
 
 
 
 
 
 
84116 if( pTab==pFKey->pFrom && nIncr==1 ){
84117 int iJump = sqlite3VdbeCurrentAddr(v) + nCol + 1;
84118 for(i=0; i<nCol; i++){
84119 int iChild = aiCol[i]+1+regData;
84120 int iParent = pIdx->aiColumn[i]+1+regData;
 
 
 
 
 
84121 sqlite3VdbeAddOp3(v, OP_Ne, iChild, iJump, iParent);
 
84122 }
84123 sqlite3VdbeAddOp2(v, OP_Goto, 0, iOk);
84124 }
84125
84126 sqlite3VdbeAddOp3(v, OP_MakeRecord, regTemp, nCol, regRec);
@@ -95336,13 +95375,12 @@
95336 "INSERT INTO %Q.%s VALUES('trigger',%Q,%Q,0,'CREATE TRIGGER %q')",
95337 db->aDb[iDb].zName, SCHEMA_TABLE(iDb), zName,
95338 pTrig->table, z);
95339 sqlite3DbFree(db, z);
95340 sqlite3ChangeCookie(pParse, iDb);
95341 sqlite3VdbeAddOp4(v, OP_ParseSchema, iDb, 0, 0, sqlite3MPrintf(
95342 db, "type='trigger' AND name='%q'", zName), P4_DYNAMIC
95343 );
95344 }
95345
95346 if( db->init.busy ){
95347 Trigger *pLink = pTrig;
95348 Hash *pHash = &db->aDb[iDb].pSchema->trigHash;
@@ -96392,11 +96430,11 @@
96392 aRegIdx = sqlite3DbMallocRaw(db, sizeof(Index*) * nIdx );
96393 if( aRegIdx==0 ) goto update_cleanup;
96394 }
96395 for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
96396 int reg;
96397 if( chngRowid ){
96398 reg = ++pParse->nMem;
96399 }else{
96400 reg = 0;
96401 for(i=0; i<pIdx->nColumn; i++){
96402 if( aXRef[pIdx->aiColumn[i]]>=0 ){
@@ -97547,11 +97585,11 @@
97547 v = sqlite3GetVdbe(pParse);
97548 sqlite3ChangeCookie(pParse, iDb);
97549
97550 sqlite3VdbeAddOp2(v, OP_Expire, 0, 0);
97551 zWhere = sqlite3MPrintf(db, "name='%q' AND type='table'", pTab->zName);
97552 sqlite3VdbeAddOp4(v, OP_ParseSchema, iDb, 0, 0, zWhere, P4_DYNAMIC);
97553 sqlite3VdbeAddOp4(v, OP_VCreate, iDb, 0, 0,
97554 pTab->zName, sqlite3Strlen30(pTab->zName) + 1);
97555 }
97556
97557 /* If we are rereading the sqlite_master table create the in-memory
@@ -107274,17 +107312,16 @@
107274 #ifndef SQLITE_OMIT_BLOB_LITERAL
107275 case 'x': case 'X': {
107276 testcase( z[0]=='x' ); testcase( z[0]=='X' );
107277 if( z[1]=='\'' ){
107278 *tokenType = TK_BLOB;
107279 for(i=2; (c=z[i])!=0 && c!='\''; i++){
107280 if( !sqlite3Isxdigit(c) ){
107281 *tokenType = TK_ILLEGAL;
107282 }
107283 }
107284 if( i%2 || !c ) *tokenType = TK_ILLEGAL;
107285 if( c ) i++;
107286 return i;
107287 }
107288 /* Otherwise fall through to the next case */
107289 }
107290 #endif
@@ -111710,16 +111747,39 @@
111710 ** similar macro called ArraySize(). Use a different name to avoid
111711 ** a collision when building an amalgamation with built-in FTS3.
111712 */
111713 #define SizeofArray(X) ((int)(sizeof(X)/sizeof(X[0])))
111714
 
 
 
 
 
111715 /*
111716 ** Maximum length of a varint encoded integer. The varint format is different
111717 ** from that used by SQLite, so the maximum length is 10, not 9.
111718 */
111719 #define FTS3_VARINT_MAX 10
111720
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
111721 /*
111722 ** The testcase() macro is only used by the amalgamation. If undefined,
111723 ** make it a no-op.
111724 */
111725 #ifndef testcase
@@ -111787,14 +111847,15 @@
111787 typedef struct Fts3Cursor Fts3Cursor;
111788 typedef struct Fts3Expr Fts3Expr;
111789 typedef struct Fts3Phrase Fts3Phrase;
111790 typedef struct Fts3PhraseToken Fts3PhraseToken;
111791
 
111792 typedef struct Fts3SegFilter Fts3SegFilter;
111793 typedef struct Fts3DeferredToken Fts3DeferredToken;
111794 typedef struct Fts3SegReader Fts3SegReader;
111795 typedef struct Fts3SegReaderCursor Fts3SegReaderCursor;
111796
111797 /*
111798 ** A connection to a fulltext index is an instance of the following
111799 ** structure. The xCreate and xConnect methods create an instance
111800 ** of this structure and xDestroy and xDisconnect free that instance.
@@ -111811,33 +111872,45 @@
111811 sqlite3_tokenizer *pTokenizer; /* tokenizer for inserts and queries */
111812
111813 /* Precompiled statements used by the implementation. Each of these
111814 ** statements is run and reset within a single virtual table API call.
111815 */
111816 sqlite3_stmt *aStmt[24];
111817
111818 char *zReadExprlist;
111819 char *zWriteExprlist;
111820
111821 int nNodeSize; /* Soft limit for node size */
111822 u8 bHasStat; /* True if %_stat table exists */
111823 u8 bHasDocsize; /* True if %_docsize table exists */
 
111824 int nPgsz; /* Page size for host database */
111825 char *zSegmentsTbl; /* Name of %_segments table */
111826 sqlite3_blob *pSegments; /* Blob handle open on %_segments table */
111827
111828 /* The following hash table is used to buffer pending index updates during
 
 
111829 ** transactions. Variable nPendingData estimates the memory size of the
111830 ** pending data, including hash table overhead, but not malloc overhead.
111831 ** When nPendingData exceeds nMaxPendingData, the buffer is flushed
111832 ** automatically. Variable iPrevDocid is the docid of the most recently
111833 ** inserted record.
 
 
 
 
 
111834 */
111835 int nMaxPendingData;
111836 int nPendingData;
111837 sqlite_int64 iPrevDocid;
111838 Fts3Hash pendingTerms;
 
 
 
 
111839
111840 #if defined(SQLITE_DEBUG)
111841 /* State variables used for validating that the transaction control
111842 ** methods of the virtual table are called at appropriate times. These
111843 ** values do not contribution to the FTS computation; they are used for
@@ -111864,13 +111937,14 @@
111864 Fts3DeferredToken *pDeferred; /* Deferred search tokens, if any */
111865 sqlite3_int64 iPrevId; /* Previous id read from aDoclist */
111866 char *pNextId; /* Pointer into the body of aDoclist */
111867 char *aDoclist; /* List of docids for full-text queries */
111868 int nDoclist; /* Size of buffer at aDoclist */
111869 int desc; /* True to sort in descending order */
111870 int eEvalmode; /* An FTS3_EVAL_XX constant */
111871 int nRowAvg; /* Average size of database rows, in pages */
 
111872
111873 int isMatchinfoNeeded; /* True when aMatchinfo[] needs filling in */
111874 u32 *aMatchinfo; /* Information about most recent match */
111875 int nMatchinfo; /* Number of elements in aMatchinfo[] */
111876 char *zMatchinfo; /* Matchinfo specification */
@@ -111897,66 +111971,90 @@
111897 */
111898 #define FTS3_FULLSCAN_SEARCH 0 /* Linear scan of %_content table */
111899 #define FTS3_DOCID_SEARCH 1 /* Lookup by rowid on %_content table */
111900 #define FTS3_FULLTEXT_SEARCH 2 /* Full-text index search */
111901
 
 
 
 
 
 
 
 
 
 
 
 
111902 /*
111903 ** A "phrase" is a sequence of one or more tokens that must match in
111904 ** sequence. A single token is the base case and the most common case.
111905 ** For a sequence of tokens contained in double-quotes (i.e. "one two three")
111906 ** nToken will be the number of tokens in the string.
111907 **
111908 ** The nDocMatch and nMatch variables contain data that may be used by the
111909 ** matchinfo() function. They are populated when the full-text index is
111910 ** queried for hits on the phrase. If one or more tokens in the phrase
111911 ** are deferred, the nDocMatch and nMatch variables are populated based
111912 ** on the assumption that the
111913 */
111914 struct Fts3PhraseToken {
111915 char *z; /* Text of the token */
111916 int n; /* Number of bytes in buffer z */
111917 int isPrefix; /* True if token ends with a "*" character */
 
 
 
 
111918 int bFulltext; /* True if full-text index was used */
111919 Fts3SegReaderCursor *pSegcsr; /* Segment-reader for this token */
111920 Fts3DeferredToken *pDeferred; /* Deferred token object for this token */
 
111921 };
111922
111923 struct Fts3Phrase {
111924 /* Variables populated by fts3_expr.c when parsing a MATCH expression */
 
 
 
 
 
 
111925 int nToken; /* Number of tokens in the phrase */
111926 int iColumn; /* Index of column this phrase must match */
111927 int isNot; /* Phrase prefixed by unary not (-) operator */
111928 Fts3PhraseToken aToken[1]; /* One entry for each token in the phrase */
111929 };
111930
111931 /*
111932 ** A tree of these objects forms the RHS of a MATCH operator.
111933 **
111934 ** If Fts3Expr.eType is either FTSQUERY_NEAR or FTSQUERY_PHRASE and isLoaded
111935 ** is true, then aDoclist points to a malloced buffer, size nDoclist bytes,
111936 ** containing the results of the NEAR or phrase query in FTS3 doclist
111937 ** format. As usual, the initial "Length" field found in doclists stored
111938 ** on disk is omitted from this buffer.
111939 **
111940 ** Variable pCurrent always points to the start of a docid field within
111941 ** aDoclist. Since the doclist is usually scanned in docid order, this can
111942 ** be used to accelerate seeking to the required docid within the doclist.
 
 
 
 
 
 
 
 
111943 */
111944 struct Fts3Expr {
111945 int eType; /* One of the FTSQUERY_XXX values defined below */
111946 int nNear; /* Valid if eType==FTSQUERY_NEAR */
111947 Fts3Expr *pParent; /* pParent->pLeft==this or pParent->pRight==this */
111948 Fts3Expr *pLeft; /* Left operand */
111949 Fts3Expr *pRight; /* Right operand */
111950 Fts3Phrase *pPhrase; /* Valid if eType==FTSQUERY_PHRASE */
111951
111952 int isLoaded; /* True if aDoclist/nDoclist are initialized. */
111953 char *aDoclist; /* Buffer containing doclist */
111954 int nDoclist; /* Size of aDoclist in bytes */
 
 
111955
111956 sqlite3_int64 iCurrent;
111957 char *pCurrent;
111958 };
111959
111960 /*
111961 ** Candidate values for Fts3Query.eType. Note that the order of the first
111962 ** four values is in order of precedence when parsing expressions. For
@@ -111980,35 +112078,36 @@
111980 SQLITE_PRIVATE int sqlite3Fts3PendingTermsFlush(Fts3Table *);
111981 SQLITE_PRIVATE void sqlite3Fts3PendingTermsClear(Fts3Table *);
111982 SQLITE_PRIVATE int sqlite3Fts3Optimize(Fts3Table *);
111983 SQLITE_PRIVATE int sqlite3Fts3SegReaderNew(int, sqlite3_int64,
111984 sqlite3_int64, sqlite3_int64, const char *, int, Fts3SegReader**);
111985 SQLITE_PRIVATE int sqlite3Fts3SegReaderPending(Fts3Table*,const char*,int,int,Fts3SegReader**);
 
111986 SQLITE_PRIVATE void sqlite3Fts3SegReaderFree(Fts3SegReader *);
111987 SQLITE_PRIVATE int sqlite3Fts3SegReaderCost(Fts3Cursor *, Fts3SegReader *, int *);
111988 SQLITE_PRIVATE int sqlite3Fts3AllSegdirs(Fts3Table*, int, sqlite3_stmt **);
111989 SQLITE_PRIVATE int sqlite3Fts3ReadLock(Fts3Table *);
111990 SQLITE_PRIVATE int sqlite3Fts3ReadBlock(Fts3Table*, sqlite3_int64, char **, int*);
111991
111992 SQLITE_PRIVATE int sqlite3Fts3SelectDoctotal(Fts3Table *, sqlite3_stmt **);
111993 SQLITE_PRIVATE int sqlite3Fts3SelectDocsize(Fts3Table *, sqlite3_int64, sqlite3_stmt **);
111994
111995 SQLITE_PRIVATE void sqlite3Fts3FreeDeferredTokens(Fts3Cursor *);
111996 SQLITE_PRIVATE int sqlite3Fts3DeferToken(Fts3Cursor *, Fts3PhraseToken *, int);
111997 SQLITE_PRIVATE int sqlite3Fts3CacheDeferredDoclists(Fts3Cursor *);
111998 SQLITE_PRIVATE void sqlite3Fts3FreeDeferredDoclists(Fts3Cursor *);
111999 SQLITE_PRIVATE char *sqlite3Fts3DeferredDoclist(Fts3DeferredToken *, int *);
112000 SQLITE_PRIVATE void sqlite3Fts3SegmentsClose(Fts3Table *);
112001
112002 #define FTS3_SEGCURSOR_PENDING -1
112003 #define FTS3_SEGCURSOR_ALL -2
 
112004
112005 SQLITE_PRIVATE int sqlite3Fts3SegReaderStart(Fts3Table*, Fts3SegReaderCursor*, Fts3SegFilter*);
112006 SQLITE_PRIVATE int sqlite3Fts3SegReaderStep(Fts3Table *, Fts3SegReaderCursor *);
112007 SQLITE_PRIVATE void sqlite3Fts3SegReaderFinish(Fts3SegReaderCursor *);
 
112008 SQLITE_PRIVATE int sqlite3Fts3SegReaderCursor(
112009 Fts3Table *, int, const char *, int, int, int, Fts3SegReaderCursor *);
112010
112011 /* Flags allowed as part of the 4th argument to SegmentReaderIterate() */
112012 #define FTS3_SEGMENT_REQUIRE_POS 0x00000001
112013 #define FTS3_SEGMENT_IGNORE_EMPTY 0x00000002
112014 #define FTS3_SEGMENT_COLUMN_FILTER 0x00000004
@@ -112021,21 +112120,24 @@
112021 int nTerm;
112022 int iCol;
112023 int flags;
112024 };
112025
112026 struct Fts3SegReaderCursor {
112027 /* Used internally by sqlite3Fts3SegReaderXXX() calls */
112028 Fts3SegReader **apSegment; /* Array of Fts3SegReader objects */
112029 int nSegment; /* Size of apSegment array */
112030 int nAdvance; /* How many seg-readers to advance */
112031 Fts3SegFilter *pFilter; /* Pointer to filter object */
112032 char *aBuffer; /* Buffer to merge doclists in */
112033 int nBuffer; /* Allocated size of aBuffer[] in bytes */
112034
112035 /* Cost of running this iterator. Used by fts3.c only. */
112036 int nCost;
 
 
 
112037
112038 /* Output values. Valid only after Fts3SegReaderStep() returns SQLITE_ROW. */
112039 char *zTerm; /* Pointer to term buffer */
112040 int nTerm; /* Size of zTerm in bytes */
112041 char *aDoclist; /* Pointer to doclist buffer */
@@ -112046,15 +112148,13 @@
112046 SQLITE_PRIVATE int sqlite3Fts3PutVarint(char *, sqlite3_int64);
112047 SQLITE_PRIVATE int sqlite3Fts3GetVarint(const char *, sqlite_int64 *);
112048 SQLITE_PRIVATE int sqlite3Fts3GetVarint32(const char *, int *);
112049 SQLITE_PRIVATE int sqlite3Fts3VarintLen(sqlite3_uint64);
112050 SQLITE_PRIVATE void sqlite3Fts3Dequote(char *);
 
112051
112052 SQLITE_PRIVATE char *sqlite3Fts3FindPositions(Fts3Cursor *, Fts3Expr *, sqlite3_int64, int);
112053 SQLITE_PRIVATE int sqlite3Fts3ExprLoadDoclist(Fts3Cursor *, Fts3Expr *);
112054 SQLITE_PRIVATE int sqlite3Fts3ExprLoadFtDoclist(Fts3Cursor *, Fts3Expr *, char **, int *);
112055 SQLITE_PRIVATE int sqlite3Fts3ExprNearTrim(Fts3Expr *, Fts3Expr *, int);
112056
112057 /* fts3_tokenizer.c */
112058 SQLITE_PRIVATE const char *sqlite3Fts3NextToken(const char *, int *);
112059 SQLITE_PRIVATE int sqlite3Fts3InitHashTable(sqlite3 *, Fts3Hash *, const char *);
112060 SQLITE_PRIVATE int sqlite3Fts3InitTokenizer(Fts3Hash *pHash, const char *,
@@ -112079,10 +112179,33 @@
112079 SQLITE_PRIVATE int sqlite3Fts3InitTerm(sqlite3 *db);
112080 #endif
112081
112082 /* fts3_aux.c */
112083 SQLITE_PRIVATE int sqlite3Fts3InitAux(sqlite3 *db);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
112084
112085 #endif /* _FTSINT_H */
112086
112087 /************** End of fts3Int.h *********************************************/
112088 /************** Continuing where we left off in fts3.c ***********************/
@@ -112200,16 +112323,16 @@
112200
112201 /*
112202 ** When this function is called, *pp points to the first byte following a
112203 ** varint that is part of a doclist (or position-list, or any other list
112204 ** of varints). This function moves *pp to point to the start of that varint,
112205 ** and decrements the value stored in *pVal by the varint value.
112206 **
112207 ** Argument pStart points to the first byte of the doclist that the
112208 ** varint is part of.
112209 */
112210 static void fts3GetReverseDeltaVarint(
112211 char **pp,
112212 char *pStart,
112213 sqlite3_int64 *pVal
112214 ){
112215 sqlite3_int64 iVal;
@@ -112221,25 +112344,11 @@
112221 for(p = (*pp)-2; p>=pStart && *p&0x80; p--);
112222 p++;
112223 *pp = p;
112224
112225 sqlite3Fts3GetVarint(p, &iVal);
112226 *pVal -= iVal;
112227 }
112228
112229 /*
112230 ** As long as *pp has not reached its end (pEnd), then do the same
112231 ** as fts3GetDeltaVarint(): read a single varint and add it to *pVal.
112232 ** But if we have reached the end of the varint, just set *pp=0 and
112233 ** leave *pVal unchanged.
112234 */
112235 static void fts3GetDeltaVarint2(char **pp, char *pEnd, sqlite3_int64 *pVal){
112236 if( *pp>=pEnd ){
112237 *pp = 0;
112238 }else{
112239 fts3GetDeltaVarint(pp, pVal);
112240 }
112241 }
112242
112243 /*
112244 ** The xDisconnect() virtual table method.
112245 */
@@ -112608,10 +112717,62 @@
112608 fts3Appendf(pRc, &zRet, ",%s(?)", zFunction);
112609 }
112610 sqlite3_free(zFree);
112611 return zRet;
112612 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
112613
112614 /*
112615 ** This function is the implementation of both the xConnect and xCreate
112616 ** methods of the FTS3 virtual table.
112617 **
@@ -112641,16 +112802,23 @@
112641 int nCol = 0; /* Number of columns in the FTS table */
112642 char *zCsr; /* Space for holding column names */
112643 int nDb; /* Bytes required to hold database name */
112644 int nName; /* Bytes required to hold table name */
112645 int isFts4 = (argv[0][3]=='4'); /* True for FTS4, false for FTS3 */
112646 int bNoDocsize = 0; /* True to omit %_docsize table */
112647 const char **aCol; /* Array of column names */
112648 sqlite3_tokenizer *pTokenizer = 0; /* Tokenizer for this table */
112649
112650 char *zCompress = 0;
112651 char *zUncompress = 0;
 
 
 
 
 
 
 
 
112652
112653 assert( strlen(argv[0])==4 );
112654 assert( (sqlite3_strnicmp(argv[0], "fts4", 4)==0 && isFts4)
112655 || (sqlite3_strnicmp(argv[0], "fts3", 4)==0 && !isFts4)
112656 );
@@ -112687,32 +112855,76 @@
112687 rc = sqlite3Fts3InitTokenizer(pHash, &z[9], &pTokenizer, pzErr);
112688 }
112689
112690 /* Check if it is an FTS4 special argument. */
112691 else if( isFts4 && fts3IsSpecialColumn(z, &nKey, &zVal) ){
 
 
 
 
 
 
 
 
 
 
 
 
 
112692 if( !zVal ){
112693 rc = SQLITE_NOMEM;
112694 goto fts3_init_out;
112695 }
112696 if( nKey==9 && 0==sqlite3_strnicmp(z, "matchinfo", 9) ){
112697 if( strlen(zVal)==4 && 0==sqlite3_strnicmp(zVal, "fts3", 4) ){
112698 bNoDocsize = 1;
112699 }else{
112700 *pzErr = sqlite3_mprintf("unrecognized matchinfo: %s", zVal);
112701 rc = SQLITE_ERROR;
112702 }
112703 }else if( nKey==8 && 0==sqlite3_strnicmp(z, "compress", 8) ){
112704 zCompress = zVal;
112705 zVal = 0;
112706 }else if( nKey==10 && 0==sqlite3_strnicmp(z, "uncompress", 10) ){
112707 zUncompress = zVal;
112708 zVal = 0;
112709 }else{
112710 *pzErr = sqlite3_mprintf("unrecognized parameter: %s", z);
112711 rc = SQLITE_ERROR;
112712 }
112713 sqlite3_free(zVal);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
112714 }
112715
112716 /* Otherwise, the argument is a column name. */
112717 else {
112718 nString += (int)(strlen(z) + 1);
@@ -112732,14 +112944,21 @@
112732 rc = sqlite3Fts3InitTokenizer(pHash, "simple", &pTokenizer, pzErr);
112733 if( rc!=SQLITE_OK ) goto fts3_init_out;
112734 }
112735 assert( pTokenizer );
112736
 
 
 
 
 
 
112737
112738 /* Allocate and populate the Fts3Table structure. */
112739 nByte = sizeof(Fts3Table) + /* Fts3Table */
112740 nCol * sizeof(char *) + /* azColumn */
 
112741 nName + /* zName */
112742 nDb + /* zDb */
112743 nString; /* Space for azColumn strings */
112744 p = (Fts3Table*)sqlite3_malloc(nByte);
112745 if( p==0 ){
@@ -112750,20 +112969,26 @@
112750 p->db = db;
112751 p->nColumn = nCol;
112752 p->nPendingData = 0;
112753 p->azColumn = (char **)&p[1];
112754 p->pTokenizer = pTokenizer;
112755 p->nNodeSize = 1000;
112756 p->nMaxPendingData = FTS3_MAX_PENDING_DATA;
112757 p->bHasDocsize = (isFts4 && bNoDocsize==0);
112758 p->bHasStat = isFts4;
 
112759 TESTONLY( p->inTransaction = -1 );
112760 TESTONLY( p->mxSavepoint = -1 );
112761 fts3HashInit(&p->pendingTerms, FTS3_HASH_STRING, 1);
 
 
 
 
 
 
112762
112763 /* Fill in the zName and zDb fields of the vtab structure. */
112764 zCsr = (char *)&p->azColumn[nCol];
112765 p->zName = zCsr;
112766 memcpy(zCsr, argv[2], nName);
112767 zCsr += nName;
112768 p->zDb = zCsr;
112769 memcpy(zCsr, argv[1], nDb);
@@ -112797,19 +113022,20 @@
112797 if( isCreate ){
112798 rc = fts3CreateTables(p);
112799 }
112800
112801 /* Figure out the page-size for the database. This is required in order to
112802 ** estimate the cost of loading large doclists from the database (see
112803 ** function sqlite3Fts3SegReaderCost() for details).
112804 */
112805 fts3DatabasePageSize(&rc, p);
 
112806
112807 /* Declare the table schema to SQLite. */
112808 fts3DeclareVtab(&rc, p);
112809
112810 fts3_init_out:
 
 
112811 sqlite3_free(zCompress);
112812 sqlite3_free(zUncompress);
112813 sqlite3_free((void *)aCol);
112814 if( rc!=SQLITE_OK ){
112815 if( p ){
@@ -112816,10 +113042,11 @@
112816 fts3DisconnectMethod((sqlite3_vtab *)p);
112817 }else if( pTokenizer ){
112818 pTokenizer->pModule->xDestroy(pTokenizer);
112819 }
112820 }else{
 
112821 *ppVTab = &p->base;
112822 }
112823 return rc;
112824 }
112825
@@ -112913,14 +113140,15 @@
112913 if( pOrder->desc ){
112914 pInfo->idxStr = "DESC";
112915 }else{
112916 pInfo->idxStr = "ASC";
112917 }
 
112918 }
112919 pInfo->orderByConsumed = 1;
112920 }
112921
 
112922 return SQLITE_OK;
112923 }
112924
112925 /*
112926 ** Implementation of xOpen method.
@@ -112952,10 +113180,11 @@
112952 sqlite3_finalize(pCsr->pStmt);
112953 sqlite3Fts3ExprFree(pCsr->pExpr);
112954 sqlite3Fts3FreeDeferredTokens(pCsr);
112955 sqlite3_free(pCsr->aDoclist);
112956 sqlite3_free(pCsr->aMatchinfo);
 
112957 sqlite3_free(pCsr);
112958 return SQLITE_OK;
112959 }
112960
112961 /*
@@ -112963,12 +113192,12 @@
112963 ** of the %_content table that contains the last match. Return
112964 ** SQLITE_OK on success.
112965 */
112966 static int fts3CursorSeek(sqlite3_context *pContext, Fts3Cursor *pCsr){
112967 if( pCsr->isRequireSeek ){
112968 pCsr->isRequireSeek = 0;
112969 sqlite3_bind_int64(pCsr->pStmt, 1, pCsr->iPrevId);
 
112970 if( SQLITE_ROW==sqlite3_step(pCsr->pStmt) ){
112971 return SQLITE_OK;
112972 }else{
112973 int rc = sqlite3_reset(pCsr->pStmt);
112974 if( rc==SQLITE_OK ){
@@ -113145,21 +113374,21 @@
113145 if( rc==SQLITE_OK && iHeight>1 ){
113146 char *zBlob = 0; /* Blob read from %_segments table */
113147 int nBlob; /* Size of zBlob in bytes */
113148
113149 if( piLeaf && piLeaf2 && (*piLeaf!=*piLeaf2) ){
113150 rc = sqlite3Fts3ReadBlock(p, *piLeaf, &zBlob, &nBlob);
113151 if( rc==SQLITE_OK ){
113152 rc = fts3SelectLeaf(p, zTerm, nTerm, zBlob, nBlob, piLeaf, 0);
113153 }
113154 sqlite3_free(zBlob);
113155 piLeaf = 0;
113156 zBlob = 0;
113157 }
113158
113159 if( rc==SQLITE_OK ){
113160 rc = sqlite3Fts3ReadBlock(p, piLeaf ? *piLeaf : *piLeaf2, &zBlob, &nBlob);
113161 }
113162 if( rc==SQLITE_OK ){
113163 rc = fts3SelectLeaf(p, zTerm, nTerm, zBlob, nBlob, piLeaf, piLeaf2);
113164 }
113165 sqlite3_free(zBlob);
@@ -113531,11 +113760,23 @@
113531 *pp = p;
113532 return 1;
113533 }
113534
113535 /*
113536 ** Merge two position-lists as required by the NEAR operator.
 
 
 
 
 
 
 
 
 
 
 
 
113537 */
113538 static int fts3PoslistNearMerge(
113539 char **pp, /* Output buffer */
113540 char *aTmp, /* Temporary buffer space */
113541 int nRight, /* Maximum difference in token positions */
@@ -113544,218 +113785,31 @@
113544 char **pp2 /* IN/OUT: Right input list */
113545 ){
113546 char *p1 = *pp1;
113547 char *p2 = *pp2;
113548
113549 if( !pp ){
113550 if( fts3PoslistPhraseMerge(0, nRight, 0, 0, pp1, pp2) ) return 1;
113551 *pp1 = p1;
113552 *pp2 = p2;
113553 return fts3PoslistPhraseMerge(0, nLeft, 0, 0, pp2, pp1);
113554 }else{
113555 char *pTmp1 = aTmp;
113556 char *pTmp2;
113557 char *aTmp2;
113558 int res = 1;
113559
113560 fts3PoslistPhraseMerge(&pTmp1, nRight, 0, 0, pp1, pp2);
113561 aTmp2 = pTmp2 = pTmp1;
113562 *pp1 = p1;
113563 *pp2 = p2;
113564 fts3PoslistPhraseMerge(&pTmp2, nLeft, 1, 0, pp2, pp1);
113565 if( pTmp1!=aTmp && pTmp2!=aTmp2 ){
113566 fts3PoslistMerge(pp, &aTmp, &aTmp2);
113567 }else if( pTmp1!=aTmp ){
113568 fts3PoslistCopy(pp, &aTmp);
113569 }else if( pTmp2!=aTmp2 ){
113570 fts3PoslistCopy(pp, &aTmp2);
113571 }else{
113572 res = 0;
113573 }
113574
113575 return res;
113576 }
113577 }
113578
113579 /*
113580 ** Values that may be used as the first parameter to fts3DoclistMerge().
113581 */
113582 #define MERGE_NOT 2 /* D + D -> D */
113583 #define MERGE_AND 3 /* D + D -> D */
113584 #define MERGE_OR 4 /* D + D -> D */
113585 #define MERGE_POS_OR 5 /* P + P -> P */
113586 #define MERGE_PHRASE 6 /* P + P -> D */
113587 #define MERGE_POS_PHRASE 7 /* P + P -> P */
113588 #define MERGE_NEAR 8 /* P + P -> D */
113589 #define MERGE_POS_NEAR 9 /* P + P -> P */
113590
113591 /*
113592 ** Merge the two doclists passed in buffer a1 (size n1 bytes) and a2
113593 ** (size n2 bytes). The output is written to pre-allocated buffer aBuffer,
113594 ** which is guaranteed to be large enough to hold the results. The number
113595 ** of bytes written to aBuffer is stored in *pnBuffer before returning.
113596 **
113597 ** If successful, SQLITE_OK is returned. Otherwise, if a malloc error
113598 ** occurs while allocating a temporary buffer as part of the merge operation,
113599 ** SQLITE_NOMEM is returned.
113600 */
113601 static int fts3DoclistMerge(
113602 int mergetype, /* One of the MERGE_XXX constants */
113603 int nParam1, /* Used by MERGE_NEAR and MERGE_POS_NEAR */
113604 int nParam2, /* Used by MERGE_NEAR and MERGE_POS_NEAR */
113605 char *aBuffer, /* Pre-allocated output buffer */
113606 int *pnBuffer, /* OUT: Bytes written to aBuffer */
113607 char *a1, /* Buffer containing first doclist */
113608 int n1, /* Size of buffer a1 */
113609 char *a2, /* Buffer containing second doclist */
113610 int n2, /* Size of buffer a2 */
113611 int *pnDoc /* OUT: Number of docids in output */
113612 ){
113613 sqlite3_int64 i1 = 0;
113614 sqlite3_int64 i2 = 0;
113615 sqlite3_int64 iPrev = 0;
113616
113617 char *p = aBuffer;
113618 char *p1 = a1;
113619 char *p2 = a2;
113620 char *pEnd1 = &a1[n1];
113621 char *pEnd2 = &a2[n2];
113622 int nDoc = 0;
113623
113624 assert( mergetype==MERGE_OR || mergetype==MERGE_POS_OR
113625 || mergetype==MERGE_AND || mergetype==MERGE_NOT
113626 || mergetype==MERGE_PHRASE || mergetype==MERGE_POS_PHRASE
113627 || mergetype==MERGE_NEAR || mergetype==MERGE_POS_NEAR
113628 );
113629
113630 if( !aBuffer ){
113631 *pnBuffer = 0;
113632 return SQLITE_NOMEM;
113633 }
113634
113635 /* Read the first docid from each doclist */
113636 fts3GetDeltaVarint2(&p1, pEnd1, &i1);
113637 fts3GetDeltaVarint2(&p2, pEnd2, &i2);
113638
113639 switch( mergetype ){
113640 case MERGE_OR:
113641 case MERGE_POS_OR:
113642 while( p1 || p2 ){
113643 if( p2 && p1 && i1==i2 ){
113644 fts3PutDeltaVarint(&p, &iPrev, i1);
113645 if( mergetype==MERGE_POS_OR ) fts3PoslistMerge(&p, &p1, &p2);
113646 fts3GetDeltaVarint2(&p1, pEnd1, &i1);
113647 fts3GetDeltaVarint2(&p2, pEnd2, &i2);
113648 }else if( !p2 || (p1 && i1<i2) ){
113649 fts3PutDeltaVarint(&p, &iPrev, i1);
113650 if( mergetype==MERGE_POS_OR ) fts3PoslistCopy(&p, &p1);
113651 fts3GetDeltaVarint2(&p1, pEnd1, &i1);
113652 }else{
113653 fts3PutDeltaVarint(&p, &iPrev, i2);
113654 if( mergetype==MERGE_POS_OR ) fts3PoslistCopy(&p, &p2);
113655 fts3GetDeltaVarint2(&p2, pEnd2, &i2);
113656 }
113657 }
113658 break;
113659
113660 case MERGE_AND:
113661 while( p1 && p2 ){
113662 if( i1==i2 ){
113663 fts3PutDeltaVarint(&p, &iPrev, i1);
113664 fts3GetDeltaVarint2(&p1, pEnd1, &i1);
113665 fts3GetDeltaVarint2(&p2, pEnd2, &i2);
113666 nDoc++;
113667 }else if( i1<i2 ){
113668 fts3GetDeltaVarint2(&p1, pEnd1, &i1);
113669 }else{
113670 fts3GetDeltaVarint2(&p2, pEnd2, &i2);
113671 }
113672 }
113673 break;
113674
113675 case MERGE_NOT:
113676 while( p1 ){
113677 if( p2 && i1==i2 ){
113678 fts3GetDeltaVarint2(&p1, pEnd1, &i1);
113679 fts3GetDeltaVarint2(&p2, pEnd2, &i2);
113680 }else if( !p2 || i1<i2 ){
113681 fts3PutDeltaVarint(&p, &iPrev, i1);
113682 fts3GetDeltaVarint2(&p1, pEnd1, &i1);
113683 }else{
113684 fts3GetDeltaVarint2(&p2, pEnd2, &i2);
113685 }
113686 }
113687 break;
113688
113689 case MERGE_POS_PHRASE:
113690 case MERGE_PHRASE: {
113691 char **ppPos = (mergetype==MERGE_PHRASE ? 0 : &p);
113692 while( p1 && p2 ){
113693 if( i1==i2 ){
113694 char *pSave = p;
113695 sqlite3_int64 iPrevSave = iPrev;
113696 fts3PutDeltaVarint(&p, &iPrev, i1);
113697 if( 0==fts3PoslistPhraseMerge(ppPos, nParam1, 0, 1, &p1, &p2) ){
113698 p = pSave;
113699 iPrev = iPrevSave;
113700 }else{
113701 nDoc++;
113702 }
113703 fts3GetDeltaVarint2(&p1, pEnd1, &i1);
113704 fts3GetDeltaVarint2(&p2, pEnd2, &i2);
113705 }else if( i1<i2 ){
113706 fts3PoslistCopy(0, &p1);
113707 fts3GetDeltaVarint2(&p1, pEnd1, &i1);
113708 }else{
113709 fts3PoslistCopy(0, &p2);
113710 fts3GetDeltaVarint2(&p2, pEnd2, &i2);
113711 }
113712 }
113713 break;
113714 }
113715
113716 default: assert( mergetype==MERGE_POS_NEAR || mergetype==MERGE_NEAR ); {
113717 char *aTmp = 0;
113718 char **ppPos = 0;
113719
113720 if( mergetype==MERGE_POS_NEAR ){
113721 ppPos = &p;
113722 aTmp = sqlite3_malloc(2*(n1+n2+1));
113723 if( !aTmp ){
113724 return SQLITE_NOMEM;
113725 }
113726 }
113727
113728 while( p1 && p2 ){
113729 if( i1==i2 ){
113730 char *pSave = p;
113731 sqlite3_int64 iPrevSave = iPrev;
113732 fts3PutDeltaVarint(&p, &iPrev, i1);
113733
113734 if( !fts3PoslistNearMerge(ppPos, aTmp, nParam1, nParam2, &p1, &p2) ){
113735 iPrev = iPrevSave;
113736 p = pSave;
113737 }
113738
113739 fts3GetDeltaVarint2(&p1, pEnd1, &i1);
113740 fts3GetDeltaVarint2(&p2, pEnd2, &i2);
113741 }else if( i1<i2 ){
113742 fts3PoslistCopy(0, &p1);
113743 fts3GetDeltaVarint2(&p1, pEnd1, &i1);
113744 }else{
113745 fts3PoslistCopy(0, &p2);
113746 fts3GetDeltaVarint2(&p2, pEnd2, &i2);
113747 }
113748 }
113749 sqlite3_free(aTmp);
113750 break;
113751 }
113752 }
113753
113754 if( pnDoc ) *pnDoc = nDoc;
113755 *pnBuffer = (int)(p-aBuffer);
113756 return SQLITE_OK;
113757 }
113758
113759 /*
113760 ** A pointer to an instance of this structure is used as the context
113761 ** argument to sqlite3Fts3SegReaderIterate()
@@ -113764,10 +113818,152 @@
113764 struct TermSelect {
113765 int isReqPos;
113766 char *aaOutput[16]; /* Malloc'd output buffer */
113767 int anOutput[16]; /* Size of output in bytes */
113768 };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
113769
113770 /*
113771 ** Merge all doclists in the TermSelect.aaOutput[] array into a single
113772 ** doclist stored in TermSelect.aaOutput[0]. If successful, delete all
113773 ** other doclists (except the aaOutput[0] one) and return SQLITE_OK.
@@ -113774,12 +113970,11 @@
113774 **
113775 ** If an OOM error occurs, return SQLITE_NOMEM. In this case it is
113776 ** the responsibility of the caller to free any doclists left in the
113777 ** TermSelect.aaOutput[] array.
113778 */
113779 static int fts3TermSelectMerge(TermSelect *pTS){
113780 int mergetype = (pTS->isReqPos ? MERGE_POS_OR : MERGE_OR);
113781 char *aOut = 0;
113782 int nOut = 0;
113783 int i;
113784
113785 /* Loop through the doclists in the aaOutput[] array. Merge them all
@@ -113790,19 +113985,21 @@
113790 if( !aOut ){
113791 aOut = pTS->aaOutput[i];
113792 nOut = pTS->anOutput[i];
113793 pTS->aaOutput[i] = 0;
113794 }else{
113795 int nNew = nOut + pTS->anOutput[i];
113796 char *aNew = sqlite3_malloc(nNew);
113797 if( !aNew ){
 
 
 
 
113798 sqlite3_free(aOut);
113799 return SQLITE_NOMEM;
113800 }
113801 fts3DoclistMerge(mergetype, 0, 0,
113802 aNew, &nNew, pTS->aaOutput[i], pTS->anOutput[i], aOut, nOut, 0
113803 );
113804 sqlite3_free(pTS->aaOutput[i]);
113805 sqlite3_free(aOut);
113806 pTS->aaOutput[i] = 0;
113807 aOut = aNew;
113808 nOut = nNew;
@@ -113834,217 +114031,241 @@
113834 UNUSED_PARAMETER(zTerm);
113835 UNUSED_PARAMETER(nTerm);
113836
113837 if( pTS->aaOutput[0]==0 ){
113838 /* If this is the first term selected, copy the doclist to the output
113839 ** buffer using memcpy(). TODO: Add a way to transfer control of the
113840 ** aDoclist buffer from the caller so as to avoid the memcpy().
113841 */
113842 pTS->aaOutput[0] = sqlite3_malloc(nDoclist);
113843 pTS->anOutput[0] = nDoclist;
113844 if( pTS->aaOutput[0] ){
113845 memcpy(pTS->aaOutput[0], aDoclist, nDoclist);
113846 }else{
113847 return SQLITE_NOMEM;
113848 }
113849 }else{
113850 int mergetype = (pTS->isReqPos ? MERGE_POS_OR : MERGE_OR);
113851 char *aMerge = aDoclist;
113852 int nMerge = nDoclist;
113853 int iOut;
113854
113855 for(iOut=0; iOut<SizeofArray(pTS->aaOutput); iOut++){
113856 char *aNew;
113857 int nNew;
113858 if( pTS->aaOutput[iOut]==0 ){
113859 assert( iOut>0 );
113860 pTS->aaOutput[iOut] = aMerge;
113861 pTS->anOutput[iOut] = nMerge;
113862 break;
113863 }
113864
113865 nNew = nMerge + pTS->anOutput[iOut];
113866 aNew = sqlite3_malloc(nNew);
113867 if( !aNew ){
113868 if( aMerge!=aDoclist ){
113869 sqlite3_free(aMerge);
113870 }
113871 return SQLITE_NOMEM;
113872 }
113873 fts3DoclistMerge(mergetype, 0, 0, aNew, &nNew,
113874 pTS->aaOutput[iOut], pTS->anOutput[iOut], aMerge, nMerge, 0
113875 );
113876
113877 if( iOut>0 ) sqlite3_free(aMerge);
113878 sqlite3_free(pTS->aaOutput[iOut]);
113879 pTS->aaOutput[iOut] = 0;
113880
113881 aMerge = aNew;
113882 nMerge = nNew;
113883 if( (iOut+1)==SizeofArray(pTS->aaOutput) ){
113884 pTS->aaOutput[iOut] = aMerge;
113885 pTS->anOutput[iOut] = nMerge;
113886 }
113887 }
113888 }
113889 return SQLITE_OK;
113890 }
113891
113892 static int fts3DeferredTermSelect(
113893 Fts3DeferredToken *pToken, /* Phrase token */
113894 int isTermPos, /* True to include positions */
113895 int *pnOut, /* OUT: Size of list */
113896 char **ppOut /* OUT: Body of list */
113897 ){
113898 char *aSource;
113899 int nSource;
113900
113901 aSource = sqlite3Fts3DeferredDoclist(pToken, &nSource);
113902 if( !aSource ){
113903 *pnOut = 0;
113904 *ppOut = 0;
113905 }else if( isTermPos ){
113906 *ppOut = sqlite3_malloc(nSource);
113907 if( !*ppOut ) return SQLITE_NOMEM;
113908 memcpy(*ppOut, aSource, nSource);
113909 *pnOut = nSource;
113910 }else{
113911 sqlite3_int64 docid;
113912 *pnOut = sqlite3Fts3GetVarint(aSource, &docid);
113913 *ppOut = sqlite3_malloc(*pnOut);
113914 if( !*ppOut ) return SQLITE_NOMEM;
113915 sqlite3Fts3PutVarint(*ppOut, docid);
113916 }
113917
113918 return SQLITE_OK;
113919 }
113920
113921 SQLITE_PRIVATE int sqlite3Fts3SegReaderCursor(
113922 Fts3Table *p, /* FTS3 table handle */
 
113923 int iLevel, /* Level of segments to scan */
113924 const char *zTerm, /* Term to query for */
113925 int nTerm, /* Size of zTerm in bytes */
113926 int isPrefix, /* True for a prefix search */
113927 int isScan, /* True to scan from zTerm to EOF */
113928 Fts3SegReaderCursor *pCsr /* Cursor object to populate */
113929 ){
113930 int rc = SQLITE_OK;
113931 int rc2;
113932 int iAge = 0;
113933 sqlite3_stmt *pStmt = 0;
113934 Fts3SegReader *pPending = 0;
113935
113936 assert( iLevel==FTS3_SEGCURSOR_ALL
113937 || iLevel==FTS3_SEGCURSOR_PENDING
113938 || iLevel>=0
113939 );
113940 assert( FTS3_SEGCURSOR_PENDING<0 );
113941 assert( FTS3_SEGCURSOR_ALL<0 );
113942 assert( iLevel==FTS3_SEGCURSOR_ALL || (zTerm==0 && isPrefix==1) );
113943 assert( isPrefix==0 || isScan==0 );
113944
113945
113946 memset(pCsr, 0, sizeof(Fts3SegReaderCursor));
113947
113948 /* If iLevel is less than 0, include a seg-reader for the pending-terms. */
113949 assert( isScan==0 || fts3HashCount(&p->pendingTerms)==0 );
113950 if( iLevel<0 && isScan==0 ){
113951 rc = sqlite3Fts3SegReaderPending(p, zTerm, nTerm, isPrefix, &pPending);
113952 if( rc==SQLITE_OK && pPending ){
113953 int nByte = (sizeof(Fts3SegReader *) * 16);
113954 pCsr->apSegment = (Fts3SegReader **)sqlite3_malloc(nByte);
113955 if( pCsr->apSegment==0 ){
113956 rc = SQLITE_NOMEM;
113957 }else{
113958 pCsr->apSegment[0] = pPending;
113959 pCsr->nSegment = 1;
113960 pPending = 0;
113961 }
113962 }
113963 }
113964
113965 if( iLevel!=FTS3_SEGCURSOR_PENDING ){
113966 if( rc==SQLITE_OK ){
113967 rc = sqlite3Fts3AllSegdirs(p, iLevel, &pStmt);
113968 }
 
113969 while( rc==SQLITE_OK && SQLITE_ROW==(rc = sqlite3_step(pStmt)) ){
 
113970
113971 /* Read the values returned by the SELECT into local variables. */
113972 sqlite3_int64 iStartBlock = sqlite3_column_int64(pStmt, 1);
113973 sqlite3_int64 iLeavesEndBlock = sqlite3_column_int64(pStmt, 2);
113974 sqlite3_int64 iEndBlock = sqlite3_column_int64(pStmt, 3);
113975 int nRoot = sqlite3_column_bytes(pStmt, 4);
113976 char const *zRoot = sqlite3_column_blob(pStmt, 4);
113977
113978 /* If nSegment is a multiple of 16 the array needs to be extended. */
113979 if( (pCsr->nSegment%16)==0 ){
113980 Fts3SegReader **apNew;
113981 int nByte = (pCsr->nSegment + 16)*sizeof(Fts3SegReader*);
113982 apNew = (Fts3SegReader **)sqlite3_realloc(pCsr->apSegment, nByte);
113983 if( !apNew ){
113984 rc = SQLITE_NOMEM;
113985 goto finished;
113986 }
113987 pCsr->apSegment = apNew;
113988 }
113989
113990 /* If zTerm is not NULL, and this segment is not stored entirely on its
113991 ** root node, the range of leaves scanned can be reduced. Do this. */
113992 if( iStartBlock && zTerm ){
113993 sqlite3_int64 *pi = (isPrefix ? &iLeavesEndBlock : 0);
113994 rc = fts3SelectLeaf(p, zTerm, nTerm, zRoot, nRoot, &iStartBlock, pi);
113995 if( rc!=SQLITE_OK ) goto finished;
113996 if( isPrefix==0 && isScan==0 ) iLeavesEndBlock = iStartBlock;
113997 }
113998
113999 rc = sqlite3Fts3SegReaderNew(iAge, iStartBlock, iLeavesEndBlock,
114000 iEndBlock, zRoot, nRoot, &pCsr->apSegment[pCsr->nSegment]
114001 );
114002 if( rc!=SQLITE_OK ) goto finished;
114003 pCsr->nSegment++;
114004 iAge++;
114005 }
114006 }
114007
114008 finished:
114009 rc2 = sqlite3_reset(pStmt);
114010 if( rc==SQLITE_DONE ) rc = rc2;
114011 sqlite3Fts3SegReaderFree(pPending);
114012
114013 return rc;
114014 }
114015
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
114016
114017 static int fts3TermSegReaderCursor(
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
114018 Fts3Cursor *pCsr, /* Virtual table cursor handle */
114019 const char *zTerm, /* Term to query for */
114020 int nTerm, /* Size of zTerm in bytes */
114021 int isPrefix, /* True for a prefix search */
114022 Fts3SegReaderCursor **ppSegcsr /* OUT: Allocated seg-reader cursor */
114023 ){
114024 Fts3SegReaderCursor *pSegcsr; /* Object to allocate and return */
114025 int rc = SQLITE_NOMEM; /* Return code */
114026
114027 pSegcsr = sqlite3_malloc(sizeof(Fts3SegReaderCursor));
114028 if( pSegcsr ){
 
 
114029 Fts3Table *p = (Fts3Table *)pCsr->base.pVtab;
114030 int i;
114031 int nCost = 0;
114032 rc = sqlite3Fts3SegReaderCursor(
114033 p, FTS3_SEGCURSOR_ALL, zTerm, nTerm, isPrefix, 0, pSegcsr);
114034
114035 for(i=0; rc==SQLITE_OK && i<pSegcsr->nSegment; i++){
114036 rc = sqlite3Fts3SegReaderCost(pCsr, pSegcsr->apSegment[i], &nCost);
114037 }
114038 pSegcsr->nCost = nCost;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
114039 }
114040
114041 *ppSegcsr = pSegcsr;
114042 return rc;
114043 }
114044
114045 static void fts3SegReaderCursorFree(Fts3SegReaderCursor *pSegcsr){
114046 sqlite3Fts3SegReaderFinish(pSegcsr);
114047 sqlite3_free(pSegcsr);
114048 }
114049
114050 /*
@@ -114065,11 +114286,11 @@
114065 int isReqPos, /* True to include position lists in output */
114066 int *pnOut, /* OUT: Size of buffer at *ppOut */
114067 char **ppOut /* OUT: Malloced result buffer */
114068 ){
114069 int rc; /* Return code */
114070 Fts3SegReaderCursor *pSegcsr; /* Seg-reader cursor for this term */
114071 TermSelect tsc; /* Context object for fts3TermSelectCb() */
114072 Fts3SegFilter filter; /* Segment term filter configuration */
114073
114074 pSegcsr = pTok->pSegcsr;
114075 memset(&tsc, 0, sizeof(TermSelect));
@@ -114091,11 +114312,11 @@
114091 pSegcsr->zTerm, pSegcsr->nTerm, pSegcsr->aDoclist, pSegcsr->nDoclist
114092 );
114093 }
114094
114095 if( rc==SQLITE_OK ){
114096 rc = fts3TermSelectMerge(&tsc);
114097 }
114098 if( rc==SQLITE_OK ){
114099 *ppOut = tsc.aaOutput[0];
114100 *pnOut = tsc.anOutput[0];
114101 }else{
@@ -114141,664 +114362,10 @@
114141 }
114142
114143 return nDoc;
114144 }
114145
114146 /*
114147 ** Call sqlite3Fts3DeferToken() for each token in the expression pExpr.
114148 */
114149 static int fts3DeferExpression(Fts3Cursor *pCsr, Fts3Expr *pExpr){
114150 int rc = SQLITE_OK;
114151 if( pExpr ){
114152 rc = fts3DeferExpression(pCsr, pExpr->pLeft);
114153 if( rc==SQLITE_OK ){
114154 rc = fts3DeferExpression(pCsr, pExpr->pRight);
114155 }
114156 if( pExpr->eType==FTSQUERY_PHRASE ){
114157 int iCol = pExpr->pPhrase->iColumn;
114158 int i;
114159 for(i=0; rc==SQLITE_OK && i<pExpr->pPhrase->nToken; i++){
114160 Fts3PhraseToken *pToken = &pExpr->pPhrase->aToken[i];
114161 if( pToken->pDeferred==0 ){
114162 rc = sqlite3Fts3DeferToken(pCsr, pToken, iCol);
114163 }
114164 }
114165 }
114166 }
114167 return rc;
114168 }
114169
114170 /*
114171 ** This function removes the position information from a doclist. When
114172 ** called, buffer aList (size *pnList bytes) contains a doclist that includes
114173 ** position information. This function removes the position information so
114174 ** that aList contains only docids, and adjusts *pnList to reflect the new
114175 ** (possibly reduced) size of the doclist.
114176 */
114177 static void fts3DoclistStripPositions(
114178 char *aList, /* IN/OUT: Buffer containing doclist */
114179 int *pnList /* IN/OUT: Size of doclist in bytes */
114180 ){
114181 if( aList ){
114182 char *aEnd = &aList[*pnList]; /* Pointer to one byte after EOF */
114183 char *p = aList; /* Input cursor */
114184 char *pOut = aList; /* Output cursor */
114185
114186 while( p<aEnd ){
114187 sqlite3_int64 delta;
114188 p += sqlite3Fts3GetVarint(p, &delta);
114189 fts3PoslistCopy(0, &p);
114190 pOut += sqlite3Fts3PutVarint(pOut, delta);
114191 }
114192
114193 *pnList = (int)(pOut - aList);
114194 }
114195 }
114196
114197 /*
114198 ** Return a DocList corresponding to the phrase *pPhrase.
114199 **
114200 ** If this function returns SQLITE_OK, but *pnOut is set to a negative value,
114201 ** then no tokens in the phrase were looked up in the full-text index. This
114202 ** is only possible when this function is called from within xFilter(). The
114203 ** caller should assume that all documents match the phrase. The actual
114204 ** filtering will take place in xNext().
114205 */
114206 static int fts3PhraseSelect(
114207 Fts3Cursor *pCsr, /* Virtual table cursor handle */
114208 Fts3Phrase *pPhrase, /* Phrase to return a doclist for */
114209 int isReqPos, /* True if output should contain positions */
114210 char **paOut, /* OUT: Pointer to malloc'd result buffer */
114211 int *pnOut /* OUT: Size of buffer at *paOut */
114212 ){
114213 char *pOut = 0;
114214 int nOut = 0;
114215 int rc = SQLITE_OK;
114216 int ii;
114217 int iCol = pPhrase->iColumn;
114218 int isTermPos = (pPhrase->nToken>1 || isReqPos);
114219 Fts3Table *p = (Fts3Table *)pCsr->base.pVtab;
114220 int isFirst = 1;
114221
114222 int iPrevTok = 0;
114223 int nDoc = 0;
114224
114225 /* If this is an xFilter() evaluation, create a segment-reader for each
114226 ** phrase token. Or, if this is an xNext() or snippet/offsets/matchinfo
114227 ** evaluation, only create segment-readers if there are no Fts3DeferredToken
114228 ** objects attached to the phrase-tokens.
114229 */
114230 for(ii=0; ii<pPhrase->nToken; ii++){
114231 Fts3PhraseToken *pTok = &pPhrase->aToken[ii];
114232 if( pTok->pSegcsr==0 ){
114233 if( (pCsr->eEvalmode==FTS3_EVAL_FILTER)
114234 || (pCsr->eEvalmode==FTS3_EVAL_NEXT && pCsr->pDeferred==0)
114235 || (pCsr->eEvalmode==FTS3_EVAL_MATCHINFO && pTok->bFulltext)
114236 ){
114237 rc = fts3TermSegReaderCursor(
114238 pCsr, pTok->z, pTok->n, pTok->isPrefix, &pTok->pSegcsr
114239 );
114240 if( rc!=SQLITE_OK ) return rc;
114241 }
114242 }
114243 }
114244
114245 for(ii=0; ii<pPhrase->nToken; ii++){
114246 Fts3PhraseToken *pTok; /* Token to find doclist for */
114247 int iTok = 0; /* The token being queried this iteration */
114248 char *pList = 0; /* Pointer to token doclist */
114249 int nList = 0; /* Size of buffer at pList */
114250
114251 /* Select a token to process. If this is an xFilter() call, then tokens
114252 ** are processed in order from least to most costly. Otherwise, tokens
114253 ** are processed in the order in which they occur in the phrase.
114254 */
114255 if( pCsr->eEvalmode==FTS3_EVAL_MATCHINFO ){
114256 assert( isReqPos );
114257 iTok = ii;
114258 pTok = &pPhrase->aToken[iTok];
114259 if( pTok->bFulltext==0 ) continue;
114260 }else if( pCsr->eEvalmode==FTS3_EVAL_NEXT || isReqPos ){
114261 iTok = ii;
114262 pTok = &pPhrase->aToken[iTok];
114263 }else{
114264 int nMinCost = 0x7FFFFFFF;
114265 int jj;
114266
114267 /* Find the remaining token with the lowest cost. */
114268 for(jj=0; jj<pPhrase->nToken; jj++){
114269 Fts3SegReaderCursor *pSegcsr = pPhrase->aToken[jj].pSegcsr;
114270 if( pSegcsr && pSegcsr->nCost<nMinCost ){
114271 iTok = jj;
114272 nMinCost = pSegcsr->nCost;
114273 }
114274 }
114275 pTok = &pPhrase->aToken[iTok];
114276
114277 /* This branch is taken if it is determined that loading the doclist
114278 ** for the next token would require more IO than loading all documents
114279 ** currently identified by doclist pOut/nOut. No further doclists will
114280 ** be loaded from the full-text index for this phrase.
114281 */
114282 if( nMinCost>nDoc && ii>0 ){
114283 rc = fts3DeferExpression(pCsr, pCsr->pExpr);
114284 break;
114285 }
114286 }
114287
114288 if( pCsr->eEvalmode==FTS3_EVAL_NEXT && pTok->pDeferred ){
114289 rc = fts3DeferredTermSelect(pTok->pDeferred, isTermPos, &nList, &pList);
114290 }else{
114291 if( pTok->pSegcsr ){
114292 rc = fts3TermSelect(p, pTok, iCol, isTermPos, &nList, &pList);
114293 }
114294 pTok->bFulltext = 1;
114295 }
114296 assert( rc!=SQLITE_OK || pCsr->eEvalmode || pTok->pSegcsr==0 );
114297 if( rc!=SQLITE_OK ) break;
114298
114299 if( isFirst ){
114300 pOut = pList;
114301 nOut = nList;
114302 if( pCsr->eEvalmode==FTS3_EVAL_FILTER && pPhrase->nToken>1 ){
114303 nDoc = fts3DoclistCountDocids(1, pOut, nOut);
114304 }
114305 isFirst = 0;
114306 iPrevTok = iTok;
114307 }else{
114308 /* Merge the new term list and the current output. */
114309 char *aLeft, *aRight;
114310 int nLeft, nRight;
114311 int nDist;
114312 int mt;
114313
114314 /* If this is the final token of the phrase, and positions were not
114315 ** requested by the caller, use MERGE_PHRASE instead of POS_PHRASE.
114316 ** This drops the position information from the output list.
114317 */
114318 mt = MERGE_POS_PHRASE;
114319 if( ii==pPhrase->nToken-1 && !isReqPos ) mt = MERGE_PHRASE;
114320
114321 assert( iPrevTok!=iTok );
114322 if( iPrevTok<iTok ){
114323 aLeft = pOut;
114324 nLeft = nOut;
114325 aRight = pList;
114326 nRight = nList;
114327 nDist = iTok-iPrevTok;
114328 iPrevTok = iTok;
114329 }else{
114330 aRight = pOut;
114331 nRight = nOut;
114332 aLeft = pList;
114333 nLeft = nList;
114334 nDist = iPrevTok-iTok;
114335 }
114336 pOut = aRight;
114337 fts3DoclistMerge(
114338 mt, nDist, 0, pOut, &nOut, aLeft, nLeft, aRight, nRight, &nDoc
114339 );
114340 sqlite3_free(aLeft);
114341 }
114342 assert( nOut==0 || pOut!=0 );
114343 }
114344
114345 if( rc==SQLITE_OK ){
114346 if( ii!=pPhrase->nToken ){
114347 assert( pCsr->eEvalmode==FTS3_EVAL_FILTER && isReqPos==0 );
114348 fts3DoclistStripPositions(pOut, &nOut);
114349 }
114350 *paOut = pOut;
114351 *pnOut = nOut;
114352 }else{
114353 sqlite3_free(pOut);
114354 }
114355 return rc;
114356 }
114357
114358 /*
114359 ** This function merges two doclists according to the requirements of a
114360 ** NEAR operator.
114361 **
114362 ** Both input doclists must include position information. The output doclist
114363 ** includes position information if the first argument to this function
114364 ** is MERGE_POS_NEAR, or does not if it is MERGE_NEAR.
114365 */
114366 static int fts3NearMerge(
114367 int mergetype, /* MERGE_POS_NEAR or MERGE_NEAR */
114368 int nNear, /* Parameter to NEAR operator */
114369 int nTokenLeft, /* Number of tokens in LHS phrase arg */
114370 char *aLeft, /* Doclist for LHS (incl. positions) */
114371 int nLeft, /* Size of LHS doclist in bytes */
114372 int nTokenRight, /* As nTokenLeft */
114373 char *aRight, /* As aLeft */
114374 int nRight, /* As nRight */
114375 char **paOut, /* OUT: Results of merge (malloced) */
114376 int *pnOut /* OUT: Sized of output buffer */
114377 ){
114378 char *aOut; /* Buffer to write output doclist to */
114379 int rc; /* Return code */
114380
114381 assert( mergetype==MERGE_POS_NEAR || MERGE_NEAR );
114382
114383 aOut = sqlite3_malloc(nLeft+nRight+1);
114384 if( aOut==0 ){
114385 rc = SQLITE_NOMEM;
114386 }else{
114387 rc = fts3DoclistMerge(mergetype, nNear+nTokenRight, nNear+nTokenLeft,
114388 aOut, pnOut, aLeft, nLeft, aRight, nRight, 0
114389 );
114390 if( rc!=SQLITE_OK ){
114391 sqlite3_free(aOut);
114392 aOut = 0;
114393 }
114394 }
114395
114396 *paOut = aOut;
114397 return rc;
114398 }
114399
114400 /*
114401 ** This function is used as part of the processing for the snippet() and
114402 ** offsets() functions.
114403 **
114404 ** Both pLeft and pRight are expression nodes of type FTSQUERY_PHRASE. Both
114405 ** have their respective doclists (including position information) loaded
114406 ** in Fts3Expr.aDoclist/nDoclist. This function removes all entries from
114407 ** each doclist that are not within nNear tokens of a corresponding entry
114408 ** in the other doclist.
114409 */
114410 SQLITE_PRIVATE int sqlite3Fts3ExprNearTrim(Fts3Expr *pLeft, Fts3Expr *pRight, int nNear){
114411 int rc; /* Return code */
114412
114413 assert( pLeft->eType==FTSQUERY_PHRASE );
114414 assert( pRight->eType==FTSQUERY_PHRASE );
114415 assert( pLeft->isLoaded && pRight->isLoaded );
114416
114417 if( pLeft->aDoclist==0 || pRight->aDoclist==0 ){
114418 sqlite3_free(pLeft->aDoclist);
114419 sqlite3_free(pRight->aDoclist);
114420 pRight->aDoclist = 0;
114421 pLeft->aDoclist = 0;
114422 rc = SQLITE_OK;
114423 }else{
114424 char *aOut; /* Buffer in which to assemble new doclist */
114425 int nOut; /* Size of buffer aOut in bytes */
114426
114427 rc = fts3NearMerge(MERGE_POS_NEAR, nNear,
114428 pLeft->pPhrase->nToken, pLeft->aDoclist, pLeft->nDoclist,
114429 pRight->pPhrase->nToken, pRight->aDoclist, pRight->nDoclist,
114430 &aOut, &nOut
114431 );
114432 if( rc!=SQLITE_OK ) return rc;
114433 sqlite3_free(pRight->aDoclist);
114434 pRight->aDoclist = aOut;
114435 pRight->nDoclist = nOut;
114436
114437 rc = fts3NearMerge(MERGE_POS_NEAR, nNear,
114438 pRight->pPhrase->nToken, pRight->aDoclist, pRight->nDoclist,
114439 pLeft->pPhrase->nToken, pLeft->aDoclist, pLeft->nDoclist,
114440 &aOut, &nOut
114441 );
114442 sqlite3_free(pLeft->aDoclist);
114443 pLeft->aDoclist = aOut;
114444 pLeft->nDoclist = nOut;
114445 }
114446 return rc;
114447 }
114448
114449
114450 /*
114451 ** Allocate an Fts3SegReaderArray for each token in the expression pExpr.
114452 ** The allocated objects are stored in the Fts3PhraseToken.pArray member
114453 ** variables of each token structure.
114454 */
114455 static int fts3ExprAllocateSegReaders(
114456 Fts3Cursor *pCsr, /* FTS3 table */
114457 Fts3Expr *pExpr, /* Expression to create seg-readers for */
114458 int *pnExpr /* OUT: Number of AND'd expressions */
114459 ){
114460 int rc = SQLITE_OK; /* Return code */
114461
114462 assert( pCsr->eEvalmode==FTS3_EVAL_FILTER );
114463 if( pnExpr && pExpr->eType!=FTSQUERY_AND ){
114464 (*pnExpr)++;
114465 pnExpr = 0;
114466 }
114467
114468 if( pExpr->eType==FTSQUERY_PHRASE ){
114469 Fts3Phrase *pPhrase = pExpr->pPhrase;
114470 int ii;
114471
114472 for(ii=0; rc==SQLITE_OK && ii<pPhrase->nToken; ii++){
114473 Fts3PhraseToken *pTok = &pPhrase->aToken[ii];
114474 if( pTok->pSegcsr==0 ){
114475 rc = fts3TermSegReaderCursor(
114476 pCsr, pTok->z, pTok->n, pTok->isPrefix, &pTok->pSegcsr
114477 );
114478 }
114479 }
114480 }else{
114481 rc = fts3ExprAllocateSegReaders(pCsr, pExpr->pLeft, pnExpr);
114482 if( rc==SQLITE_OK ){
114483 rc = fts3ExprAllocateSegReaders(pCsr, pExpr->pRight, pnExpr);
114484 }
114485 }
114486 return rc;
114487 }
114488
114489 /*
114490 ** Free the Fts3SegReaderArray objects associated with each token in the
114491 ** expression pExpr. In other words, this function frees the resources
114492 ** allocated by fts3ExprAllocateSegReaders().
114493 */
114494 static void fts3ExprFreeSegReaders(Fts3Expr *pExpr){
114495 if( pExpr ){
114496 Fts3Phrase *pPhrase = pExpr->pPhrase;
114497 if( pPhrase ){
114498 int kk;
114499 for(kk=0; kk<pPhrase->nToken; kk++){
114500 fts3SegReaderCursorFree(pPhrase->aToken[kk].pSegcsr);
114501 pPhrase->aToken[kk].pSegcsr = 0;
114502 }
114503 }
114504 fts3ExprFreeSegReaders(pExpr->pLeft);
114505 fts3ExprFreeSegReaders(pExpr->pRight);
114506 }
114507 }
114508
114509 /*
114510 ** Return the sum of the costs of all tokens in the expression pExpr. This
114511 ** function must be called after Fts3SegReaderArrays have been allocated
114512 ** for all tokens using fts3ExprAllocateSegReaders().
114513 */
114514 static int fts3ExprCost(Fts3Expr *pExpr){
114515 int nCost; /* Return value */
114516 if( pExpr->eType==FTSQUERY_PHRASE ){
114517 Fts3Phrase *pPhrase = pExpr->pPhrase;
114518 int ii;
114519 nCost = 0;
114520 for(ii=0; ii<pPhrase->nToken; ii++){
114521 Fts3SegReaderCursor *pSegcsr = pPhrase->aToken[ii].pSegcsr;
114522 if( pSegcsr ) nCost += pSegcsr->nCost;
114523 }
114524 }else{
114525 nCost = fts3ExprCost(pExpr->pLeft) + fts3ExprCost(pExpr->pRight);
114526 }
114527 return nCost;
114528 }
114529
114530 /*
114531 ** The following is a helper function (and type) for fts3EvalExpr(). It
114532 ** must be called after Fts3SegReaders have been allocated for every token
114533 ** in the expression. See the context it is called from in fts3EvalExpr()
114534 ** for further explanation.
114535 */
114536 typedef struct ExprAndCost ExprAndCost;
114537 struct ExprAndCost {
114538 Fts3Expr *pExpr;
114539 int nCost;
114540 };
114541 static void fts3ExprAssignCosts(
114542 Fts3Expr *pExpr, /* Expression to create seg-readers for */
114543 ExprAndCost **ppExprCost /* OUT: Write to *ppExprCost */
114544 ){
114545 if( pExpr->eType==FTSQUERY_AND ){
114546 fts3ExprAssignCosts(pExpr->pLeft, ppExprCost);
114547 fts3ExprAssignCosts(pExpr->pRight, ppExprCost);
114548 }else{
114549 (*ppExprCost)->pExpr = pExpr;
114550 (*ppExprCost)->nCost = fts3ExprCost(pExpr);
114551 (*ppExprCost)++;
114552 }
114553 }
114554
114555 /*
114556 ** Evaluate the full-text expression pExpr against FTS3 table pTab. Store
114557 ** the resulting doclist in *paOut and *pnOut. This routine mallocs for
114558 ** the space needed to store the output. The caller is responsible for
114559 ** freeing the space when it has finished.
114560 **
114561 ** This function is called in two distinct contexts:
114562 **
114563 ** * From within the virtual table xFilter() method. In this case, the
114564 ** output doclist contains entries for all rows in the table, based on
114565 ** data read from the full-text index.
114566 **
114567 ** In this case, if the query expression contains one or more tokens that
114568 ** are very common, then the returned doclist may contain a superset of
114569 ** the documents that actually match the expression.
114570 **
114571 ** * From within the virtual table xNext() method. This call is only made
114572 ** if the call from within xFilter() found that there were very common
114573 ** tokens in the query expression and did return a superset of the
114574 ** matching documents. In this case the returned doclist contains only
114575 ** entries that correspond to the current row of the table. Instead of
114576 ** reading the data for each token from the full-text index, the data is
114577 ** already available in-memory in the Fts3PhraseToken.pDeferred structures.
114578 ** See fts3EvalDeferred() for how it gets there.
114579 **
114580 ** In the first case above, Fts3Cursor.doDeferred==0. In the second (if it is
114581 ** required) Fts3Cursor.doDeferred==1.
114582 **
114583 ** If the SQLite invokes the snippet(), offsets() or matchinfo() function
114584 ** as part of a SELECT on an FTS3 table, this function is called on each
114585 ** individual phrase expression in the query. If there were very common tokens
114586 ** found in the xFilter() call, then this function is called once for phrase
114587 ** for each row visited, and the returned doclist contains entries for the
114588 ** current row only. Otherwise, if there were no very common tokens, then this
114589 ** function is called once only for each phrase in the query and the returned
114590 ** doclist contains entries for all rows of the table.
114591 **
114592 ** Fts3Cursor.doDeferred==1 when this function is called on phrases as a
114593 ** result of a snippet(), offsets() or matchinfo() invocation.
114594 */
114595 static int fts3EvalExpr(
114596 Fts3Cursor *p, /* Virtual table cursor handle */
114597 Fts3Expr *pExpr, /* Parsed fts3 expression */
114598 char **paOut, /* OUT: Pointer to malloc'd result buffer */
114599 int *pnOut, /* OUT: Size of buffer at *paOut */
114600 int isReqPos /* Require positions in output buffer */
114601 ){
114602 int rc = SQLITE_OK; /* Return code */
114603
114604 /* Zero the output parameters. */
114605 *paOut = 0;
114606 *pnOut = 0;
114607
114608 if( pExpr ){
114609 assert( pExpr->eType==FTSQUERY_NEAR || pExpr->eType==FTSQUERY_OR
114610 || pExpr->eType==FTSQUERY_AND || pExpr->eType==FTSQUERY_NOT
114611 || pExpr->eType==FTSQUERY_PHRASE
114612 );
114613 assert( pExpr->eType==FTSQUERY_PHRASE || isReqPos==0 );
114614
114615 if( pExpr->eType==FTSQUERY_PHRASE ){
114616 rc = fts3PhraseSelect(p, pExpr->pPhrase,
114617 isReqPos || (pExpr->pParent && pExpr->pParent->eType==FTSQUERY_NEAR),
114618 paOut, pnOut
114619 );
114620 fts3ExprFreeSegReaders(pExpr);
114621 }else if( p->eEvalmode==FTS3_EVAL_FILTER && pExpr->eType==FTSQUERY_AND ){
114622 ExprAndCost *aExpr = 0; /* Array of AND'd expressions and costs */
114623 int nExpr = 0; /* Size of aExpr[] */
114624 char *aRet = 0; /* Doclist to return to caller */
114625 int nRet = 0; /* Length of aRet[] in bytes */
114626 int nDoc = 0x7FFFFFFF;
114627
114628 assert( !isReqPos );
114629
114630 rc = fts3ExprAllocateSegReaders(p, pExpr, &nExpr);
114631 if( rc==SQLITE_OK ){
114632 assert( nExpr>1 );
114633 aExpr = sqlite3_malloc(sizeof(ExprAndCost) * nExpr);
114634 if( !aExpr ) rc = SQLITE_NOMEM;
114635 }
114636 if( rc==SQLITE_OK ){
114637 int ii; /* Used to iterate through expressions */
114638
114639 fts3ExprAssignCosts(pExpr, &aExpr);
114640 aExpr -= nExpr;
114641 for(ii=0; ii<nExpr; ii++){
114642 char *aNew;
114643 int nNew;
114644 int jj;
114645 ExprAndCost *pBest = 0;
114646
114647 for(jj=0; jj<nExpr; jj++){
114648 ExprAndCost *pCand = &aExpr[jj];
114649 if( pCand->pExpr && (pBest==0 || pCand->nCost<pBest->nCost) ){
114650 pBest = pCand;
114651 }
114652 }
114653
114654 if( pBest->nCost>nDoc ){
114655 rc = fts3DeferExpression(p, p->pExpr);
114656 break;
114657 }else{
114658 rc = fts3EvalExpr(p, pBest->pExpr, &aNew, &nNew, 0);
114659 if( rc!=SQLITE_OK ) break;
114660 pBest->pExpr = 0;
114661 if( ii==0 ){
114662 aRet = aNew;
114663 nRet = nNew;
114664 nDoc = fts3DoclistCountDocids(0, aRet, nRet);
114665 }else{
114666 fts3DoclistMerge(
114667 MERGE_AND, 0, 0, aRet, &nRet, aRet, nRet, aNew, nNew, &nDoc
114668 );
114669 sqlite3_free(aNew);
114670 }
114671 }
114672 }
114673 }
114674
114675 if( rc==SQLITE_OK ){
114676 *paOut = aRet;
114677 *pnOut = nRet;
114678 }else{
114679 assert( *paOut==0 );
114680 sqlite3_free(aRet);
114681 }
114682 sqlite3_free(aExpr);
114683 fts3ExprFreeSegReaders(pExpr);
114684
114685 }else{
114686 char *aLeft;
114687 char *aRight;
114688 int nLeft;
114689 int nRight;
114690
114691 assert( pExpr->eType==FTSQUERY_NEAR
114692 || pExpr->eType==FTSQUERY_OR
114693 || pExpr->eType==FTSQUERY_NOT
114694 || (pExpr->eType==FTSQUERY_AND && p->eEvalmode==FTS3_EVAL_NEXT)
114695 );
114696
114697 if( 0==(rc = fts3EvalExpr(p, pExpr->pRight, &aRight, &nRight, isReqPos))
114698 && 0==(rc = fts3EvalExpr(p, pExpr->pLeft, &aLeft, &nLeft, isReqPos))
114699 ){
114700 switch( pExpr->eType ){
114701 case FTSQUERY_NEAR: {
114702 Fts3Expr *pLeft;
114703 Fts3Expr *pRight;
114704 int mergetype = MERGE_NEAR;
114705 if( pExpr->pParent && pExpr->pParent->eType==FTSQUERY_NEAR ){
114706 mergetype = MERGE_POS_NEAR;
114707 }
114708 pLeft = pExpr->pLeft;
114709 while( pLeft->eType==FTSQUERY_NEAR ){
114710 pLeft=pLeft->pRight;
114711 }
114712 pRight = pExpr->pRight;
114713 assert( pRight->eType==FTSQUERY_PHRASE );
114714 assert( pLeft->eType==FTSQUERY_PHRASE );
114715
114716 rc = fts3NearMerge(mergetype, pExpr->nNear,
114717 pLeft->pPhrase->nToken, aLeft, nLeft,
114718 pRight->pPhrase->nToken, aRight, nRight,
114719 paOut, pnOut
114720 );
114721 sqlite3_free(aLeft);
114722 break;
114723 }
114724
114725 case FTSQUERY_OR: {
114726 /* Allocate a buffer for the output. The maximum size is the
114727 ** sum of the sizes of the two input buffers. The +1 term is
114728 ** so that a buffer of zero bytes is never allocated - this can
114729 ** cause fts3DoclistMerge() to incorrectly return SQLITE_NOMEM.
114730 */
114731 char *aBuffer = sqlite3_malloc(nRight+nLeft+1);
114732 rc = fts3DoclistMerge(MERGE_OR, 0, 0, aBuffer, pnOut,
114733 aLeft, nLeft, aRight, nRight, 0
114734 );
114735 *paOut = aBuffer;
114736 sqlite3_free(aLeft);
114737 break;
114738 }
114739
114740 default: {
114741 assert( FTSQUERY_NOT==MERGE_NOT && FTSQUERY_AND==MERGE_AND );
114742 fts3DoclistMerge(pExpr->eType, 0, 0, aLeft, pnOut,
114743 aLeft, nLeft, aRight, nRight, 0
114744 );
114745 *paOut = aLeft;
114746 break;
114747 }
114748 }
114749 }
114750 sqlite3_free(aRight);
114751 }
114752 }
114753
114754 assert( rc==SQLITE_OK || *paOut==0 );
114755 return rc;
114756 }
114757
114758 /*
114759 ** This function is called from within xNext() for each row visited by
114760 ** an FTS3 query. If evaluating the FTS3 query expression within xFilter()
114761 ** was able to determine the exact set of matching rows, this function sets
114762 ** *pbRes to true and returns SQLITE_IO immediately.
114763 **
114764 ** Otherwise, if evaluating the query expression within xFilter() returned a
114765 ** superset of the matching documents instead of an exact set (this happens
114766 ** when the query includes very common tokens and it is deemed too expensive to
114767 ** load their doclists from disk), this function tests if the current row
114768 ** really does match the FTS3 query.
114769 **
114770 ** If an error occurs, an SQLite error code is returned. Otherwise, SQLITE_OK
114771 ** is returned and *pbRes is set to true if the current row matches the
114772 ** FTS3 query (and should be included in the results returned to SQLite), or
114773 ** false otherwise.
114774 */
114775 static int fts3EvalDeferred(
114776 Fts3Cursor *pCsr, /* FTS3 cursor pointing at row to test */
114777 int *pbRes /* OUT: Set to true if row is a match */
114778 ){
114779 int rc = SQLITE_OK;
114780 if( pCsr->pDeferred==0 ){
114781 *pbRes = 1;
114782 }else{
114783 rc = fts3CursorSeek(0, pCsr);
114784 if( rc==SQLITE_OK ){
114785 sqlite3Fts3FreeDeferredDoclists(pCsr);
114786 rc = sqlite3Fts3CacheDeferredDoclists(pCsr);
114787 }
114788 if( rc==SQLITE_OK ){
114789 char *a = 0;
114790 int n = 0;
114791 rc = fts3EvalExpr(pCsr, pCsr->pExpr, &a, &n, 0);
114792 assert( n>=0 );
114793 *pbRes = (n>0);
114794 sqlite3_free(a);
114795 }
114796 }
114797 return rc;
114798 }
114799
114800 /*
114801 ** Advance the cursor to the next row in the %_content table that
114802 ** matches the search criteria. For a MATCH search, this will be
114803 ** the next row that matches. For a full-table scan, this will be
114804 ** simply the next row in the %_content table. For a docid lookup,
@@ -114807,43 +114374,24 @@
114807 ** Return SQLITE_OK if nothing goes wrong. SQLITE_OK is returned
114808 ** even if we reach end-of-file. The fts3EofMethod() will be called
114809 ** subsequently to determine whether or not an EOF was hit.
114810 */
114811 static int fts3NextMethod(sqlite3_vtab_cursor *pCursor){
114812 int res;
114813 int rc = SQLITE_OK; /* Return code */
114814 Fts3Cursor *pCsr = (Fts3Cursor *)pCursor;
114815
114816 pCsr->eEvalmode = FTS3_EVAL_NEXT;
114817 do {
114818 if( pCsr->aDoclist==0 ){
114819 if( SQLITE_ROW!=sqlite3_step(pCsr->pStmt) ){
114820 pCsr->isEof = 1;
114821 rc = sqlite3_reset(pCsr->pStmt);
114822 break;
114823 }
114824 pCsr->iPrevId = sqlite3_column_int64(pCsr->pStmt, 0);
114825 }else{
114826 if( pCsr->desc==0 ){
114827 if( pCsr->pNextId>=&pCsr->aDoclist[pCsr->nDoclist] ){
114828 pCsr->isEof = 1;
114829 break;
114830 }
114831 fts3GetDeltaVarint(&pCsr->pNextId, &pCsr->iPrevId);
114832 }else{
114833 fts3GetReverseDeltaVarint(&pCsr->pNextId,pCsr->aDoclist,&pCsr->iPrevId);
114834 if( pCsr->pNextId<=pCsr->aDoclist ){
114835 pCsr->isEof = 1;
114836 break;
114837 }
114838 }
114839 sqlite3_reset(pCsr->pStmt);
114840 pCsr->isRequireSeek = 1;
114841 pCsr->isMatchinfoNeeded = 1;
114842 }
114843 }while( SQLITE_OK==(rc = fts3EvalDeferred(pCsr, &res)) && res==0 );
114844
114845 return rc;
114846 }
114847
114848 /*
114849 ** This is the xFilter interface for the virtual table. See
@@ -114866,15 +114414,11 @@
114866 int idxNum, /* Strategy index */
114867 const char *idxStr, /* Unused */
114868 int nVal, /* Number of elements in apVal */
114869 sqlite3_value **apVal /* Arguments for the indexing scheme */
114870 ){
114871 const char *azSql[] = {
114872 "SELECT %s FROM %Q.'%q_content' AS x WHERE docid = ?", /* non-full-scan */
114873 "SELECT %s FROM %Q.'%q_content' AS x ORDER BY docid %s", /* full-scan */
114874 };
114875 int rc; /* Return code */
114876 char *zSql; /* SQL statement used to access %_content */
114877 Fts3Table *p = (Fts3Table *)pCursor->pVtab;
114878 Fts3Cursor *pCsr = (Fts3Cursor *)pCursor;
114879
114880 UNUSED_PARAMETER(idxStr);
@@ -114889,10 +114433,17 @@
114889 sqlite3_finalize(pCsr->pStmt);
114890 sqlite3_free(pCsr->aDoclist);
114891 sqlite3Fts3ExprFree(pCsr->pExpr);
114892 memset(&pCursor[1], 0, sizeof(Fts3Cursor)-sizeof(sqlite3_vtab_cursor));
114893
 
 
 
 
 
 
 
114894 if( idxNum!=FTS3_DOCID_SEARCH && idxNum!=FTS3_FULLSCAN_SEARCH ){
114895 int iCol = idxNum-FTS3_FULLTEXT_SEARCH;
114896 const char *zQuery = (const char *)sqlite3_value_text(apVal[0]);
114897
114898 if( zQuery==0 && sqlite3_value_type(apVal[0])!=SQLITE_NULL ){
@@ -114902,20 +114453,21 @@
114902 rc = sqlite3Fts3ExprParse(p->pTokenizer, p->azColumn, p->nColumn,
114903 iCol, zQuery, -1, &pCsr->pExpr
114904 );
114905 if( rc!=SQLITE_OK ){
114906 if( rc==SQLITE_ERROR ){
114907 p->base.zErrMsg = sqlite3_mprintf("malformed MATCH expression: [%s]",
114908 zQuery);
114909 }
114910 return rc;
114911 }
114912
114913 rc = sqlite3Fts3ReadLock(p);
114914 if( rc!=SQLITE_OK ) return rc;
114915
114916 rc = fts3EvalExpr(pCsr, pCsr->pExpr, &pCsr->aDoclist, &pCsr->nDoclist, 0);
 
114917 sqlite3Fts3SegmentsClose(p);
114918 if( rc!=SQLITE_OK ) return rc;
114919 pCsr->pNextId = pCsr->aDoclist;
114920 pCsr->iPrevId = 0;
114921 }
@@ -114923,41 +114475,28 @@
114923 /* Compile a SELECT statement for this cursor. For a full-table-scan, the
114924 ** statement loops through all rows of the %_content table. For a
114925 ** full-text query or docid lookup, the statement retrieves a single
114926 ** row by docid.
114927 */
114928 zSql = (char *)azSql[idxNum==FTS3_FULLSCAN_SEARCH];
114929 zSql = sqlite3_mprintf(
114930 zSql, p->zReadExprlist, p->zDb, p->zName, (idxStr ? idxStr : "ASC")
114931 );
114932 if( !zSql ){
114933 rc = SQLITE_NOMEM;
114934 }else{
114935 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pCsr->pStmt, 0);
114936 sqlite3_free(zSql);
114937 }
114938 if( rc==SQLITE_OK && idxNum==FTS3_DOCID_SEARCH ){
 
 
 
 
 
114939 rc = sqlite3_bind_value(pCsr->pStmt, 1, apVal[0]);
114940 }
114941 pCsr->eSearch = (i16)idxNum;
114942
114943 assert( pCsr->desc==0 );
114944 if( rc!=SQLITE_OK ) return rc;
114945 if( rc==SQLITE_OK && pCsr->nDoclist>0 && idxStr && idxStr[0]=='D' ){
114946 sqlite3_int64 iDocid = 0;
114947 char *csr = pCsr->aDoclist;
114948 while( csr<&pCsr->aDoclist[pCsr->nDoclist] ){
114949 fts3GetDeltaVarint(&csr, &iDocid);
114950 }
114951 pCsr->pNextId = csr;
114952 pCsr->iPrevId = iDocid;
114953 pCsr->desc = 1;
114954 pCsr->isRequireSeek = 1;
114955 pCsr->isMatchinfoNeeded = 1;
114956 pCsr->eEvalmode = FTS3_EVAL_NEXT;
114957 return SQLITE_OK;
114958 }
114959 return fts3NextMethod(pCursor);
114960 }
114961
114962 /*
114963 ** This is the xEof method of the virtual table. SQLite calls this
@@ -114973,20 +114512,11 @@
114973 ** exposes %_content.docid as the rowid for the virtual table. The
114974 ** rowid should be written to *pRowid.
114975 */
114976 static int fts3RowidMethod(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){
114977 Fts3Cursor *pCsr = (Fts3Cursor *) pCursor;
114978 if( pCsr->aDoclist ){
114979 *pRowid = pCsr->iPrevId;
114980 }else{
114981 /* This branch runs if the query is implemented using a full-table scan
114982 ** (not using the full-text index). In this case grab the rowid from the
114983 ** SELECT statement.
114984 */
114985 assert( pCsr->isRequireSeek==0 );
114986 *pRowid = sqlite3_column_int64(pCsr->pStmt, 0);
114987 }
114988 return SQLITE_OK;
114989 }
114990
114991 /*
114992 ** This is the xColumn method, called by SQLite to request a value from
@@ -114995,11 +114525,11 @@
114995 static int fts3ColumnMethod(
114996 sqlite3_vtab_cursor *pCursor, /* Cursor to retrieve value from */
114997 sqlite3_context *pContext, /* Context for sqlite3_result_xxx() calls */
114998 int iCol /* Index of column to read value from */
114999 ){
115000 int rc; /* Return Code */
115001 Fts3Cursor *pCsr = (Fts3Cursor *) pCursor;
115002 Fts3Table *p = (Fts3Table *)pCursor->pVtab;
115003
115004 /* The column value supplied by SQLite must be in range. */
115005 assert( iCol>=0 && iCol<=p->nColumn+1 );
@@ -115006,25 +114536,24 @@
115006
115007 if( iCol==p->nColumn+1 ){
115008 /* This call is a request for the "docid" column. Since "docid" is an
115009 ** alias for "rowid", use the xRowid() method to obtain the value.
115010 */
115011 sqlite3_int64 iRowid;
115012 rc = fts3RowidMethod(pCursor, &iRowid);
115013 sqlite3_result_int64(pContext, iRowid);
115014 }else if( iCol==p->nColumn ){
115015 /* The extra column whose name is the same as the table.
115016 ** Return a blob which is a pointer to the cursor.
115017 */
115018 sqlite3_result_blob(pContext, &pCsr, sizeof(pCsr), SQLITE_TRANSIENT);
115019 rc = SQLITE_OK;
115020 }else{
115021 rc = fts3CursorSeek(0, pCsr);
115022 if( rc==SQLITE_OK ){
115023 sqlite3_result_value(pContext, sqlite3_column_value(pCsr->pStmt, iCol+1));
115024 }
115025 }
 
 
115026 return rc;
115027 }
115028
115029 /*
115030 ** This function is the implementation of the xUpdate callback used by
@@ -115054,10 +114583,11 @@
115054 ** Implementation of xBegin() method. This is a no-op.
115055 */
115056 static int fts3BeginMethod(sqlite3_vtab *pVtab){
115057 UNUSED_PARAMETER(pVtab);
115058 TESTONLY( Fts3Table *p = (Fts3Table*)pVtab );
 
115059 assert( p->nPendingData==0 );
115060 assert( p->inTransaction!=1 );
115061 TESTONLY( p->inTransaction = 1 );
115062 TESTONLY( p->mxSavepoint = -1; );
115063 return SQLITE_OK;
@@ -115071,10 +114601,11 @@
115071 static int fts3CommitMethod(sqlite3_vtab *pVtab){
115072 UNUSED_PARAMETER(pVtab);
115073 TESTONLY( Fts3Table *p = (Fts3Table*)pVtab );
115074 assert( p->nPendingData==0 );
115075 assert( p->inTransaction!=0 );
 
115076 TESTONLY( p->inTransaction = 0 );
115077 TESTONLY( p->mxSavepoint = -1; );
115078 return SQLITE_OK;
115079 }
115080
@@ -115088,132 +114619,30 @@
115088 assert( p->inTransaction!=0 );
115089 TESTONLY( p->inTransaction = 0 );
115090 TESTONLY( p->mxSavepoint = -1; );
115091 return SQLITE_OK;
115092 }
115093
115094 /*
115095 ** Load the doclist associated with expression pExpr to pExpr->aDoclist.
115096 ** The loaded doclist contains positions as well as the document ids.
115097 ** This is used by the matchinfo(), snippet() and offsets() auxillary
115098 ** functions.
115099 */
115100 SQLITE_PRIVATE int sqlite3Fts3ExprLoadDoclist(Fts3Cursor *pCsr, Fts3Expr *pExpr){
115101 int rc;
115102 assert( pExpr->eType==FTSQUERY_PHRASE && pExpr->pPhrase );
115103 assert( pCsr->eEvalmode==FTS3_EVAL_NEXT );
115104 rc = fts3EvalExpr(pCsr, pExpr, &pExpr->aDoclist, &pExpr->nDoclist, 1);
115105 return rc;
115106 }
115107
115108 SQLITE_PRIVATE int sqlite3Fts3ExprLoadFtDoclist(
115109 Fts3Cursor *pCsr,
115110 Fts3Expr *pExpr,
115111 char **paDoclist,
115112 int *pnDoclist
115113 ){
115114 int rc;
115115 assert( pCsr->eEvalmode==FTS3_EVAL_NEXT );
115116 assert( pExpr->eType==FTSQUERY_PHRASE && pExpr->pPhrase );
115117 pCsr->eEvalmode = FTS3_EVAL_MATCHINFO;
115118 rc = fts3EvalExpr(pCsr, pExpr, paDoclist, pnDoclist, 1);
115119 pCsr->eEvalmode = FTS3_EVAL_NEXT;
115120 return rc;
115121 }
115122
115123
115124 /*
115125 ** When called, *ppPoslist must point to the byte immediately following the
115126 ** end of a position-list. i.e. ( (*ppPoslist)[-1]==POS_END ). This function
115127 ** moves *ppPoslist so that it instead points to the first byte of the
115128 ** same position list.
115129 */
115130 static void fts3ReversePoslist(char *pStart, char **ppPoslist){
115131 char *p = &(*ppPoslist)[-3];
115132 char c = p[1];
 
 
115133 while( p>pStart && (*p & 0x80) | c ){
115134 c = *p--;
115135 }
115136 if( p>pStart ){ p = &p[2]; }
115137 while( *p++&0x80 );
115138 *ppPoslist = p;
115139 }
115140
115141
115142 /*
115143 ** After ExprLoadDoclist() (see above) has been called, this function is
115144 ** used to iterate/search through the position lists that make up the doclist
115145 ** stored in pExpr->aDoclist.
115146 */
115147 SQLITE_PRIVATE char *sqlite3Fts3FindPositions(
115148 Fts3Cursor *pCursor, /* Associate FTS3 cursor */
115149 Fts3Expr *pExpr, /* Access this expressions doclist */
115150 sqlite3_int64 iDocid, /* Docid associated with requested pos-list */
115151 int iCol /* Column of requested pos-list */
115152 ){
115153 assert( pExpr->isLoaded );
115154 if( pExpr->aDoclist ){
115155 char *pEnd = &pExpr->aDoclist[pExpr->nDoclist];
115156 char *pCsr;
115157
115158 if( pExpr->pCurrent==0 ){
115159 if( pCursor->desc==0 ){
115160 pExpr->pCurrent = pExpr->aDoclist;
115161 pExpr->iCurrent = 0;
115162 fts3GetDeltaVarint(&pExpr->pCurrent, &pExpr->iCurrent);
115163 }else{
115164 pCsr = pExpr->aDoclist;
115165 while( pCsr<pEnd ){
115166 fts3GetDeltaVarint(&pCsr, &pExpr->iCurrent);
115167 fts3PoslistCopy(0, &pCsr);
115168 }
115169 fts3ReversePoslist(pExpr->aDoclist, &pCsr);
115170 pExpr->pCurrent = pCsr;
115171 }
115172 }
115173 pCsr = pExpr->pCurrent;
115174 assert( pCsr );
115175
115176 while( (pCursor->desc==0 && pCsr<pEnd)
115177 || (pCursor->desc && pCsr>pExpr->aDoclist)
115178 ){
115179 if( pCursor->desc==0 && pExpr->iCurrent<iDocid ){
115180 fts3PoslistCopy(0, &pCsr);
115181 if( pCsr<pEnd ){
115182 fts3GetDeltaVarint(&pCsr, &pExpr->iCurrent);
115183 }
115184 pExpr->pCurrent = pCsr;
115185 }else if( pCursor->desc && pExpr->iCurrent>iDocid ){
115186 fts3GetReverseDeltaVarint(&pCsr, pExpr->aDoclist, &pExpr->iCurrent);
115187 fts3ReversePoslist(pExpr->aDoclist, &pCsr);
115188 pExpr->pCurrent = pCsr;
115189 }else{
115190 if( pExpr->iCurrent==iDocid ){
115191 int iThis = 0;
115192 if( iCol<0 ){
115193 /* If iCol is negative, return a pointer to the start of the
115194 ** position-list (instead of a pointer to the start of a list
115195 ** of offsets associated with a specific column).
115196 */
115197 return pCsr;
115198 }
115199 while( iThis<iCol ){
115200 fts3ColumnlistCopy(0, &pCsr);
115201 if( *pCsr==0x00 ) return 0;
115202 pCsr++;
115203 pCsr += sqlite3Fts3GetVarint32(pCsr, &iThis);
115204 }
115205 if( iCol==iThis && (*pCsr&0xFE) ) return pCsr;
115206 }
115207 return 0;
115208 }
115209 }
115210 }
115211
115212 return 0;
115213 }
115214
115215 /*
115216 ** Helper function used by the implementation of the overloaded snippet(),
115217 ** offsets() and optimize() SQL functions.
115218 **
115219 ** If the value passed as the third argument is a blob of size
@@ -115441,16 +114870,15 @@
115441 );
115442 return rc;
115443 }
115444
115445 static int fts3SavepointMethod(sqlite3_vtab *pVtab, int iSavepoint){
115446 Fts3Table *p = (Fts3Table*)pVtab;
115447 UNUSED_PARAMETER(iSavepoint);
115448 assert( p->inTransaction );
115449 assert( p->mxSavepoint < iSavepoint );
115450 TESTONLY( p->mxSavepoint = iSavepoint );
115451 return sqlite3Fts3PendingTermsFlush(p);
115452 }
115453 static int fts3ReleaseMethod(sqlite3_vtab *pVtab, int iSavepoint){
115454 TESTONLY( Fts3Table *p = (Fts3Table*)pVtab );
115455 UNUSED_PARAMETER(iSavepoint);
115456 UNUSED_PARAMETER(pVtab);
@@ -115617,10 +115045,1282 @@
115617 SQLITE_EXTENSION_INIT2(pApi)
115618 return sqlite3Fts3Init(db);
115619 }
115620 #endif
115621
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
115622 #endif
115623
115624 /************** End of fts3.c ************************************************/
115625 /************** Begin file fts3_aux.c ****************************************/
115626 /*
@@ -115648,11 +116348,11 @@
115648 Fts3Table *pFts3Tab;
115649 };
115650
115651 struct Fts3auxCursor {
115652 sqlite3_vtab_cursor base; /* Base class used by SQLite core */
115653 Fts3SegReaderCursor csr; /* Must be right after "base" */
115654 Fts3SegFilter filter;
115655 char *zStop;
115656 int nStop; /* Byte-length of string zStop */
115657 int isEof; /* True if cursor is at EOF */
115658 sqlite3_int64 iRowid; /* Current rowid */
@@ -115716,10 +116416,11 @@
115716
115717 p->pFts3Tab = (Fts3Table *)&p[1];
115718 p->pFts3Tab->zDb = (char *)&p->pFts3Tab[1];
115719 p->pFts3Tab->zName = &p->pFts3Tab->zDb[nDb+1];
115720 p->pFts3Tab->db = db;
 
115721
115722 memcpy((char *)p->pFts3Tab->zDb, zDb, nDb);
115723 memcpy((char *)p->pFts3Tab->zName, zFts3, nFts3);
115724 sqlite3Fts3Dequote((char *)p->pFts3Tab->zName);
115725
@@ -115996,11 +116697,11 @@
115996 pCsr->zStop = sqlite3_mprintf("%s", sqlite3_value_text(apVal[iIdx]));
115997 pCsr->nStop = sqlite3_value_bytes(apVal[iIdx]);
115998 if( pCsr->zStop==0 ) return SQLITE_NOMEM;
115999 }
116000
116001 rc = sqlite3Fts3SegReaderCursor(pFts3, FTS3_SEGCURSOR_ALL,
116002 pCsr->filter.zTerm, pCsr->filter.nTerm, 0, isScan, &pCsr->csr
116003 );
116004 if( rc==SQLITE_OK ){
116005 rc = sqlite3Fts3SegReaderStart(pFts3, &pCsr->csr, &pCsr->filter);
116006 }
@@ -116175,16 +116876,25 @@
116175 ** Default span for NEAR operators.
116176 */
116177 #define SQLITE_FTS3_DEFAULT_NEAR_PARAM 10
116178
116179
 
 
 
 
 
 
 
 
116180 typedef struct ParseContext ParseContext;
116181 struct ParseContext {
116182 sqlite3_tokenizer *pTokenizer; /* Tokenizer module */
116183 const char **azCol; /* Array of column names for fts3 table */
116184 int nCol; /* Number of entries in azCol[] */
116185 int iDefaultCol; /* Default column to query */
 
116186 sqlite3_context *pCtx; /* Write error message here */
116187 int nNest; /* Number of nested brackets */
116188 };
116189
116190 /*
@@ -116266,11 +116976,11 @@
116266 if( iEnd<n && z[iEnd]=='*' ){
116267 pRet->pPhrase->aToken[0].isPrefix = 1;
116268 iEnd++;
116269 }
116270 if( !sqlite3_fts3_enable_parentheses && iStart>0 && z[iStart-1]=='-' ){
116271 pRet->pPhrase->isNot = 1;
116272 }
116273 }
116274 nConsumed = iEnd;
116275 }
116276
@@ -116318,71 +117028,86 @@
116318 Fts3Expr *p = 0;
116319 sqlite3_tokenizer_cursor *pCursor = 0;
116320 char *zTemp = 0;
116321 int nTemp = 0;
116322
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
116323 rc = pModule->xOpen(pTokenizer, zInput, nInput, &pCursor);
116324 if( rc==SQLITE_OK ){
116325 int ii;
116326 pCursor->pTokenizer = pTokenizer;
116327 for(ii=0; rc==SQLITE_OK; ii++){
116328 const char *zToken;
116329 int nToken, iBegin, iEnd, iPos;
116330 rc = pModule->xNext(pCursor, &zToken, &nToken, &iBegin, &iEnd, &iPos);
116331 if( rc==SQLITE_OK ){
116332 int nByte = sizeof(Fts3Expr) + sizeof(Fts3Phrase);
116333 p = fts3ReallocOrFree(p, nByte+ii*sizeof(Fts3PhraseToken));
116334 zTemp = fts3ReallocOrFree(zTemp, nTemp + nToken);
116335 if( !p || !zTemp ){
116336 goto no_mem;
116337 }
116338 if( ii==0 ){
116339 memset(p, 0, nByte);
116340 p->pPhrase = (Fts3Phrase *)&p[1];
116341 }
116342 p->pPhrase = (Fts3Phrase *)&p[1];
116343 memset(&p->pPhrase->aToken[ii], 0, sizeof(Fts3PhraseToken));
116344 p->pPhrase->nToken = ii+1;
116345 p->pPhrase->aToken[ii].n = nToken;
116346 memcpy(&zTemp[nTemp], zToken, nToken);
116347 nTemp += nToken;
116348 if( iEnd<nInput && zInput[iEnd]=='*' ){
116349 p->pPhrase->aToken[ii].isPrefix = 1;
116350 }else{
116351 p->pPhrase->aToken[ii].isPrefix = 0;
116352 }
116353 }
116354 }
116355
116356 pModule->xClose(pCursor);
116357 pCursor = 0;
116358 }
116359
116360 if( rc==SQLITE_DONE ){
116361 int jj;
116362 char *zNew = NULL;
116363 int nNew = 0;
116364 int nByte = sizeof(Fts3Expr) + sizeof(Fts3Phrase);
116365 nByte += (p?(p->pPhrase->nToken-1):0) * sizeof(Fts3PhraseToken);
116366 p = fts3ReallocOrFree(p, nByte + nTemp);
116367 if( !p ){
116368 goto no_mem;
116369 }
116370 if( zTemp ){
116371 zNew = &(((char *)p)[nByte]);
116372 memcpy(zNew, zTemp, nTemp);
116373 }else{
116374 memset(p, 0, nByte+nTemp);
116375 }
116376 p->pPhrase = (Fts3Phrase *)&p[1];
 
 
 
 
 
 
 
116377 for(jj=0; jj<p->pPhrase->nToken; jj++){
116378 p->pPhrase->aToken[jj].z = &zNew[nNew];
116379 nNew += p->pPhrase->aToken[jj].n;
116380 }
116381 sqlite3_free(zTemp);
116382 p->eType = FTSQUERY_PHRASE;
116383 p->pPhrase->iColumn = pParse->iDefaultCol;
116384 rc = SQLITE_OK;
116385 }
116386
116387 *ppExpr = p;
116388 return rc;
@@ -116434,10 +117159,12 @@
116434 int rc;
116435 Fts3Expr *pRet = 0;
116436
116437 const char *zInput = z;
116438 int nInput = n;
 
 
116439
116440 /* Skip over any whitespace before checking for a keyword, an open or
116441 ** close bracket, or a quoted string.
116442 */
116443 while( nInput>0 && fts3isspace(*zInput) ){
@@ -116653,11 +117380,11 @@
116653 rc = getNextNode(pParse, zIn, nIn, &p, &nByte);
116654 if( rc==SQLITE_OK ){
116655 int isPhrase;
116656
116657 if( !sqlite3_fts3_enable_parentheses
116658 && p->eType==FTSQUERY_PHRASE && p->pPhrase->isNot
116659 ){
116660 /* Create an implicit NOT operator. */
116661 Fts3Expr *pNot = fts3MallocZero(sizeof(Fts3Expr));
116662 if( !pNot ){
116663 sqlite3Fts3ExprFree(p);
@@ -116671,11 +117398,10 @@
116671 }
116672 pNotBranch = pNot;
116673 p = pPrev;
116674 }else{
116675 int eType = p->eType;
116676 assert( eType!=FTSQUERY_PHRASE || !p->pPhrase->isNot );
116677 isPhrase = (eType==FTSQUERY_PHRASE || p->pLeft);
116678
116679 /* The isRequirePhrase variable is set to true if a phrase or
116680 ** an expression contained in parenthesis is required. If a
116681 ** binary operator (AND, OR, NOT or NEAR) is encounted when
@@ -116834,13 +117560,15 @@
116834 /*
116835 ** Free a parsed fts3 query expression allocated by sqlite3Fts3ExprParse().
116836 */
116837 SQLITE_PRIVATE void sqlite3Fts3ExprFree(Fts3Expr *p){
116838 if( p ){
 
116839 sqlite3Fts3ExprFree(p->pLeft);
116840 sqlite3Fts3ExprFree(p->pRight);
116841 sqlite3_free(p->aDoclist);
 
116842 sqlite3_free(p);
116843 }
116844 }
116845
116846 /****************************************************************************
@@ -116893,11 +117621,11 @@
116893 switch( pExpr->eType ){
116894 case FTSQUERY_PHRASE: {
116895 Fts3Phrase *pPhrase = pExpr->pPhrase;
116896 int i;
116897 zBuf = sqlite3_mprintf(
116898 "%zPHRASE %d %d", zBuf, pPhrase->iColumn, pPhrase->isNot);
116899 for(i=0; zBuf && i<pPhrase->nToken; i++){
116900 zBuf = sqlite3_mprintf("%z %.*s%s", zBuf,
116901 pPhrase->aToken[i].n, pPhrase->aToken[i].z,
116902 (pPhrase->aToken[i].isPrefix?"+":"")
116903 );
@@ -118811,18 +119539,44 @@
118811 ** it is always safe to read up to two varints from it without risking an
118812 ** overread, even if the node data is corrupted.
118813 */
118814 #define FTS3_NODE_PADDING (FTS3_VARINT_MAX*2)
118815
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
118816 typedef struct PendingList PendingList;
118817 typedef struct SegmentNode SegmentNode;
118818 typedef struct SegmentWriter SegmentWriter;
118819
118820 /*
118821 ** Data structure used while accumulating terms in the pending-terms hash
118822 ** table. The hash table entry maps from term (a string) to a malloc'd
118823 ** instance of this structure.
118824 */
118825 struct PendingList {
118826 int nData;
118827 char *aData;
118828 int nSpace;
@@ -118849,11 +119603,10 @@
118849 ** of type Fts3SegReader* are also used by code in fts3.c to iterate through
118850 ** terms when querying the full-text index. See functions:
118851 **
118852 ** sqlite3Fts3SegReaderNew()
118853 ** sqlite3Fts3SegReaderFree()
118854 ** sqlite3Fts3SegReaderCost()
118855 ** sqlite3Fts3SegReaderIterate()
118856 **
118857 ** Methods used to manipulate Fts3SegReader structures:
118858 **
118859 ** fts3SegReaderNext()
@@ -118868,10 +119621,13 @@
118868 sqlite3_int64 iEndBlock; /* Rowid of final block in segment (or 0) */
118869 sqlite3_int64 iCurrentBlock; /* Current leaf block (or 0) */
118870
118871 char *aNode; /* Pointer to node data (or NULL) */
118872 int nNode; /* Size of buffer at aNode (or 0) */
 
 
 
118873 Fts3HashElem **ppNextElem;
118874
118875 /* Variables set by fts3SegReaderNext(). These may be read directly
118876 ** by the caller. They are valid from the time SegmentReaderNew() returns
118877 ** until SegmentReaderNext() returns something other than SQLITE_OK
@@ -118881,12 +119637,15 @@
118881 char *zTerm; /* Pointer to current term */
118882 int nTermAlloc; /* Allocated size of zTerm buffer */
118883 char *aDoclist; /* Pointer to doclist of current entry */
118884 int nDoclist; /* Size of doclist in current entry */
118885
118886 /* The following variables are used to iterate through the current doclist */
 
 
118887 char *pOffsetList;
 
118888 sqlite3_int64 iDocid;
118889 };
118890
118891 #define fts3SegReaderIsPending(p) ((p)->ppNextElem!=0)
118892 #define fts3SegReaderIsRootOnly(p) ((p)->aNode==(char *)&(p)[1])
@@ -118920,10 +119679,18 @@
118920 ** within the fts3SegWriterXXX() family of functions described above.
118921 **
118922 ** fts3NodeAddTerm()
118923 ** fts3NodeWrite()
118924 ** fts3NodeFree()
 
 
 
 
 
 
 
 
118925 */
118926 struct SegmentNode {
118927 SegmentNode *pParent; /* Parent node (or NULL for root node) */
118928 SegmentNode *pRight; /* Pointer to right-sibling */
118929 SegmentNode *pLeftmost; /* Pointer to left-most node of this depth */
@@ -118950,21 +119717,26 @@
118950 #define SQL_NEXT_SEGMENT_INDEX 8
118951 #define SQL_INSERT_SEGMENTS 9
118952 #define SQL_NEXT_SEGMENTS_ID 10
118953 #define SQL_INSERT_SEGDIR 11
118954 #define SQL_SELECT_LEVEL 12
118955 #define SQL_SELECT_ALL_LEVEL 13
118956 #define SQL_SELECT_LEVEL_COUNT 14
118957 #define SQL_SELECT_SEGDIR_COUNT_MAX 15
118958 #define SQL_DELETE_SEGDIR_BY_LEVEL 16
118959 #define SQL_DELETE_SEGMENTS_RANGE 17
118960 #define SQL_CONTENT_INSERT 18
118961 #define SQL_DELETE_DOCSIZE 19
118962 #define SQL_REPLACE_DOCSIZE 20
118963 #define SQL_SELECT_DOCSIZE 21
118964 #define SQL_SELECT_DOCTOTAL 22
118965 #define SQL_REPLACE_DOCTOTAL 23
 
 
 
 
 
118966
118967 /*
118968 ** This function is used to obtain an SQLite prepared statement handle
118969 ** for the statement identified by the second argument. If successful,
118970 ** *pp is set to the requested statement handle and SQLITE_OK returned.
@@ -118997,23 +119769,29 @@
118997
118998 /* Return segments in order from oldest to newest.*/
118999 /* 12 */ "SELECT idx, start_block, leaves_end_block, end_block, root "
119000 "FROM %Q.'%q_segdir' WHERE level = ? ORDER BY idx ASC",
119001 /* 13 */ "SELECT idx, start_block, leaves_end_block, end_block, root "
119002 "FROM %Q.'%q_segdir' ORDER BY level DESC, idx ASC",
 
119003
119004 /* 14 */ "SELECT count(*) FROM %Q.'%q_segdir' WHERE level = ?",
119005 /* 15 */ "SELECT count(*), max(level) FROM %Q.'%q_segdir'",
119006
119007 /* 16 */ "DELETE FROM %Q.'%q_segdir' WHERE level = ?",
119008 /* 17 */ "DELETE FROM %Q.'%q_segments' WHERE blockid BETWEEN ? AND ?",
119009 /* 18 */ "INSERT INTO %Q.'%q_content' VALUES(%s)",
119010 /* 19 */ "DELETE FROM %Q.'%q_docsize' WHERE docid = ?",
119011 /* 20 */ "REPLACE INTO %Q.'%q_docsize' VALUES(?,?)",
119012 /* 21 */ "SELECT size FROM %Q.'%q_docsize' WHERE docid=?",
119013 /* 22 */ "SELECT value FROM %Q.'%q_stat' WHERE id=0",
119014 /* 23 */ "REPLACE INTO %Q.'%q_stat' VALUES(0,?)",
 
 
 
 
 
119015 };
119016 int rc = SQLITE_OK;
119017 sqlite3_stmt *pStmt;
119018
119019 assert( SizeofArray(azSql)==SizeofArray(p->aStmt) );
@@ -119165,18 +119943,36 @@
119165 ** 1: start_block
119166 ** 2: leaves_end_block
119167 ** 3: end_block
119168 ** 4: root
119169 */
119170 SQLITE_PRIVATE int sqlite3Fts3AllSegdirs(Fts3Table *p, int iLevel, sqlite3_stmt **ppStmt){
 
 
 
 
 
119171 int rc;
119172 sqlite3_stmt *pStmt = 0;
 
 
 
 
 
119173 if( iLevel<0 ){
119174 rc = fts3SqlStmt(p, SQL_SELECT_ALL_LEVEL, &pStmt, 0);
 
 
 
 
 
119175 }else{
 
119176 rc = fts3SqlStmt(p, SQL_SELECT_LEVEL, &pStmt, 0);
119177 if( rc==SQLITE_OK ) sqlite3_bind_int(pStmt, 1, iLevel);
 
 
119178 }
119179 *ppStmt = pStmt;
119180 return rc;
119181 }
119182
@@ -119286,10 +120082,51 @@
119286 *pp = p;
119287 return 1;
119288 }
119289 return 0;
119290 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
119291
119292 /*
119293 ** Tokenize the nul-terminated string zText and add all tokens to the
119294 ** pending-terms hash-table. The docid used is that currently stored in
119295 ** p->iPrevDocid, and the column is specified by argument iCol.
@@ -119335,12 +120172,11 @@
119335
119336 xNext = pModule->xNext;
119337 while( SQLITE_OK==rc
119338 && SQLITE_OK==(rc = xNext(pCsr, &zToken, &nToken, &iStart, &iEnd, &iPos))
119339 ){
119340 PendingList *pList;
119341
119342 if( iPos>=nWord ) nWord = iPos+1;
119343
119344 /* Positions cannot be negative; we use -1 as a terminator internally.
119345 ** Tokens must have a non-zero length.
119346 */
@@ -119347,26 +120183,23 @@
119347 if( iPos<0 || !zToken || nToken<=0 ){
119348 rc = SQLITE_ERROR;
119349 break;
119350 }
119351
119352 pList = (PendingList *)fts3HashFind(&p->pendingTerms, zToken, nToken);
119353 if( pList ){
119354 p->nPendingData -= (pList->nData + nToken + sizeof(Fts3HashElem));
119355 }
119356 if( fts3PendingListAppend(&pList, p->iPrevDocid, iCol, iPos, &rc) ){
119357 if( pList==fts3HashInsert(&p->pendingTerms, zToken, nToken, pList) ){
119358 /* Malloc failed while inserting the new entry. This can only
119359 ** happen if there was no previous entry for this token.
119360 */
119361 assert( 0==fts3HashFind(&p->pendingTerms, zToken, nToken) );
119362 sqlite3_free(pList);
119363 rc = SQLITE_NOMEM;
119364 }
119365 }
119366 if( rc==SQLITE_OK ){
119367 p->nPendingData += (pList->nData + nToken + sizeof(Fts3HashElem));
119368 }
119369 }
119370
119371 pModule->xClose(pCsr);
119372 *pnWord = nWord;
@@ -119392,18 +120225,23 @@
119392 p->iPrevDocid = iDocid;
119393 return SQLITE_OK;
119394 }
119395
119396 /*
119397 ** Discard the contents of the pending-terms hash table.
119398 */
119399 SQLITE_PRIVATE void sqlite3Fts3PendingTermsClear(Fts3Table *p){
119400 Fts3HashElem *pElem;
119401 for(pElem=fts3HashFirst(&p->pendingTerms); pElem; pElem=fts3HashNext(pElem)){
119402 sqlite3_free(fts3HashData(pElem));
 
 
 
 
 
 
119403 }
119404 fts3HashClear(&p->pendingTerms);
119405 p->nPendingData = 0;
119406 }
119407
119408 /*
119409 ** This function is called by the xUpdate() method as part of an INSERT
@@ -119555,11 +120393,11 @@
119555
119556 /*
119557 ** Forward declaration to account for the circular dependency between
119558 ** functions fts3SegmentMerge() and fts3AllocateSegdirIdx().
119559 */
119560 static int fts3SegmentMerge(Fts3Table *, int);
119561
119562 /*
119563 ** This function allocates a new level iLevel index in the segdir table.
119564 ** Usually, indexes are allocated within a level sequentially starting
119565 ** with 0, so the allocated index is one greater than the value returned
@@ -119572,19 +120410,24 @@
119572 ** allocated index is 0.
119573 **
119574 ** If successful, *piIdx is set to the allocated index slot and SQLITE_OK
119575 ** returned. Otherwise, an SQLite error code is returned.
119576 */
119577 static int fts3AllocateSegdirIdx(Fts3Table *p, int iLevel, int *piIdx){
 
 
 
 
 
119578 int rc; /* Return Code */
119579 sqlite3_stmt *pNextIdx; /* Query for next idx at level iLevel */
119580 int iNext = 0; /* Result of query pNextIdx */
119581
119582 /* Set variable iNext to the next available segdir index at level iLevel. */
119583 rc = fts3SqlStmt(p, SQL_NEXT_SEGMENT_INDEX, &pNextIdx, 0);
119584 if( rc==SQLITE_OK ){
119585 sqlite3_bind_int(pNextIdx, 1, iLevel);
119586 if( SQLITE_ROW==sqlite3_step(pNextIdx) ){
119587 iNext = sqlite3_column_int(pNextIdx, 0);
119588 }
119589 rc = sqlite3_reset(pNextIdx);
119590 }
@@ -119594,11 +120437,11 @@
119594 ** full, merge all segments in level iLevel into a single iLevel+1
119595 ** segment and allocate (newly freed) index 0 at level iLevel. Otherwise,
119596 ** if iNext is less than FTS3_MERGE_COUNT, allocate index iNext.
119597 */
119598 if( iNext>=FTS3_MERGE_COUNT ){
119599 rc = fts3SegmentMerge(p, iLevel);
119600 *piIdx = 0;
119601 }else{
119602 *piIdx = iNext;
119603 }
119604 }
@@ -119635,11 +120478,12 @@
119635 */
119636 SQLITE_PRIVATE int sqlite3Fts3ReadBlock(
119637 Fts3Table *p, /* FTS3 table handle */
119638 sqlite3_int64 iBlockid, /* Access the row with blockid=$iBlockid */
119639 char **paBlob, /* OUT: Blob data in malloc'd buffer */
119640 int *pnBlob /* OUT: Size of blob data */
 
119641 ){
119642 int rc; /* Return code */
119643
119644 /* pnBlob must be non-NULL. paBlob may be NULL or non-NULL. */
119645 assert( pnBlob);
@@ -119656,25 +120500,29 @@
119656 );
119657 }
119658
119659 if( rc==SQLITE_OK ){
119660 int nByte = sqlite3_blob_bytes(p->pSegments);
 
119661 if( paBlob ){
119662 char *aByte = sqlite3_malloc(nByte + FTS3_NODE_PADDING);
119663 if( !aByte ){
119664 rc = SQLITE_NOMEM;
119665 }else{
 
 
 
 
119666 rc = sqlite3_blob_read(p->pSegments, aByte, nByte, 0);
119667 memset(&aByte[nByte], 0, FTS3_NODE_PADDING);
119668 if( rc!=SQLITE_OK ){
119669 sqlite3_free(aByte);
119670 aByte = 0;
119671 }
119672 }
119673 *paBlob = aByte;
119674 }
119675 *pnBlob = nByte;
119676 }
119677
119678 return rc;
119679 }
119680
@@ -119684,17 +120532,59 @@
119684 */
119685 SQLITE_PRIVATE void sqlite3Fts3SegmentsClose(Fts3Table *p){
119686 sqlite3_blob_close(p->pSegments);
119687 p->pSegments = 0;
119688 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
119689
119690 /*
119691 ** Move the iterator passed as the first argument to the next term in the
119692 ** segment. If successful, SQLITE_OK is returned. If there is no next term,
119693 ** SQLITE_DONE. Otherwise, an SQLite error code.
119694 */
119695 static int fts3SegReaderNext(Fts3Table *p, Fts3SegReader *pReader){
 
 
 
 
 
119696 char *pNext; /* Cursor variable */
119697 int nPrefix; /* Number of bytes in term prefix */
119698 int nSuffix; /* Number of bytes in term suffix */
119699
119700 if( !pReader->aDoclist ){
@@ -119702,11 +120592,10 @@
119702 }else{
119703 pNext = &pReader->aDoclist[pReader->nDoclist];
119704 }
119705
119706 if( !pNext || pNext>=&pReader->aNode[pReader->nNode] ){
119707 int rc; /* Return code from Fts3ReadBlock() */
119708
119709 if( fts3SegReaderIsPending(pReader) ){
119710 Fts3HashElem *pElem = *(pReader->ppNextElem);
119711 if( pElem==0 ){
119712 pReader->aNode = 0;
@@ -119722,10 +120611,12 @@
119722 return SQLITE_OK;
119723 }
119724
119725 if( !fts3SegReaderIsRootOnly(pReader) ){
119726 sqlite3_free(pReader->aNode);
 
 
119727 }
119728 pReader->aNode = 0;
119729
119730 /* If iCurrentBlock>=iLeafEndBlock, this is an EOF condition. All leaf
119731 ** blocks have already been traversed. */
@@ -119733,19 +120624,29 @@
119733 if( pReader->iCurrentBlock>=pReader->iLeafEndBlock ){
119734 return SQLITE_OK;
119735 }
119736
119737 rc = sqlite3Fts3ReadBlock(
119738 p, ++pReader->iCurrentBlock, &pReader->aNode, &pReader->nNode
 
119739 );
119740 if( rc!=SQLITE_OK ) return rc;
 
 
 
 
 
119741 pNext = pReader->aNode;
119742 }
 
 
 
 
 
119743
119744 /* Because of the FTS3_NODE_PADDING bytes of padding, the following is
119745 ** safe (no risk of overread) even if the node data is corrupted.
119746 */
119747 pNext += sqlite3Fts3GetVarint32(pNext, &nPrefix);
119748 pNext += sqlite3Fts3GetVarint32(pNext, &nSuffix);
119749 if( nPrefix<0 || nSuffix<=0
119750 || &pNext[nSuffix]>&pReader->aNode[pReader->nNode]
119751 ){
@@ -119759,10 +120660,14 @@
119759 return SQLITE_NOMEM;
119760 }
119761 pReader->zTerm = zNew;
119762 pReader->nTermAlloc = nNew;
119763 }
 
 
 
 
119764 memcpy(&pReader->zTerm[nPrefix], pNext, nSuffix);
119765 pReader->nTerm = nPrefix+nSuffix;
119766 pNext += nSuffix;
119767 pNext += sqlite3Fts3GetVarint32(pNext, &pReader->nDoclist);
119768 pReader->aDoclist = pNext;
@@ -119771,11 +120676,11 @@
119771 /* Check that the doclist does not appear to extend past the end of the
119772 ** b-tree node. And that the final byte of the doclist is 0x00. If either
119773 ** of these statements is untrue, then the data structure is corrupt.
119774 */
119775 if( &pReader->aDoclist[pReader->nDoclist]>&pReader->aNode[pReader->nNode]
119776 || pReader->aDoclist[pReader->nDoclist-1]
119777 ){
119778 return SQLITE_CORRUPT_VTAB;
119779 }
119780 return SQLITE_OK;
119781 }
@@ -119782,16 +120687,30 @@
119782
119783 /*
119784 ** Set the SegReader to point to the first docid in the doclist associated
119785 ** with the current term.
119786 */
119787 static void fts3SegReaderFirstDocid(Fts3SegReader *pReader){
119788 int n;
119789 assert( pReader->aDoclist );
119790 assert( !pReader->pOffsetList );
119791 n = sqlite3Fts3GetVarint(pReader->aDoclist, &pReader->iDocid);
119792 pReader->pOffsetList = &pReader->aDoclist[n];
 
 
 
 
 
 
 
 
 
 
 
 
 
 
119793 }
119794
119795 /*
119796 ** Advance the SegReader to point to the next docid in the doclist
119797 ** associated with the current term.
@@ -119800,132 +120719,126 @@
119800 ** *ppOffsetList is set to point to the first column-offset list
119801 ** in the doclist entry (i.e. immediately past the docid varint).
119802 ** *pnOffsetList is set to the length of the set of column-offset
119803 ** lists, not including the nul-terminator byte. For example:
119804 */
119805 static void fts3SegReaderNextDocid(
119806 Fts3SegReader *pReader,
119807 char **ppOffsetList,
119808 int *pnOffsetList
 
119809 ){
 
119810 char *p = pReader->pOffsetList;
119811 char c = 0;
119812
119813 /* Pointer p currently points at the first byte of an offset list. The
119814 ** following two lines advance it to point one byte past the end of
119815 ** the same offset list.
119816 */
119817 while( *p | c ) c = *p++ & 0x80;
119818 p++;
119819
119820 /* If required, populate the output variables with a pointer to and the
119821 ** size of the previous offset-list.
119822 */
119823 if( ppOffsetList ){
119824 *ppOffsetList = pReader->pOffsetList;
119825 *pnOffsetList = (int)(p - pReader->pOffsetList - 1);
119826 }
119827
119828 /* If there are no more entries in the doclist, set pOffsetList to
119829 ** NULL. Otherwise, set Fts3SegReader.iDocid to the next docid and
119830 ** Fts3SegReader.pOffsetList to point to the next offset list before
119831 ** returning.
119832 */
119833 if( p>=&pReader->aDoclist[pReader->nDoclist] ){
119834 pReader->pOffsetList = 0;
119835 }else{
119836 sqlite3_int64 iDelta;
119837 pReader->pOffsetList = p + sqlite3Fts3GetVarint(p, &iDelta);
119838 pReader->iDocid += iDelta;
119839 }
119840 }
119841
119842 /*
119843 ** This function is called to estimate the amount of data that will be
119844 ** loaded from the disk If SegReaderIterate() is called on this seg-reader,
119845 ** in units of average document size.
119846 **
119847 ** This can be used as follows: If the caller has a small doclist that
119848 ** contains references to N documents, and is considering merging it with
119849 ** a large doclist (size X "average documents"), it may opt not to load
119850 ** the large doclist if X>N.
119851 */
119852 SQLITE_PRIVATE int sqlite3Fts3SegReaderCost(
119853 Fts3Cursor *pCsr, /* FTS3 cursor handle */
119854 Fts3SegReader *pReader, /* Segment-reader handle */
119855 int *pnCost /* IN/OUT: Number of bytes read */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
119856 ){
119857 Fts3Table *p = (Fts3Table*)pCsr->base.pVtab;
119858 int rc = SQLITE_OK; /* Return code */
119859 int nCost = 0; /* Cost in bytes to return */
119860 int pgsz = p->nPgsz; /* Database page size */
119861
119862 /* If this seg-reader is reading the pending-terms table, or if all data
119863 ** for the segment is stored on the root page of the b-tree, then the cost
119864 ** is zero. In this case all required data is already in main memory.
119865 */
119866 if( p->bHasStat
119867 && !fts3SegReaderIsPending(pReader)
119868 && !fts3SegReaderIsRootOnly(pReader)
119869 ){
119870 int nBlob = 0;
119871 sqlite3_int64 iBlock;
119872
119873 if( pCsr->nRowAvg==0 ){
119874 /* The average document size, which is required to calculate the cost
119875 ** of each doclist, has not yet been determined. Read the required
119876 ** data from the %_stat table to calculate it.
119877 **
119878 ** Entry 0 of the %_stat table is a blob containing (nCol+1) FTS3
119879 ** varints, where nCol is the number of columns in the FTS3 table.
119880 ** The first varint is the number of documents currently stored in
119881 ** the table. The following nCol varints contain the total amount of
119882 ** data stored in all rows of each column of the table, from left
119883 ** to right.
119884 */
119885 sqlite3_stmt *pStmt;
119886 sqlite3_int64 nDoc = 0;
119887 sqlite3_int64 nByte = 0;
119888 const char *pEnd;
119889 const char *a;
119890
119891 rc = sqlite3Fts3SelectDoctotal(p, &pStmt);
119892 if( rc!=SQLITE_OK ) return rc;
119893 a = sqlite3_column_blob(pStmt, 0);
119894 assert( a );
119895
119896 pEnd = &a[sqlite3_column_bytes(pStmt, 0)];
119897 a += sqlite3Fts3GetVarint(a, &nDoc);
119898 while( a<pEnd ){
119899 a += sqlite3Fts3GetVarint(a, &nByte);
119900 }
119901 if( nDoc==0 || nByte==0 ){
119902 sqlite3_reset(pStmt);
119903 return SQLITE_CORRUPT_VTAB;
119904 }
119905
119906 pCsr->nRowAvg = (int)(((nByte / nDoc) + pgsz) / pgsz);
119907 assert( pCsr->nRowAvg>0 );
119908 rc = sqlite3_reset(pStmt);
119909 if( rc!=SQLITE_OK ) return rc;
119910 }
119911
119912 /* Assume that a blob flows over onto overflow pages if it is larger
119913 ** than (pgsz-35) bytes in size (the file-format documentation
119914 ** confirms this).
119915 */
119916 for(iBlock=pReader->iStartBlock; iBlock<=pReader->iLeafEndBlock; iBlock++){
119917 rc = sqlite3Fts3ReadBlock(p, iBlock, 0, &nBlob);
119918 if( rc!=SQLITE_OK ) break;
119919 if( (nBlob+35)>pgsz ){
119920 int nOvfl = (nBlob + 34)/pgsz;
119921 nCost += ((nOvfl + pCsr->nRowAvg - 1)/pCsr->nRowAvg);
119922 }
119923 }
119924 }
119925
119926 *pnCost += nCost;
119927 return rc;
119928 }
119929
119930 /*
119931 ** Free all allocations associated with the iterator passed as the
@@ -119934,10 +120847,11 @@
119934 SQLITE_PRIVATE void sqlite3Fts3SegReaderFree(Fts3SegReader *pReader){
119935 if( pReader && !fts3SegReaderIsPending(pReader) ){
119936 sqlite3_free(pReader->zTerm);
119937 if( !fts3SegReaderIsRootOnly(pReader) ){
119938 sqlite3_free(pReader->aNode);
 
119939 }
119940 }
119941 sqlite3_free(pReader);
119942 }
119943
@@ -120010,28 +120924,46 @@
120010 }
120011
120012 /*
120013 ** This function is used to allocate an Fts3SegReader that iterates through
120014 ** a subset of the terms stored in the Fts3Table.pendingTerms array.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
120015 */
120016 SQLITE_PRIVATE int sqlite3Fts3SegReaderPending(
120017 Fts3Table *p, /* Virtual table handle */
 
120018 const char *zTerm, /* Term to search for */
120019 int nTerm, /* Size of buffer zTerm */
120020 int isPrefix, /* True for a term-prefix query */
120021 Fts3SegReader **ppReader /* OUT: SegReader for pending-terms */
120022 ){
120023 Fts3SegReader *pReader = 0; /* Fts3SegReader object to return */
120024 Fts3HashElem **aElem = 0; /* Array of term hash entries to scan */
120025 int nElem = 0; /* Size of array at aElem */
120026 int rc = SQLITE_OK; /* Return Code */
 
120027
120028 if( isPrefix ){
 
120029 int nAlloc = 0; /* Size of allocated array at aElem */
120030 Fts3HashElem *pE = 0; /* Iterator variable */
120031
120032 for(pE=fts3HashFirst(&p->pendingTerms); pE; pE=fts3HashNext(pE)){
120033 char *zKey = (char *)fts3HashKey(pE);
120034 int nKey = fts3HashKeysize(pE);
120035 if( nTerm==0 || (nKey>=nTerm && 0==memcmp(zKey, zTerm, nTerm)) ){
120036 if( nElem==nAlloc ){
120037 Fts3HashElem **aElem2;
@@ -120044,10 +120976,11 @@
120044 nElem = 0;
120045 break;
120046 }
120047 aElem = aElem2;
120048 }
 
120049 aElem[nElem++] = pE;
120050 }
120051 }
120052
120053 /* If more than one term matches the prefix, sort the Fts3HashElem
@@ -120057,11 +120990,13 @@
120057 if( nElem>1 ){
120058 qsort(aElem, nElem, sizeof(Fts3HashElem *), fts3CompareElemByTerm);
120059 }
120060
120061 }else{
120062 Fts3HashElem *pE = fts3HashFindElem(&p->pendingTerms, zTerm, nTerm);
 
 
120063 if( pE ){
120064 aElem = &pE;
120065 nElem = 1;
120066 }
120067 }
@@ -120077,11 +121012,11 @@
120077 pReader->ppNextElem = (Fts3HashElem **)&pReader[1];
120078 memcpy(pReader->ppNextElem, aElem, nElem*sizeof(Fts3HashElem *));
120079 }
120080 }
120081
120082 if( isPrefix ){
120083 sqlite3_free(aElem);
120084 }
120085 *ppReader = pReader;
120086 return rc;
120087 }
@@ -120137,10 +121072,22 @@
120137 if( pLhs->iDocid==pRhs->iDocid ){
120138 rc = pRhs->iIdx - pLhs->iIdx;
120139 }else{
120140 rc = (pLhs->iDocid > pRhs->iDocid) ? 1 : -1;
120141 }
 
 
 
 
 
 
 
 
 
 
 
 
120142 }
120143 assert( pLhs->aNode && pRhs->aNode );
120144 return rc;
120145 }
120146
@@ -120689,25 +121636,34 @@
120689 }
120690 return rc;
120691 }
120692
120693 /*
120694 ** Set *pnSegment to the total number of segments in the database. Set
120695 ** *pnMax to the largest segment level in the database (segment levels
120696 ** are stored in the 'level' column of the %_segdir table).
 
120697 **
120698 ** Return SQLITE_OK if successful, or an SQLite error code if not.
120699 */
120700 static int fts3SegmentCountMax(Fts3Table *p, int *pnSegment, int *pnMax){
120701 sqlite3_stmt *pStmt;
120702 int rc;
 
120703
120704 rc = fts3SqlStmt(p, SQL_SELECT_SEGDIR_COUNT_MAX, &pStmt, 0);
 
 
 
 
 
 
120705 if( rc!=SQLITE_OK ) return rc;
 
 
120706 if( SQLITE_ROW==sqlite3_step(pStmt) ){
120707 *pnSegment = sqlite3_column_int(pStmt, 0);
120708 *pnMax = sqlite3_column_int(pStmt, 1);
120709 }
120710 return sqlite3_reset(pStmt);
120711 }
120712
120713 /*
@@ -120724,10 +121680,11 @@
120724 **
120725 ** SQLITE_OK is returned if successful, otherwise an SQLite error code.
120726 */
120727 static int fts3DeleteSegdir(
120728 Fts3Table *p, /* Virtual table handle */
 
120729 int iLevel, /* Level of %_segdir entries to delete */
120730 Fts3SegReader **apSegment, /* Array of SegReader objects */
120731 int nReader /* Size of array apSegment */
120732 ){
120733 int rc; /* Return Code */
@@ -120746,23 +121703,28 @@
120746 }
120747 if( rc!=SQLITE_OK ){
120748 return rc;
120749 }
120750
 
120751 if( iLevel==FTS3_SEGCURSOR_ALL ){
120752 fts3SqlExec(&rc, p, SQL_DELETE_ALL_SEGDIR, 0);
120753 }else if( iLevel==FTS3_SEGCURSOR_PENDING ){
120754 sqlite3Fts3PendingTermsClear(p);
 
 
120755 }else{
120756 assert( iLevel>=0 );
120757 rc = fts3SqlStmt(p, SQL_DELETE_SEGDIR_BY_LEVEL, &pDelete, 0);
120758 if( rc==SQLITE_OK ){
120759 sqlite3_bind_int(pDelete, 1, iLevel);
120760 sqlite3_step(pDelete);
120761 rc = sqlite3_reset(pDelete);
120762 }
120763 }
 
 
 
 
 
120764
120765 return rc;
120766 }
120767
120768 /*
@@ -120805,14 +121767,124 @@
120805 }
120806
120807 *ppList = pList;
120808 *pnList = nList;
120809 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
120810
120811 SQLITE_PRIVATE int sqlite3Fts3SegReaderStart(
120812 Fts3Table *p, /* Virtual table handle */
120813 Fts3SegReaderCursor *pCsr, /* Cursor object */
120814 Fts3SegFilter *pFilter /* Restrictions on range of iteration */
120815 ){
120816 int i;
120817
120818 /* Initialize the cursor object */
@@ -120827,11 +121899,11 @@
120827 for(i=0; i<pCsr->nSegment; i++){
120828 int nTerm = pFilter->nTerm;
120829 const char *zTerm = pFilter->zTerm;
120830 Fts3SegReader *pSeg = pCsr->apSegment[i];
120831 do {
120832 int rc = fts3SegReaderNext(p, pSeg);
120833 if( rc!=SQLITE_OK ) return rc;
120834 }while( zTerm && fts3SegReaderTermCmp(pSeg, zTerm, nTerm)<0 );
120835 }
120836 fts3SegReaderSort(
120837 pCsr->apSegment, pCsr->nSegment, pCsr->nSegment, fts3SegReaderCmp);
@@ -120839,11 +121911,11 @@
120839 return SQLITE_OK;
120840 }
120841
120842 SQLITE_PRIVATE int sqlite3Fts3SegReaderStep(
120843 Fts3Table *p, /* Virtual table handle */
120844 Fts3SegReaderCursor *pCsr /* Cursor object */
120845 ){
120846 int rc = SQLITE_OK;
120847
120848 int isIgnoreEmpty = (pCsr->pFilter->flags & FTS3_SEGMENT_IGNORE_EMPTY);
120849 int isRequirePos = (pCsr->pFilter->flags & FTS3_SEGMENT_REQUIRE_POS);
@@ -120852,10 +121924,13 @@
120852 int isScan = (pCsr->pFilter->flags & FTS3_SEGMENT_SCAN);
120853
120854 Fts3SegReader **apSegment = pCsr->apSegment;
120855 int nSegment = pCsr->nSegment;
120856 Fts3SegFilter *pFilter = pCsr->pFilter;
 
 
 
120857
120858 if( pCsr->nSegment==0 ) return SQLITE_OK;
120859
120860 do {
120861 int nMerge;
@@ -120863,11 +121938,11 @@
120863
120864 /* Advance the first pCsr->nAdvance entries in the apSegment[] array
120865 ** forward. Then sort the list in order of current term again.
120866 */
120867 for(i=0; i<pCsr->nAdvance; i++){
120868 rc = fts3SegReaderNext(p, apSegment[i]);
120869 if( rc!=SQLITE_OK ) return rc;
120870 }
120871 fts3SegReaderSort(apSegment, nSegment, pCsr->nAdvance, fts3SegReaderCmp);
120872 pCsr->nAdvance = 0;
120873
@@ -120902,11 +121977,14 @@
120902 ){
120903 nMerge++;
120904 }
120905
120906 assert( isIgnoreEmpty || (isRequirePos && !isColFilter) );
120907 if( nMerge==1 && !isIgnoreEmpty ){
 
 
 
120908 pCsr->aDoclist = apSegment[0]->aDoclist;
120909 pCsr->nDoclist = apSegment[0]->nDoclist;
120910 rc = SQLITE_ROW;
120911 }else{
120912 int nDoclist = 0; /* Size of doclist */
@@ -120915,56 +121993,66 @@
120915 /* The current term of the first nMerge entries in the array
120916 ** of Fts3SegReader objects is the same. The doclists must be merged
120917 ** and a single term returned with the merged doclist.
120918 */
120919 for(i=0; i<nMerge; i++){
120920 fts3SegReaderFirstDocid(apSegment[i]);
120921 }
120922 fts3SegReaderSort(apSegment, nMerge, nMerge, fts3SegReaderDoclistCmp);
120923 while( apSegment[0]->pOffsetList ){
120924 int j; /* Number of segments that share a docid */
120925 char *pList;
120926 int nList;
120927 int nByte;
120928 sqlite3_int64 iDocid = apSegment[0]->iDocid;
120929 fts3SegReaderNextDocid(apSegment[0], &pList, &nList);
120930 j = 1;
120931 while( j<nMerge
120932 && apSegment[j]->pOffsetList
120933 && apSegment[j]->iDocid==iDocid
120934 ){
120935 fts3SegReaderNextDocid(apSegment[j], 0, 0);
120936 j++;
120937 }
120938
120939 if( isColFilter ){
120940 fts3ColumnFilter(pFilter->iCol, &pList, &nList);
120941 }
120942
120943 if( !isIgnoreEmpty || nList>0 ){
120944 nByte = sqlite3Fts3VarintLen(iDocid-iPrev) + (isRequirePos?nList+1:0);
 
 
 
 
 
 
 
 
 
 
 
 
120945 if( nDoclist+nByte>pCsr->nBuffer ){
120946 char *aNew;
120947 pCsr->nBuffer = (nDoclist+nByte)*2;
120948 aNew = sqlite3_realloc(pCsr->aBuffer, pCsr->nBuffer);
120949 if( !aNew ){
120950 return SQLITE_NOMEM;
120951 }
120952 pCsr->aBuffer = aNew;
120953 }
120954 nDoclist += sqlite3Fts3PutVarint(
120955 &pCsr->aBuffer[nDoclist], iDocid-iPrev
120956 );
120957 iPrev = iDocid;
120958 if( isRequirePos ){
120959 memcpy(&pCsr->aBuffer[nDoclist], pList, nList);
120960 nDoclist += nList;
120961 pCsr->aBuffer[nDoclist++] = '\0';
120962 }
120963 }
120964
120965 fts3SegReaderSort(apSegment, nMerge, j, fts3SegReaderDoclistCmp);
120966 }
120967 if( nDoclist>0 ){
120968 pCsr->aDoclist = pCsr->aBuffer;
120969 pCsr->nDoclist = nDoclist;
120970 rc = SQLITE_ROW;
@@ -120973,13 +122061,14 @@
120973 pCsr->nAdvance = nMerge;
120974 }while( rc==SQLITE_OK );
120975
120976 return rc;
120977 }
 
120978
120979 SQLITE_PRIVATE void sqlite3Fts3SegReaderFinish(
120980 Fts3SegReaderCursor *pCsr /* Cursor object */
120981 ){
120982 if( pCsr ){
120983 int i;
120984 for(i=0; i<pCsr->nSegment; i++){
120985 sqlite3Fts3SegReaderFree(pCsr->apSegment[i]);
@@ -121002,47 +122091,60 @@
121002 ** If this function is called with iLevel<0, but there is only one
121003 ** segment in the database, SQLITE_DONE is returned immediately.
121004 ** Otherwise, if successful, SQLITE_OK is returned. If an error occurs,
121005 ** an SQLite error code is returned.
121006 */
121007 static int fts3SegmentMerge(Fts3Table *p, int iLevel){
121008 int rc; /* Return code */
121009 int iIdx = 0; /* Index of new segment */
121010 int iNewLevel = 0; /* Level to create new segment at */
121011 SegmentWriter *pWriter = 0; /* Used to write the new, merged, segment */
121012 Fts3SegFilter filter; /* Segment term filter condition */
121013 Fts3SegReaderCursor csr; /* Cursor to iterate through level(s) */
 
121014
121015 rc = sqlite3Fts3SegReaderCursor(p, iLevel, 0, 0, 1, 0, &csr);
 
 
 
 
 
 
 
121016 if( rc!=SQLITE_OK || csr.nSegment==0 ) goto finished;
121017
121018 if( iLevel==FTS3_SEGCURSOR_ALL ){
121019 /* This call is to merge all segments in the database to a single
121020 ** segment. The level of the new segment is equal to the the numerically
121021 ** greatest segment level currently present in the database. The index
121022 ** of the new segment is always 0. */
121023 int nDummy; /* TODO: Remove this */
121024 if( csr.nSegment==1 ){
121025 rc = SQLITE_DONE;
121026 goto finished;
121027 }
121028 rc = fts3SegmentCountMax(p, &nDummy, &iNewLevel);
 
 
 
 
 
121029 }else{
121030 /* This call is to merge all segments at level iLevel. Find the next
121031 ** available segment index at level iLevel+1. The call to
121032 ** fts3AllocateSegdirIdx() will merge the segments at level iLevel+1 to
121033 ** a single iLevel+2 segment if necessary. */
121034 iNewLevel = iLevel+1;
121035 rc = fts3AllocateSegdirIdx(p, iNewLevel, &iIdx);
121036 }
121037 if( rc!=SQLITE_OK ) goto finished;
121038 assert( csr.nSegment>0 );
121039 assert( iNewLevel>=0 );
 
121040
121041 memset(&filter, 0, sizeof(Fts3SegFilter));
121042 filter.flags = FTS3_SEGMENT_REQUIRE_POS;
121043 filter.flags |= (iLevel==FTS3_SEGCURSOR_ALL ? FTS3_SEGMENT_IGNORE_EMPTY : 0);
121044
121045 rc = sqlite3Fts3SegReaderStart(p, &csr, &filter);
121046 while( SQLITE_OK==rc ){
121047 rc = sqlite3Fts3SegReaderStep(p, &csr);
121048 if( rc!=SQLITE_ROW ) break;
@@ -121050,12 +122152,14 @@
121050 csr.zTerm, csr.nTerm, csr.aDoclist, csr.nDoclist);
121051 }
121052 if( rc!=SQLITE_OK ) goto finished;
121053 assert( pWriter );
121054
121055 rc = fts3DeleteSegdir(p, iLevel, csr.apSegment, csr.nSegment);
121056 if( rc!=SQLITE_OK ) goto finished;
 
 
121057 rc = fts3SegWriterFlush(p, pWriter, iNewLevel, iIdx);
121058
121059 finished:
121060 fts3SegWriterFree(pWriter);
121061 sqlite3Fts3SegReaderFinish(&csr);
@@ -121062,14 +122166,21 @@
121062 return rc;
121063 }
121064
121065
121066 /*
121067 ** Flush the contents of pendingTerms to a level 0 segment.
121068 */
121069 SQLITE_PRIVATE int sqlite3Fts3PendingTermsFlush(Fts3Table *p){
121070 return fts3SegmentMerge(p, FTS3_SEGCURSOR_PENDING);
 
 
 
 
 
 
 
121071 }
121072
121073 /*
121074 ** Encode N integers as varints into a blob.
121075 */
@@ -121215,10 +122326,27 @@
121215 sqlite3_bind_blob(pStmt, 1, pBlob, nBlob, SQLITE_STATIC);
121216 sqlite3_step(pStmt);
121217 *pRC = sqlite3_reset(pStmt);
121218 sqlite3_free(a);
121219 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
121220
121221 /*
121222 ** Handle a 'special' INSERT of the form:
121223 **
121224 ** "INSERT INTO tbl(tbl) VALUES(<expr>)"
@@ -121232,16 +122360,11 @@
121232 int nVal = sqlite3_value_bytes(pVal);
121233
121234 if( !zVal ){
121235 return SQLITE_NOMEM;
121236 }else if( nVal==8 && 0==sqlite3_strnicmp(zVal, "optimize", 8) ){
121237 rc = fts3SegmentMerge(p, FTS3_SEGCURSOR_ALL);
121238 if( rc==SQLITE_DONE ){
121239 rc = SQLITE_OK;
121240 }else{
121241 sqlite3Fts3PendingTermsClear(p);
121242 }
121243 #ifdef SQLITE_TEST
121244 }else if( nVal>9 && 0==sqlite3_strnicmp(zVal, "nodesize=", 9) ){
121245 p->nNodeSize = atoi(&zVal[9]);
121246 rc = SQLITE_OK;
121247 }else if( nVal>11 && 0==sqlite3_strnicmp(zVal, "maxpending=", 9) ){
@@ -121250,61 +122373,23 @@
121250 #endif
121251 }else{
121252 rc = SQLITE_ERROR;
121253 }
121254
121255 sqlite3Fts3SegmentsClose(p);
121256 return rc;
121257 }
121258
121259 /*
121260 ** Return the deferred doclist associated with deferred token pDeferred.
121261 ** This function assumes that sqlite3Fts3CacheDeferredDoclists() has already
121262 ** been called to allocate and populate the doclist.
121263 */
121264 SQLITE_PRIVATE char *sqlite3Fts3DeferredDoclist(Fts3DeferredToken *pDeferred, int *pnByte){
121265 if( pDeferred->pList ){
121266 *pnByte = pDeferred->pList->nData;
121267 return pDeferred->pList->aData;
121268 }
121269 *pnByte = 0;
121270 return 0;
121271 }
121272
121273 /*
121274 ** Helper fucntion for FreeDeferredDoclists(). This function removes all
121275 ** references to deferred doclists from within the tree of Fts3Expr
121276 ** structures headed by
121277 */
121278 static void fts3DeferredDoclistClear(Fts3Expr *pExpr){
121279 if( pExpr ){
121280 fts3DeferredDoclistClear(pExpr->pLeft);
121281 fts3DeferredDoclistClear(pExpr->pRight);
121282 if( pExpr->isLoaded ){
121283 sqlite3_free(pExpr->aDoclist);
121284 pExpr->isLoaded = 0;
121285 pExpr->aDoclist = 0;
121286 pExpr->nDoclist = 0;
121287 pExpr->pCurrent = 0;
121288 pExpr->iCurrent = 0;
121289 }
121290 }
121291 }
121292
121293 /*
121294 ** Delete all cached deferred doclists. Deferred doclists are cached
121295 ** (allocated) by the sqlite3Fts3CacheDeferredDoclists() function.
121296 */
121297 SQLITE_PRIVATE void sqlite3Fts3FreeDeferredDoclists(Fts3Cursor *pCsr){
121298 Fts3DeferredToken *pDef;
121299 for(pDef=pCsr->pDeferred; pDef; pDef=pDef->pNext){
121300 sqlite3_free(pDef->pList);
121301 pDef->pList = 0;
121302 }
121303 if( pCsr->pDeferred ){
121304 fts3DeferredDoclistClear(pCsr->pExpr);
121305 }
121306 }
121307
121308 /*
121309 ** Free all entries in the pCsr->pDeffered list. Entries are added to
121310 ** this list using sqlite3Fts3DeferToken().
@@ -121312,11 +122397,11 @@
121312 SQLITE_PRIVATE void sqlite3Fts3FreeDeferredTokens(Fts3Cursor *pCsr){
121313 Fts3DeferredToken *pDef;
121314 Fts3DeferredToken *pNext;
121315 for(pDef=pCsr->pDeferred; pDef; pDef=pNext){
121316 pNext = pDef->pNext;
121317 sqlite3_free(pDef->pList);
121318 sqlite3_free(pDef);
121319 }
121320 pCsr->pDeferred = 0;
121321 }
121322
@@ -121376,10 +122461,37 @@
121376 }
121377 }
121378
121379 return rc;
121380 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
121381
121382 /*
121383 ** Add an entry for token pToken to the pCsr->pDeferred list.
121384 */
121385 SQLITE_PRIVATE int sqlite3Fts3DeferToken(
@@ -121451,11 +122563,11 @@
121451 ){
121452 Fts3Table *p = (Fts3Table *)pVtab;
121453 int rc = SQLITE_OK; /* Return Code */
121454 int isRemove = 0; /* True for an UPDATE or DELETE */
121455 sqlite3_int64 iRemove = 0; /* Rowid removed by UPDATE or DELETE */
121456 u32 *aSzIns; /* Sizes of inserted documents */
121457 u32 *aSzDel; /* Sizes of deleted documents */
121458 int nChng = 0; /* Net change in number of documents */
121459 int bInsertDone = 0;
121460
121461 assert( p->pSegments==0 );
@@ -121466,16 +122578,20 @@
121466 */
121467 if( nArg>1
121468 && sqlite3_value_type(apVal[0])==SQLITE_NULL
121469 && sqlite3_value_type(apVal[p->nColumn+2])!=SQLITE_NULL
121470 ){
121471 return fts3SpecialInsert(p, apVal[p->nColumn+2]);
 
121472 }
121473
121474 /* Allocate space to hold the change in document sizes */
121475 aSzIns = sqlite3_malloc( sizeof(aSzIns[0])*(p->nColumn+1)*2 );
121476 if( aSzIns==0 ) return SQLITE_NOMEM;
 
 
 
121477 aSzDel = &aSzIns[p->nColumn+1];
121478 memset(aSzIns, 0, sizeof(aSzIns[0])*(p->nColumn+1)*2);
121479
121480 /* If this is an INSERT operation, or an UPDATE that modifies the rowid
121481 ** value, then this operation requires constraint handling.
@@ -121521,12 +122637,11 @@
121521 bInsertDone = 1;
121522 }
121523 }
121524 }
121525 if( rc!=SQLITE_OK ){
121526 sqlite3_free(aSzIns);
121527 return rc;
121528 }
121529
121530 /* If this is a DELETE or UPDATE operation, remove the old record. */
121531 if( sqlite3_value_type(apVal[0])!=SQLITE_NULL ){
121532 assert( sqlite3_value_type(apVal[0])==SQLITE_INTEGER );
@@ -121555,10 +122670,11 @@
121555
121556 if( p->bHasStat ){
121557 fts3UpdateDocTotals(&rc, p, aSzIns, aSzDel, nChng);
121558 }
121559
 
121560 sqlite3_free(aSzIns);
121561 sqlite3Fts3SegmentsClose(p);
121562 return rc;
121563 }
121564
@@ -121569,16 +122685,14 @@
121569 */
121570 SQLITE_PRIVATE int sqlite3Fts3Optimize(Fts3Table *p){
121571 int rc;
121572 rc = sqlite3_exec(p->db, "SAVEPOINT fts3", 0, 0, 0);
121573 if( rc==SQLITE_OK ){
121574 rc = fts3SegmentMerge(p, FTS3_SEGCURSOR_ALL);
121575 if( rc==SQLITE_OK ){
121576 rc = sqlite3_exec(p->db, "RELEASE fts3", 0, 0, 0);
121577 if( rc==SQLITE_OK ){
121578 sqlite3Fts3PendingTermsClear(p);
121579 }
121580 }else{
121581 sqlite3_exec(p->db, "ROLLBACK TO fts3", 0, 0, 0);
121582 sqlite3_exec(p->db, "RELEASE fts3", 0, 0, 0);
121583 }
121584 }
@@ -121763,76 +122877,24 @@
121763 ){
121764 int iPhrase = 0; /* Variable used as the phrase counter */
121765 return fts3ExprIterate2(pExpr, &iPhrase, x, pCtx);
121766 }
121767
121768 /*
121769 ** The argument to this function is always a phrase node. Its doclist
121770 ** (Fts3Expr.aDoclist[]) and the doclists associated with all phrase nodes
121771 ** to the left of this one in the query tree have already been loaded.
121772 **
121773 ** If this phrase node is part of a series of phrase nodes joined by
121774 ** NEAR operators (and is not the left-most of said series), then elements are
121775 ** removed from the phrases doclist consistent with the NEAR restriction. If
121776 ** required, elements may be removed from the doclists of phrases to the
121777 ** left of this one that are part of the same series of NEAR operator
121778 ** connected phrases.
121779 **
121780 ** If an OOM error occurs, SQLITE_NOMEM is returned. Otherwise, SQLITE_OK.
121781 */
121782 static int fts3ExprNearTrim(Fts3Expr *pExpr){
121783 int rc = SQLITE_OK;
121784 Fts3Expr *pParent = pExpr->pParent;
121785
121786 assert( pExpr->eType==FTSQUERY_PHRASE );
121787 while( rc==SQLITE_OK
121788 && pParent
121789 && pParent->eType==FTSQUERY_NEAR
121790 && pParent->pRight==pExpr
121791 ){
121792 /* This expression (pExpr) is the right-hand-side of a NEAR operator.
121793 ** Find the expression to the left of the same operator.
121794 */
121795 int nNear = pParent->nNear;
121796 Fts3Expr *pLeft = pParent->pLeft;
121797
121798 if( pLeft->eType!=FTSQUERY_PHRASE ){
121799 assert( pLeft->eType==FTSQUERY_NEAR );
121800 assert( pLeft->pRight->eType==FTSQUERY_PHRASE );
121801 pLeft = pLeft->pRight;
121802 }
121803
121804 rc = sqlite3Fts3ExprNearTrim(pLeft, pExpr, nNear);
121805
121806 pExpr = pLeft;
121807 pParent = pExpr->pParent;
121808 }
121809
121810 return rc;
121811 }
121812
121813 /*
121814 ** This is an fts3ExprIterate() callback used while loading the doclists
121815 ** for each phrase into Fts3Expr.aDoclist[]/nDoclist. See also
121816 ** fts3ExprLoadDoclists().
121817 */
121818 static int fts3ExprLoadDoclistsCb(Fts3Expr *pExpr, int iPhrase, void *ctx){
121819 int rc = SQLITE_OK;
 
121820 LoadDoclistCtx *p = (LoadDoclistCtx *)ctx;
121821
121822 UNUSED_PARAMETER(iPhrase);
121823
121824 p->nPhrase++;
121825 p->nToken += pExpr->pPhrase->nToken;
121826
121827 if( pExpr->isLoaded==0 ){
121828 rc = sqlite3Fts3ExprLoadDoclist(p->pCsr, pExpr);
121829 pExpr->isLoaded = 1;
121830 if( rc==SQLITE_OK ){
121831 rc = fts3ExprNearTrim(pExpr);
121832 }
121833 }
121834
121835 return rc;
121836 }
121837
121838 /*
@@ -122002,11 +123064,11 @@
122002 SnippetPhrase *pPhrase = &p->aPhrase[iPhrase];
122003 char *pCsr;
122004
122005 pPhrase->nToken = pExpr->pPhrase->nToken;
122006
122007 pCsr = sqlite3Fts3FindPositions(p->pCsr, pExpr, p->pCsr->iPrevId, p->iCol);
122008 if( pCsr ){
122009 int iFirst = 0;
122010 pPhrase->pList = pCsr;
122011 fts3GetDeltaPosition(&pCsr, &iFirst);
122012 pPhrase->pHead = pCsr;
@@ -122359,30 +123421,10 @@
122359
122360 *ppCollist = pEnd;
122361 return nEntry;
122362 }
122363
122364 static void fts3LoadColumnlistCounts(char **pp, u32 *aOut, int isGlobal){
122365 char *pCsr = *pp;
122366 while( *pCsr ){
122367 int nHit;
122368 sqlite3_int64 iCol = 0;
122369 if( *pCsr==0x01 ){
122370 pCsr++;
122371 pCsr += sqlite3Fts3GetVarint(pCsr, &iCol);
122372 }
122373 nHit = fts3ColumnlistCount(&pCsr);
122374 assert( nHit>0 );
122375 if( isGlobal ){
122376 aOut[iCol*3+1]++;
122377 }
122378 aOut[iCol*3] += nHit;
122379 }
122380 pCsr++;
122381 *pp = pCsr;
122382 }
122383
122384 /*
122385 ** fts3ExprIterate() callback used to collect the "global" matchinfo stats
122386 ** for a single query.
122387 **
122388 ** fts3ExprIterate() callback to load the 'global' elements of a
@@ -122412,52 +123454,13 @@
122412 Fts3Expr *pExpr, /* Phrase expression node */
122413 int iPhrase, /* Phrase number (numbered from zero) */
122414 void *pCtx /* Pointer to MatchInfo structure */
122415 ){
122416 MatchInfo *p = (MatchInfo *)pCtx;
122417 Fts3Cursor *pCsr = p->pCursor;
122418 char *pIter;
122419 char *pEnd;
122420 char *pFree = 0;
122421 u32 *aOut = &p->aMatchinfo[3*iPhrase*p->nCol];
122422
122423 assert( pExpr->isLoaded );
122424 assert( pExpr->eType==FTSQUERY_PHRASE );
122425
122426 if( pCsr->pDeferred ){
122427 Fts3Phrase *pPhrase = pExpr->pPhrase;
122428 int ii;
122429 for(ii=0; ii<pPhrase->nToken; ii++){
122430 if( pPhrase->aToken[ii].bFulltext ) break;
122431 }
122432 if( ii<pPhrase->nToken ){
122433 int nFree = 0;
122434 int rc = sqlite3Fts3ExprLoadFtDoclist(pCsr, pExpr, &pFree, &nFree);
122435 if( rc!=SQLITE_OK ) return rc;
122436 pIter = pFree;
122437 pEnd = &pFree[nFree];
122438 }else{
122439 int iCol; /* Column index */
122440 for(iCol=0; iCol<p->nCol; iCol++){
122441 aOut[iCol*3 + 1] = (u32)p->nDoc;
122442 aOut[iCol*3 + 2] = (u32)p->nDoc;
122443 }
122444 return SQLITE_OK;
122445 }
122446 }else{
122447 pIter = pExpr->aDoclist;
122448 pEnd = &pExpr->aDoclist[pExpr->nDoclist];
122449 }
122450
122451 /* Fill in the global hit count matrix row for this phrase. */
122452 while( pIter<pEnd ){
122453 while( *pIter++ & 0x80 ); /* Skip past docid. */
122454 fts3LoadColumnlistCounts(&pIter, &aOut[1], 1);
122455 }
122456
122457 sqlite3_free(pFree);
122458 return SQLITE_OK;
122459 }
122460
122461 /*
122462 ** fts3ExprIterate() callback used to collect the "local" part of the
122463 ** FTS3_MATCHINFO_HITS array. The local stats are those elements of the
@@ -122470,18 +123473,17 @@
122470 ){
122471 MatchInfo *p = (MatchInfo *)pCtx;
122472 int iStart = iPhrase * p->nCol * 3;
122473 int i;
122474
122475 for(i=0; i<p->nCol; i++) p->aMatchinfo[iStart+i*3] = 0;
122476
122477 if( pExpr->aDoclist ){
122478 char *pCsr;
122479
122480 pCsr = sqlite3Fts3FindPositions(p->pCursor, pExpr, p->pCursor->iPrevId, -1);
122481 if( pCsr ){
122482 fts3LoadColumnlistCounts(&pCsr, &p->aMatchinfo[iStart], 0);
 
 
122483 }
122484 }
122485
122486 return SQLITE_OK;
122487 }
@@ -122563,13 +123565,12 @@
122563 ** values for a matchinfo() FTS3_MATCHINFO_LCS request.
122564 */
122565 typedef struct LcsIterator LcsIterator;
122566 struct LcsIterator {
122567 Fts3Expr *pExpr; /* Pointer to phrase expression */
122568 char *pRead; /* Cursor used to iterate through aDoclist */
122569 int iPosOffset; /* Tokens count up to end of this phrase */
122570 int iCol; /* Current column number */
122571 int iPos; /* Current position */
122572 };
122573
122574 /*
122575 ** If LcsIterator.iCol is set to the following value, the iterator has
@@ -122596,21 +123597,14 @@
122596 char *pRead = pIter->pRead;
122597 sqlite3_int64 iRead;
122598 int rc = 0;
122599
122600 pRead += sqlite3Fts3GetVarint(pRead, &iRead);
122601 if( iRead==0 ){
122602 pIter->iCol = LCS_ITERATOR_FINISHED;
122603 rc = 1;
122604 }else{
122605 if( iRead==1 ){
122606 pRead += sqlite3Fts3GetVarint(pRead, &iRead);
122607 pIter->iCol = (int)iRead;
122608 pIter->iPos = pIter->iPosOffset;
122609 pRead += sqlite3Fts3GetVarint(pRead, &iRead);
122610 rc = 1;
122611 }
122612 pIter->iPos += (int)(iRead-2);
122613 }
122614
122615 pIter->pRead = pRead;
122616 return rc;
@@ -122638,46 +123632,38 @@
122638 **/
122639 aIter = sqlite3_malloc(sizeof(LcsIterator) * pCsr->nPhrase);
122640 if( !aIter ) return SQLITE_NOMEM;
122641 memset(aIter, 0, sizeof(LcsIterator) * pCsr->nPhrase);
122642 (void)fts3ExprIterate(pCsr->pExpr, fts3MatchinfoLcsCb, (void*)aIter);
 
122643 for(i=0; i<pInfo->nPhrase; i++){
122644 LcsIterator *pIter = &aIter[i];
122645 nToken -= pIter->pExpr->pPhrase->nToken;
122646 pIter->iPosOffset = nToken;
122647 pIter->pRead = sqlite3Fts3FindPositions(pCsr,pIter->pExpr,pCsr->iPrevId,-1);
122648 if( pIter->pRead ){
122649 pIter->iPos = pIter->iPosOffset;
122650 fts3LcsIteratorAdvance(&aIter[i]);
122651 }else{
122652 pIter->iCol = LCS_ITERATOR_FINISHED;
122653 }
122654 }
122655
122656 for(iCol=0; iCol<pInfo->nCol; iCol++){
122657 int nLcs = 0; /* LCS value for this column */
122658 int nLive = 0; /* Number of iterators in aIter not at EOF */
122659
122660 /* Loop through the iterators in aIter[]. Set nLive to the number of
122661 ** iterators that point to a position-list corresponding to column iCol.
122662 */
122663 for(i=0; i<pInfo->nPhrase; i++){
122664 assert( aIter[i].iCol>=iCol );
122665 if( aIter[i].iCol==iCol ) nLive++;
 
 
 
 
 
122666 }
122667
122668 /* The following loop runs until all iterators in aIter[] have finished
122669 ** iterating through positions in column iCol. Exactly one of the
122670 ** iterators is advanced each time the body of the loop is run.
122671 */
122672 while( nLive>0 ){
122673 LcsIterator *pAdv = 0; /* The iterator to advance by one position */
122674 int nThisLcs = 0; /* LCS for the current iterator positions */
122675
122676 for(i=0; i<pInfo->nPhrase; i++){
122677 LcsIterator *pIter = &aIter[i];
122678 if( iCol!=pIter->iCol ){
122679 /* This iterator is already at EOF for this column. */
122680 nThisLcs = 0;
122681 }else{
122682 if( pAdv==0 || pIter->iPos<pAdv->iPos ){
122683 pAdv = pIter;
@@ -123013,11 +123999,11 @@
123013 int iTerm; /* For looping through nTerm phrase terms */
123014 char *pList; /* Pointer to position list for phrase */
123015 int iPos = 0; /* First position in position-list */
123016
123017 UNUSED_PARAMETER(iPhrase);
123018 pList = sqlite3Fts3FindPositions(p->pCsr, pExpr, p->iDocid, p->iCol);
123019 nTerm = pExpr->pPhrase->nToken;
123020 if( pList ){
123021 fts3GetDeltaPosition(&pList, &iPos);
123022 assert( iPos>=0 );
123023 }
123024
--- src/sqlite3.c
+++ src/sqlite3.c
@@ -650,11 +650,11 @@
650 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
651 ** [sqlite_version()] and [sqlite_source_id()].
652 */
653 #define SQLITE_VERSION "3.7.7"
654 #define SQLITE_VERSION_NUMBER 3007007
655 #define SQLITE_SOURCE_ID "2011-06-15 13:11:06 f9750870ee04935f338e4d808900fee5a8b2b389"
656
657 /*
658 ** CAPI3REF: Run-Time Library Version Numbers
659 ** KEYWORDS: sqlite3_version, sqlite3_sourceid
660 **
@@ -8483,10 +8483,11 @@
8483 SQLITE_PRIVATE int sqlite3VdbeAddOp2(Vdbe*,int,int,int);
8484 SQLITE_PRIVATE int sqlite3VdbeAddOp3(Vdbe*,int,int,int,int);
8485 SQLITE_PRIVATE int sqlite3VdbeAddOp4(Vdbe*,int,int,int,int,const char *zP4,int);
8486 SQLITE_PRIVATE int sqlite3VdbeAddOp4Int(Vdbe*,int,int,int,int,int);
8487 SQLITE_PRIVATE int sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp);
8488 SQLITE_PRIVATE void sqlite3VdbeAddParseSchemaOp(Vdbe*,int,char*);
8489 SQLITE_PRIVATE void sqlite3VdbeChangeP1(Vdbe*, int addr, int P1);
8490 SQLITE_PRIVATE void sqlite3VdbeChangeP2(Vdbe*, int addr, int P2);
8491 SQLITE_PRIVATE void sqlite3VdbeChangeP3(Vdbe*, int addr, int P3);
8492 SQLITE_PRIVATE void sqlite3VdbeChangeP5(Vdbe*, u8 P5);
8493 SQLITE_PRIVATE void sqlite3VdbeJumpHere(Vdbe*, int addr);
@@ -9282,11 +9283,11 @@
9283 ** sqlite3_close().
9284 *
9285 ** A thread must be holding a mutex on the corresponding Btree in order
9286 ** to access Schema content. This implies that the thread must also be
9287 ** holding a mutex on the sqlite3 connection pointer that owns the Btree.
9288 ** For a TEMP Schema, only the connection mutex is required.
9289 */
9290 struct Schema {
9291 int schema_cookie; /* Database schema version number for this file */
9292 int iGeneration; /* Generation counter. Incremented with each change */
9293 Hash tblHash; /* All tables indexed by name */
@@ -11479,11 +11480,11 @@
11480 SQLITE_PRIVATE int sqlite3AtoF(const char *z, double*, int, u8);
11481 SQLITE_PRIVATE int sqlite3GetInt32(const char *, int*);
11482 SQLITE_PRIVATE int sqlite3Atoi(const char*);
11483 SQLITE_PRIVATE int sqlite3Utf16ByteLen(const void *pData, int nChar);
11484 SQLITE_PRIVATE int sqlite3Utf8CharLen(const char *pData, int nByte);
11485 SQLITE_PRIVATE u32 sqlite3Utf8Read(const u8*, const u8**);
11486
11487 /*
11488 ** Routines to read and write variable-length integers. These used to
11489 ** be defined locally, but now we use the varint routines in the util.c
11490 ** file. Code should use the MACRO forms below, as the Varint32 versions
@@ -20086,11 +20087,11 @@
20087 } \
20088 if( c<0x80 \
20089 || (c&0xFFFFF800)==0xD800 \
20090 || (c&0xFFFFFFFE)==0xFFFE ){ c = 0xFFFD; } \
20091 }
20092 SQLITE_PRIVATE u32 sqlite3Utf8Read(
20093 const unsigned char *zIn, /* First byte of UTF-8 character */
20094 const unsigned char **pzNext /* Write first byte past UTF-8 char here */
20095 ){
20096 unsigned int c;
20097
@@ -35805,11 +35806,11 @@
35806 memset(pCache, 0, sz);
35807 if( separateCache ){
35808 pGroup = (PGroup*)&pCache[1];
35809 pGroup->mxPinned = 10;
35810 }else{
35811 pGroup = &pcache1.grp;
35812 }
35813 pCache->pGroup = pGroup;
35814 pCache->szPage = szPage;
35815 pCache->bPurgeable = (bPurgeable ? 1 : 0);
35816 if( bPurgeable ){
@@ -48324,10 +48325,12 @@
48325 **
48326 ** This routine works only for pages that do not contain overflow cells.
48327 */
48328 #define findCell(P,I) \
48329 ((P)->aData + ((P)->maskPage & get2byte(&(P)->aData[(P)->cellOffset+2*(I)])))
48330 #define findCellv2(D,M,O,I) (D+(M&get2byte(D+(O+2*(I)))))
48331
48332
48333 /*
48334 ** This a more complex version of findCell() that works for
48335 ** pages that do contain overflow cells.
48336 */
@@ -51918,11 +51921,11 @@
51921 assert( pCur->apPage[pCur->iPage]->nCell==0 );
51922 return SQLITE_OK;
51923 }
51924 assert( pCur->apPage[0]->intKey || pIdxKey );
51925 for(;;){
51926 int lwr, upr, idx;
51927 Pgno chldPg;
51928 MemPage *pPage = pCur->apPage[pCur->iPage];
51929 int c;
51930
51931 /* pPage->nCell must be greater than zero. If this is the root-page
@@ -51934,18 +51937,18 @@
51937 assert( pPage->nCell>0 );
51938 assert( pPage->intKey==(pIdxKey==0) );
51939 lwr = 0;
51940 upr = pPage->nCell-1;
51941 if( biasRight ){
51942 pCur->aiIdx[pCur->iPage] = (u16)(idx = upr);
51943 }else{
51944 pCur->aiIdx[pCur->iPage] = (u16)(idx = (upr+lwr)/2);
51945 }
51946 for(;;){
 
51947 u8 *pCell; /* Pointer to current cell in pPage */
51948
51949 assert( idx==pCur->aiIdx[pCur->iPage] );
51950 pCur->info.nSize = 0;
51951 pCell = findCell(pPage, idx) + pPage->childPtrSize;
51952 if( pPage->intKey ){
51953 i64 nCellKey;
51954 if( pPage->hasData ){
@@ -52024,11 +52027,11 @@
52027 upr = idx-1;
52028 }
52029 if( lwr>upr ){
52030 break;
52031 }
52032 pCur->aiIdx[pCur->iPage] = (u16)(idx = (lwr+upr)/2);
52033 }
52034 assert( lwr==upr+1 );
52035 assert( pPage->isInit );
52036 if( pPage->leaf ){
52037 chldPg = 0;
@@ -52886,13 +52889,13 @@
52889 if( rc ){
52890 *pRC = rc;
52891 return;
52892 }
52893 endPtr = &data[pPage->cellOffset + 2*pPage->nCell - 2];
52894 assert( (SQLITE_PTR_TO_INT(ptr)&1)==0 ); /* ptr is always 2-byte aligned */
52895 while( ptr<endPtr ){
52896 *(u16*)ptr = *(u16*)&ptr[2];
 
52897 ptr += 2;
52898 }
52899 pPage->nCell--;
52900 put2byte(&data[hdr+3], pPage->nCell);
52901 pPage->nFree += 2;
@@ -52929,10 +52932,11 @@
52932 int end; /* First byte past the last cell pointer in data[] */
52933 int ins; /* Index in data[] where new cell pointer is inserted */
52934 int cellOffset; /* Address of first cell pointer in data[] */
52935 u8 *data; /* The content of the whole page */
52936 u8 *ptr; /* Used for moving information around in data[] */
52937 u8 *endPtr; /* End of the loop */
52938
52939 int nSkip = (iChild ? 4 : 0);
52940
52941 if( *pRC ) return;
52942
@@ -52979,13 +52983,16 @@
52983 pPage->nFree -= (u16)(2 + sz);
52984 memcpy(&data[idx+nSkip], pCell+nSkip, sz-nSkip);
52985 if( iChild ){
52986 put4byte(&data[idx], iChild);
52987 }
52988 ptr = &data[end];
52989 endPtr = &data[ins];
52990 assert( (SQLITE_PTR_TO_INT(ptr)&1)==0 ); /* ptr is always 2-byte aligned */
52991 while( ptr>endPtr ){
52992 *(u16*)ptr = *(u16*)&ptr[-2];
52993 ptr -= 2;
52994 }
52995 put2byte(&data[ins], idx);
52996 put2byte(&data[pPage->hdrOffset+3], pPage->nCell);
52997 #ifndef SQLITE_OMIT_AUTOVACUUM
52998 if( pPage->pBt->autoVacuum ){
@@ -53026,14 +53033,15 @@
53033 assert( get2byteNotZero(&data[hdr+5])==nUsable );
53034
53035 pCellptr = &data[pPage->cellOffset + nCell*2];
53036 cellbody = nUsable;
53037 for(i=nCell-1; i>=0; i--){
53038 u16 sz = aSize[i];
53039 pCellptr -= 2;
53040 cellbody -= sz;
53041 put2byte(pCellptr, cellbody);
53042 memcpy(&data[cellbody], apCell[i], sz);
53043 }
53044 put2byte(&data[hdr+3], nCell);
53045 put2byte(&data[hdr+5], cellbody);
53046 pPage->nFree -= (nCell*2 + nUsable - cellbody);
53047 pPage->nCell = (u16)nCell;
@@ -53483,16 +53491,28 @@
53491 memcpy(pOld, apOld[i], sizeof(MemPage));
53492 pOld->aData = (void*)&pOld[1];
53493 memcpy(pOld->aData, apOld[i]->aData, pBt->pageSize);
53494
53495 limit = pOld->nCell+pOld->nOverflow;
53496 if( pOld->nOverflow>0 ){
53497 for(j=0; j<limit; j++){
53498 assert( nCell<nMaxCells );
53499 apCell[nCell] = findOverflowCell(pOld, j);
53500 szCell[nCell] = cellSizePtr(pOld, apCell[nCell]);
53501 nCell++;
53502 }
53503 }else{
53504 u8 *aData = pOld->aData;
53505 u16 maskPage = pOld->maskPage;
53506 u16 cellOffset = pOld->cellOffset;
53507 for(j=0; j<limit; j++){
53508 assert( nCell<nMaxCells );
53509 apCell[nCell] = findCellv2(aData, maskPage, cellOffset, j);
53510 szCell[nCell] = cellSizePtr(pOld, apCell[nCell]);
53511 nCell++;
53512 }
53513 }
53514 if( i<nOld-1 && !leafData){
53515 u16 sz = (u16)szNew[i];
53516 u8 *pTemp;
53517 assert( nCell<nMaxCells );
53518 szCell[nCell] = sz;
@@ -57637,17 +57657,10 @@
57657 pOp->p1 = p1;
57658 pOp->p2 = p2;
57659 pOp->p3 = p3;
57660 pOp->p4.p = 0;
57661 pOp->p4type = P4_NOTUSED;
 
 
 
 
 
 
 
57662 #ifdef SQLITE_DEBUG
57663 pOp->zComment = 0;
57664 if( sqlite3VdbeAddopTrace ) sqlite3VdbePrintOp(0, i, &p->aOp[i]);
57665 #endif
57666 #ifdef VDBE_PROFILE
@@ -57681,10 +57694,24 @@
57694 ){
57695 int addr = sqlite3VdbeAddOp3(p, op, p1, p2, p3);
57696 sqlite3VdbeChangeP4(p, addr, zP4, p4type);
57697 return addr;
57698 }
57699
57700 /*
57701 ** Add an OP_ParseSchema opcode. This routine is broken out from
57702 ** sqlite3VdbeAddOp4() since it needs to also local all btrees.
57703 **
57704 ** The zWhere string must have been obtained from sqlite3_malloc().
57705 ** This routine will take ownership of the allocated memory.
57706 */
57707 SQLITE_PRIVATE void sqlite3VdbeAddParseSchemaOp(Vdbe *p, int iDb, char *zWhere){
57708 int j;
57709 int addr = sqlite3VdbeAddOp3(p, OP_ParseSchema, iDb, 0, 0);
57710 sqlite3VdbeChangeP4(p, addr, zWhere, P4_DYNAMIC);
57711 for(j=0; j<p->db->nDb; j++) sqlite3VdbeUsesBtree(p, j);
57712 }
57713
57714 /*
57715 ** Add an opcode that includes the p4 value as an integer.
57716 */
57717 SQLITE_PRIVATE int sqlite3VdbeAddOp4Int(
@@ -64083,10 +64110,20 @@
64110 u.ag.ctx.pColl = pOp[-1].p4.pColl;
64111 }
64112 db->lastRowid = lastRowid;
64113 (*u.ag.ctx.pFunc->xFunc)(&u.ag.ctx, u.ag.n, u.ag.apVal); /* IMP: R-24505-23230 */
64114 lastRowid = db->lastRowid;
64115
64116 /* If any auxiliary data functions have been called by this user function,
64117 ** immediately call the destructor for any non-static values.
64118 */
64119 if( u.ag.ctx.pVdbeFunc ){
64120 sqlite3VdbeDeleteAuxData(u.ag.ctx.pVdbeFunc, pOp->p1);
64121 pOp->p4.pVdbeFunc = u.ag.ctx.pVdbeFunc;
64122 pOp->p4type = P4_VDBEFUNC;
64123 }
64124
64125 if( db->mallocFailed ){
64126 /* Even though a malloc() has failed, the implementation of the
64127 ** user function may have called an sqlite3_result_XXX() function
64128 ** to return a value. The following call releases any resources
64129 ** associated with such a value.
@@ -64093,19 +64130,10 @@
64130 */
64131 sqlite3VdbeMemRelease(&u.ag.ctx.s);
64132 goto no_mem;
64133 }
64134
 
 
 
 
 
 
 
 
 
64135 /* If the function returned an error, throw an exception */
64136 if( u.ag.ctx.isError ){
64137 sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(&u.ag.ctx.s));
64138 rc = u.ag.ctx.isError;
64139 }
@@ -75255,18 +75283,18 @@
75283 sqlite3VdbeAddOp4(v, OP_DropTable, iDb, 0, 0, pTab->zName, 0);
75284
75285 /* Reload the table, index and permanent trigger schemas. */
75286 zWhere = sqlite3MPrintf(pParse->db, "tbl_name=%Q", zName);
75287 if( !zWhere ) return;
75288 sqlite3VdbeAddParseSchemaOp(v, iDb, zWhere);
75289
75290 #ifndef SQLITE_OMIT_TRIGGER
75291 /* Now, if the table is not stored in the temp database, reload any temp
75292 ** triggers. Don't use IN(...) in case SQLITE_OMIT_SUBQUERY is defined.
75293 */
75294 if( (zWhere=whereTempTriggers(pParse, pTab))!=0 ){
75295 sqlite3VdbeAddParseSchemaOp(v, 1, zWhere);
75296 }
75297 #endif
75298 }
75299
75300 /*
@@ -78875,12 +78903,12 @@
78903 }
78904 }
78905 #endif
78906
78907 /* Reparse everything to update our internal data structures */
78908 sqlite3VdbeAddParseSchemaOp(v, iDb,
78909 sqlite3MPrintf(db, "tbl_name='%q'", p->zName));
78910 }
78911
78912
78913 /* Add the table to the in-memory representation of the database.
78914 */
@@ -80073,13 +80101,12 @@
80101 ** to invalidate all pre-compiled statements.
80102 */
80103 if( pTblName ){
80104 sqlite3RefillIndex(pParse, pIndex, iMem);
80105 sqlite3ChangeCookie(pParse, iDb);
80106 sqlite3VdbeAddParseSchemaOp(v, iDb,
80107 sqlite3MPrintf(db, "name='%q' AND type='index'", pIndex->zName));
 
80108 sqlite3VdbeAddOp1(v, OP_Expire, 0);
80109 }
80110 }
80111
80112 /* When adding an index to the list of indices for a table, make
@@ -82621,14 +82648,14 @@
82648 ** character is exactly one byte in size. Also, all characters are
82649 ** able to participate in upper-case-to-lower-case mappings in EBCDIC
82650 ** whereas only characters less than 0x80 do in ASCII.
82651 */
82652 #if defined(SQLITE_EBCDIC)
82653 # define sqlite3Utf8Read(A,C) (*(A++))
82654 # define GlogUpperToLower(A) A = sqlite3UpperToLower[A]
82655 #else
82656 # define GlogUpperToLower(A) if( !((A)&~0x7f) ){ A = sqlite3UpperToLower[A]; }
82657 #endif
82658
82659 static const struct compareInfo globInfo = { '*', '?', '[', 0 };
82660 /* The correct SQL-92 behavior is for the LIKE operator to ignore
82661 ** case. Thus 'a' LIKE 'A' would be true. */
@@ -82667,13 +82694,13 @@
82694 */
82695 static int patternCompare(
82696 const u8 *zPattern, /* The glob pattern */
82697 const u8 *zString, /* The string to compare against the glob */
82698 const struct compareInfo *pInfo, /* Information about how to do the compare */
82699 u32 esc /* The escape character */
82700 ){
82701 u32 c, c2;
82702 int invert;
82703 int seen;
82704 u8 matchOne = pInfo->matchOne;
82705 u8 matchAll = pInfo->matchAll;
82706 u8 matchSet = pInfo->matchSet;
@@ -82723,11 +82750,11 @@
82750 }else if( !prevEscape && c==matchOne ){
82751 if( sqlite3Utf8Read(zString, &zString)==0 ){
82752 return 0;
82753 }
82754 }else if( c==matchSet ){
82755 u32 prior_c = 0;
82756 assert( esc==0 ); /* This only occurs for GLOB, not LIKE */
82757 seen = 0;
82758 invert = 0;
82759 c = sqlite3Utf8Read(zString, &zString);
82760 if( c==0 ) return 0;
@@ -82799,11 +82826,11 @@
82826 sqlite3_context *context,
82827 int argc,
82828 sqlite3_value **argv
82829 ){
82830 const unsigned char *zA, *zB;
82831 u32 escape = 0;
82832 int nPat;
82833 sqlite3 *db = sqlite3_context_db_handle(context);
82834
82835 zB = sqlite3_value_text(argv[0]);
82836 zA = sqlite3_value_text(argv[1]);
@@ -84110,17 +84137,29 @@
84137 }
84138
84139 /* If the parent table is the same as the child table, and we are about
84140 ** to increment the constraint-counter (i.e. this is an INSERT operation),
84141 ** then check if the row being inserted matches itself. If so, do not
84142 ** increment the constraint-counter.
84143 **
84144 ** If any of the parent-key values are NULL, then the row cannot match
84145 ** itself. So set JUMPIFNULL to make sure we do the OP_Found if any
84146 ** of the parent-key values are NULL (at this point it is known that
84147 ** none of the child key values are).
84148 */
84149 if( pTab==pFKey->pFrom && nIncr==1 ){
84150 int iJump = sqlite3VdbeCurrentAddr(v) + nCol + 1;
84151 for(i=0; i<nCol; i++){
84152 int iChild = aiCol[i]+1+regData;
84153 int iParent = pIdx->aiColumn[i]+1+regData;
84154 assert( aiCol[i]!=pTab->iPKey );
84155 if( pIdx->aiColumn[i]==pTab->iPKey ){
84156 /* The parent key is a composite key that includes the IPK column */
84157 iParent = regData;
84158 }
84159 sqlite3VdbeAddOp3(v, OP_Ne, iChild, iJump, iParent);
84160 sqlite3VdbeChangeP5(v, SQLITE_JUMPIFNULL);
84161 }
84162 sqlite3VdbeAddOp2(v, OP_Goto, 0, iOk);
84163 }
84164
84165 sqlite3VdbeAddOp3(v, OP_MakeRecord, regTemp, nCol, regRec);
@@ -95336,13 +95375,12 @@
95375 "INSERT INTO %Q.%s VALUES('trigger',%Q,%Q,0,'CREATE TRIGGER %q')",
95376 db->aDb[iDb].zName, SCHEMA_TABLE(iDb), zName,
95377 pTrig->table, z);
95378 sqlite3DbFree(db, z);
95379 sqlite3ChangeCookie(pParse, iDb);
95380 sqlite3VdbeAddParseSchemaOp(v, iDb,
95381 sqlite3MPrintf(db, "type='trigger' AND name='%q'", zName));
 
95382 }
95383
95384 if( db->init.busy ){
95385 Trigger *pLink = pTrig;
95386 Hash *pHash = &db->aDb[iDb].pSchema->trigHash;
@@ -96392,11 +96430,11 @@
96430 aRegIdx = sqlite3DbMallocRaw(db, sizeof(Index*) * nIdx );
96431 if( aRegIdx==0 ) goto update_cleanup;
96432 }
96433 for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
96434 int reg;
96435 if( hasFK || chngRowid ){
96436 reg = ++pParse->nMem;
96437 }else{
96438 reg = 0;
96439 for(i=0; i<pIdx->nColumn; i++){
96440 if( aXRef[pIdx->aiColumn[i]]>=0 ){
@@ -97547,11 +97585,11 @@
97585 v = sqlite3GetVdbe(pParse);
97586 sqlite3ChangeCookie(pParse, iDb);
97587
97588 sqlite3VdbeAddOp2(v, OP_Expire, 0, 0);
97589 zWhere = sqlite3MPrintf(db, "name='%q' AND type='table'", pTab->zName);
97590 sqlite3VdbeAddParseSchemaOp(v, iDb, zWhere);
97591 sqlite3VdbeAddOp4(v, OP_VCreate, iDb, 0, 0,
97592 pTab->zName, sqlite3Strlen30(pTab->zName) + 1);
97593 }
97594
97595 /* If we are rereading the sqlite_master table create the in-memory
@@ -107274,17 +107312,16 @@
107312 #ifndef SQLITE_OMIT_BLOB_LITERAL
107313 case 'x': case 'X': {
107314 testcase( z[0]=='x' ); testcase( z[0]=='X' );
107315 if( z[1]=='\'' ){
107316 *tokenType = TK_BLOB;
107317 for(i=2; sqlite3Isxdigit(z[i]); i++){}
107318 if( z[i]!='\'' || i%2 ){
107319 *tokenType = TK_ILLEGAL;
107320 while( z[i] && z[i]!='\'' ){ i++; }
107321 }
107322 if( z[i] ) i++;
 
107323 return i;
107324 }
107325 /* Otherwise fall through to the next case */
107326 }
107327 #endif
@@ -111710,16 +111747,39 @@
111747 ** similar macro called ArraySize(). Use a different name to avoid
111748 ** a collision when building an amalgamation with built-in FTS3.
111749 */
111750 #define SizeofArray(X) ((int)(sizeof(X)/sizeof(X[0])))
111751
111752
111753 #ifndef MIN
111754 # define MIN(x,y) ((x)<(y)?(x):(y))
111755 #endif
111756
111757 /*
111758 ** Maximum length of a varint encoded integer. The varint format is different
111759 ** from that used by SQLite, so the maximum length is 10, not 9.
111760 */
111761 #define FTS3_VARINT_MAX 10
111762
111763 /*
111764 ** FTS4 virtual tables may maintain multiple indexes - one index of all terms
111765 ** in the document set and zero or more prefix indexes. All indexes are stored
111766 ** as one or more b+-trees in the %_segments and %_segdir tables.
111767 **
111768 ** It is possible to determine which index a b+-tree belongs to based on the
111769 ** value stored in the "%_segdir.level" column. Given this value L, the index
111770 ** that the b+-tree belongs to is (L<<10). In other words, all b+-trees with
111771 ** level values between 0 and 1023 (inclusive) belong to index 0, all levels
111772 ** between 1024 and 2047 to index 1, and so on.
111773 **
111774 ** It is considered impossible for an index to use more than 1024 levels. In
111775 ** theory though this may happen, but only after at least
111776 ** (FTS3_MERGE_COUNT^1024) separate flushes of the pending-terms tables.
111777 */
111778 #define FTS3_SEGDIR_MAXLEVEL 1024
111779 #define FTS3_SEGDIR_MAXLEVEL_STR "1024"
111780
111781 /*
111782 ** The testcase() macro is only used by the amalgamation. If undefined,
111783 ** make it a no-op.
111784 */
111785 #ifndef testcase
@@ -111787,14 +111847,15 @@
111847 typedef struct Fts3Cursor Fts3Cursor;
111848 typedef struct Fts3Expr Fts3Expr;
111849 typedef struct Fts3Phrase Fts3Phrase;
111850 typedef struct Fts3PhraseToken Fts3PhraseToken;
111851
111852 typedef struct Fts3Doclist Fts3Doclist;
111853 typedef struct Fts3SegFilter Fts3SegFilter;
111854 typedef struct Fts3DeferredToken Fts3DeferredToken;
111855 typedef struct Fts3SegReader Fts3SegReader;
111856 typedef struct Fts3MultiSegReader Fts3MultiSegReader;
111857
111858 /*
111859 ** A connection to a fulltext index is an instance of the following
111860 ** structure. The xCreate and xConnect methods create an instance
111861 ** of this structure and xDestroy and xDisconnect free that instance.
@@ -111811,33 +111872,45 @@
111872 sqlite3_tokenizer *pTokenizer; /* tokenizer for inserts and queries */
111873
111874 /* Precompiled statements used by the implementation. Each of these
111875 ** statements is run and reset within a single virtual table API call.
111876 */
111877 sqlite3_stmt *aStmt[27];
111878
111879 char *zReadExprlist;
111880 char *zWriteExprlist;
111881
111882 int nNodeSize; /* Soft limit for node size */
111883 u8 bHasStat; /* True if %_stat table exists */
111884 u8 bHasDocsize; /* True if %_docsize table exists */
111885 u8 bDescIdx; /* True if doclists are in reverse order */
111886 int nPgsz; /* Page size for host database */
111887 char *zSegmentsTbl; /* Name of %_segments table */
111888 sqlite3_blob *pSegments; /* Blob handle open on %_segments table */
111889
111890 /* TODO: Fix the first paragraph of this comment.
111891 **
111892 ** The following hash table is used to buffer pending index updates during
111893 ** transactions. Variable nPendingData estimates the memory size of the
111894 ** pending data, including hash table overhead, but not malloc overhead.
111895 ** When nPendingData exceeds nMaxPendingData, the buffer is flushed
111896 ** automatically. Variable iPrevDocid is the docid of the most recently
111897 ** inserted record.
111898 **
111899 ** A single FTS4 table may have multiple full-text indexes. For each index
111900 ** there is an entry in the aIndex[] array. Index 0 is an index of all the
111901 ** terms that appear in the document set. Each subsequent index in aIndex[]
111902 ** is an index of prefixes of a specific length.
111903 */
111904 int nIndex; /* Size of aIndex[] */
111905 struct Fts3Index {
111906 int nPrefix; /* Prefix length (0 for main terms index) */
111907 Fts3Hash hPending; /* Pending terms table for this index */
111908 } *aIndex;
111909 int nMaxPendingData; /* Max pending data before flush to disk */
111910 int nPendingData; /* Current bytes of pending data */
111911 sqlite_int64 iPrevDocid; /* Docid of most recently inserted document */
111912
111913 #if defined(SQLITE_DEBUG)
111914 /* State variables used for validating that the transaction control
111915 ** methods of the virtual table are called at appropriate times. These
111916 ** values do not contribution to the FTS computation; they are used for
@@ -111864,13 +111937,14 @@
111937 Fts3DeferredToken *pDeferred; /* Deferred search tokens, if any */
111938 sqlite3_int64 iPrevId; /* Previous id read from aDoclist */
111939 char *pNextId; /* Pointer into the body of aDoclist */
111940 char *aDoclist; /* List of docids for full-text queries */
111941 int nDoclist; /* Size of buffer at aDoclist */
111942 u8 bDesc; /* True to sort in descending order */
111943 int eEvalmode; /* An FTS3_EVAL_XX constant */
111944 int nRowAvg; /* Average size of database rows, in pages */
111945 int nDoc; /* Documents in table */
111946
111947 int isMatchinfoNeeded; /* True when aMatchinfo[] needs filling in */
111948 u32 *aMatchinfo; /* Information about most recent match */
111949 int nMatchinfo; /* Number of elements in aMatchinfo[] */
111950 char *zMatchinfo; /* Matchinfo specification */
@@ -111897,66 +111971,90 @@
111971 */
111972 #define FTS3_FULLSCAN_SEARCH 0 /* Linear scan of %_content table */
111973 #define FTS3_DOCID_SEARCH 1 /* Lookup by rowid on %_content table */
111974 #define FTS3_FULLTEXT_SEARCH 2 /* Full-text index search */
111975
111976
111977 struct Fts3Doclist {
111978 char *aAll; /* Array containing doclist (or NULL) */
111979 int nAll; /* Size of a[] in bytes */
111980 char *pNextDocid; /* Pointer to next docid */
111981
111982 sqlite3_int64 iDocid; /* Current docid (if pList!=0) */
111983 int bFreeList; /* True if pList should be sqlite3_free()d */
111984 char *pList; /* Pointer to position list following iDocid */
111985 int nList; /* Length of position list */
111986 } doclist;
111987
111988 /*
111989 ** A "phrase" is a sequence of one or more tokens that must match in
111990 ** sequence. A single token is the base case and the most common case.
111991 ** For a sequence of tokens contained in double-quotes (i.e. "one two three")
111992 ** nToken will be the number of tokens in the string.
 
 
 
 
 
 
111993 */
111994 struct Fts3PhraseToken {
111995 char *z; /* Text of the token */
111996 int n; /* Number of bytes in buffer z */
111997 int isPrefix; /* True if token ends with a "*" character */
111998
111999 /* Variables above this point are populated when the expression is
112000 ** parsed (by code in fts3_expr.c). Below this point the variables are
112001 ** used when evaluating the expression. */
112002 int bFulltext; /* True if full-text index was used */
 
112003 Fts3DeferredToken *pDeferred; /* Deferred token object for this token */
112004 Fts3MultiSegReader *pSegcsr; /* Segment-reader for this token */
112005 };
112006
112007 struct Fts3Phrase {
112008 /* Cache of doclist for this phrase. */
112009 Fts3Doclist doclist;
112010 int bIncr; /* True if doclist is loaded incrementally */
112011
112012 /* Variables below this point are populated by fts3_expr.c when parsing
112013 ** a MATCH expression. Everything above is part of the evaluation phase.
112014 */
112015 int nToken; /* Number of tokens in the phrase */
112016 int iColumn; /* Index of column this phrase must match */
 
112017 Fts3PhraseToken aToken[1]; /* One entry for each token in the phrase */
112018 };
112019
112020 /*
112021 ** A tree of these objects forms the RHS of a MATCH operator.
112022 **
112023 ** If Fts3Expr.eType is FTSQUERY_PHRASE and isLoaded is true, then aDoclist
112024 ** points to a malloced buffer, size nDoclist bytes, containing the results
112025 ** of this phrase query in FTS3 doclist format. As usual, the initial
112026 ** "Length" field found in doclists stored on disk is omitted from this
112027 ** buffer.
112028 **
112029 ** Variable aMI is used only for FTSQUERY_NEAR nodes to store the global
112030 ** matchinfo data. If it is not NULL, it points to an array of size nCol*3,
112031 ** where nCol is the number of columns in the queried FTS table. The array
112032 ** is populated as follows:
112033 **
112034 ** aMI[iCol*3 + 0] = Undefined
112035 ** aMI[iCol*3 + 1] = Number of occurrences
112036 ** aMI[iCol*3 + 2] = Number of rows containing at least one instance
112037 **
112038 ** The aMI array is allocated using sqlite3_malloc(). It should be freed
112039 ** when the expression node is.
112040 */
112041 struct Fts3Expr {
112042 int eType; /* One of the FTSQUERY_XXX values defined below */
112043 int nNear; /* Valid if eType==FTSQUERY_NEAR */
112044 Fts3Expr *pParent; /* pParent->pLeft==this or pParent->pRight==this */
112045 Fts3Expr *pLeft; /* Left operand */
112046 Fts3Expr *pRight; /* Right operand */
112047 Fts3Phrase *pPhrase; /* Valid if eType==FTSQUERY_PHRASE */
112048
112049 /* The following are used by the fts3_eval.c module. */
112050 sqlite3_int64 iDocid; /* Current docid */
112051 u8 bEof; /* True this expression is at EOF already */
112052 u8 bStart; /* True if iDocid is valid */
112053 u8 bDeferred; /* True if this expression is entirely deferred */
112054
112055 u32 *aMI;
 
112056 };
112057
112058 /*
112059 ** Candidate values for Fts3Query.eType. Note that the order of the first
112060 ** four values is in order of precedence when parsing expressions. For
@@ -111980,35 +112078,36 @@
112078 SQLITE_PRIVATE int sqlite3Fts3PendingTermsFlush(Fts3Table *);
112079 SQLITE_PRIVATE void sqlite3Fts3PendingTermsClear(Fts3Table *);
112080 SQLITE_PRIVATE int sqlite3Fts3Optimize(Fts3Table *);
112081 SQLITE_PRIVATE int sqlite3Fts3SegReaderNew(int, sqlite3_int64,
112082 sqlite3_int64, sqlite3_int64, const char *, int, Fts3SegReader**);
112083 SQLITE_PRIVATE int sqlite3Fts3SegReaderPending(
112084 Fts3Table*,int,const char*,int,int,Fts3SegReader**);
112085 SQLITE_PRIVATE void sqlite3Fts3SegReaderFree(Fts3SegReader *);
112086 SQLITE_PRIVATE int sqlite3Fts3AllSegdirs(Fts3Table*, int, int, sqlite3_stmt **);
 
112087 SQLITE_PRIVATE int sqlite3Fts3ReadLock(Fts3Table *);
112088 SQLITE_PRIVATE int sqlite3Fts3ReadBlock(Fts3Table*, sqlite3_int64, char **, int*, int*);
112089
112090 SQLITE_PRIVATE int sqlite3Fts3SelectDoctotal(Fts3Table *, sqlite3_stmt **);
112091 SQLITE_PRIVATE int sqlite3Fts3SelectDocsize(Fts3Table *, sqlite3_int64, sqlite3_stmt **);
112092
112093 SQLITE_PRIVATE void sqlite3Fts3FreeDeferredTokens(Fts3Cursor *);
112094 SQLITE_PRIVATE int sqlite3Fts3DeferToken(Fts3Cursor *, Fts3PhraseToken *, int);
112095 SQLITE_PRIVATE int sqlite3Fts3CacheDeferredDoclists(Fts3Cursor *);
112096 SQLITE_PRIVATE void sqlite3Fts3FreeDeferredDoclists(Fts3Cursor *);
 
112097 SQLITE_PRIVATE void sqlite3Fts3SegmentsClose(Fts3Table *);
112098
112099 /* Special values interpreted by sqlite3SegReaderCursor() */
112100 #define FTS3_SEGCURSOR_PENDING -1
112101 #define FTS3_SEGCURSOR_ALL -2
112102
112103 SQLITE_PRIVATE int sqlite3Fts3SegReaderStart(Fts3Table*, Fts3MultiSegReader*, Fts3SegFilter*);
112104 SQLITE_PRIVATE int sqlite3Fts3SegReaderStep(Fts3Table *, Fts3MultiSegReader *);
112105 SQLITE_PRIVATE void sqlite3Fts3SegReaderFinish(Fts3MultiSegReader *);
112106
112107 SQLITE_PRIVATE int sqlite3Fts3SegReaderCursor(
112108 Fts3Table *, int, int, const char *, int, int, int, Fts3MultiSegReader *);
112109
112110 /* Flags allowed as part of the 4th argument to SegmentReaderIterate() */
112111 #define FTS3_SEGMENT_REQUIRE_POS 0x00000001
112112 #define FTS3_SEGMENT_IGNORE_EMPTY 0x00000002
112113 #define FTS3_SEGMENT_COLUMN_FILTER 0x00000004
@@ -112021,21 +112120,24 @@
112120 int nTerm;
112121 int iCol;
112122 int flags;
112123 };
112124
112125 struct Fts3MultiSegReader {
112126 /* Used internally by sqlite3Fts3SegReaderXXX() calls */
112127 Fts3SegReader **apSegment; /* Array of Fts3SegReader objects */
112128 int nSegment; /* Size of apSegment array */
112129 int nAdvance; /* How many seg-readers to advance */
112130 Fts3SegFilter *pFilter; /* Pointer to filter object */
112131 char *aBuffer; /* Buffer to merge doclists in */
112132 int nBuffer; /* Allocated size of aBuffer[] in bytes */
112133
112134 int iColFilter; /* If >=0, filter for this column */
112135
112136 /* Used by fts3.c only. */
112137 int nCost; /* Cost of running iterator */
112138 int bLookup; /* True if a lookup of a single entry. */
112139
112140 /* Output values. Valid only after Fts3SegReaderStep() returns SQLITE_ROW. */
112141 char *zTerm; /* Pointer to term buffer */
112142 int nTerm; /* Size of zTerm in bytes */
112143 char *aDoclist; /* Pointer to doclist buffer */
@@ -112046,15 +112148,13 @@
112148 SQLITE_PRIVATE int sqlite3Fts3PutVarint(char *, sqlite3_int64);
112149 SQLITE_PRIVATE int sqlite3Fts3GetVarint(const char *, sqlite_int64 *);
112150 SQLITE_PRIVATE int sqlite3Fts3GetVarint32(const char *, int *);
112151 SQLITE_PRIVATE int sqlite3Fts3VarintLen(sqlite3_uint64);
112152 SQLITE_PRIVATE void sqlite3Fts3Dequote(char *);
112153 SQLITE_PRIVATE void sqlite3Fts3DoclistPrev(int,char*,int,char**,sqlite3_int64*,int*,u8*);
112154
112155 SQLITE_PRIVATE int sqlite3Fts3EvalPhraseStats(Fts3Cursor *, Fts3Expr *, u32 *);
 
 
 
112156
112157 /* fts3_tokenizer.c */
112158 SQLITE_PRIVATE const char *sqlite3Fts3NextToken(const char *, int *);
112159 SQLITE_PRIVATE int sqlite3Fts3InitHashTable(sqlite3 *, Fts3Hash *, const char *);
112160 SQLITE_PRIVATE int sqlite3Fts3InitTokenizer(Fts3Hash *pHash, const char *,
@@ -112079,10 +112179,33 @@
112179 SQLITE_PRIVATE int sqlite3Fts3InitTerm(sqlite3 *db);
112180 #endif
112181
112182 /* fts3_aux.c */
112183 SQLITE_PRIVATE int sqlite3Fts3InitAux(sqlite3 *db);
112184
112185 SQLITE_PRIVATE int sqlite3Fts3TermSegReaderCursor(
112186 Fts3Cursor *pCsr, /* Virtual table cursor handle */
112187 const char *zTerm, /* Term to query for */
112188 int nTerm, /* Size of zTerm in bytes */
112189 int isPrefix, /* True for a prefix search */
112190 Fts3MultiSegReader **ppSegcsr /* OUT: Allocated seg-reader cursor */
112191 );
112192
112193 SQLITE_PRIVATE void sqlite3Fts3EvalPhraseCleanup(Fts3Phrase *);
112194
112195 SQLITE_PRIVATE int sqlite3Fts3EvalStart(Fts3Cursor *, Fts3Expr *, int);
112196 SQLITE_PRIVATE int sqlite3Fts3EvalNext(Fts3Cursor *pCsr);
112197
112198 SQLITE_PRIVATE int sqlite3Fts3MsrIncrStart(
112199 Fts3Table*, Fts3MultiSegReader*, int, const char*, int);
112200 SQLITE_PRIVATE int sqlite3Fts3MsrIncrNext(
112201 Fts3Table *, Fts3MultiSegReader *, sqlite3_int64 *, char **, int *);
112202 SQLITE_PRIVATE char *sqlite3Fts3EvalPhrasePoslist(Fts3Cursor *, Fts3Expr *, int iCol);
112203 SQLITE_PRIVATE int sqlite3Fts3MsrOvfl(Fts3Cursor *, Fts3MultiSegReader *, int *);
112204
112205 SQLITE_PRIVATE int sqlite3Fts3DeferredTokenList(Fts3DeferredToken *, char **, int *);
112206
112207
112208 #endif /* _FTSINT_H */
112209
112210 /************** End of fts3Int.h *********************************************/
112211 /************** Continuing where we left off in fts3.c ***********************/
@@ -112200,16 +112323,16 @@
112323
112324 /*
112325 ** When this function is called, *pp points to the first byte following a
112326 ** varint that is part of a doclist (or position-list, or any other list
112327 ** of varints). This function moves *pp to point to the start of that varint,
112328 ** and sets *pVal by the varint value.
112329 **
112330 ** Argument pStart points to the first byte of the doclist that the
112331 ** varint is part of.
112332 */
112333 static void fts3GetReverseVarint(
112334 char **pp,
112335 char *pStart,
112336 sqlite3_int64 *pVal
112337 ){
112338 sqlite3_int64 iVal;
@@ -112221,25 +112344,11 @@
112344 for(p = (*pp)-2; p>=pStart && *p&0x80; p--);
112345 p++;
112346 *pp = p;
112347
112348 sqlite3Fts3GetVarint(p, &iVal);
112349 *pVal = iVal;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
112350 }
112351
112352 /*
112353 ** The xDisconnect() virtual table method.
112354 */
@@ -112608,10 +112717,62 @@
112717 fts3Appendf(pRc, &zRet, ",%s(?)", zFunction);
112718 }
112719 sqlite3_free(zFree);
112720 return zRet;
112721 }
112722
112723 static int fts3GobbleInt(const char **pp, int *pnOut){
112724 const char *p = *pp;
112725 int nInt = 0;
112726 for(p=*pp; p[0]>='0' && p[0]<='9'; p++){
112727 nInt = nInt * 10 + (p[0] - '0');
112728 }
112729 if( p==*pp ) return SQLITE_ERROR;
112730 *pnOut = nInt;
112731 *pp = p;
112732 return SQLITE_OK;
112733 }
112734
112735
112736 static int fts3PrefixParameter(
112737 const char *zParam, /* ABC in prefix=ABC parameter to parse */
112738 int *pnIndex, /* OUT: size of *apIndex[] array */
112739 struct Fts3Index **apIndex, /* OUT: Array of indexes for this table */
112740 struct Fts3Index **apFree /* OUT: Free this with sqlite3_free() */
112741 ){
112742 struct Fts3Index *aIndex;
112743 int nIndex = 1;
112744
112745 if( zParam && zParam[0] ){
112746 const char *p;
112747 nIndex++;
112748 for(p=zParam; *p; p++){
112749 if( *p==',' ) nIndex++;
112750 }
112751 }
112752
112753 aIndex = sqlite3_malloc(sizeof(struct Fts3Index) * nIndex);
112754 *apIndex = *apFree = aIndex;
112755 *pnIndex = nIndex;
112756 if( !aIndex ){
112757 return SQLITE_NOMEM;
112758 }
112759
112760 memset(aIndex, 0, sizeof(struct Fts3Index) * nIndex);
112761 if( zParam ){
112762 const char *p = zParam;
112763 int i;
112764 for(i=1; i<nIndex; i++){
112765 int nPrefix;
112766 if( fts3GobbleInt(&p, &nPrefix) ) return SQLITE_ERROR;
112767 aIndex[i].nPrefix = nPrefix;
112768 p++;
112769 }
112770 }
112771
112772 return SQLITE_OK;
112773 }
112774
112775 /*
112776 ** This function is the implementation of both the xConnect and xCreate
112777 ** methods of the FTS3 virtual table.
112778 **
@@ -112641,16 +112802,23 @@
112802 int nCol = 0; /* Number of columns in the FTS table */
112803 char *zCsr; /* Space for holding column names */
112804 int nDb; /* Bytes required to hold database name */
112805 int nName; /* Bytes required to hold table name */
112806 int isFts4 = (argv[0][3]=='4'); /* True for FTS4, false for FTS3 */
 
112807 const char **aCol; /* Array of column names */
112808 sqlite3_tokenizer *pTokenizer = 0; /* Tokenizer for this table */
112809
112810 int nIndex; /* Size of aIndex[] array */
112811 struct Fts3Index *aIndex; /* Array of indexes for this table */
112812 struct Fts3Index *aFree = 0; /* Free this before returning */
112813
112814 /* The results of parsing supported FTS4 key=value options: */
112815 int bNoDocsize = 0; /* True to omit %_docsize table */
112816 int bDescIdx = 0; /* True to store descending indexes */
112817 char *zPrefix = 0; /* Prefix parameter value (or NULL) */
112818 char *zCompress = 0; /* compress=? parameter (or NULL) */
112819 char *zUncompress = 0; /* uncompress=? parameter (or NULL) */
112820
112821 assert( strlen(argv[0])==4 );
112822 assert( (sqlite3_strnicmp(argv[0], "fts4", 4)==0 && isFts4)
112823 || (sqlite3_strnicmp(argv[0], "fts3", 4)==0 && !isFts4)
112824 );
@@ -112687,32 +112855,76 @@
112855 rc = sqlite3Fts3InitTokenizer(pHash, &z[9], &pTokenizer, pzErr);
112856 }
112857
112858 /* Check if it is an FTS4 special argument. */
112859 else if( isFts4 && fts3IsSpecialColumn(z, &nKey, &zVal) ){
112860 struct Fts4Option {
112861 const char *zOpt;
112862 int nOpt;
112863 char **pzVar;
112864 } aFts4Opt[] = {
112865 { "matchinfo", 9, 0 }, /* 0 -> MATCHINFO */
112866 { "prefix", 6, 0 }, /* 1 -> PREFIX */
112867 { "compress", 8, 0 }, /* 2 -> COMPRESS */
112868 { "uncompress", 10, 0 }, /* 3 -> UNCOMPRESS */
112869 { "order", 5, 0 } /* 4 -> ORDER */
112870 };
112871
112872 int iOpt;
112873 if( !zVal ){
112874 rc = SQLITE_NOMEM;
112875 }else{
112876 for(iOpt=0; iOpt<SizeofArray(aFts4Opt); iOpt++){
112877 struct Fts4Option *pOp = &aFts4Opt[iOpt];
112878 if( nKey==pOp->nOpt && !sqlite3_strnicmp(z, pOp->zOpt, pOp->nOpt) ){
112879 break;
112880 }
112881 }
112882 if( iOpt==SizeofArray(aFts4Opt) ){
112883 *pzErr = sqlite3_mprintf("unrecognized parameter: %s", z);
112884 rc = SQLITE_ERROR;
112885 }else{
112886 switch( iOpt ){
112887 case 0: /* MATCHINFO */
112888 if( strlen(zVal)!=4 || sqlite3_strnicmp(zVal, "fts3", 4) ){
112889 *pzErr = sqlite3_mprintf("unrecognized matchinfo: %s", zVal);
112890 rc = SQLITE_ERROR;
112891 }
112892 bNoDocsize = 1;
112893 break;
112894
112895 case 1: /* PREFIX */
112896 sqlite3_free(zPrefix);
112897 zPrefix = zVal;
112898 zVal = 0;
112899 break;
112900
112901 case 2: /* COMPRESS */
112902 sqlite3_free(zCompress);
112903 zCompress = zVal;
112904 zVal = 0;
112905 break;
112906
112907 case 3: /* UNCOMPRESS */
112908 sqlite3_free(zUncompress);
112909 zUncompress = zVal;
112910 zVal = 0;
112911 break;
112912
112913 case 4: /* ORDER */
112914 if( (strlen(zVal)!=3 || sqlite3_strnicmp(zVal, "asc", 3))
112915 && (strlen(zVal)!=4 || sqlite3_strnicmp(zVal, "desc", 3))
112916 ){
112917 *pzErr = sqlite3_mprintf("unrecognized order: %s", zVal);
112918 rc = SQLITE_ERROR;
112919 }
112920 bDescIdx = (zVal[0]=='d' || zVal[0]=='D');
112921 break;
112922 }
112923 }
112924 sqlite3_free(zVal);
112925 }
112926 }
112927
112928 /* Otherwise, the argument is a column name. */
112929 else {
112930 nString += (int)(strlen(z) + 1);
@@ -112732,14 +112944,21 @@
112944 rc = sqlite3Fts3InitTokenizer(pHash, "simple", &pTokenizer, pzErr);
112945 if( rc!=SQLITE_OK ) goto fts3_init_out;
112946 }
112947 assert( pTokenizer );
112948
112949 rc = fts3PrefixParameter(zPrefix, &nIndex, &aIndex, &aFree);
112950 if( rc==SQLITE_ERROR ){
112951 assert( zPrefix );
112952 *pzErr = sqlite3_mprintf("error parsing prefix parameter: %s", zPrefix);
112953 }
112954 if( rc!=SQLITE_OK ) goto fts3_init_out;
112955
112956 /* Allocate and populate the Fts3Table structure. */
112957 nByte = sizeof(Fts3Table) + /* Fts3Table */
112958 nCol * sizeof(char *) + /* azColumn */
112959 nIndex * sizeof(struct Fts3Index) + /* aIndex */
112960 nName + /* zName */
112961 nDb + /* zDb */
112962 nString; /* Space for azColumn strings */
112963 p = (Fts3Table*)sqlite3_malloc(nByte);
112964 if( p==0 ){
@@ -112750,20 +112969,26 @@
112969 p->db = db;
112970 p->nColumn = nCol;
112971 p->nPendingData = 0;
112972 p->azColumn = (char **)&p[1];
112973 p->pTokenizer = pTokenizer;
 
112974 p->nMaxPendingData = FTS3_MAX_PENDING_DATA;
112975 p->bHasDocsize = (isFts4 && bNoDocsize==0);
112976 p->bHasStat = isFts4;
112977 p->bDescIdx = bDescIdx;
112978 TESTONLY( p->inTransaction = -1 );
112979 TESTONLY( p->mxSavepoint = -1 );
112980
112981 p->aIndex = (struct Fts3Index *)&p->azColumn[nCol];
112982 memcpy(p->aIndex, aIndex, sizeof(struct Fts3Index) * nIndex);
112983 p->nIndex = nIndex;
112984 for(i=0; i<nIndex; i++){
112985 fts3HashInit(&p->aIndex[i].hPending, FTS3_HASH_STRING, 1);
112986 }
112987
112988 /* Fill in the zName and zDb fields of the vtab structure. */
112989 zCsr = (char *)&p->aIndex[nIndex];
112990 p->zName = zCsr;
112991 memcpy(zCsr, argv[2], nName);
112992 zCsr += nName;
112993 p->zDb = zCsr;
112994 memcpy(zCsr, argv[1], nDb);
@@ -112797,19 +113022,20 @@
113022 if( isCreate ){
113023 rc = fts3CreateTables(p);
113024 }
113025
113026 /* Figure out the page-size for the database. This is required in order to
113027 ** estimate the cost of loading large doclists from the database. */
 
 
113028 fts3DatabasePageSize(&rc, p);
113029 p->nNodeSize = p->nPgsz-35;
113030
113031 /* Declare the table schema to SQLite. */
113032 fts3DeclareVtab(&rc, p);
113033
113034 fts3_init_out:
113035 sqlite3_free(zPrefix);
113036 sqlite3_free(aFree);
113037 sqlite3_free(zCompress);
113038 sqlite3_free(zUncompress);
113039 sqlite3_free((void *)aCol);
113040 if( rc!=SQLITE_OK ){
113041 if( p ){
@@ -112816,10 +113042,11 @@
113042 fts3DisconnectMethod((sqlite3_vtab *)p);
113043 }else if( pTokenizer ){
113044 pTokenizer->pModule->xDestroy(pTokenizer);
113045 }
113046 }else{
113047 assert( p->pSegments==0 );
113048 *ppVTab = &p->base;
113049 }
113050 return rc;
113051 }
113052
@@ -112913,14 +113140,15 @@
113140 if( pOrder->desc ){
113141 pInfo->idxStr = "DESC";
113142 }else{
113143 pInfo->idxStr = "ASC";
113144 }
113145 pInfo->orderByConsumed = 1;
113146 }
 
113147 }
113148
113149 assert( p->pSegments==0 );
113150 return SQLITE_OK;
113151 }
113152
113153 /*
113154 ** Implementation of xOpen method.
@@ -112952,10 +113180,11 @@
113180 sqlite3_finalize(pCsr->pStmt);
113181 sqlite3Fts3ExprFree(pCsr->pExpr);
113182 sqlite3Fts3FreeDeferredTokens(pCsr);
113183 sqlite3_free(pCsr->aDoclist);
113184 sqlite3_free(pCsr->aMatchinfo);
113185 assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 );
113186 sqlite3_free(pCsr);
113187 return SQLITE_OK;
113188 }
113189
113190 /*
@@ -112963,12 +113192,12 @@
113192 ** of the %_content table that contains the last match. Return
113193 ** SQLITE_OK on success.
113194 */
113195 static int fts3CursorSeek(sqlite3_context *pContext, Fts3Cursor *pCsr){
113196 if( pCsr->isRequireSeek ){
 
113197 sqlite3_bind_int64(pCsr->pStmt, 1, pCsr->iPrevId);
113198 pCsr->isRequireSeek = 0;
113199 if( SQLITE_ROW==sqlite3_step(pCsr->pStmt) ){
113200 return SQLITE_OK;
113201 }else{
113202 int rc = sqlite3_reset(pCsr->pStmt);
113203 if( rc==SQLITE_OK ){
@@ -113145,21 +113374,21 @@
113374 if( rc==SQLITE_OK && iHeight>1 ){
113375 char *zBlob = 0; /* Blob read from %_segments table */
113376 int nBlob; /* Size of zBlob in bytes */
113377
113378 if( piLeaf && piLeaf2 && (*piLeaf!=*piLeaf2) ){
113379 rc = sqlite3Fts3ReadBlock(p, *piLeaf, &zBlob, &nBlob, 0);
113380 if( rc==SQLITE_OK ){
113381 rc = fts3SelectLeaf(p, zTerm, nTerm, zBlob, nBlob, piLeaf, 0);
113382 }
113383 sqlite3_free(zBlob);
113384 piLeaf = 0;
113385 zBlob = 0;
113386 }
113387
113388 if( rc==SQLITE_OK ){
113389 rc = sqlite3Fts3ReadBlock(p, piLeaf?*piLeaf:*piLeaf2, &zBlob, &nBlob, 0);
113390 }
113391 if( rc==SQLITE_OK ){
113392 rc = fts3SelectLeaf(p, zTerm, nTerm, zBlob, nBlob, piLeaf, piLeaf2);
113393 }
113394 sqlite3_free(zBlob);
@@ -113531,11 +113760,23 @@
113760 *pp = p;
113761 return 1;
113762 }
113763
113764 /*
113765 ** Merge two position-lists as required by the NEAR operator. The argument
113766 ** position lists correspond to the left and right phrases of an expression
113767 ** like:
113768 **
113769 ** "phrase 1" NEAR "phrase number 2"
113770 **
113771 ** Position list *pp1 corresponds to the left-hand side of the NEAR
113772 ** expression and *pp2 to the right. As usual, the indexes in the position
113773 ** lists are the offsets of the last token in each phrase (tokens "1" and "2"
113774 ** in the example above).
113775 **
113776 ** The output position list - written to *pp - is a copy of *pp2 with those
113777 ** entries that are not sufficiently NEAR entries in *pp1 removed.
113778 */
113779 static int fts3PoslistNearMerge(
113780 char **pp, /* Output buffer */
113781 char *aTmp, /* Temporary buffer space */
113782 int nRight, /* Maximum difference in token positions */
@@ -113544,218 +113785,31 @@
113785 char **pp2 /* IN/OUT: Right input list */
113786 ){
113787 char *p1 = *pp1;
113788 char *p2 = *pp2;
113789
113790 char *pTmp1 = aTmp;
113791 char *pTmp2;
113792 char *aTmp2;
113793 int res = 1;
113794
113795 fts3PoslistPhraseMerge(&pTmp1, nRight, 0, 0, pp1, pp2);
113796 aTmp2 = pTmp2 = pTmp1;
113797 *pp1 = p1;
113798 *pp2 = p2;
113799 fts3PoslistPhraseMerge(&pTmp2, nLeft, 1, 0, pp2, pp1);
113800 if( pTmp1!=aTmp && pTmp2!=aTmp2 ){
113801 fts3PoslistMerge(pp, &aTmp, &aTmp2);
113802 }else if( pTmp1!=aTmp ){
113803 fts3PoslistCopy(pp, &aTmp);
113804 }else if( pTmp2!=aTmp2 ){
113805 fts3PoslistCopy(pp, &aTmp2);
113806 }else{
113807 res = 0;
113808 }
113809
113810 return res;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
113811 }
113812
113813 /*
113814 ** A pointer to an instance of this structure is used as the context
113815 ** argument to sqlite3Fts3SegReaderIterate()
@@ -113764,10 +113818,152 @@
113818 struct TermSelect {
113819 int isReqPos;
113820 char *aaOutput[16]; /* Malloc'd output buffer */
113821 int anOutput[16]; /* Size of output in bytes */
113822 };
113823
113824
113825 static void fts3GetDeltaVarint3(
113826 char **pp,
113827 char *pEnd,
113828 int bDescIdx,
113829 sqlite3_int64 *pVal
113830 ){
113831 if( *pp>=pEnd ){
113832 *pp = 0;
113833 }else{
113834 sqlite3_int64 iVal;
113835 *pp += sqlite3Fts3GetVarint(*pp, &iVal);
113836 if( bDescIdx ){
113837 *pVal -= iVal;
113838 }else{
113839 *pVal += iVal;
113840 }
113841 }
113842 }
113843
113844 static void fts3PutDeltaVarint3(
113845 char **pp, /* IN/OUT: Output pointer */
113846 int bDescIdx, /* True for descending docids */
113847 sqlite3_int64 *piPrev, /* IN/OUT: Previous value written to list */
113848 int *pbFirst, /* IN/OUT: True after first int written */
113849 sqlite3_int64 iVal /* Write this value to the list */
113850 ){
113851 sqlite3_int64 iWrite;
113852 if( bDescIdx==0 || *pbFirst==0 ){
113853 iWrite = iVal - *piPrev;
113854 }else{
113855 iWrite = *piPrev - iVal;
113856 }
113857 assert( *pbFirst || *piPrev==0 );
113858 assert( *pbFirst==0 || iWrite>0 );
113859 *pp += sqlite3Fts3PutVarint(*pp, iWrite);
113860 *piPrev = iVal;
113861 *pbFirst = 1;
113862 }
113863
113864 #define COMPARE_DOCID(i1, i2) ((bDescIdx?-1:1) * (i1-i2))
113865
113866 static int fts3DoclistOrMerge(
113867 int bDescIdx, /* True if arguments are desc */
113868 char *a1, int n1, /* First doclist */
113869 char *a2, int n2, /* Second doclist */
113870 char **paOut, int *pnOut /* OUT: Malloc'd doclist */
113871 ){
113872 sqlite3_int64 i1 = 0;
113873 sqlite3_int64 i2 = 0;
113874 sqlite3_int64 iPrev = 0;
113875 char *pEnd1 = &a1[n1];
113876 char *pEnd2 = &a2[n2];
113877 char *p1 = a1;
113878 char *p2 = a2;
113879 char *p;
113880 char *aOut;
113881 int bFirstOut = 0;
113882
113883 *paOut = 0;
113884 *pnOut = 0;
113885 aOut = sqlite3_malloc(n1+n2);
113886 if( !aOut ) return SQLITE_NOMEM;
113887
113888 p = aOut;
113889 fts3GetDeltaVarint3(&p1, pEnd1, 0, &i1);
113890 fts3GetDeltaVarint3(&p2, pEnd2, 0, &i2);
113891 while( p1 || p2 ){
113892 sqlite3_int64 iDiff = COMPARE_DOCID(i1, i2);
113893
113894 if( p2 && p1 && iDiff==0 ){
113895 fts3PutDeltaVarint3(&p, bDescIdx, &iPrev, &bFirstOut, i1);
113896 fts3PoslistMerge(&p, &p1, &p2);
113897 fts3GetDeltaVarint3(&p1, pEnd1, bDescIdx, &i1);
113898 fts3GetDeltaVarint3(&p2, pEnd2, bDescIdx, &i2);
113899 }else if( !p2 || (p1 && iDiff<0) ){
113900 fts3PutDeltaVarint3(&p, bDescIdx, &iPrev, &bFirstOut, i1);
113901 fts3PoslistCopy(&p, &p1);
113902 fts3GetDeltaVarint3(&p1, pEnd1, bDescIdx, &i1);
113903 }else{
113904 fts3PutDeltaVarint3(&p, bDescIdx, &iPrev, &bFirstOut, i2);
113905 fts3PoslistCopy(&p, &p2);
113906 fts3GetDeltaVarint3(&p2, pEnd2, bDescIdx, &i2);
113907 }
113908 }
113909
113910 *paOut = aOut;
113911 *pnOut = (p-aOut);
113912 return SQLITE_OK;
113913 }
113914
113915 static void fts3DoclistPhraseMerge(
113916 int bDescIdx, /* True if arguments are desc */
113917 int nDist, /* Distance from left to right (1=adjacent) */
113918 char *aLeft, int nLeft, /* Left doclist */
113919 char *aRight, int *pnRight /* IN/OUT: Right/output doclist */
113920 ){
113921 sqlite3_int64 i1 = 0;
113922 sqlite3_int64 i2 = 0;
113923 sqlite3_int64 iPrev = 0;
113924 char *pEnd1 = &aLeft[nLeft];
113925 char *pEnd2 = &aRight[*pnRight];
113926 char *p1 = aLeft;
113927 char *p2 = aRight;
113928 char *p;
113929 int bFirstOut = 0;
113930 char *aOut = aRight;
113931
113932 assert( nDist>0 );
113933
113934 p = aOut;
113935 fts3GetDeltaVarint3(&p1, pEnd1, 0, &i1);
113936 fts3GetDeltaVarint3(&p2, pEnd2, 0, &i2);
113937
113938 while( p1 && p2 ){
113939 sqlite3_int64 iDiff = COMPARE_DOCID(i1, i2);
113940 if( iDiff==0 ){
113941 char *pSave = p;
113942 sqlite3_int64 iPrevSave = iPrev;
113943 int bFirstOutSave = bFirstOut;
113944
113945 fts3PutDeltaVarint3(&p, bDescIdx, &iPrev, &bFirstOut, i1);
113946 if( 0==fts3PoslistPhraseMerge(&p, nDist, 0, 1, &p1, &p2) ){
113947 p = pSave;
113948 iPrev = iPrevSave;
113949 bFirstOut = bFirstOutSave;
113950 }
113951 fts3GetDeltaVarint3(&p1, pEnd1, bDescIdx, &i1);
113952 fts3GetDeltaVarint3(&p2, pEnd2, bDescIdx, &i2);
113953 }else if( iDiff<0 ){
113954 fts3PoslistCopy(0, &p1);
113955 fts3GetDeltaVarint3(&p1, pEnd1, bDescIdx, &i1);
113956 }else{
113957 fts3PoslistCopy(0, &p2);
113958 fts3GetDeltaVarint3(&p2, pEnd2, bDescIdx, &i2);
113959 }
113960 }
113961
113962 *pnRight = p - aOut;
113963 }
113964
113965
113966 /*
113967 ** Merge all doclists in the TermSelect.aaOutput[] array into a single
113968 ** doclist stored in TermSelect.aaOutput[0]. If successful, delete all
113969 ** other doclists (except the aaOutput[0] one) and return SQLITE_OK.
@@ -113774,12 +113970,11 @@
113970 **
113971 ** If an OOM error occurs, return SQLITE_NOMEM. In this case it is
113972 ** the responsibility of the caller to free any doclists left in the
113973 ** TermSelect.aaOutput[] array.
113974 */
113975 static int fts3TermSelectMerge(Fts3Table *p, TermSelect *pTS){
 
113976 char *aOut = 0;
113977 int nOut = 0;
113978 int i;
113979
113980 /* Loop through the doclists in the aaOutput[] array. Merge them all
@@ -113790,19 +113985,21 @@
113985 if( !aOut ){
113986 aOut = pTS->aaOutput[i];
113987 nOut = pTS->anOutput[i];
113988 pTS->aaOutput[i] = 0;
113989 }else{
113990 int nNew;
113991 char *aNew;
113992
113993 int rc = fts3DoclistOrMerge(p->bDescIdx,
113994 pTS->aaOutput[i], pTS->anOutput[i], aOut, nOut, &aNew, &nNew
113995 );
113996 if( rc!=SQLITE_OK ){
113997 sqlite3_free(aOut);
113998 return rc;
113999 }
114000
 
 
114001 sqlite3_free(pTS->aaOutput[i]);
114002 sqlite3_free(aOut);
114003 pTS->aaOutput[i] = 0;
114004 aOut = aNew;
114005 nOut = nNew;
@@ -113834,217 +114031,241 @@
114031 UNUSED_PARAMETER(zTerm);
114032 UNUSED_PARAMETER(nTerm);
114033
114034 if( pTS->aaOutput[0]==0 ){
114035 /* If this is the first term selected, copy the doclist to the output
114036 ** buffer using memcpy(). */
 
 
114037 pTS->aaOutput[0] = sqlite3_malloc(nDoclist);
114038 pTS->anOutput[0] = nDoclist;
114039 if( pTS->aaOutput[0] ){
114040 memcpy(pTS->aaOutput[0], aDoclist, nDoclist);
114041 }else{
114042 return SQLITE_NOMEM;
114043 }
114044 }else{
 
114045 char *aMerge = aDoclist;
114046 int nMerge = nDoclist;
114047 int iOut;
114048
114049 for(iOut=0; iOut<SizeofArray(pTS->aaOutput); iOut++){
 
 
114050 if( pTS->aaOutput[iOut]==0 ){
114051 assert( iOut>0 );
114052 pTS->aaOutput[iOut] = aMerge;
114053 pTS->anOutput[iOut] = nMerge;
114054 break;
114055 }else{
114056 char *aNew;
114057 int nNew;
114058
114059 int rc = fts3DoclistOrMerge(p->bDescIdx, aMerge, nMerge,
114060 pTS->aaOutput[iOut], pTS->anOutput[iOut], &aNew, &nNew
114061 );
114062 if( rc!=SQLITE_OK ){
114063 if( aMerge!=aDoclist ) sqlite3_free(aMerge);
114064 return rc;
114065 }
114066
114067 if( aMerge!=aDoclist ) sqlite3_free(aMerge);
114068 sqlite3_free(pTS->aaOutput[iOut]);
114069 pTS->aaOutput[iOut] = 0;
114070
114071 aMerge = aNew;
114072 nMerge = nNew;
114073 if( (iOut+1)==SizeofArray(pTS->aaOutput) ){
114074 pTS->aaOutput[iOut] = aMerge;
114075 pTS->anOutput[iOut] = nMerge;
114076 }
114077 }
114078 }
114079 }
114080 return SQLITE_OK;
114081 }
114082
114083 /*
114084 ** Append SegReader object pNew to the end of the pCsr->apSegment[] array.
114085 */
114086 static int fts3SegReaderCursorAppend(
114087 Fts3MultiSegReader *pCsr,
114088 Fts3SegReader *pNew
114089 ){
114090 if( (pCsr->nSegment%16)==0 ){
114091 Fts3SegReader **apNew;
114092 int nByte = (pCsr->nSegment + 16)*sizeof(Fts3SegReader*);
114093 apNew = (Fts3SegReader **)sqlite3_realloc(pCsr->apSegment, nByte);
114094 if( !apNew ){
114095 sqlite3Fts3SegReaderFree(pNew);
114096 return SQLITE_NOMEM;
114097 }
114098 pCsr->apSegment = apNew;
114099 }
114100 pCsr->apSegment[pCsr->nSegment++] = pNew;
114101 return SQLITE_OK;
114102 }
114103
114104 static int fts3SegReaderCursor(
 
 
 
 
 
 
 
 
 
114105 Fts3Table *p, /* FTS3 table handle */
114106 int iIndex, /* Index to search (from 0 to p->nIndex-1) */
114107 int iLevel, /* Level of segments to scan */
114108 const char *zTerm, /* Term to query for */
114109 int nTerm, /* Size of zTerm in bytes */
114110 int isPrefix, /* True for a prefix search */
114111 int isScan, /* True to scan from zTerm to EOF */
114112 Fts3MultiSegReader *pCsr /* Cursor object to populate */
114113 ){
114114 int rc = SQLITE_OK;
114115 int rc2;
 
114116 sqlite3_stmt *pStmt = 0;
114117
114118 /* If iLevel is less than 0 and this is not a scan, include a seg-reader
114119 ** for the pending-terms. If this is a scan, then this call must be being
114120 ** made by an fts4aux module, not an FTS table. In this case calling
114121 ** Fts3SegReaderPending might segfault, as the data structures used by
114122 ** fts4aux are not completely populated. So it's easiest to filter these
114123 ** calls out here. */
114124 if( iLevel<0 && p->aIndex ){
114125 Fts3SegReader *pSeg = 0;
114126 rc = sqlite3Fts3SegReaderPending(p, iIndex, zTerm, nTerm, isPrefix, &pSeg);
114127 if( rc==SQLITE_OK && pSeg ){
114128 rc = fts3SegReaderCursorAppend(pCsr, pSeg);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
114129 }
114130 }
114131
114132 if( iLevel!=FTS3_SEGCURSOR_PENDING ){
114133 if( rc==SQLITE_OK ){
114134 rc = sqlite3Fts3AllSegdirs(p, iIndex, iLevel, &pStmt);
114135 }
114136
114137 while( rc==SQLITE_OK && SQLITE_ROW==(rc = sqlite3_step(pStmt)) ){
114138 Fts3SegReader *pSeg = 0;
114139
114140 /* Read the values returned by the SELECT into local variables. */
114141 sqlite3_int64 iStartBlock = sqlite3_column_int64(pStmt, 1);
114142 sqlite3_int64 iLeavesEndBlock = sqlite3_column_int64(pStmt, 2);
114143 sqlite3_int64 iEndBlock = sqlite3_column_int64(pStmt, 3);
114144 int nRoot = sqlite3_column_bytes(pStmt, 4);
114145 char const *zRoot = sqlite3_column_blob(pStmt, 4);
114146
 
 
 
 
 
 
 
 
 
 
 
 
114147 /* If zTerm is not NULL, and this segment is not stored entirely on its
114148 ** root node, the range of leaves scanned can be reduced. Do this. */
114149 if( iStartBlock && zTerm ){
114150 sqlite3_int64 *pi = (isPrefix ? &iLeavesEndBlock : 0);
114151 rc = fts3SelectLeaf(p, zTerm, nTerm, zRoot, nRoot, &iStartBlock, pi);
114152 if( rc!=SQLITE_OK ) goto finished;
114153 if( isPrefix==0 && isScan==0 ) iLeavesEndBlock = iStartBlock;
114154 }
114155
114156 rc = sqlite3Fts3SegReaderNew(pCsr->nSegment+1,
114157 iStartBlock, iLeavesEndBlock, iEndBlock, zRoot, nRoot, &pSeg
114158 );
114159 if( rc!=SQLITE_OK ) goto finished;
114160 rc = fts3SegReaderCursorAppend(pCsr, pSeg);
 
114161 }
114162 }
114163
114164 finished:
114165 rc2 = sqlite3_reset(pStmt);
114166 if( rc==SQLITE_DONE ) rc = rc2;
 
114167
114168 return rc;
114169 }
114170
114171 /*
114172 ** Set up a cursor object for iterating through a full-text index or a
114173 ** single level therein.
114174 */
114175 SQLITE_PRIVATE int sqlite3Fts3SegReaderCursor(
114176 Fts3Table *p, /* FTS3 table handle */
114177 int iIndex, /* Index to search (from 0 to p->nIndex-1) */
114178 int iLevel, /* Level of segments to scan */
114179 const char *zTerm, /* Term to query for */
114180 int nTerm, /* Size of zTerm in bytes */
114181 int isPrefix, /* True for a prefix search */
114182 int isScan, /* True to scan from zTerm to EOF */
114183 Fts3MultiSegReader *pCsr /* Cursor object to populate */
114184 ){
114185 assert( iIndex>=0 && iIndex<p->nIndex );
114186 assert( iLevel==FTS3_SEGCURSOR_ALL
114187 || iLevel==FTS3_SEGCURSOR_PENDING
114188 || iLevel>=0
114189 );
114190 assert( iLevel<FTS3_SEGDIR_MAXLEVEL );
114191 assert( FTS3_SEGCURSOR_ALL<0 && FTS3_SEGCURSOR_PENDING<0 );
114192 assert( isPrefix==0 || isScan==0 );
114193
114194 /* "isScan" is only set to true by the ft4aux module, an ordinary
114195 ** full-text tables. */
114196 assert( isScan==0 || p->aIndex==0 );
114197
114198 memset(pCsr, 0, sizeof(Fts3MultiSegReader));
114199
114200 return fts3SegReaderCursor(
114201 p, iIndex, iLevel, zTerm, nTerm, isPrefix, isScan, pCsr
114202 );
114203 }
114204
114205 static int fts3SegReaderCursorAddZero(
114206 Fts3Table *p,
114207 const char *zTerm,
114208 int nTerm,
114209 Fts3MultiSegReader *pCsr
114210 ){
114211 return fts3SegReaderCursor(p, 0, FTS3_SEGCURSOR_ALL, zTerm, nTerm, 0, 0,pCsr);
114212 }
114213
114214
114215 SQLITE_PRIVATE int sqlite3Fts3TermSegReaderCursor(
114216 Fts3Cursor *pCsr, /* Virtual table cursor handle */
114217 const char *zTerm, /* Term to query for */
114218 int nTerm, /* Size of zTerm in bytes */
114219 int isPrefix, /* True for a prefix search */
114220 Fts3MultiSegReader **ppSegcsr /* OUT: Allocated seg-reader cursor */
114221 ){
114222 Fts3MultiSegReader *pSegcsr; /* Object to allocate and return */
114223 int rc = SQLITE_NOMEM; /* Return code */
114224
114225 pSegcsr = sqlite3_malloc(sizeof(Fts3MultiSegReader));
114226 if( pSegcsr ){
114227 int i;
114228 int bFound = 0; /* True once an index has been found */
114229 Fts3Table *p = (Fts3Table *)pCsr->base.pVtab;
114230
114231 if( isPrefix ){
114232 for(i=1; bFound==0 && i<p->nIndex; i++){
114233 if( p->aIndex[i].nPrefix==nTerm ){
114234 bFound = 1;
114235 rc = sqlite3Fts3SegReaderCursor(
114236 p, i, FTS3_SEGCURSOR_ALL, zTerm, nTerm, 0, 0, pSegcsr);
114237 pSegcsr->bLookup = 1;
114238 }
114239 }
114240
114241 for(i=1; bFound==0 && i<p->nIndex; i++){
114242 if( p->aIndex[i].nPrefix==nTerm+1 ){
114243 bFound = 1;
114244 rc = sqlite3Fts3SegReaderCursor(
114245 p, i, FTS3_SEGCURSOR_ALL, zTerm, nTerm, 1, 0, pSegcsr
114246 );
114247 if( rc==SQLITE_OK ){
114248 rc = fts3SegReaderCursorAddZero(p, zTerm, nTerm, pSegcsr);
114249 }
114250 }
114251 }
114252 }
114253
114254 if( bFound==0 ){
114255 rc = sqlite3Fts3SegReaderCursor(
114256 p, 0, FTS3_SEGCURSOR_ALL, zTerm, nTerm, isPrefix, 0, pSegcsr
114257 );
114258 pSegcsr->bLookup = !isPrefix;
114259 }
114260 }
114261
114262 *ppSegcsr = pSegcsr;
114263 return rc;
114264 }
114265
114266 static void fts3SegReaderCursorFree(Fts3MultiSegReader *pSegcsr){
114267 sqlite3Fts3SegReaderFinish(pSegcsr);
114268 sqlite3_free(pSegcsr);
114269 }
114270
114271 /*
@@ -114065,11 +114286,11 @@
114286 int isReqPos, /* True to include position lists in output */
114287 int *pnOut, /* OUT: Size of buffer at *ppOut */
114288 char **ppOut /* OUT: Malloced result buffer */
114289 ){
114290 int rc; /* Return code */
114291 Fts3MultiSegReader *pSegcsr; /* Seg-reader cursor for this term */
114292 TermSelect tsc; /* Context object for fts3TermSelectCb() */
114293 Fts3SegFilter filter; /* Segment term filter configuration */
114294
114295 pSegcsr = pTok->pSegcsr;
114296 memset(&tsc, 0, sizeof(TermSelect));
@@ -114091,11 +114312,11 @@
114312 pSegcsr->zTerm, pSegcsr->nTerm, pSegcsr->aDoclist, pSegcsr->nDoclist
114313 );
114314 }
114315
114316 if( rc==SQLITE_OK ){
114317 rc = fts3TermSelectMerge(p, &tsc);
114318 }
114319 if( rc==SQLITE_OK ){
114320 *ppOut = tsc.aaOutput[0];
114321 *pnOut = tsc.anOutput[0];
114322 }else{
@@ -114141,664 +114362,10 @@
114362 }
114363
114364 return nDoc;
114365 }
114366
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
114367 /*
114368 ** Advance the cursor to the next row in the %_content table that
114369 ** matches the search criteria. For a MATCH search, this will be
114370 ** the next row that matches. For a full-table scan, this will be
114371 ** simply the next row in the %_content table. For a docid lookup,
@@ -114807,43 +114374,24 @@
114374 ** Return SQLITE_OK if nothing goes wrong. SQLITE_OK is returned
114375 ** even if we reach end-of-file. The fts3EofMethod() will be called
114376 ** subsequently to determine whether or not an EOF was hit.
114377 */
114378 static int fts3NextMethod(sqlite3_vtab_cursor *pCursor){
114379 int rc;
 
114380 Fts3Cursor *pCsr = (Fts3Cursor *)pCursor;
114381 if( pCsr->eSearch==FTS3_DOCID_SEARCH || pCsr->eSearch==FTS3_FULLSCAN_SEARCH ){
114382 if( SQLITE_ROW!=sqlite3_step(pCsr->pStmt) ){
114383 pCsr->isEof = 1;
114384 rc = sqlite3_reset(pCsr->pStmt);
114385 }else{
 
 
 
 
114386 pCsr->iPrevId = sqlite3_column_int64(pCsr->pStmt, 0);
114387 rc = SQLITE_OK;
114388 }
114389 }else{
114390 rc = sqlite3Fts3EvalNext((Fts3Cursor *)pCursor);
114391 }
114392 assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
114393 return rc;
114394 }
114395
114396 /*
114397 ** This is the xFilter interface for the virtual table. See
@@ -114866,15 +114414,11 @@
114414 int idxNum, /* Strategy index */
114415 const char *idxStr, /* Unused */
114416 int nVal, /* Number of elements in apVal */
114417 sqlite3_value **apVal /* Arguments for the indexing scheme */
114418 ){
114419 int rc;
 
 
 
 
114420 char *zSql; /* SQL statement used to access %_content */
114421 Fts3Table *p = (Fts3Table *)pCursor->pVtab;
114422 Fts3Cursor *pCsr = (Fts3Cursor *)pCursor;
114423
114424 UNUSED_PARAMETER(idxStr);
@@ -114889,10 +114433,17 @@
114433 sqlite3_finalize(pCsr->pStmt);
114434 sqlite3_free(pCsr->aDoclist);
114435 sqlite3Fts3ExprFree(pCsr->pExpr);
114436 memset(&pCursor[1], 0, sizeof(Fts3Cursor)-sizeof(sqlite3_vtab_cursor));
114437
114438 if( idxStr ){
114439 pCsr->bDesc = (idxStr[0]=='D');
114440 }else{
114441 pCsr->bDesc = p->bDescIdx;
114442 }
114443 pCsr->eSearch = (i16)idxNum;
114444
114445 if( idxNum!=FTS3_DOCID_SEARCH && idxNum!=FTS3_FULLSCAN_SEARCH ){
114446 int iCol = idxNum-FTS3_FULLTEXT_SEARCH;
114447 const char *zQuery = (const char *)sqlite3_value_text(apVal[0]);
114448
114449 if( zQuery==0 && sqlite3_value_type(apVal[0])!=SQLITE_NULL ){
@@ -114902,20 +114453,21 @@
114453 rc = sqlite3Fts3ExprParse(p->pTokenizer, p->azColumn, p->nColumn,
114454 iCol, zQuery, -1, &pCsr->pExpr
114455 );
114456 if( rc!=SQLITE_OK ){
114457 if( rc==SQLITE_ERROR ){
114458 static const char *zErr = "malformed MATCH expression: [%s]";
114459 p->base.zErrMsg = sqlite3_mprintf(zErr, zQuery);
114460 }
114461 return rc;
114462 }
114463
114464 rc = sqlite3Fts3ReadLock(p);
114465 if( rc!=SQLITE_OK ) return rc;
114466
114467 rc = sqlite3Fts3EvalStart(pCsr, pCsr->pExpr, 1);
114468
114469 sqlite3Fts3SegmentsClose(p);
114470 if( rc!=SQLITE_OK ) return rc;
114471 pCsr->pNextId = pCsr->aDoclist;
114472 pCsr->iPrevId = 0;
114473 }
@@ -114923,41 +114475,28 @@
114475 /* Compile a SELECT statement for this cursor. For a full-table-scan, the
114476 ** statement loops through all rows of the %_content table. For a
114477 ** full-text query or docid lookup, the statement retrieves a single
114478 ** row by docid.
114479 */
114480 if( idxNum==FTS3_FULLSCAN_SEARCH ){
114481 const char *zSort = (pCsr->bDesc ? "DESC" : "ASC");
114482 const char *zTmpl = "SELECT %s FROM %Q.'%q_content' AS x ORDER BY docid %s";
114483 zSql = sqlite3_mprintf(zTmpl, p->zReadExprlist, p->zDb, p->zName, zSort);
 
 
114484 }else{
114485 const char *zTmpl = "SELECT %s FROM %Q.'%q_content' AS x WHERE docid = ?";
114486 zSql = sqlite3_mprintf(zTmpl, p->zReadExprlist, p->zDb, p->zName);
114487 }
114488 if( !zSql ) return SQLITE_NOMEM;
114489 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pCsr->pStmt, 0);
114490 sqlite3_free(zSql);
114491 if( rc!=SQLITE_OK ) return rc;
114492
114493 if( idxNum==FTS3_DOCID_SEARCH ){
114494 rc = sqlite3_bind_value(pCsr->pStmt, 1, apVal[0]);
114495 if( rc!=SQLITE_OK ) return rc;
114496 }
114497
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
114498 return fts3NextMethod(pCursor);
114499 }
114500
114501 /*
114502 ** This is the xEof method of the virtual table. SQLite calls this
@@ -114973,20 +114512,11 @@
114512 ** exposes %_content.docid as the rowid for the virtual table. The
114513 ** rowid should be written to *pRowid.
114514 */
114515 static int fts3RowidMethod(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){
114516 Fts3Cursor *pCsr = (Fts3Cursor *) pCursor;
114517 *pRowid = pCsr->iPrevId;
 
 
 
 
 
 
 
 
 
114518 return SQLITE_OK;
114519 }
114520
114521 /*
114522 ** This is the xColumn method, called by SQLite to request a value from
@@ -114995,11 +114525,11 @@
114525 static int fts3ColumnMethod(
114526 sqlite3_vtab_cursor *pCursor, /* Cursor to retrieve value from */
114527 sqlite3_context *pContext, /* Context for sqlite3_result_xxx() calls */
114528 int iCol /* Index of column to read value from */
114529 ){
114530 int rc = SQLITE_OK; /* Return Code */
114531 Fts3Cursor *pCsr = (Fts3Cursor *) pCursor;
114532 Fts3Table *p = (Fts3Table *)pCursor->pVtab;
114533
114534 /* The column value supplied by SQLite must be in range. */
114535 assert( iCol>=0 && iCol<=p->nColumn+1 );
@@ -115006,25 +114536,24 @@
114536
114537 if( iCol==p->nColumn+1 ){
114538 /* This call is a request for the "docid" column. Since "docid" is an
114539 ** alias for "rowid", use the xRowid() method to obtain the value.
114540 */
114541 sqlite3_result_int64(pContext, pCsr->iPrevId);
 
 
114542 }else if( iCol==p->nColumn ){
114543 /* The extra column whose name is the same as the table.
114544 ** Return a blob which is a pointer to the cursor.
114545 */
114546 sqlite3_result_blob(pContext, &pCsr, sizeof(pCsr), SQLITE_TRANSIENT);
 
114547 }else{
114548 rc = fts3CursorSeek(0, pCsr);
114549 if( rc==SQLITE_OK ){
114550 sqlite3_result_value(pContext, sqlite3_column_value(pCsr->pStmt, iCol+1));
114551 }
114552 }
114553
114554 assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 );
114555 return rc;
114556 }
114557
114558 /*
114559 ** This function is the implementation of the xUpdate callback used by
@@ -115054,10 +114583,11 @@
114583 ** Implementation of xBegin() method. This is a no-op.
114584 */
114585 static int fts3BeginMethod(sqlite3_vtab *pVtab){
114586 UNUSED_PARAMETER(pVtab);
114587 TESTONLY( Fts3Table *p = (Fts3Table*)pVtab );
114588 assert( p->pSegments==0 );
114589 assert( p->nPendingData==0 );
114590 assert( p->inTransaction!=1 );
114591 TESTONLY( p->inTransaction = 1 );
114592 TESTONLY( p->mxSavepoint = -1; );
114593 return SQLITE_OK;
@@ -115071,10 +114601,11 @@
114601 static int fts3CommitMethod(sqlite3_vtab *pVtab){
114602 UNUSED_PARAMETER(pVtab);
114603 TESTONLY( Fts3Table *p = (Fts3Table*)pVtab );
114604 assert( p->nPendingData==0 );
114605 assert( p->inTransaction!=0 );
114606 assert( p->pSegments==0 );
114607 TESTONLY( p->inTransaction = 0 );
114608 TESTONLY( p->mxSavepoint = -1; );
114609 return SQLITE_OK;
114610 }
114611
@@ -115088,132 +114619,30 @@
114619 assert( p->inTransaction!=0 );
114620 TESTONLY( p->inTransaction = 0 );
114621 TESTONLY( p->mxSavepoint = -1; );
114622 return SQLITE_OK;
114623 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
114624
114625 /*
114626 ** When called, *ppPoslist must point to the byte immediately following the
114627 ** end of a position-list. i.e. ( (*ppPoslist)[-1]==POS_END ). This function
114628 ** moves *ppPoslist so that it instead points to the first byte of the
114629 ** same position list.
114630 */
114631 static void fts3ReversePoslist(char *pStart, char **ppPoslist){
114632 char *p = &(*ppPoslist)[-2];
114633 char c;
114634
114635 while( p>pStart && (c=*p--)==0 );
114636 while( p>pStart && (*p & 0x80) | c ){
114637 c = *p--;
114638 }
114639 if( p>pStart ){ p = &p[2]; }
114640 while( *p++&0x80 );
114641 *ppPoslist = p;
114642 }
114643
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
114644 /*
114645 ** Helper function used by the implementation of the overloaded snippet(),
114646 ** offsets() and optimize() SQL functions.
114647 **
114648 ** If the value passed as the third argument is a blob of size
@@ -115441,16 +114870,15 @@
114870 );
114871 return rc;
114872 }
114873
114874 static int fts3SavepointMethod(sqlite3_vtab *pVtab, int iSavepoint){
 
114875 UNUSED_PARAMETER(iSavepoint);
114876 assert( ((Fts3Table *)pVtab)->inTransaction );
114877 assert( ((Fts3Table *)pVtab)->mxSavepoint < iSavepoint );
114878 TESTONLY( ((Fts3Table *)pVtab)->mxSavepoint = iSavepoint );
114879 return fts3SyncMethod(pVtab);
114880 }
114881 static int fts3ReleaseMethod(sqlite3_vtab *pVtab, int iSavepoint){
114882 TESTONLY( Fts3Table *p = (Fts3Table*)pVtab );
114883 UNUSED_PARAMETER(iSavepoint);
114884 UNUSED_PARAMETER(pVtab);
@@ -115617,10 +115045,1282 @@
115045 SQLITE_EXTENSION_INIT2(pApi)
115046 return sqlite3Fts3Init(db);
115047 }
115048 #endif
115049
115050
115051 /*
115052 ** Allocate an Fts3MultiSegReader for each token in the expression headed
115053 ** by pExpr.
115054 **
115055 ** An Fts3SegReader object is a cursor that can seek or scan a range of
115056 ** entries within a single segment b-tree. An Fts3MultiSegReader uses multiple
115057 ** Fts3SegReader objects internally to provide an interface to seek or scan
115058 ** within the union of all segments of a b-tree. Hence the name.
115059 **
115060 ** If the allocated Fts3MultiSegReader just seeks to a single entry in a
115061 ** segment b-tree (if the term is not a prefix or it is a prefix for which
115062 ** there exists prefix b-tree of the right length) then it may be traversed
115063 ** and merged incrementally. Otherwise, it has to be merged into an in-memory
115064 ** doclist and then traversed.
115065 */
115066 static void fts3EvalAllocateReaders(
115067 Fts3Cursor *pCsr,
115068 Fts3Expr *pExpr,
115069 int *pnToken, /* OUT: Total number of tokens in phrase. */
115070 int *pnOr, /* OUT: Total number of OR nodes in expr. */
115071 int *pRc
115072 ){
115073 if( pExpr && SQLITE_OK==*pRc ){
115074 if( pExpr->eType==FTSQUERY_PHRASE ){
115075 int i;
115076 int nToken = pExpr->pPhrase->nToken;
115077 *pnToken += nToken;
115078 for(i=0; i<nToken; i++){
115079 Fts3PhraseToken *pToken = &pExpr->pPhrase->aToken[i];
115080 int rc = sqlite3Fts3TermSegReaderCursor(pCsr,
115081 pToken->z, pToken->n, pToken->isPrefix, &pToken->pSegcsr
115082 );
115083 if( rc!=SQLITE_OK ){
115084 *pRc = rc;
115085 return;
115086 }
115087 }
115088 }else{
115089 *pnOr += (pExpr->eType==FTSQUERY_OR);
115090 fts3EvalAllocateReaders(pCsr, pExpr->pLeft, pnToken, pnOr, pRc);
115091 fts3EvalAllocateReaders(pCsr, pExpr->pRight, pnToken, pnOr, pRc);
115092 }
115093 }
115094 }
115095
115096 static int fts3EvalPhraseLoad(
115097 Fts3Cursor *pCsr,
115098 Fts3Phrase *p
115099 ){
115100 Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
115101 int iToken;
115102 int rc = SQLITE_OK;
115103
115104 char *aDoclist = 0;
115105 int nDoclist = 0;
115106 int iPrev = -1;
115107
115108 for(iToken=0; rc==SQLITE_OK && iToken<p->nToken; iToken++){
115109 Fts3PhraseToken *pToken = &p->aToken[iToken];
115110 assert( pToken->pSegcsr || pToken->pDeferred );
115111
115112 if( pToken->pDeferred==0 ){
115113 int nThis = 0;
115114 char *pThis = 0;
115115 rc = fts3TermSelect(pTab, pToken, p->iColumn, 1, &nThis, &pThis);
115116 if( rc==SQLITE_OK ){
115117 if( pThis==0 ){
115118 sqlite3_free(aDoclist);
115119 aDoclist = 0;
115120 nDoclist = 0;
115121 break;
115122 }else if( aDoclist==0 ){
115123 aDoclist = pThis;
115124 nDoclist = nThis;
115125 }else{
115126 assert( iPrev>=0 );
115127 fts3DoclistPhraseMerge(pTab->bDescIdx,
115128 iToken-iPrev, aDoclist, nDoclist, pThis, &nThis
115129 );
115130 sqlite3_free(aDoclist);
115131 aDoclist = pThis;
115132 nDoclist = nThis;
115133 }
115134 iPrev = iToken;
115135 }
115136 }
115137 }
115138
115139 if( rc==SQLITE_OK ){
115140 p->doclist.aAll = aDoclist;
115141 p->doclist.nAll = nDoclist;
115142 }else{
115143 sqlite3_free(aDoclist);
115144 }
115145 return rc;
115146 }
115147
115148 static int fts3EvalDeferredPhrase(Fts3Cursor *pCsr, Fts3Phrase *pPhrase){
115149 int iToken;
115150 int rc = SQLITE_OK;
115151
115152 int nMaxUndeferred = -1;
115153 char *aPoslist = 0;
115154 int nPoslist = 0;
115155 int iPrev = -1;
115156
115157 assert( pPhrase->doclist.bFreeList==0 );
115158
115159 for(iToken=0; rc==SQLITE_OK && iToken<pPhrase->nToken; iToken++){
115160 Fts3PhraseToken *pToken = &pPhrase->aToken[iToken];
115161 Fts3DeferredToken *pDeferred = pToken->pDeferred;
115162
115163 if( pDeferred ){
115164 char *pList;
115165 int nList;
115166 rc = sqlite3Fts3DeferredTokenList(pDeferred, &pList, &nList);
115167 if( rc!=SQLITE_OK ) return rc;
115168
115169 if( pList==0 ){
115170 sqlite3_free(aPoslist);
115171 pPhrase->doclist.pList = 0;
115172 pPhrase->doclist.nList = 0;
115173 return SQLITE_OK;
115174
115175 }else if( aPoslist==0 ){
115176 aPoslist = pList;
115177 nPoslist = nList;
115178
115179 }else{
115180 char *aOut = pList;
115181 char *p1 = aPoslist;
115182 char *p2 = aOut;
115183
115184 assert( iPrev>=0 );
115185 fts3PoslistPhraseMerge(&aOut, iToken-iPrev, 0, 1, &p1, &p2);
115186 sqlite3_free(aPoslist);
115187 aPoslist = pList;
115188 nPoslist = aOut - aPoslist;
115189 if( nPoslist==0 ){
115190 sqlite3_free(aPoslist);
115191 pPhrase->doclist.pList = 0;
115192 pPhrase->doclist.nList = 0;
115193 return SQLITE_OK;
115194 }
115195 }
115196 iPrev = iToken;
115197 }else{
115198 nMaxUndeferred = iToken;
115199 }
115200 }
115201
115202 if( iPrev>=0 ){
115203 if( nMaxUndeferred<0 ){
115204 pPhrase->doclist.pList = aPoslist;
115205 pPhrase->doclist.nList = nPoslist;
115206 pPhrase->doclist.iDocid = pCsr->iPrevId;
115207 pPhrase->doclist.bFreeList = 1;
115208 }else{
115209 int nDistance;
115210 char *p1;
115211 char *p2;
115212 char *aOut;
115213
115214 if( nMaxUndeferred>iPrev ){
115215 p1 = aPoslist;
115216 p2 = pPhrase->doclist.pList;
115217 nDistance = nMaxUndeferred - iPrev;
115218 }else{
115219 p1 = pPhrase->doclist.pList;
115220 p2 = aPoslist;
115221 nDistance = iPrev - nMaxUndeferred;
115222 }
115223
115224 aOut = (char *)sqlite3_malloc(nPoslist+8);
115225 if( !aOut ){
115226 sqlite3_free(aPoslist);
115227 return SQLITE_NOMEM;
115228 }
115229
115230 pPhrase->doclist.pList = aOut;
115231 if( fts3PoslistPhraseMerge(&aOut, nDistance, 0, 1, &p1, &p2) ){
115232 pPhrase->doclist.bFreeList = 1;
115233 pPhrase->doclist.nList = (aOut - pPhrase->doclist.pList);
115234 }else{
115235 sqlite3_free(aOut);
115236 pPhrase->doclist.pList = 0;
115237 pPhrase->doclist.nList = 0;
115238 }
115239 sqlite3_free(aPoslist);
115240 }
115241 }
115242
115243 return SQLITE_OK;
115244 }
115245
115246 /*
115247 ** This function is called for each Fts3Phrase in a full-text query
115248 ** expression to initialize the mechanism for returning rows. Once this
115249 ** function has been called successfully on an Fts3Phrase, it may be
115250 ** used with fts3EvalPhraseNext() to iterate through the matching docids.
115251 */
115252 static int fts3EvalPhraseStart(Fts3Cursor *pCsr, int bOptOk, Fts3Phrase *p){
115253 int rc;
115254 Fts3PhraseToken *pFirst = &p->aToken[0];
115255 Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
115256
115257 assert( p->doclist.aAll==0 );
115258 if( pCsr->bDesc==pTab->bDescIdx && bOptOk==1 && p->nToken==1
115259 && pFirst->pSegcsr && pFirst->pSegcsr->bLookup
115260 ){
115261 /* Use the incremental approach. */
115262 int iCol = (p->iColumn >= pTab->nColumn ? -1 : p->iColumn);
115263 rc = sqlite3Fts3MsrIncrStart(
115264 pTab, pFirst->pSegcsr, iCol, pFirst->z, pFirst->n);
115265 p->bIncr = 1;
115266
115267 }else{
115268 /* Load the full doclist for the phrase into memory. */
115269 rc = fts3EvalPhraseLoad(pCsr, p);
115270 p->bIncr = 0;
115271 }
115272
115273 assert( rc!=SQLITE_OK || p->nToken<1 || p->aToken[0].pSegcsr==0 || p->bIncr );
115274 return rc;
115275 }
115276
115277 /*
115278 ** This function is used to iterate backwards (from the end to start)
115279 ** through doclists.
115280 */
115281 SQLITE_PRIVATE void sqlite3Fts3DoclistPrev(
115282 int bDescIdx, /* True if the doclist is desc */
115283 char *aDoclist, /* Pointer to entire doclist */
115284 int nDoclist, /* Length of aDoclist in bytes */
115285 char **ppIter, /* IN/OUT: Iterator pointer */
115286 sqlite3_int64 *piDocid, /* IN/OUT: Docid pointer */
115287 int *pnList, /* IN/OUT: List length pointer */
115288 u8 *pbEof /* OUT: End-of-file flag */
115289 ){
115290 char *p = *ppIter;
115291
115292 assert( nDoclist>0 );
115293 assert( *pbEof==0 );
115294 assert( p || *piDocid==0 );
115295 assert( !p || (p>aDoclist && p<&aDoclist[nDoclist]) );
115296
115297 if( p==0 ){
115298 sqlite3_int64 iDocid = 0;
115299 char *pNext = 0;
115300 char *pDocid = aDoclist;
115301 char *pEnd = &aDoclist[nDoclist];
115302 int iMul = 1;
115303
115304 while( pDocid<pEnd ){
115305 sqlite3_int64 iDelta;
115306 pDocid += sqlite3Fts3GetVarint(pDocid, &iDelta);
115307 iDocid += (iMul * iDelta);
115308 pNext = pDocid;
115309 fts3PoslistCopy(0, &pDocid);
115310 while( pDocid<pEnd && *pDocid==0 ) pDocid++;
115311 iMul = (bDescIdx ? -1 : 1);
115312 }
115313
115314 *pnList = pEnd - pNext;
115315 *ppIter = pNext;
115316 *piDocid = iDocid;
115317 }else{
115318 int iMul = (bDescIdx ? -1 : 1);
115319 sqlite3_int64 iDelta;
115320 fts3GetReverseVarint(&p, aDoclist, &iDelta);
115321 *piDocid -= (iMul * iDelta);
115322
115323 if( p==aDoclist ){
115324 *pbEof = 1;
115325 }else{
115326 char *pSave = p;
115327 fts3ReversePoslist(aDoclist, &p);
115328 *pnList = (pSave - p);
115329 }
115330 *ppIter = p;
115331 }
115332 }
115333
115334 /*
115335 ** Attempt to move the phrase iterator to point to the next matching docid.
115336 ** If an error occurs, return an SQLite error code. Otherwise, return
115337 ** SQLITE_OK.
115338 **
115339 ** If there is no "next" entry and no error occurs, then *pbEof is set to
115340 ** 1 before returning. Otherwise, if no error occurs and the iterator is
115341 ** successfully advanced, *pbEof is set to 0.
115342 */
115343 static int fts3EvalPhraseNext(
115344 Fts3Cursor *pCsr,
115345 Fts3Phrase *p,
115346 u8 *pbEof
115347 ){
115348 int rc = SQLITE_OK;
115349 Fts3Doclist *pDL = &p->doclist;
115350 Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
115351
115352 if( p->bIncr ){
115353 assert( p->nToken==1 );
115354 assert( pDL->pNextDocid==0 );
115355 rc = sqlite3Fts3MsrIncrNext(pTab, p->aToken[0].pSegcsr,
115356 &pDL->iDocid, &pDL->pList, &pDL->nList
115357 );
115358 if( rc==SQLITE_OK && !pDL->pList ){
115359 *pbEof = 1;
115360 }
115361 }else if( pCsr->bDesc!=pTab->bDescIdx && pDL->nAll ){
115362 sqlite3Fts3DoclistPrev(pTab->bDescIdx, pDL->aAll, pDL->nAll,
115363 &pDL->pNextDocid, &pDL->iDocid, &pDL->nList, pbEof
115364 );
115365 pDL->pList = pDL->pNextDocid;
115366 }else{
115367 char *pIter; /* Used to iterate through aAll */
115368 char *pEnd = &pDL->aAll[pDL->nAll]; /* 1 byte past end of aAll */
115369 if( pDL->pNextDocid ){
115370 pIter = pDL->pNextDocid;
115371 }else{
115372 pIter = pDL->aAll;
115373 }
115374
115375 if( pIter>=pEnd ){
115376 /* We have already reached the end of this doclist. EOF. */
115377 *pbEof = 1;
115378 }else{
115379 sqlite3_int64 iDelta;
115380 pIter += sqlite3Fts3GetVarint(pIter, &iDelta);
115381 if( pTab->bDescIdx==0 || pDL->pNextDocid==0 ){
115382 pDL->iDocid += iDelta;
115383 }else{
115384 pDL->iDocid -= iDelta;
115385 }
115386 pDL->pList = pIter;
115387 fts3PoslistCopy(0, &pIter);
115388 pDL->nList = (pIter - pDL->pList);
115389
115390 /* pIter now points just past the 0x00 that terminates the position-
115391 ** list for document pDL->iDocid. However, if this position-list was
115392 ** edited in place by fts3EvalNearTrim2(), then pIter may not actually
115393 ** point to the start of the next docid value. The following line deals
115394 ** with this case by advancing pIter past the zero-padding added by
115395 ** fts3EvalNearTrim2(). */
115396 while( pIter<pEnd && *pIter==0 ) pIter++;
115397
115398 pDL->pNextDocid = pIter;
115399 assert( *pIter || pIter>=&pDL->aAll[pDL->nAll] );
115400 *pbEof = 0;
115401 }
115402 }
115403
115404 return rc;
115405 }
115406
115407 static void fts3EvalStartReaders(
115408 Fts3Cursor *pCsr,
115409 Fts3Expr *pExpr,
115410 int bOptOk,
115411 int *pRc
115412 ){
115413 if( pExpr && SQLITE_OK==*pRc ){
115414 if( pExpr->eType==FTSQUERY_PHRASE ){
115415 int i;
115416 int nToken = pExpr->pPhrase->nToken;
115417 for(i=0; i<nToken; i++){
115418 if( pExpr->pPhrase->aToken[i].pDeferred==0 ) break;
115419 }
115420 pExpr->bDeferred = (i==nToken);
115421 *pRc = fts3EvalPhraseStart(pCsr, bOptOk, pExpr->pPhrase);
115422 }else{
115423 fts3EvalStartReaders(pCsr, pExpr->pLeft, bOptOk, pRc);
115424 fts3EvalStartReaders(pCsr, pExpr->pRight, bOptOk, pRc);
115425 pExpr->bDeferred = (pExpr->pLeft->bDeferred && pExpr->pRight->bDeferred);
115426 }
115427 }
115428 }
115429
115430
115431 typedef struct Fts3TokenAndCost Fts3TokenAndCost;
115432 struct Fts3TokenAndCost {
115433 Fts3PhraseToken *pToken;
115434 Fts3Expr *pRoot;
115435 int nOvfl;
115436 int iCol;
115437 };
115438
115439 static void fts3EvalTokenCosts(
115440 Fts3Cursor *pCsr,
115441 Fts3Expr *pRoot,
115442 Fts3Expr *pExpr,
115443 Fts3TokenAndCost **ppTC,
115444 Fts3Expr ***ppOr,
115445 int *pRc
115446 ){
115447 if( *pRc==SQLITE_OK && pExpr ){
115448 if( pExpr->eType==FTSQUERY_PHRASE ){
115449 Fts3Phrase *pPhrase = pExpr->pPhrase;
115450 int i;
115451 for(i=0; *pRc==SQLITE_OK && i<pPhrase->nToken; i++){
115452 Fts3TokenAndCost *pTC = (*ppTC)++;
115453 pTC->pRoot = pRoot;
115454 pTC->pToken = &pPhrase->aToken[i];
115455 pTC->iCol = pPhrase->iColumn;
115456 *pRc = sqlite3Fts3MsrOvfl(pCsr, pTC->pToken->pSegcsr, &pTC->nOvfl);
115457 }
115458 }else if( pExpr->eType!=FTSQUERY_NOT ){
115459 if( pExpr->eType==FTSQUERY_OR ){
115460 pRoot = pExpr->pLeft;
115461 **ppOr = pRoot;
115462 (*ppOr)++;
115463 }
115464 fts3EvalTokenCosts(pCsr, pRoot, pExpr->pLeft, ppTC, ppOr, pRc);
115465 if( pExpr->eType==FTSQUERY_OR ){
115466 pRoot = pExpr->pRight;
115467 **ppOr = pRoot;
115468 (*ppOr)++;
115469 }
115470 fts3EvalTokenCosts(pCsr, pRoot, pExpr->pRight, ppTC, ppOr, pRc);
115471 }
115472 }
115473 }
115474
115475 static int fts3EvalAverageDocsize(Fts3Cursor *pCsr, int *pnPage){
115476 if( pCsr->nRowAvg==0 ){
115477 /* The average document size, which is required to calculate the cost
115478 ** of each doclist, has not yet been determined. Read the required
115479 ** data from the %_stat table to calculate it.
115480 **
115481 ** Entry 0 of the %_stat table is a blob containing (nCol+1) FTS3
115482 ** varints, where nCol is the number of columns in the FTS3 table.
115483 ** The first varint is the number of documents currently stored in
115484 ** the table. The following nCol varints contain the total amount of
115485 ** data stored in all rows of each column of the table, from left
115486 ** to right.
115487 */
115488 int rc;
115489 Fts3Table *p = (Fts3Table*)pCsr->base.pVtab;
115490 sqlite3_stmt *pStmt;
115491 sqlite3_int64 nDoc = 0;
115492 sqlite3_int64 nByte = 0;
115493 const char *pEnd;
115494 const char *a;
115495
115496 rc = sqlite3Fts3SelectDoctotal(p, &pStmt);
115497 if( rc!=SQLITE_OK ) return rc;
115498 a = sqlite3_column_blob(pStmt, 0);
115499 assert( a );
115500
115501 pEnd = &a[sqlite3_column_bytes(pStmt, 0)];
115502 a += sqlite3Fts3GetVarint(a, &nDoc);
115503 while( a<pEnd ){
115504 a += sqlite3Fts3GetVarint(a, &nByte);
115505 }
115506 if( nDoc==0 || nByte==0 ){
115507 sqlite3_reset(pStmt);
115508 return SQLITE_CORRUPT_VTAB;
115509 }
115510
115511 pCsr->nDoc = nDoc;
115512 pCsr->nRowAvg = (int)(((nByte / nDoc) + p->nPgsz) / p->nPgsz);
115513 assert( pCsr->nRowAvg>0 );
115514 rc = sqlite3_reset(pStmt);
115515 if( rc!=SQLITE_OK ) return rc;
115516 }
115517
115518 *pnPage = pCsr->nRowAvg;
115519 return SQLITE_OK;
115520 }
115521
115522 static int fts3EvalSelectDeferred(
115523 Fts3Cursor *pCsr,
115524 Fts3Expr *pRoot,
115525 Fts3TokenAndCost *aTC,
115526 int nTC
115527 ){
115528 int nDocSize = 0;
115529 int nDocEst = 0;
115530 int rc = SQLITE_OK;
115531 Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
115532 int ii;
115533
115534 int nOvfl = 0;
115535 int nTerm = 0;
115536
115537 for(ii=0; ii<nTC; ii++){
115538 if( aTC[ii].pRoot==pRoot ){
115539 nOvfl += aTC[ii].nOvfl;
115540 nTerm++;
115541 }
115542 }
115543 if( nOvfl==0 || nTerm<2 ) return SQLITE_OK;
115544
115545 rc = fts3EvalAverageDocsize(pCsr, &nDocSize);
115546
115547 for(ii=0; ii<nTerm && rc==SQLITE_OK; ii++){
115548 int jj;
115549 Fts3TokenAndCost *pTC = 0;
115550
115551 for(jj=0; jj<nTC; jj++){
115552 if( aTC[jj].pToken && aTC[jj].pRoot==pRoot
115553 && (!pTC || aTC[jj].nOvfl<pTC->nOvfl)
115554 ){
115555 pTC = &aTC[jj];
115556 }
115557 }
115558 assert( pTC );
115559
115560 /* At this point pTC points to the cheapest remaining token. */
115561 if( ii==0 ){
115562 if( pTC->nOvfl ){
115563 nDocEst = (pTC->nOvfl * pTab->nPgsz + pTab->nPgsz) / 10;
115564 }else{
115565 /* TODO: Fix this so that the doclist need not be read twice. */
115566 Fts3PhraseToken *pToken = pTC->pToken;
115567 int nList = 0;
115568 char *pList = 0;
115569 rc = fts3TermSelect(pTab, pToken, pTC->iCol, 1, &nList, &pList);
115570 if( rc==SQLITE_OK ){
115571 nDocEst = fts3DoclistCountDocids(1, pList, nList);
115572 }
115573 sqlite3_free(pList);
115574 if( rc==SQLITE_OK ){
115575 rc = sqlite3Fts3TermSegReaderCursor(pCsr,
115576 pToken->z, pToken->n, pToken->isPrefix, &pToken->pSegcsr
115577 );
115578 }
115579 }
115580 }else{
115581 if( pTC->nOvfl>=(nDocEst*nDocSize) ){
115582 Fts3PhraseToken *pToken = pTC->pToken;
115583 rc = sqlite3Fts3DeferToken(pCsr, pToken, pTC->iCol);
115584 fts3SegReaderCursorFree(pToken->pSegcsr);
115585 pToken->pSegcsr = 0;
115586 }
115587 nDocEst = 1 + (nDocEst/4);
115588 }
115589 pTC->pToken = 0;
115590 }
115591
115592 return rc;
115593 }
115594
115595 SQLITE_PRIVATE int sqlite3Fts3EvalStart(Fts3Cursor *pCsr, Fts3Expr *pExpr, int bOptOk){
115596 Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
115597 int rc = SQLITE_OK;
115598 int nToken = 0;
115599 int nOr = 0;
115600
115601 /* Allocate a MultiSegReader for each token in the expression. */
115602 fts3EvalAllocateReaders(pCsr, pExpr, &nToken, &nOr, &rc);
115603
115604 /* Call fts3EvalPhraseStart() on all phrases in the expression. TODO:
115605 ** This call will eventually also be responsible for determining which
115606 ** tokens are 'deferred' until the document text is loaded into memory.
115607 **
115608 ** Each token in each phrase is dealt with using one of the following
115609 ** three strategies:
115610 **
115611 ** 1. Entire doclist loaded into memory as part of the
115612 ** fts3EvalStartReaders() call.
115613 **
115614 ** 2. Doclist loaded into memory incrementally, as part of each
115615 ** sqlite3Fts3EvalNext() call.
115616 **
115617 ** 3. Token doclist is never loaded. Instead, documents are loaded into
115618 ** memory and scanned for the token as part of the sqlite3Fts3EvalNext()
115619 ** call. This is known as a "deferred" token.
115620 */
115621
115622 /* If bOptOk is true, check if there are any tokens that should be deferred.
115623 */
115624 if( rc==SQLITE_OK && bOptOk && nToken>1 && pTab->bHasStat ){
115625 Fts3TokenAndCost *aTC;
115626 Fts3Expr **apOr;
115627 aTC = (Fts3TokenAndCost *)sqlite3_malloc(
115628 sizeof(Fts3TokenAndCost) * nToken
115629 + sizeof(Fts3Expr *) * nOr * 2
115630 );
115631 apOr = (Fts3Expr **)&aTC[nToken];
115632
115633 if( !aTC ){
115634 rc = SQLITE_NOMEM;
115635 }else{
115636 int ii;
115637 Fts3TokenAndCost *pTC = aTC;
115638 Fts3Expr **ppOr = apOr;
115639
115640 fts3EvalTokenCosts(pCsr, 0, pExpr, &pTC, &ppOr, &rc);
115641 nToken = pTC-aTC;
115642 nOr = ppOr-apOr;
115643
115644 if( rc==SQLITE_OK ){
115645 rc = fts3EvalSelectDeferred(pCsr, 0, aTC, nToken);
115646 for(ii=0; rc==SQLITE_OK && ii<nOr; ii++){
115647 rc = fts3EvalSelectDeferred(pCsr, apOr[ii], aTC, nToken);
115648 }
115649 }
115650
115651 sqlite3_free(aTC);
115652 }
115653 }
115654
115655 fts3EvalStartReaders(pCsr, pExpr, bOptOk, &rc);
115656 return rc;
115657 }
115658
115659 static void fts3EvalZeroPoslist(Fts3Phrase *pPhrase){
115660 if( pPhrase->doclist.bFreeList ){
115661 sqlite3_free(pPhrase->doclist.pList);
115662 }
115663 pPhrase->doclist.pList = 0;
115664 pPhrase->doclist.nList = 0;
115665 pPhrase->doclist.bFreeList = 0;
115666 }
115667
115668 static int fts3EvalNearTrim2(
115669 int nNear,
115670 char *aTmp, /* Temporary space to use */
115671 char **paPoslist, /* IN/OUT: Position list */
115672 int *pnToken, /* IN/OUT: Tokens in phrase of *paPoslist */
115673 Fts3Phrase *pPhrase /* The phrase object to trim the doclist of */
115674 ){
115675 int nParam1 = nNear + pPhrase->nToken;
115676 int nParam2 = nNear + *pnToken;
115677 int nNew;
115678 char *p2;
115679 char *pOut;
115680 int res;
115681
115682 assert( pPhrase->doclist.pList );
115683
115684 p2 = pOut = pPhrase->doclist.pList;
115685 res = fts3PoslistNearMerge(
115686 &pOut, aTmp, nParam1, nParam2, paPoslist, &p2
115687 );
115688 if( res ){
115689 nNew = (pOut - pPhrase->doclist.pList) - 1;
115690 assert( pPhrase->doclist.pList[nNew]=='\0' );
115691 assert( nNew<=pPhrase->doclist.nList && nNew>0 );
115692 memset(&pPhrase->doclist.pList[nNew], 0, pPhrase->doclist.nList - nNew);
115693 pPhrase->doclist.nList = nNew;
115694 *paPoslist = pPhrase->doclist.pList;
115695 *pnToken = pPhrase->nToken;
115696 }
115697
115698 return res;
115699 }
115700
115701 static int fts3EvalNearTest(Fts3Expr *pExpr, int *pRc){
115702 int res = 1;
115703
115704 /* The following block runs if pExpr is the root of a NEAR query.
115705 ** For example, the query:
115706 **
115707 ** "w" NEAR "x" NEAR "y" NEAR "z"
115708 **
115709 ** which is represented in tree form as:
115710 **
115711 ** |
115712 ** +--NEAR--+ <-- root of NEAR query
115713 ** | |
115714 ** +--NEAR--+ "z"
115715 ** | |
115716 ** +--NEAR--+ "y"
115717 ** | |
115718 ** "w" "x"
115719 **
115720 ** The right-hand child of a NEAR node is always a phrase. The
115721 ** left-hand child may be either a phrase or a NEAR node. There are
115722 ** no exceptions to this.
115723 */
115724 if( *pRc==SQLITE_OK
115725 && pExpr->eType==FTSQUERY_NEAR
115726 && pExpr->bEof==0
115727 && (pExpr->pParent==0 || pExpr->pParent->eType!=FTSQUERY_NEAR)
115728 ){
115729 Fts3Expr *p;
115730 int nTmp = 0; /* Bytes of temp space */
115731 char *aTmp; /* Temp space for PoslistNearMerge() */
115732
115733 /* Allocate temporary working space. */
115734 for(p=pExpr; p->pLeft; p=p->pLeft){
115735 nTmp += p->pRight->pPhrase->doclist.nList;
115736 }
115737 nTmp += p->pPhrase->doclist.nList;
115738 aTmp = sqlite3_malloc(nTmp*2);
115739 if( !aTmp ){
115740 *pRc = SQLITE_NOMEM;
115741 res = 0;
115742 }else{
115743 char *aPoslist = p->pPhrase->doclist.pList;
115744 int nToken = p->pPhrase->nToken;
115745
115746 for(p=p->pParent;res && p && p->eType==FTSQUERY_NEAR; p=p->pParent){
115747 Fts3Phrase *pPhrase = p->pRight->pPhrase;
115748 int nNear = p->nNear;
115749 res = fts3EvalNearTrim2(nNear, aTmp, &aPoslist, &nToken, pPhrase);
115750 }
115751
115752 aPoslist = pExpr->pRight->pPhrase->doclist.pList;
115753 nToken = pExpr->pRight->pPhrase->nToken;
115754 for(p=pExpr->pLeft; p && res; p=p->pLeft){
115755 int nNear = p->pParent->nNear;
115756 Fts3Phrase *pPhrase = (
115757 p->eType==FTSQUERY_NEAR ? p->pRight->pPhrase : p->pPhrase
115758 );
115759 res = fts3EvalNearTrim2(nNear, aTmp, &aPoslist, &nToken, pPhrase);
115760 }
115761 }
115762
115763 sqlite3_free(aTmp);
115764 }
115765
115766 return res;
115767 }
115768
115769 /*
115770 ** This macro is used by the fts3EvalNext() function. The two arguments are
115771 ** 64-bit docid values. If the current query is "ORDER BY docid ASC", then
115772 ** the macro returns (i1 - i2). Or if it is "ORDER BY docid DESC", then
115773 ** it returns (i2 - i1). This allows the same code to be used for merging
115774 ** doclists in ascending or descending order.
115775 */
115776 #define DOCID_CMP(i1, i2) ((pCsr->bDesc?-1:1) * (i1-i2))
115777
115778 static void fts3EvalNext(
115779 Fts3Cursor *pCsr,
115780 Fts3Expr *pExpr,
115781 int *pRc
115782 ){
115783 if( *pRc==SQLITE_OK ){
115784 assert( pExpr->bEof==0 );
115785 pExpr->bStart = 1;
115786
115787 switch( pExpr->eType ){
115788 case FTSQUERY_NEAR:
115789 case FTSQUERY_AND: {
115790 Fts3Expr *pLeft = pExpr->pLeft;
115791 Fts3Expr *pRight = pExpr->pRight;
115792 assert( !pLeft->bDeferred || !pRight->bDeferred );
115793 if( pLeft->bDeferred ){
115794 fts3EvalNext(pCsr, pRight, pRc);
115795 pExpr->iDocid = pRight->iDocid;
115796 pExpr->bEof = pRight->bEof;
115797 }else if( pRight->bDeferred ){
115798 fts3EvalNext(pCsr, pLeft, pRc);
115799 pExpr->iDocid = pLeft->iDocid;
115800 pExpr->bEof = pLeft->bEof;
115801 }else{
115802 fts3EvalNext(pCsr, pLeft, pRc);
115803 fts3EvalNext(pCsr, pRight, pRc);
115804
115805 while( !pLeft->bEof && !pRight->bEof && *pRc==SQLITE_OK ){
115806 sqlite3_int64 iDiff = DOCID_CMP(pLeft->iDocid, pRight->iDocid);
115807 if( iDiff==0 ) break;
115808 if( iDiff<0 ){
115809 fts3EvalNext(pCsr, pLeft, pRc);
115810 }else{
115811 fts3EvalNext(pCsr, pRight, pRc);
115812 }
115813 }
115814
115815 pExpr->iDocid = pLeft->iDocid;
115816 pExpr->bEof = (pLeft->bEof || pRight->bEof);
115817 }
115818 break;
115819 }
115820
115821 case FTSQUERY_OR: {
115822 Fts3Expr *pLeft = pExpr->pLeft;
115823 Fts3Expr *pRight = pExpr->pRight;
115824 sqlite3_int64 iCmp = DOCID_CMP(pLeft->iDocid, pRight->iDocid);
115825
115826 assert( pLeft->bStart || pLeft->iDocid==pRight->iDocid );
115827 assert( pRight->bStart || pLeft->iDocid==pRight->iDocid );
115828
115829 if( pRight->bEof || (pLeft->bEof==0 && iCmp<0) ){
115830 fts3EvalNext(pCsr, pLeft, pRc);
115831 }else if( pLeft->bEof || (pRight->bEof==0 && iCmp>0) ){
115832 fts3EvalNext(pCsr, pRight, pRc);
115833 }else{
115834 fts3EvalNext(pCsr, pLeft, pRc);
115835 fts3EvalNext(pCsr, pRight, pRc);
115836 }
115837
115838 pExpr->bEof = (pLeft->bEof && pRight->bEof);
115839 iCmp = DOCID_CMP(pLeft->iDocid, pRight->iDocid);
115840 if( pRight->bEof || (pLeft->bEof==0 && iCmp<0) ){
115841 pExpr->iDocid = pLeft->iDocid;
115842 }else{
115843 pExpr->iDocid = pRight->iDocid;
115844 }
115845
115846 break;
115847 }
115848
115849 case FTSQUERY_NOT: {
115850 Fts3Expr *pLeft = pExpr->pLeft;
115851 Fts3Expr *pRight = pExpr->pRight;
115852
115853 if( pRight->bStart==0 ){
115854 fts3EvalNext(pCsr, pRight, pRc);
115855 assert( *pRc!=SQLITE_OK || pRight->bStart );
115856 }
115857
115858 fts3EvalNext(pCsr, pLeft, pRc);
115859 if( pLeft->bEof==0 ){
115860 while( !*pRc
115861 && !pRight->bEof
115862 && DOCID_CMP(pLeft->iDocid, pRight->iDocid)>0
115863 ){
115864 fts3EvalNext(pCsr, pRight, pRc);
115865 }
115866 }
115867 pExpr->iDocid = pLeft->iDocid;
115868 pExpr->bEof = pLeft->bEof;
115869 break;
115870 }
115871
115872 default: {
115873 Fts3Phrase *pPhrase = pExpr->pPhrase;
115874 fts3EvalZeroPoslist(pPhrase);
115875 *pRc = fts3EvalPhraseNext(pCsr, pPhrase, &pExpr->bEof);
115876 pExpr->iDocid = pPhrase->doclist.iDocid;
115877 break;
115878 }
115879 }
115880 }
115881 }
115882
115883 static int fts3EvalDeferredTest(Fts3Cursor *pCsr, Fts3Expr *pExpr, int *pRc){
115884 int bHit = 1;
115885 if( *pRc==SQLITE_OK ){
115886 switch( pExpr->eType ){
115887 case FTSQUERY_NEAR:
115888 case FTSQUERY_AND:
115889 bHit = (
115890 fts3EvalDeferredTest(pCsr, pExpr->pLeft, pRc)
115891 && fts3EvalDeferredTest(pCsr, pExpr->pRight, pRc)
115892 && fts3EvalNearTest(pExpr, pRc)
115893 );
115894
115895 /* If the NEAR expression does not match any rows, zero the doclist for
115896 ** all phrases involved in the NEAR. This is because the snippet(),
115897 ** offsets() and matchinfo() functions are not supposed to recognize
115898 ** any instances of phrases that are part of unmatched NEAR queries.
115899 ** For example if this expression:
115900 **
115901 ** ... MATCH 'a OR (b NEAR c)'
115902 **
115903 ** is matched against a row containing:
115904 **
115905 ** 'a b d e'
115906 **
115907 ** then any snippet() should ony highlight the "a" term, not the "b"
115908 ** (as "b" is part of a non-matching NEAR clause).
115909 */
115910 if( bHit==0
115911 && pExpr->eType==FTSQUERY_NEAR
115912 && (pExpr->pParent==0 || pExpr->pParent->eType!=FTSQUERY_NEAR)
115913 ){
115914 Fts3Expr *p;
115915 for(p=pExpr; p->pPhrase==0; p=p->pLeft){
115916 if( p->pRight->iDocid==pCsr->iPrevId ){
115917 fts3EvalZeroPoslist(p->pRight->pPhrase);
115918 }
115919 }
115920 if( p->iDocid==pCsr->iPrevId ){
115921 fts3EvalZeroPoslist(p->pPhrase);
115922 }
115923 }
115924
115925 break;
115926
115927 case FTSQUERY_OR: {
115928 int bHit1 = fts3EvalDeferredTest(pCsr, pExpr->pLeft, pRc);
115929 int bHit2 = fts3EvalDeferredTest(pCsr, pExpr->pRight, pRc);
115930 bHit = bHit1 || bHit2;
115931 break;
115932 }
115933
115934 case FTSQUERY_NOT:
115935 bHit = (
115936 fts3EvalDeferredTest(pCsr, pExpr->pLeft, pRc)
115937 && !fts3EvalDeferredTest(pCsr, pExpr->pRight, pRc)
115938 );
115939 break;
115940
115941 default: {
115942 if( pCsr->pDeferred
115943 && (pExpr->iDocid==pCsr->iPrevId || pExpr->bDeferred)
115944 ){
115945 Fts3Phrase *pPhrase = pExpr->pPhrase;
115946 assert( pExpr->bDeferred || pPhrase->doclist.bFreeList==0 );
115947 if( pExpr->bDeferred ){
115948 fts3EvalZeroPoslist(pPhrase);
115949 }
115950 *pRc = fts3EvalDeferredPhrase(pCsr, pPhrase);
115951 bHit = (pPhrase->doclist.pList!=0);
115952 pExpr->iDocid = pCsr->iPrevId;
115953 }else{
115954 bHit = (pExpr->bEof==0 && pExpr->iDocid==pCsr->iPrevId);
115955 }
115956 break;
115957 }
115958 }
115959 }
115960 return bHit;
115961 }
115962
115963 /*
115964 ** Return 1 if both of the following are true:
115965 **
115966 ** 1. *pRc is SQLITE_OK when this function returns, and
115967 **
115968 ** 2. After scanning the current FTS table row for the deferred tokens,
115969 ** it is determined that the row does not match the query.
115970 **
115971 ** Or, if no error occurs and it seems the current row does match the FTS
115972 ** query, return 0.
115973 */
115974 static int fts3EvalLoadDeferred(Fts3Cursor *pCsr, int *pRc){
115975 int rc = *pRc;
115976 int bMiss = 0;
115977 if( rc==SQLITE_OK ){
115978 if( pCsr->pDeferred ){
115979 rc = fts3CursorSeek(0, pCsr);
115980 if( rc==SQLITE_OK ){
115981 rc = sqlite3Fts3CacheDeferredDoclists(pCsr);
115982 }
115983 }
115984 bMiss = (0==fts3EvalDeferredTest(pCsr, pCsr->pExpr, &rc));
115985 sqlite3Fts3FreeDeferredDoclists(pCsr);
115986 *pRc = rc;
115987 }
115988 return (rc==SQLITE_OK && bMiss);
115989 }
115990
115991 /*
115992 ** Advance to the next document that matches the FTS expression in
115993 ** Fts3Cursor.pExpr.
115994 */
115995 SQLITE_PRIVATE int sqlite3Fts3EvalNext(Fts3Cursor *pCsr){
115996 int rc = SQLITE_OK; /* Return Code */
115997 Fts3Expr *pExpr = pCsr->pExpr;
115998 assert( pCsr->isEof==0 );
115999 if( pExpr==0 ){
116000 pCsr->isEof = 1;
116001 }else{
116002 do {
116003 if( pCsr->isRequireSeek==0 ){
116004 sqlite3_reset(pCsr->pStmt);
116005 }
116006 assert( sqlite3_data_count(pCsr->pStmt)==0 );
116007 fts3EvalNext(pCsr, pExpr, &rc);
116008 pCsr->isEof = pExpr->bEof;
116009 pCsr->isRequireSeek = 1;
116010 pCsr->isMatchinfoNeeded = 1;
116011 pCsr->iPrevId = pExpr->iDocid;
116012 }while( pCsr->isEof==0 && fts3EvalLoadDeferred(pCsr, &rc) );
116013 }
116014 return rc;
116015 }
116016
116017 /*
116018 ** Restart interation for expression pExpr so that the next call to
116019 ** sqlite3Fts3EvalNext() visits the first row. Do not allow incremental
116020 ** loading or merging of phrase doclists for this iteration.
116021 **
116022 ** If *pRc is other than SQLITE_OK when this function is called, it is
116023 ** a no-op. If an error occurs within this function, *pRc is set to an
116024 ** SQLite error code before returning.
116025 */
116026 static void fts3EvalRestart(
116027 Fts3Cursor *pCsr,
116028 Fts3Expr *pExpr,
116029 int *pRc
116030 ){
116031 if( pExpr && *pRc==SQLITE_OK ){
116032 Fts3Phrase *pPhrase = pExpr->pPhrase;
116033
116034 if( pPhrase ){
116035 fts3EvalZeroPoslist(pPhrase);
116036 if( pPhrase->bIncr ){
116037 sqlite3Fts3EvalPhraseCleanup(pPhrase);
116038 memset(&pPhrase->doclist, 0, sizeof(Fts3Doclist));
116039 *pRc = sqlite3Fts3EvalStart(pCsr, pExpr, 0);
116040 }else{
116041 pPhrase->doclist.pNextDocid = 0;
116042 pPhrase->doclist.iDocid = 0;
116043 }
116044 }
116045
116046 pExpr->iDocid = 0;
116047 pExpr->bEof = 0;
116048 pExpr->bStart = 0;
116049
116050 fts3EvalRestart(pCsr, pExpr->pLeft, pRc);
116051 fts3EvalRestart(pCsr, pExpr->pRight, pRc);
116052 }
116053 }
116054
116055 /*
116056 ** After allocating the Fts3Expr.aMI[] array for each phrase in the
116057 ** expression rooted at pExpr, the cursor iterates through all rows matched
116058 ** by pExpr, calling this function for each row. This function increments
116059 ** the values in Fts3Expr.aMI[] according to the position-list currently
116060 ** found in Fts3Expr.pPhrase->doclist.pList for each of the phrase
116061 ** expression nodes.
116062 */
116063 static void fts3EvalUpdateCounts(Fts3Expr *pExpr){
116064 if( pExpr ){
116065 Fts3Phrase *pPhrase = pExpr->pPhrase;
116066 if( pPhrase && pPhrase->doclist.pList ){
116067 int iCol = 0;
116068 char *p = pPhrase->doclist.pList;
116069
116070 assert( *p );
116071 while( 1 ){
116072 u8 c = 0;
116073 int iCnt = 0;
116074 while( 0xFE & (*p | c) ){
116075 if( (c&0x80)==0 ) iCnt++;
116076 c = *p++ & 0x80;
116077 }
116078
116079 /* aMI[iCol*3 + 1] = Number of occurrences
116080 ** aMI[iCol*3 + 2] = Number of rows containing at least one instance
116081 */
116082 pExpr->aMI[iCol*3 + 1] += iCnt;
116083 pExpr->aMI[iCol*3 + 2] += (iCnt>0);
116084 if( *p==0x00 ) break;
116085 p++;
116086 p += sqlite3Fts3GetVarint32(p, &iCol);
116087 }
116088 }
116089
116090 fts3EvalUpdateCounts(pExpr->pLeft);
116091 fts3EvalUpdateCounts(pExpr->pRight);
116092 }
116093 }
116094
116095 /*
116096 ** Expression pExpr must be of type FTSQUERY_PHRASE.
116097 **
116098 ** If it is not already allocated and populated, this function allocates and
116099 ** populates the Fts3Expr.aMI[] array for expression pExpr. If pExpr is part
116100 ** of a NEAR expression, then it also allocates and populates the same array
116101 ** for all other phrases that are part of the NEAR expression.
116102 **
116103 ** SQLITE_OK is returned if the aMI[] array is successfully allocated and
116104 ** populated. Otherwise, if an error occurs, an SQLite error code is returned.
116105 */
116106 static int fts3EvalGatherStats(
116107 Fts3Cursor *pCsr, /* Cursor object */
116108 Fts3Expr *pExpr /* FTSQUERY_PHRASE expression */
116109 ){
116110 int rc = SQLITE_OK; /* Return code */
116111
116112 assert( pExpr->eType==FTSQUERY_PHRASE );
116113 if( pExpr->aMI==0 ){
116114 Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
116115 Fts3Expr *pRoot; /* Root of NEAR expression */
116116 Fts3Expr *p; /* Iterator used for several purposes */
116117
116118 sqlite3_int64 iPrevId = pCsr->iPrevId;
116119 sqlite3_int64 iDocid;
116120 u8 bEof;
116121
116122 /* Find the root of the NEAR expression */
116123 pRoot = pExpr;
116124 while( pRoot->pParent && pRoot->pParent->eType==FTSQUERY_NEAR ){
116125 pRoot = pRoot->pParent;
116126 }
116127 iDocid = pRoot->iDocid;
116128 bEof = pRoot->bEof;
116129 assert( pRoot->bStart );
116130
116131 /* Allocate space for the aMSI[] array of each FTSQUERY_PHRASE node */
116132 for(p=pRoot; p; p=p->pLeft){
116133 Fts3Expr *pE = (p->eType==FTSQUERY_PHRASE?p:p->pRight);
116134 assert( pE->aMI==0 );
116135 pE->aMI = (u32 *)sqlite3_malloc(pTab->nColumn * 3 * sizeof(u32));
116136 if( !pE->aMI ) return SQLITE_NOMEM;
116137 memset(pE->aMI, 0, pTab->nColumn * 3 * sizeof(u32));
116138 }
116139
116140 fts3EvalRestart(pCsr, pRoot, &rc);
116141
116142 while( pCsr->isEof==0 && rc==SQLITE_OK ){
116143
116144 do {
116145 /* Ensure the %_content statement is reset. */
116146 if( pCsr->isRequireSeek==0 ) sqlite3_reset(pCsr->pStmt);
116147 assert( sqlite3_data_count(pCsr->pStmt)==0 );
116148
116149 /* Advance to the next document */
116150 fts3EvalNext(pCsr, pRoot, &rc);
116151 pCsr->isEof = pRoot->bEof;
116152 pCsr->isRequireSeek = 1;
116153 pCsr->isMatchinfoNeeded = 1;
116154 pCsr->iPrevId = pRoot->iDocid;
116155 }while( pCsr->isEof==0
116156 && pRoot->eType==FTSQUERY_NEAR
116157 && fts3EvalLoadDeferred(pCsr, &rc)
116158 );
116159
116160 if( rc==SQLITE_OK && pCsr->isEof==0 ){
116161 fts3EvalUpdateCounts(pRoot);
116162 }
116163 }
116164
116165 pCsr->isEof = 0;
116166 pCsr->iPrevId = iPrevId;
116167
116168 if( bEof ){
116169 pRoot->bEof = bEof;
116170 }else{
116171 /* Caution: pRoot may iterate through docids in ascending or descending
116172 ** order. For this reason, even though it seems more defensive, the
116173 ** do loop can not be written:
116174 **
116175 ** do {...} while( pRoot->iDocid<iDocid && rc==SQLITE_OK );
116176 */
116177 fts3EvalRestart(pCsr, pRoot, &rc);
116178 do {
116179 fts3EvalNext(pCsr, pRoot, &rc);
116180 assert( pRoot->bEof==0 );
116181 }while( pRoot->iDocid!=iDocid && rc==SQLITE_OK );
116182 fts3EvalLoadDeferred(pCsr, &rc);
116183 }
116184 }
116185 return rc;
116186 }
116187
116188 /*
116189 ** This function is used by the matchinfo() module to query a phrase
116190 ** expression node for the following information:
116191 **
116192 ** 1. The total number of occurrences of the phrase in each column of
116193 ** the FTS table (considering all rows), and
116194 **
116195 ** 2. For each column, the number of rows in the table for which the
116196 ** column contains at least one instance of the phrase.
116197 **
116198 ** If no error occurs, SQLITE_OK is returned and the values for each column
116199 ** written into the array aiOut as follows:
116200 **
116201 ** aiOut[iCol*3 + 1] = Number of occurrences
116202 ** aiOut[iCol*3 + 2] = Number of rows containing at least one instance
116203 **
116204 ** Caveats:
116205 **
116206 ** * If a phrase consists entirely of deferred tokens, then all output
116207 ** values are set to the number of documents in the table. In other
116208 ** words we assume that very common tokens occur exactly once in each
116209 ** column of each row of the table.
116210 **
116211 ** * If a phrase contains some deferred tokens (and some non-deferred
116212 ** tokens), count the potential occurrence identified by considering
116213 ** the non-deferred tokens instead of actual phrase occurrences.
116214 **
116215 ** * If the phrase is part of a NEAR expression, then only phrase instances
116216 ** that meet the NEAR constraint are included in the counts.
116217 */
116218 SQLITE_PRIVATE int sqlite3Fts3EvalPhraseStats(
116219 Fts3Cursor *pCsr, /* FTS cursor handle */
116220 Fts3Expr *pExpr, /* Phrase expression */
116221 u32 *aiOut /* Array to write results into (see above) */
116222 ){
116223 Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
116224 int rc = SQLITE_OK;
116225 int iCol;
116226
116227 if( pExpr->bDeferred && pExpr->pParent->eType!=FTSQUERY_NEAR ){
116228 assert( pCsr->nDoc>0 );
116229 for(iCol=0; iCol<pTab->nColumn; iCol++){
116230 aiOut[iCol*3 + 1] = pCsr->nDoc;
116231 aiOut[iCol*3 + 2] = pCsr->nDoc;
116232 }
116233 }else{
116234 rc = fts3EvalGatherStats(pCsr, pExpr);
116235 if( rc==SQLITE_OK ){
116236 assert( pExpr->aMI );
116237 for(iCol=0; iCol<pTab->nColumn; iCol++){
116238 aiOut[iCol*3 + 1] = pExpr->aMI[iCol*3 + 1];
116239 aiOut[iCol*3 + 2] = pExpr->aMI[iCol*3 + 2];
116240 }
116241 }
116242 }
116243
116244 return rc;
116245 }
116246
116247 /*
116248 ** The expression pExpr passed as the second argument to this function
116249 ** must be of type FTSQUERY_PHRASE.
116250 **
116251 ** The returned value is either NULL or a pointer to a buffer containing
116252 ** a position-list indicating the occurrences of the phrase in column iCol
116253 ** of the current row.
116254 **
116255 ** More specifically, the returned buffer contains 1 varint for each
116256 ** occurence of the phrase in the column, stored using the normal (delta+2)
116257 ** compression and is terminated by either an 0x01 or 0x00 byte. For example,
116258 ** if the requested column contains "a b X c d X X" and the position-list
116259 ** for 'X' is requested, the buffer returned may contain:
116260 **
116261 ** 0x04 0x05 0x03 0x01 or 0x04 0x05 0x03 0x00
116262 **
116263 ** This function works regardless of whether or not the phrase is deferred,
116264 ** incremental, or neither.
116265 */
116266 SQLITE_PRIVATE char *sqlite3Fts3EvalPhrasePoslist(
116267 Fts3Cursor *pCsr, /* FTS3 cursor object */
116268 Fts3Expr *pExpr, /* Phrase to return doclist for */
116269 int iCol /* Column to return position list for */
116270 ){
116271 Fts3Phrase *pPhrase = pExpr->pPhrase;
116272 Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
116273 char *pIter = pPhrase->doclist.pList;
116274 int iThis;
116275
116276 assert( iCol>=0 && iCol<pTab->nColumn );
116277 if( !pIter
116278 || pExpr->bEof
116279 || pExpr->iDocid!=pCsr->iPrevId
116280 || (pPhrase->iColumn<pTab->nColumn && pPhrase->iColumn!=iCol)
116281 ){
116282 return 0;
116283 }
116284
116285 assert( pPhrase->doclist.nList>0 );
116286 if( *pIter==0x01 ){
116287 pIter++;
116288 pIter += sqlite3Fts3GetVarint32(pIter, &iThis);
116289 }else{
116290 iThis = 0;
116291 }
116292 while( iThis<iCol ){
116293 fts3ColumnlistCopy(0, &pIter);
116294 if( *pIter==0x00 ) return 0;
116295 pIter++;
116296 pIter += sqlite3Fts3GetVarint32(pIter, &iThis);
116297 }
116298
116299 return ((iCol==iThis)?pIter:0);
116300 }
116301
116302 /*
116303 ** Free all components of the Fts3Phrase structure that were allocated by
116304 ** the eval module. Specifically, this means to free:
116305 **
116306 ** * the contents of pPhrase->doclist, and
116307 ** * any Fts3MultiSegReader objects held by phrase tokens.
116308 */
116309 SQLITE_PRIVATE void sqlite3Fts3EvalPhraseCleanup(Fts3Phrase *pPhrase){
116310 if( pPhrase ){
116311 int i;
116312 sqlite3_free(pPhrase->doclist.aAll);
116313 fts3EvalZeroPoslist(pPhrase);
116314 memset(&pPhrase->doclist, 0, sizeof(Fts3Doclist));
116315 for(i=0; i<pPhrase->nToken; i++){
116316 fts3SegReaderCursorFree(pPhrase->aToken[i].pSegcsr);
116317 pPhrase->aToken[i].pSegcsr = 0;
116318 }
116319 }
116320 }
116321
116322 #endif
116323
116324 /************** End of fts3.c ************************************************/
116325 /************** Begin file fts3_aux.c ****************************************/
116326 /*
@@ -115648,11 +116348,11 @@
116348 Fts3Table *pFts3Tab;
116349 };
116350
116351 struct Fts3auxCursor {
116352 sqlite3_vtab_cursor base; /* Base class used by SQLite core */
116353 Fts3MultiSegReader csr; /* Must be right after "base" */
116354 Fts3SegFilter filter;
116355 char *zStop;
116356 int nStop; /* Byte-length of string zStop */
116357 int isEof; /* True if cursor is at EOF */
116358 sqlite3_int64 iRowid; /* Current rowid */
@@ -115716,10 +116416,11 @@
116416
116417 p->pFts3Tab = (Fts3Table *)&p[1];
116418 p->pFts3Tab->zDb = (char *)&p->pFts3Tab[1];
116419 p->pFts3Tab->zName = &p->pFts3Tab->zDb[nDb+1];
116420 p->pFts3Tab->db = db;
116421 p->pFts3Tab->nIndex = 1;
116422
116423 memcpy((char *)p->pFts3Tab->zDb, zDb, nDb);
116424 memcpy((char *)p->pFts3Tab->zName, zFts3, nFts3);
116425 sqlite3Fts3Dequote((char *)p->pFts3Tab->zName);
116426
@@ -115996,11 +116697,11 @@
116697 pCsr->zStop = sqlite3_mprintf("%s", sqlite3_value_text(apVal[iIdx]));
116698 pCsr->nStop = sqlite3_value_bytes(apVal[iIdx]);
116699 if( pCsr->zStop==0 ) return SQLITE_NOMEM;
116700 }
116701
116702 rc = sqlite3Fts3SegReaderCursor(pFts3, 0, FTS3_SEGCURSOR_ALL,
116703 pCsr->filter.zTerm, pCsr->filter.nTerm, 0, isScan, &pCsr->csr
116704 );
116705 if( rc==SQLITE_OK ){
116706 rc = sqlite3Fts3SegReaderStart(pFts3, &pCsr->csr, &pCsr->filter);
116707 }
@@ -116175,16 +116876,25 @@
116876 ** Default span for NEAR operators.
116877 */
116878 #define SQLITE_FTS3_DEFAULT_NEAR_PARAM 10
116879
116880
116881 /*
116882 ** isNot:
116883 ** This variable is used by function getNextNode(). When getNextNode() is
116884 ** called, it sets ParseContext.isNot to true if the 'next node' is a
116885 ** FTSQUERY_PHRASE with a unary "-" attached to it. i.e. "mysql" in the
116886 ** FTS3 query "sqlite -mysql". Otherwise, ParseContext.isNot is set to
116887 ** zero.
116888 */
116889 typedef struct ParseContext ParseContext;
116890 struct ParseContext {
116891 sqlite3_tokenizer *pTokenizer; /* Tokenizer module */
116892 const char **azCol; /* Array of column names for fts3 table */
116893 int nCol; /* Number of entries in azCol[] */
116894 int iDefaultCol; /* Default column to query */
116895 int isNot; /* True if getNextNode() sees a unary - */
116896 sqlite3_context *pCtx; /* Write error message here */
116897 int nNest; /* Number of nested brackets */
116898 };
116899
116900 /*
@@ -116266,11 +116976,11 @@
116976 if( iEnd<n && z[iEnd]=='*' ){
116977 pRet->pPhrase->aToken[0].isPrefix = 1;
116978 iEnd++;
116979 }
116980 if( !sqlite3_fts3_enable_parentheses && iStart>0 && z[iStart-1]=='-' ){
116981 pParse->isNot = 1;
116982 }
116983 }
116984 nConsumed = iEnd;
116985 }
116986
@@ -116318,71 +117028,86 @@
117028 Fts3Expr *p = 0;
117029 sqlite3_tokenizer_cursor *pCursor = 0;
117030 char *zTemp = 0;
117031 int nTemp = 0;
117032
117033 const int nSpace = sizeof(Fts3Expr) + sizeof(Fts3Phrase);
117034 int nToken = 0;
117035
117036 /* The final Fts3Expr data structure, including the Fts3Phrase,
117037 ** Fts3PhraseToken structures token buffers are all stored as a single
117038 ** allocation so that the expression can be freed with a single call to
117039 ** sqlite3_free(). Setting this up requires a two pass approach.
117040 **
117041 ** The first pass, in the block below, uses a tokenizer cursor to iterate
117042 ** through the tokens in the expression. This pass uses fts3ReallocOrFree()
117043 ** to assemble data in two dynamic buffers:
117044 **
117045 ** Buffer p: Points to the Fts3Expr structure, followed by the Fts3Phrase
117046 ** structure, followed by the array of Fts3PhraseToken
117047 ** structures. This pass only populates the Fts3PhraseToken array.
117048 **
117049 ** Buffer zTemp: Contains copies of all tokens.
117050 **
117051 ** The second pass, in the block that begins "if( rc==SQLITE_DONE )" below,
117052 ** appends buffer zTemp to buffer p, and fills in the Fts3Expr and Fts3Phrase
117053 ** structures.
117054 */
117055 rc = pModule->xOpen(pTokenizer, zInput, nInput, &pCursor);
117056 if( rc==SQLITE_OK ){
117057 int ii;
117058 pCursor->pTokenizer = pTokenizer;
117059 for(ii=0; rc==SQLITE_OK; ii++){
117060 const char *zByte;
117061 int nByte, iBegin, iEnd, iPos;
117062 rc = pModule->xNext(pCursor, &zByte, &nByte, &iBegin, &iEnd, &iPos);
117063 if( rc==SQLITE_OK ){
117064 Fts3PhraseToken *pToken;
117065
117066 p = fts3ReallocOrFree(p, nSpace + ii*sizeof(Fts3PhraseToken));
117067 if( !p ) goto no_mem;
117068
117069 zTemp = fts3ReallocOrFree(zTemp, nTemp + nByte);
117070 if( !zTemp ) goto no_mem;
117071
117072 assert( nToken==ii );
117073 pToken = &((Fts3Phrase *)(&p[1]))->aToken[ii];
117074 memset(pToken, 0, sizeof(Fts3PhraseToken));
117075
117076 memcpy(&zTemp[nTemp], zByte, nByte);
117077 nTemp += nByte;
117078
117079 pToken->n = nByte;
117080 pToken->isPrefix = (iEnd<nInput && zInput[iEnd]=='*');
117081 nToken = ii+1;
 
 
 
117082 }
117083 }
117084
117085 pModule->xClose(pCursor);
117086 pCursor = 0;
117087 }
117088
117089 if( rc==SQLITE_DONE ){
117090 int jj;
117091 char *zBuf = 0;
117092
117093 p = fts3ReallocOrFree(p, nSpace + nToken*sizeof(Fts3PhraseToken) + nTemp);
117094 if( !p ) goto no_mem;
117095 memset(p, 0, (char *)&(((Fts3Phrase *)&p[1])->aToken[0])-(char *)p);
117096 p->eType = FTSQUERY_PHRASE;
 
 
 
 
 
 
 
 
117097 p->pPhrase = (Fts3Phrase *)&p[1];
117098 p->pPhrase->iColumn = pParse->iDefaultCol;
117099 p->pPhrase->nToken = nToken;
117100
117101 zBuf = (char *)&p->pPhrase->aToken[nToken];
117102 memcpy(zBuf, zTemp, nTemp);
117103 sqlite3_free(zTemp);
117104
117105 for(jj=0; jj<p->pPhrase->nToken; jj++){
117106 p->pPhrase->aToken[jj].z = zBuf;
117107 zBuf += p->pPhrase->aToken[jj].n;
117108 }
 
 
 
117109 rc = SQLITE_OK;
117110 }
117111
117112 *ppExpr = p;
117113 return rc;
@@ -116434,10 +117159,12 @@
117159 int rc;
117160 Fts3Expr *pRet = 0;
117161
117162 const char *zInput = z;
117163 int nInput = n;
117164
117165 pParse->isNot = 0;
117166
117167 /* Skip over any whitespace before checking for a keyword, an open or
117168 ** close bracket, or a quoted string.
117169 */
117170 while( nInput>0 && fts3isspace(*zInput) ){
@@ -116653,11 +117380,11 @@
117380 rc = getNextNode(pParse, zIn, nIn, &p, &nByte);
117381 if( rc==SQLITE_OK ){
117382 int isPhrase;
117383
117384 if( !sqlite3_fts3_enable_parentheses
117385 && p->eType==FTSQUERY_PHRASE && pParse->isNot
117386 ){
117387 /* Create an implicit NOT operator. */
117388 Fts3Expr *pNot = fts3MallocZero(sizeof(Fts3Expr));
117389 if( !pNot ){
117390 sqlite3Fts3ExprFree(p);
@@ -116671,11 +117398,10 @@
117398 }
117399 pNotBranch = pNot;
117400 p = pPrev;
117401 }else{
117402 int eType = p->eType;
 
117403 isPhrase = (eType==FTSQUERY_PHRASE || p->pLeft);
117404
117405 /* The isRequirePhrase variable is set to true if a phrase or
117406 ** an expression contained in parenthesis is required. If a
117407 ** binary operator (AND, OR, NOT or NEAR) is encounted when
@@ -116834,13 +117560,15 @@
117560 /*
117561 ** Free a parsed fts3 query expression allocated by sqlite3Fts3ExprParse().
117562 */
117563 SQLITE_PRIVATE void sqlite3Fts3ExprFree(Fts3Expr *p){
117564 if( p ){
117565 assert( p->eType==FTSQUERY_PHRASE || p->pPhrase==0 );
117566 sqlite3Fts3ExprFree(p->pLeft);
117567 sqlite3Fts3ExprFree(p->pRight);
117568 sqlite3Fts3EvalPhraseCleanup(p->pPhrase);
117569 sqlite3_free(p->aMI);
117570 sqlite3_free(p);
117571 }
117572 }
117573
117574 /****************************************************************************
@@ -116893,11 +117621,11 @@
117621 switch( pExpr->eType ){
117622 case FTSQUERY_PHRASE: {
117623 Fts3Phrase *pPhrase = pExpr->pPhrase;
117624 int i;
117625 zBuf = sqlite3_mprintf(
117626 "%zPHRASE %d 0", zBuf, pPhrase->iColumn);
117627 for(i=0; zBuf && i<pPhrase->nToken; i++){
117628 zBuf = sqlite3_mprintf("%z %.*s%s", zBuf,
117629 pPhrase->aToken[i].n, pPhrase->aToken[i].z,
117630 (pPhrase->aToken[i].isPrefix?"+":"")
117631 );
@@ -118811,18 +119539,44 @@
119539 ** it is always safe to read up to two varints from it without risking an
119540 ** overread, even if the node data is corrupted.
119541 */
119542 #define FTS3_NODE_PADDING (FTS3_VARINT_MAX*2)
119543
119544 /*
119545 ** Under certain circumstances, b-tree nodes (doclists) can be loaded into
119546 ** memory incrementally instead of all at once. This can be a big performance
119547 ** win (reduced IO and CPU) if SQLite stops calling the virtual table xNext()
119548 ** method before retrieving all query results (as may happen, for example,
119549 ** if a query has a LIMIT clause).
119550 **
119551 ** Incremental loading is used for b-tree nodes FTS3_NODE_CHUNK_THRESHOLD
119552 ** bytes and larger. Nodes are loaded in chunks of FTS3_NODE_CHUNKSIZE bytes.
119553 ** The code is written so that the hard lower-limit for each of these values
119554 ** is 1. Clearly such small values would be inefficient, but can be useful
119555 ** for testing purposes.
119556 **
119557 ** If this module is built with SQLITE_TEST defined, these constants may
119558 ** be overridden at runtime for testing purposes. File fts3_test.c contains
119559 ** a Tcl interface to read and write the values.
119560 */
119561 #ifdef SQLITE_TEST
119562 int test_fts3_node_chunksize = (4*1024);
119563 int test_fts3_node_chunk_threshold = (4*1024)*4;
119564 # define FTS3_NODE_CHUNKSIZE test_fts3_node_chunksize
119565 # define FTS3_NODE_CHUNK_THRESHOLD test_fts3_node_chunk_threshold
119566 #else
119567 # define FTS3_NODE_CHUNKSIZE (4*1024)
119568 # define FTS3_NODE_CHUNK_THRESHOLD (FTS3_NODE_CHUNKSIZE*4)
119569 #endif
119570
119571 typedef struct PendingList PendingList;
119572 typedef struct SegmentNode SegmentNode;
119573 typedef struct SegmentWriter SegmentWriter;
119574
119575 /*
119576 ** An instance of the following data structure is used to build doclists
119577 ** incrementally. See function fts3PendingListAppend() for details.
 
119578 */
119579 struct PendingList {
119580 int nData;
119581 char *aData;
119582 int nSpace;
@@ -118849,11 +119603,10 @@
119603 ** of type Fts3SegReader* are also used by code in fts3.c to iterate through
119604 ** terms when querying the full-text index. See functions:
119605 **
119606 ** sqlite3Fts3SegReaderNew()
119607 ** sqlite3Fts3SegReaderFree()
 
119608 ** sqlite3Fts3SegReaderIterate()
119609 **
119610 ** Methods used to manipulate Fts3SegReader structures:
119611 **
119612 ** fts3SegReaderNext()
@@ -118868,10 +119621,13 @@
119621 sqlite3_int64 iEndBlock; /* Rowid of final block in segment (or 0) */
119622 sqlite3_int64 iCurrentBlock; /* Current leaf block (or 0) */
119623
119624 char *aNode; /* Pointer to node data (or NULL) */
119625 int nNode; /* Size of buffer at aNode (or 0) */
119626 int nPopulate; /* If >0, bytes of buffer aNode[] loaded */
119627 sqlite3_blob *pBlob; /* If not NULL, blob handle to read node */
119628
119629 Fts3HashElem **ppNextElem;
119630
119631 /* Variables set by fts3SegReaderNext(). These may be read directly
119632 ** by the caller. They are valid from the time SegmentReaderNew() returns
119633 ** until SegmentReaderNext() returns something other than SQLITE_OK
@@ -118881,12 +119637,15 @@
119637 char *zTerm; /* Pointer to current term */
119638 int nTermAlloc; /* Allocated size of zTerm buffer */
119639 char *aDoclist; /* Pointer to doclist of current entry */
119640 int nDoclist; /* Size of doclist in current entry */
119641
119642 /* The following variables are used by fts3SegReaderNextDocid() to iterate
119643 ** through the current doclist (aDoclist/nDoclist).
119644 */
119645 char *pOffsetList;
119646 int nOffsetList; /* For descending pending seg-readers only */
119647 sqlite3_int64 iDocid;
119648 };
119649
119650 #define fts3SegReaderIsPending(p) ((p)->ppNextElem!=0)
119651 #define fts3SegReaderIsRootOnly(p) ((p)->aNode==(char *)&(p)[1])
@@ -118920,10 +119679,18 @@
119679 ** within the fts3SegWriterXXX() family of functions described above.
119680 **
119681 ** fts3NodeAddTerm()
119682 ** fts3NodeWrite()
119683 ** fts3NodeFree()
119684 **
119685 ** When a b+tree is written to the database (either as a result of a merge
119686 ** or the pending-terms table being flushed), leaves are written into the
119687 ** database file as soon as they are completely populated. The interior of
119688 ** the tree is assembled in memory and written out only once all leaves have
119689 ** been populated and stored. This is Ok, as the b+-tree fanout is usually
119690 ** very large, meaning that the interior of the tree consumes relatively
119691 ** little memory.
119692 */
119693 struct SegmentNode {
119694 SegmentNode *pParent; /* Parent node (or NULL for root node) */
119695 SegmentNode *pRight; /* Pointer to right-sibling */
119696 SegmentNode *pLeftmost; /* Pointer to left-most node of this depth */
@@ -118950,21 +119717,26 @@
119717 #define SQL_NEXT_SEGMENT_INDEX 8
119718 #define SQL_INSERT_SEGMENTS 9
119719 #define SQL_NEXT_SEGMENTS_ID 10
119720 #define SQL_INSERT_SEGDIR 11
119721 #define SQL_SELECT_LEVEL 12
119722 #define SQL_SELECT_LEVEL_RANGE 13
119723 #define SQL_SELECT_LEVEL_COUNT 14
119724 #define SQL_SELECT_SEGDIR_MAX_LEVEL 15
119725 #define SQL_DELETE_SEGDIR_LEVEL 16
119726 #define SQL_DELETE_SEGMENTS_RANGE 17
119727 #define SQL_CONTENT_INSERT 18
119728 #define SQL_DELETE_DOCSIZE 19
119729 #define SQL_REPLACE_DOCSIZE 20
119730 #define SQL_SELECT_DOCSIZE 21
119731 #define SQL_SELECT_DOCTOTAL 22
119732 #define SQL_REPLACE_DOCTOTAL 23
119733
119734 #define SQL_SELECT_ALL_PREFIX_LEVEL 24
119735 #define SQL_DELETE_ALL_TERMS_SEGDIR 25
119736
119737 #define SQL_DELETE_SEGDIR_RANGE 26
119738
119739 /*
119740 ** This function is used to obtain an SQLite prepared statement handle
119741 ** for the statement identified by the second argument. If successful,
119742 ** *pp is set to the requested statement handle and SQLITE_OK returned.
@@ -118997,23 +119769,29 @@
119769
119770 /* Return segments in order from oldest to newest.*/
119771 /* 12 */ "SELECT idx, start_block, leaves_end_block, end_block, root "
119772 "FROM %Q.'%q_segdir' WHERE level = ? ORDER BY idx ASC",
119773 /* 13 */ "SELECT idx, start_block, leaves_end_block, end_block, root "
119774 "FROM %Q.'%q_segdir' WHERE level BETWEEN ? AND ?"
119775 "ORDER BY level DESC, idx ASC",
119776
119777 /* 14 */ "SELECT count(*) FROM %Q.'%q_segdir' WHERE level = ?",
119778 /* 15 */ "SELECT max(level) FROM %Q.'%q_segdir' WHERE level BETWEEN ? AND ?",
119779
119780 /* 16 */ "DELETE FROM %Q.'%q_segdir' WHERE level = ?",
119781 /* 17 */ "DELETE FROM %Q.'%q_segments' WHERE blockid BETWEEN ? AND ?",
119782 /* 18 */ "INSERT INTO %Q.'%q_content' VALUES(%s)",
119783 /* 19 */ "DELETE FROM %Q.'%q_docsize' WHERE docid = ?",
119784 /* 20 */ "REPLACE INTO %Q.'%q_docsize' VALUES(?,?)",
119785 /* 21 */ "SELECT size FROM %Q.'%q_docsize' WHERE docid=?",
119786 /* 22 */ "SELECT value FROM %Q.'%q_stat' WHERE id=0",
119787 /* 23 */ "REPLACE INTO %Q.'%q_stat' VALUES(0,?)",
119788 /* 24 */ "",
119789 /* 25 */ "",
119790
119791 /* 26 */ "DELETE FROM %Q.'%q_segdir' WHERE level BETWEEN ? AND ?",
119792
119793 };
119794 int rc = SQLITE_OK;
119795 sqlite3_stmt *pStmt;
119796
119797 assert( SizeofArray(azSql)==SizeofArray(p->aStmt) );
@@ -119165,18 +119943,36 @@
119943 ** 1: start_block
119944 ** 2: leaves_end_block
119945 ** 3: end_block
119946 ** 4: root
119947 */
119948 SQLITE_PRIVATE int sqlite3Fts3AllSegdirs(
119949 Fts3Table *p, /* FTS3 table */
119950 int iIndex, /* Index for p->aIndex[] */
119951 int iLevel, /* Level to select */
119952 sqlite3_stmt **ppStmt /* OUT: Compiled statement */
119953 ){
119954 int rc;
119955 sqlite3_stmt *pStmt = 0;
119956
119957 assert( iLevel==FTS3_SEGCURSOR_ALL || iLevel>=0 );
119958 assert( iLevel<FTS3_SEGDIR_MAXLEVEL );
119959 assert( iIndex>=0 && iIndex<p->nIndex );
119960
119961 if( iLevel<0 ){
119962 /* "SELECT * FROM %_segdir WHERE level BETWEEN ? AND ? ORDER BY ..." */
119963 rc = fts3SqlStmt(p, SQL_SELECT_LEVEL_RANGE, &pStmt, 0);
119964 if( rc==SQLITE_OK ){
119965 sqlite3_bind_int(pStmt, 1, iIndex*FTS3_SEGDIR_MAXLEVEL);
119966 sqlite3_bind_int(pStmt, 2, (iIndex+1)*FTS3_SEGDIR_MAXLEVEL-1);
119967 }
119968 }else{
119969 /* "SELECT * FROM %_segdir WHERE level = ? ORDER BY ..." */
119970 rc = fts3SqlStmt(p, SQL_SELECT_LEVEL, &pStmt, 0);
119971 if( rc==SQLITE_OK ){
119972 sqlite3_bind_int(pStmt, 1, iLevel+iIndex*FTS3_SEGDIR_MAXLEVEL);
119973 }
119974 }
119975 *ppStmt = pStmt;
119976 return rc;
119977 }
119978
@@ -119286,10 +120082,51 @@
120082 *pp = p;
120083 return 1;
120084 }
120085 return 0;
120086 }
120087
120088 /*
120089 ** Free a PendingList object allocated by fts3PendingListAppend().
120090 */
120091 static void fts3PendingListDelete(PendingList *pList){
120092 sqlite3_free(pList);
120093 }
120094
120095 /*
120096 ** Add an entry to one of the pending-terms hash tables.
120097 */
120098 static int fts3PendingTermsAddOne(
120099 Fts3Table *p,
120100 int iCol,
120101 int iPos,
120102 Fts3Hash *pHash, /* Pending terms hash table to add entry to */
120103 const char *zToken,
120104 int nToken
120105 ){
120106 PendingList *pList;
120107 int rc = SQLITE_OK;
120108
120109 pList = (PendingList *)fts3HashFind(pHash, zToken, nToken);
120110 if( pList ){
120111 p->nPendingData -= (pList->nData + nToken + sizeof(Fts3HashElem));
120112 }
120113 if( fts3PendingListAppend(&pList, p->iPrevDocid, iCol, iPos, &rc) ){
120114 if( pList==fts3HashInsert(pHash, zToken, nToken, pList) ){
120115 /* Malloc failed while inserting the new entry. This can only
120116 ** happen if there was no previous entry for this token.
120117 */
120118 assert( 0==fts3HashFind(pHash, zToken, nToken) );
120119 sqlite3_free(pList);
120120 rc = SQLITE_NOMEM;
120121 }
120122 }
120123 if( rc==SQLITE_OK ){
120124 p->nPendingData += (pList->nData + nToken + sizeof(Fts3HashElem));
120125 }
120126 return rc;
120127 }
120128
120129 /*
120130 ** Tokenize the nul-terminated string zText and add all tokens to the
120131 ** pending-terms hash-table. The docid used is that currently stored in
120132 ** p->iPrevDocid, and the column is specified by argument iCol.
@@ -119335,12 +120172,11 @@
120172
120173 xNext = pModule->xNext;
120174 while( SQLITE_OK==rc
120175 && SQLITE_OK==(rc = xNext(pCsr, &zToken, &nToken, &iStart, &iEnd, &iPos))
120176 ){
120177 int i;
 
120178 if( iPos>=nWord ) nWord = iPos+1;
120179
120180 /* Positions cannot be negative; we use -1 as a terminator internally.
120181 ** Tokens must have a non-zero length.
120182 */
@@ -119347,26 +120183,23 @@
120183 if( iPos<0 || !zToken || nToken<=0 ){
120184 rc = SQLITE_ERROR;
120185 break;
120186 }
120187
120188 /* Add the term to the terms index */
120189 rc = fts3PendingTermsAddOne(
120190 p, iCol, iPos, &p->aIndex[0].hPending, zToken, nToken
120191 );
120192
120193 /* Add the term to each of the prefix indexes that it is not too
120194 ** short for. */
120195 for(i=1; rc==SQLITE_OK && i<p->nIndex; i++){
120196 struct Fts3Index *pIndex = &p->aIndex[i];
120197 if( nToken<pIndex->nPrefix ) continue;
120198 rc = fts3PendingTermsAddOne(
120199 p, iCol, iPos, &pIndex->hPending, zToken, pIndex->nPrefix
120200 );
 
 
 
120201 }
120202 }
120203
120204 pModule->xClose(pCsr);
120205 *pnWord = nWord;
@@ -119392,18 +120225,23 @@
120225 p->iPrevDocid = iDocid;
120226 return SQLITE_OK;
120227 }
120228
120229 /*
120230 ** Discard the contents of the pending-terms hash tables.
120231 */
120232 SQLITE_PRIVATE void sqlite3Fts3PendingTermsClear(Fts3Table *p){
120233 int i;
120234 for(i=0; i<p->nIndex; i++){
120235 Fts3HashElem *pElem;
120236 Fts3Hash *pHash = &p->aIndex[i].hPending;
120237 for(pElem=fts3HashFirst(pHash); pElem; pElem=fts3HashNext(pElem)){
120238 PendingList *pList = (PendingList *)fts3HashData(pElem);
120239 fts3PendingListDelete(pList);
120240 }
120241 fts3HashClear(pHash);
120242 }
 
120243 p->nPendingData = 0;
120244 }
120245
120246 /*
120247 ** This function is called by the xUpdate() method as part of an INSERT
@@ -119555,11 +120393,11 @@
120393
120394 /*
120395 ** Forward declaration to account for the circular dependency between
120396 ** functions fts3SegmentMerge() and fts3AllocateSegdirIdx().
120397 */
120398 static int fts3SegmentMerge(Fts3Table *, int, int);
120399
120400 /*
120401 ** This function allocates a new level iLevel index in the segdir table.
120402 ** Usually, indexes are allocated within a level sequentially starting
120403 ** with 0, so the allocated index is one greater than the value returned
@@ -119572,19 +120410,24 @@
120410 ** allocated index is 0.
120411 **
120412 ** If successful, *piIdx is set to the allocated index slot and SQLITE_OK
120413 ** returned. Otherwise, an SQLite error code is returned.
120414 */
120415 static int fts3AllocateSegdirIdx(
120416 Fts3Table *p,
120417 int iIndex, /* Index for p->aIndex */
120418 int iLevel,
120419 int *piIdx
120420 ){
120421 int rc; /* Return Code */
120422 sqlite3_stmt *pNextIdx; /* Query for next idx at level iLevel */
120423 int iNext = 0; /* Result of query pNextIdx */
120424
120425 /* Set variable iNext to the next available segdir index at level iLevel. */
120426 rc = fts3SqlStmt(p, SQL_NEXT_SEGMENT_INDEX, &pNextIdx, 0);
120427 if( rc==SQLITE_OK ){
120428 sqlite3_bind_int(pNextIdx, 1, iIndex*FTS3_SEGDIR_MAXLEVEL + iLevel);
120429 if( SQLITE_ROW==sqlite3_step(pNextIdx) ){
120430 iNext = sqlite3_column_int(pNextIdx, 0);
120431 }
120432 rc = sqlite3_reset(pNextIdx);
120433 }
@@ -119594,11 +120437,11 @@
120437 ** full, merge all segments in level iLevel into a single iLevel+1
120438 ** segment and allocate (newly freed) index 0 at level iLevel. Otherwise,
120439 ** if iNext is less than FTS3_MERGE_COUNT, allocate index iNext.
120440 */
120441 if( iNext>=FTS3_MERGE_COUNT ){
120442 rc = fts3SegmentMerge(p, iIndex, iLevel);
120443 *piIdx = 0;
120444 }else{
120445 *piIdx = iNext;
120446 }
120447 }
@@ -119635,11 +120478,12 @@
120478 */
120479 SQLITE_PRIVATE int sqlite3Fts3ReadBlock(
120480 Fts3Table *p, /* FTS3 table handle */
120481 sqlite3_int64 iBlockid, /* Access the row with blockid=$iBlockid */
120482 char **paBlob, /* OUT: Blob data in malloc'd buffer */
120483 int *pnBlob, /* OUT: Size of blob data */
120484 int *pnLoad /* OUT: Bytes actually loaded */
120485 ){
120486 int rc; /* Return code */
120487
120488 /* pnBlob must be non-NULL. paBlob may be NULL or non-NULL. */
120489 assert( pnBlob);
@@ -119656,25 +120500,29 @@
120500 );
120501 }
120502
120503 if( rc==SQLITE_OK ){
120504 int nByte = sqlite3_blob_bytes(p->pSegments);
120505 *pnBlob = nByte;
120506 if( paBlob ){
120507 char *aByte = sqlite3_malloc(nByte + FTS3_NODE_PADDING);
120508 if( !aByte ){
120509 rc = SQLITE_NOMEM;
120510 }else{
120511 if( pnLoad && nByte>(FTS3_NODE_CHUNK_THRESHOLD) ){
120512 nByte = FTS3_NODE_CHUNKSIZE;
120513 *pnLoad = nByte;
120514 }
120515 rc = sqlite3_blob_read(p->pSegments, aByte, nByte, 0);
120516 memset(&aByte[nByte], 0, FTS3_NODE_PADDING);
120517 if( rc!=SQLITE_OK ){
120518 sqlite3_free(aByte);
120519 aByte = 0;
120520 }
120521 }
120522 *paBlob = aByte;
120523 }
 
120524 }
120525
120526 return rc;
120527 }
120528
@@ -119684,17 +120532,59 @@
120532 */
120533 SQLITE_PRIVATE void sqlite3Fts3SegmentsClose(Fts3Table *p){
120534 sqlite3_blob_close(p->pSegments);
120535 p->pSegments = 0;
120536 }
120537
120538 static int fts3SegReaderIncrRead(Fts3SegReader *pReader){
120539 int nRead; /* Number of bytes to read */
120540 int rc; /* Return code */
120541
120542 nRead = MIN(pReader->nNode - pReader->nPopulate, FTS3_NODE_CHUNKSIZE);
120543 rc = sqlite3_blob_read(
120544 pReader->pBlob,
120545 &pReader->aNode[pReader->nPopulate],
120546 nRead,
120547 pReader->nPopulate
120548 );
120549
120550 if( rc==SQLITE_OK ){
120551 pReader->nPopulate += nRead;
120552 memset(&pReader->aNode[pReader->nPopulate], 0, FTS3_NODE_PADDING);
120553 if( pReader->nPopulate==pReader->nNode ){
120554 sqlite3_blob_close(pReader->pBlob);
120555 pReader->pBlob = 0;
120556 pReader->nPopulate = 0;
120557 }
120558 }
120559 return rc;
120560 }
120561
120562 static int fts3SegReaderRequire(Fts3SegReader *pReader, char *pFrom, int nByte){
120563 int rc = SQLITE_OK;
120564 assert( !pReader->pBlob
120565 || (pFrom>=pReader->aNode && pFrom<&pReader->aNode[pReader->nNode])
120566 );
120567 while( pReader->pBlob && rc==SQLITE_OK
120568 && (pFrom - pReader->aNode + nByte)>pReader->nPopulate
120569 ){
120570 rc = fts3SegReaderIncrRead(pReader);
120571 }
120572 return rc;
120573 }
120574
120575 /*
120576 ** Move the iterator passed as the first argument to the next term in the
120577 ** segment. If successful, SQLITE_OK is returned. If there is no next term,
120578 ** SQLITE_DONE. Otherwise, an SQLite error code.
120579 */
120580 static int fts3SegReaderNext(
120581 Fts3Table *p,
120582 Fts3SegReader *pReader,
120583 int bIncr
120584 ){
120585 int rc; /* Return code of various sub-routines */
120586 char *pNext; /* Cursor variable */
120587 int nPrefix; /* Number of bytes in term prefix */
120588 int nSuffix; /* Number of bytes in term suffix */
120589
120590 if( !pReader->aDoclist ){
@@ -119702,11 +120592,10 @@
120592 }else{
120593 pNext = &pReader->aDoclist[pReader->nDoclist];
120594 }
120595
120596 if( !pNext || pNext>=&pReader->aNode[pReader->nNode] ){
 
120597
120598 if( fts3SegReaderIsPending(pReader) ){
120599 Fts3HashElem *pElem = *(pReader->ppNextElem);
120600 if( pElem==0 ){
120601 pReader->aNode = 0;
@@ -119722,10 +120611,12 @@
120611 return SQLITE_OK;
120612 }
120613
120614 if( !fts3SegReaderIsRootOnly(pReader) ){
120615 sqlite3_free(pReader->aNode);
120616 sqlite3_blob_close(pReader->pBlob);
120617 pReader->pBlob = 0;
120618 }
120619 pReader->aNode = 0;
120620
120621 /* If iCurrentBlock>=iLeafEndBlock, this is an EOF condition. All leaf
120622 ** blocks have already been traversed. */
@@ -119733,19 +120624,29 @@
120624 if( pReader->iCurrentBlock>=pReader->iLeafEndBlock ){
120625 return SQLITE_OK;
120626 }
120627
120628 rc = sqlite3Fts3ReadBlock(
120629 p, ++pReader->iCurrentBlock, &pReader->aNode, &pReader->nNode,
120630 (bIncr ? &pReader->nPopulate : 0)
120631 );
120632 if( rc!=SQLITE_OK ) return rc;
120633 assert( pReader->pBlob==0 );
120634 if( bIncr && pReader->nPopulate<pReader->nNode ){
120635 pReader->pBlob = p->pSegments;
120636 p->pSegments = 0;
120637 }
120638 pNext = pReader->aNode;
120639 }
120640
120641 assert( !fts3SegReaderIsPending(pReader) );
120642
120643 rc = fts3SegReaderRequire(pReader, pNext, FTS3_VARINT_MAX*2);
120644 if( rc!=SQLITE_OK ) return rc;
120645
120646 /* Because of the FTS3_NODE_PADDING bytes of padding, the following is
120647 ** safe (no risk of overread) even if the node data is corrupted. */
 
120648 pNext += sqlite3Fts3GetVarint32(pNext, &nPrefix);
120649 pNext += sqlite3Fts3GetVarint32(pNext, &nSuffix);
120650 if( nPrefix<0 || nSuffix<=0
120651 || &pNext[nSuffix]>&pReader->aNode[pReader->nNode]
120652 ){
@@ -119759,10 +120660,14 @@
120660 return SQLITE_NOMEM;
120661 }
120662 pReader->zTerm = zNew;
120663 pReader->nTermAlloc = nNew;
120664 }
120665
120666 rc = fts3SegReaderRequire(pReader, pNext, nSuffix+FTS3_VARINT_MAX);
120667 if( rc!=SQLITE_OK ) return rc;
120668
120669 memcpy(&pReader->zTerm[nPrefix], pNext, nSuffix);
120670 pReader->nTerm = nPrefix+nSuffix;
120671 pNext += nSuffix;
120672 pNext += sqlite3Fts3GetVarint32(pNext, &pReader->nDoclist);
120673 pReader->aDoclist = pNext;
@@ -119771,11 +120676,11 @@
120676 /* Check that the doclist does not appear to extend past the end of the
120677 ** b-tree node. And that the final byte of the doclist is 0x00. If either
120678 ** of these statements is untrue, then the data structure is corrupt.
120679 */
120680 if( &pReader->aDoclist[pReader->nDoclist]>&pReader->aNode[pReader->nNode]
120681 || (pReader->nPopulate==0 && pReader->aDoclist[pReader->nDoclist-1])
120682 ){
120683 return SQLITE_CORRUPT_VTAB;
120684 }
120685 return SQLITE_OK;
120686 }
@@ -119782,16 +120687,30 @@
120687
120688 /*
120689 ** Set the SegReader to point to the first docid in the doclist associated
120690 ** with the current term.
120691 */
120692 static int fts3SegReaderFirstDocid(Fts3Table *pTab, Fts3SegReader *pReader){
120693 int rc = SQLITE_OK;
120694 assert( pReader->aDoclist );
120695 assert( !pReader->pOffsetList );
120696 if( pTab->bDescIdx && fts3SegReaderIsPending(pReader) ){
120697 u8 bEof = 0;
120698 pReader->iDocid = 0;
120699 pReader->nOffsetList = 0;
120700 sqlite3Fts3DoclistPrev(0,
120701 pReader->aDoclist, pReader->nDoclist, &pReader->pOffsetList,
120702 &pReader->iDocid, &pReader->nOffsetList, &bEof
120703 );
120704 }else{
120705 rc = fts3SegReaderRequire(pReader, pReader->aDoclist, FTS3_VARINT_MAX);
120706 if( rc==SQLITE_OK ){
120707 int n = sqlite3Fts3GetVarint(pReader->aDoclist, &pReader->iDocid);
120708 pReader->pOffsetList = &pReader->aDoclist[n];
120709 }
120710 }
120711 return rc;
120712 }
120713
120714 /*
120715 ** Advance the SegReader to point to the next docid in the doclist
120716 ** associated with the current term.
@@ -119800,132 +120719,126 @@
120719 ** *ppOffsetList is set to point to the first column-offset list
120720 ** in the doclist entry (i.e. immediately past the docid varint).
120721 ** *pnOffsetList is set to the length of the set of column-offset
120722 ** lists, not including the nul-terminator byte. For example:
120723 */
120724 static int fts3SegReaderNextDocid(
120725 Fts3Table *pTab,
120726 Fts3SegReader *pReader, /* Reader to advance to next docid */
120727 char **ppOffsetList, /* OUT: Pointer to current position-list */
120728 int *pnOffsetList /* OUT: Length of *ppOffsetList in bytes */
120729 ){
120730 int rc = SQLITE_OK;
120731 char *p = pReader->pOffsetList;
120732 char c = 0;
120733
120734 assert( p );
120735
120736 if( pTab->bDescIdx && fts3SegReaderIsPending(pReader) ){
120737 /* A pending-terms seg-reader for an FTS4 table that uses order=desc.
120738 ** Pending-terms doclists are always built up in ascending order, so
120739 ** we have to iterate through them backwards here. */
120740 u8 bEof = 0;
120741 if( ppOffsetList ){
120742 *ppOffsetList = pReader->pOffsetList;
120743 *pnOffsetList = pReader->nOffsetList - 1;
120744 }
120745 sqlite3Fts3DoclistPrev(0,
120746 pReader->aDoclist, pReader->nDoclist, &p, &pReader->iDocid,
120747 &pReader->nOffsetList, &bEof
120748 );
120749 if( bEof ){
120750 pReader->pOffsetList = 0;
120751 }else{
120752 pReader->pOffsetList = p;
120753 }
 
 
120754 }else{
120755
120756 /* Pointer p currently points at the first byte of an offset list. The
120757 ** following block advances it to point one byte past the end of
120758 ** the same offset list. */
120759 while( 1 ){
120760
120761 /* The following line of code (and the "p++" below the while() loop) is
120762 ** normally all that is required to move pointer p to the desired
120763 ** position. The exception is if this node is being loaded from disk
120764 ** incrementally and pointer "p" now points to the first byte passed
120765 ** the populated part of pReader->aNode[].
120766 */
120767 while( *p | c ) c = *p++ & 0x80;
120768 assert( *p==0 );
120769
120770 if( pReader->pBlob==0 || p<&pReader->aNode[pReader->nPopulate] ) break;
120771 rc = fts3SegReaderIncrRead(pReader);
120772 if( rc!=SQLITE_OK ) return rc;
120773 }
120774 p++;
120775
120776 /* If required, populate the output variables with a pointer to and the
120777 ** size of the previous offset-list.
120778 */
120779 if( ppOffsetList ){
120780 *ppOffsetList = pReader->pOffsetList;
120781 *pnOffsetList = (int)(p - pReader->pOffsetList - 1);
120782 }
120783
120784 /* If there are no more entries in the doclist, set pOffsetList to
120785 ** NULL. Otherwise, set Fts3SegReader.iDocid to the next docid and
120786 ** Fts3SegReader.pOffsetList to point to the next offset list before
120787 ** returning.
120788 */
120789 if( p>=&pReader->aDoclist[pReader->nDoclist] ){
120790 pReader->pOffsetList = 0;
120791 }else{
120792 rc = fts3SegReaderRequire(pReader, p, FTS3_VARINT_MAX);
120793 if( rc==SQLITE_OK ){
120794 sqlite3_int64 iDelta;
120795 pReader->pOffsetList = p + sqlite3Fts3GetVarint(p, &iDelta);
120796 if( pTab->bDescIdx ){
120797 pReader->iDocid -= iDelta;
120798 }else{
120799 pReader->iDocid += iDelta;
120800 }
120801 }
120802 }
120803 }
120804
120805 return SQLITE_OK;
120806 }
120807
120808
120809 SQLITE_PRIVATE int sqlite3Fts3MsrOvfl(
120810 Fts3Cursor *pCsr,
120811 Fts3MultiSegReader *pMsr,
120812 int *pnOvfl
120813 ){
120814 Fts3Table *p = (Fts3Table*)pCsr->base.pVtab;
120815 int nOvfl = 0;
120816 int ii;
120817 int rc = SQLITE_OK;
120818 int pgsz = p->nPgsz;
120819
120820 assert( p->bHasStat );
120821 assert( pgsz>0 );
120822
120823 for(ii=0; rc==SQLITE_OK && ii<pMsr->nSegment; ii++){
120824 Fts3SegReader *pReader = pMsr->apSegment[ii];
120825 if( !fts3SegReaderIsPending(pReader)
120826 && !fts3SegReaderIsRootOnly(pReader)
120827 ){
120828 int jj;
120829 for(jj=pReader->iStartBlock; jj<=pReader->iLeafEndBlock; jj++){
120830 int nBlob;
120831 rc = sqlite3Fts3ReadBlock(p, jj, 0, &nBlob, 0);
120832 if( rc!=SQLITE_OK ) break;
120833 if( (nBlob+35)>pgsz ){
120834 nOvfl += (nBlob + 34)/pgsz;
120835 }
120836 }
120837 }
120838 }
120839 *pnOvfl = nOvfl;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
120840 return rc;
120841 }
120842
120843 /*
120844 ** Free all allocations associated with the iterator passed as the
@@ -119934,10 +120847,11 @@
120847 SQLITE_PRIVATE void sqlite3Fts3SegReaderFree(Fts3SegReader *pReader){
120848 if( pReader && !fts3SegReaderIsPending(pReader) ){
120849 sqlite3_free(pReader->zTerm);
120850 if( !fts3SegReaderIsRootOnly(pReader) ){
120851 sqlite3_free(pReader->aNode);
120852 sqlite3_blob_close(pReader->pBlob);
120853 }
120854 }
120855 sqlite3_free(pReader);
120856 }
120857
@@ -120010,28 +120924,46 @@
120924 }
120925
120926 /*
120927 ** This function is used to allocate an Fts3SegReader that iterates through
120928 ** a subset of the terms stored in the Fts3Table.pendingTerms array.
120929 **
120930 ** If the isPrefixIter parameter is zero, then the returned SegReader iterates
120931 ** through each term in the pending-terms table. Or, if isPrefixIter is
120932 ** non-zero, it iterates through each term and its prefixes. For example, if
120933 ** the pending terms hash table contains the terms "sqlite", "mysql" and
120934 ** "firebird", then the iterator visits the following 'terms' (in the order
120935 ** shown):
120936 **
120937 ** f fi fir fire fireb firebi firebir firebird
120938 ** m my mys mysq mysql
120939 ** s sq sql sqli sqlit sqlite
120940 **
120941 ** Whereas if isPrefixIter is zero, the terms visited are:
120942 **
120943 ** firebird mysql sqlite
120944 */
120945 SQLITE_PRIVATE int sqlite3Fts3SegReaderPending(
120946 Fts3Table *p, /* Virtual table handle */
120947 int iIndex, /* Index for p->aIndex */
120948 const char *zTerm, /* Term to search for */
120949 int nTerm, /* Size of buffer zTerm */
120950 int bPrefix, /* True for a prefix iterator */
120951 Fts3SegReader **ppReader /* OUT: SegReader for pending-terms */
120952 ){
120953 Fts3SegReader *pReader = 0; /* Fts3SegReader object to return */
120954 Fts3HashElem **aElem = 0; /* Array of term hash entries to scan */
120955 int nElem = 0; /* Size of array at aElem */
120956 int rc = SQLITE_OK; /* Return Code */
120957 Fts3Hash *pHash;
120958
120959 pHash = &p->aIndex[iIndex].hPending;
120960 if( bPrefix ){
120961 int nAlloc = 0; /* Size of allocated array at aElem */
120962 Fts3HashElem *pE = 0; /* Iterator variable */
120963
120964 for(pE=fts3HashFirst(pHash); pE; pE=fts3HashNext(pE)){
120965 char *zKey = (char *)fts3HashKey(pE);
120966 int nKey = fts3HashKeysize(pE);
120967 if( nTerm==0 || (nKey>=nTerm && 0==memcmp(zKey, zTerm, nTerm)) ){
120968 if( nElem==nAlloc ){
120969 Fts3HashElem **aElem2;
@@ -120044,10 +120976,11 @@
120976 nElem = 0;
120977 break;
120978 }
120979 aElem = aElem2;
120980 }
120981
120982 aElem[nElem++] = pE;
120983 }
120984 }
120985
120986 /* If more than one term matches the prefix, sort the Fts3HashElem
@@ -120057,11 +120990,13 @@
120990 if( nElem>1 ){
120991 qsort(aElem, nElem, sizeof(Fts3HashElem *), fts3CompareElemByTerm);
120992 }
120993
120994 }else{
120995 /* The query is a simple term lookup that matches at most one term in
120996 ** the index. All that is required is a straight hash-lookup. */
120997 Fts3HashElem *pE = fts3HashFindElem(pHash, zTerm, nTerm);
120998 if( pE ){
120999 aElem = &pE;
121000 nElem = 1;
121001 }
121002 }
@@ -120077,11 +121012,11 @@
121012 pReader->ppNextElem = (Fts3HashElem **)&pReader[1];
121013 memcpy(pReader->ppNextElem, aElem, nElem*sizeof(Fts3HashElem *));
121014 }
121015 }
121016
121017 if( bPrefix ){
121018 sqlite3_free(aElem);
121019 }
121020 *ppReader = pReader;
121021 return rc;
121022 }
@@ -120137,10 +121072,22 @@
121072 if( pLhs->iDocid==pRhs->iDocid ){
121073 rc = pRhs->iIdx - pLhs->iIdx;
121074 }else{
121075 rc = (pLhs->iDocid > pRhs->iDocid) ? 1 : -1;
121076 }
121077 }
121078 assert( pLhs->aNode && pRhs->aNode );
121079 return rc;
121080 }
121081 static int fts3SegReaderDoclistCmpRev(Fts3SegReader *pLhs, Fts3SegReader *pRhs){
121082 int rc = (pLhs->pOffsetList==0)-(pRhs->pOffsetList==0);
121083 if( rc==0 ){
121084 if( pLhs->iDocid==pRhs->iDocid ){
121085 rc = pRhs->iIdx - pLhs->iIdx;
121086 }else{
121087 rc = (pLhs->iDocid < pRhs->iDocid) ? 1 : -1;
121088 }
121089 }
121090 assert( pLhs->aNode && pRhs->aNode );
121091 return rc;
121092 }
121093
@@ -120689,25 +121636,34 @@
121636 }
121637 return rc;
121638 }
121639
121640 /*
121641 ** Set *pnMax to the largest segment level in the database for the index
121642 ** iIndex.
121643 **
121644 ** Segment levels are stored in the 'level' column of the %_segdir table.
121645 **
121646 ** Return SQLITE_OK if successful, or an SQLite error code if not.
121647 */
121648 static int fts3SegmentMaxLevel(Fts3Table *p, int iIndex, int *pnMax){
121649 sqlite3_stmt *pStmt;
121650 int rc;
121651 assert( iIndex>=0 && iIndex<p->nIndex );
121652
121653 /* Set pStmt to the compiled version of:
121654 **
121655 ** SELECT max(level) FROM %Q.'%q_segdir' WHERE level BETWEEN ? AND ?
121656 **
121657 ** (1024 is actually the value of macro FTS3_SEGDIR_PREFIXLEVEL_STR).
121658 */
121659 rc = fts3SqlStmt(p, SQL_SELECT_SEGDIR_MAX_LEVEL, &pStmt, 0);
121660 if( rc!=SQLITE_OK ) return rc;
121661 sqlite3_bind_int(pStmt, 1, iIndex*FTS3_SEGDIR_MAXLEVEL);
121662 sqlite3_bind_int(pStmt, 2, (iIndex+1)*FTS3_SEGDIR_MAXLEVEL - 1);
121663 if( SQLITE_ROW==sqlite3_step(pStmt) ){
121664 *pnMax = sqlite3_column_int(pStmt, 0);
 
121665 }
121666 return sqlite3_reset(pStmt);
121667 }
121668
121669 /*
@@ -120724,10 +121680,11 @@
121680 **
121681 ** SQLITE_OK is returned if successful, otherwise an SQLite error code.
121682 */
121683 static int fts3DeleteSegdir(
121684 Fts3Table *p, /* Virtual table handle */
121685 int iIndex, /* Index for p->aIndex */
121686 int iLevel, /* Level of %_segdir entries to delete */
121687 Fts3SegReader **apSegment, /* Array of SegReader objects */
121688 int nReader /* Size of array apSegment */
121689 ){
121690 int rc; /* Return Code */
@@ -120746,23 +121703,28 @@
121703 }
121704 if( rc!=SQLITE_OK ){
121705 return rc;
121706 }
121707
121708 assert( iLevel>=0 || iLevel==FTS3_SEGCURSOR_ALL );
121709 if( iLevel==FTS3_SEGCURSOR_ALL ){
121710 rc = fts3SqlStmt(p, SQL_DELETE_SEGDIR_RANGE, &pDelete, 0);
121711 if( rc==SQLITE_OK ){
121712 sqlite3_bind_int(pDelete, 1, iIndex*FTS3_SEGDIR_MAXLEVEL);
121713 sqlite3_bind_int(pDelete, 2, (iIndex+1) * FTS3_SEGDIR_MAXLEVEL - 1);
121714 }
121715 }else{
121716 rc = fts3SqlStmt(p, SQL_DELETE_SEGDIR_LEVEL, &pDelete, 0);
 
121717 if( rc==SQLITE_OK ){
121718 sqlite3_bind_int(pDelete, 1, iIndex*FTS3_SEGDIR_MAXLEVEL + iLevel);
 
 
121719 }
121720 }
121721
121722 if( rc==SQLITE_OK ){
121723 sqlite3_step(pDelete);
121724 rc = sqlite3_reset(pDelete);
121725 }
121726
121727 return rc;
121728 }
121729
121730 /*
@@ -120805,14 +121767,124 @@
121767 }
121768
121769 *ppList = pList;
121770 *pnList = nList;
121771 }
121772
121773 SQLITE_PRIVATE int sqlite3Fts3MsrIncrStart(
121774 Fts3Table *p, /* Virtual table handle */
121775 Fts3MultiSegReader *pCsr, /* Cursor object */
121776 int iCol, /* Column to match on. */
121777 const char *zTerm, /* Term to iterate through a doclist for */
121778 int nTerm /* Number of bytes in zTerm */
121779 ){
121780 int i;
121781 int nSegment = pCsr->nSegment;
121782 int (*xCmp)(Fts3SegReader *, Fts3SegReader *) = (
121783 p->bDescIdx ? fts3SegReaderDoclistCmpRev : fts3SegReaderDoclistCmp
121784 );
121785
121786 assert( pCsr->pFilter==0 );
121787 assert( zTerm && nTerm>0 );
121788
121789 /* Advance each segment iterator until it points to the term zTerm/nTerm. */
121790 for(i=0; i<nSegment; i++){
121791 Fts3SegReader *pSeg = pCsr->apSegment[i];
121792 do {
121793 int rc = fts3SegReaderNext(p, pSeg, 1);
121794 if( rc!=SQLITE_OK ) return rc;
121795 }while( fts3SegReaderTermCmp(pSeg, zTerm, nTerm)<0 );
121796 }
121797 fts3SegReaderSort(pCsr->apSegment, nSegment, nSegment, fts3SegReaderCmp);
121798
121799 /* Determine how many of the segments actually point to zTerm/nTerm. */
121800 for(i=0; i<nSegment; i++){
121801 Fts3SegReader *pSeg = pCsr->apSegment[i];
121802 if( !pSeg->aNode || fts3SegReaderTermCmp(pSeg, zTerm, nTerm) ){
121803 break;
121804 }
121805 }
121806 pCsr->nAdvance = i;
121807
121808 /* Advance each of the segments to point to the first docid. */
121809 for(i=0; i<pCsr->nAdvance; i++){
121810 int rc = fts3SegReaderFirstDocid(p, pCsr->apSegment[i]);
121811 if( rc!=SQLITE_OK ) return rc;
121812 }
121813 fts3SegReaderSort(pCsr->apSegment, i, i, xCmp);
121814
121815 assert( iCol<0 || iCol<p->nColumn );
121816 pCsr->iColFilter = iCol;
121817
121818 return SQLITE_OK;
121819 }
121820
121821 SQLITE_PRIVATE int sqlite3Fts3MsrIncrNext(
121822 Fts3Table *p, /* Virtual table handle */
121823 Fts3MultiSegReader *pMsr, /* Multi-segment-reader handle */
121824 sqlite3_int64 *piDocid, /* OUT: Docid value */
121825 char **paPoslist, /* OUT: Pointer to position list */
121826 int *pnPoslist /* OUT: Size of position list in bytes */
121827 ){
121828 int nMerge = pMsr->nAdvance;
121829 Fts3SegReader **apSegment = pMsr->apSegment;
121830 int (*xCmp)(Fts3SegReader *, Fts3SegReader *) = (
121831 p->bDescIdx ? fts3SegReaderDoclistCmpRev : fts3SegReaderDoclistCmp
121832 );
121833
121834 if( nMerge==0 ){
121835 *paPoslist = 0;
121836 return SQLITE_OK;
121837 }
121838
121839 while( 1 ){
121840 Fts3SegReader *pSeg;
121841 pSeg = pMsr->apSegment[0];
121842
121843 if( pSeg->pOffsetList==0 ){
121844 *paPoslist = 0;
121845 break;
121846 }else{
121847 int rc;
121848 char *pList;
121849 int nList;
121850 int j;
121851 sqlite3_int64 iDocid = apSegment[0]->iDocid;
121852
121853 rc = fts3SegReaderNextDocid(p, apSegment[0], &pList, &nList);
121854 j = 1;
121855 while( rc==SQLITE_OK
121856 && j<nMerge
121857 && apSegment[j]->pOffsetList
121858 && apSegment[j]->iDocid==iDocid
121859 ){
121860 rc = fts3SegReaderNextDocid(p, apSegment[j], 0, 0);
121861 j++;
121862 }
121863 if( rc!=SQLITE_OK ) return rc;
121864 fts3SegReaderSort(pMsr->apSegment, nMerge, j, xCmp);
121865
121866 if( pMsr->iColFilter>=0 ){
121867 fts3ColumnFilter(pMsr->iColFilter, &pList, &nList);
121868 }
121869
121870 if( nList>0 ){
121871 *piDocid = iDocid;
121872 *paPoslist = pList;
121873 *pnPoslist = nList;
121874 break;
121875 }
121876 }
121877
121878 }
121879
121880 return SQLITE_OK;
121881 }
121882
121883 SQLITE_PRIVATE int sqlite3Fts3SegReaderStart(
121884 Fts3Table *p, /* Virtual table handle */
121885 Fts3MultiSegReader *pCsr, /* Cursor object */
121886 Fts3SegFilter *pFilter /* Restrictions on range of iteration */
121887 ){
121888 int i;
121889
121890 /* Initialize the cursor object */
@@ -120827,11 +121899,11 @@
121899 for(i=0; i<pCsr->nSegment; i++){
121900 int nTerm = pFilter->nTerm;
121901 const char *zTerm = pFilter->zTerm;
121902 Fts3SegReader *pSeg = pCsr->apSegment[i];
121903 do {
121904 int rc = fts3SegReaderNext(p, pSeg, 0);
121905 if( rc!=SQLITE_OK ) return rc;
121906 }while( zTerm && fts3SegReaderTermCmp(pSeg, zTerm, nTerm)<0 );
121907 }
121908 fts3SegReaderSort(
121909 pCsr->apSegment, pCsr->nSegment, pCsr->nSegment, fts3SegReaderCmp);
@@ -120839,11 +121911,11 @@
121911 return SQLITE_OK;
121912 }
121913
121914 SQLITE_PRIVATE int sqlite3Fts3SegReaderStep(
121915 Fts3Table *p, /* Virtual table handle */
121916 Fts3MultiSegReader *pCsr /* Cursor object */
121917 ){
121918 int rc = SQLITE_OK;
121919
121920 int isIgnoreEmpty = (pCsr->pFilter->flags & FTS3_SEGMENT_IGNORE_EMPTY);
121921 int isRequirePos = (pCsr->pFilter->flags & FTS3_SEGMENT_REQUIRE_POS);
@@ -120852,10 +121924,13 @@
121924 int isScan = (pCsr->pFilter->flags & FTS3_SEGMENT_SCAN);
121925
121926 Fts3SegReader **apSegment = pCsr->apSegment;
121927 int nSegment = pCsr->nSegment;
121928 Fts3SegFilter *pFilter = pCsr->pFilter;
121929 int (*xCmp)(Fts3SegReader *, Fts3SegReader *) = (
121930 p->bDescIdx ? fts3SegReaderDoclistCmpRev : fts3SegReaderDoclistCmp
121931 );
121932
121933 if( pCsr->nSegment==0 ) return SQLITE_OK;
121934
121935 do {
121936 int nMerge;
@@ -120863,11 +121938,11 @@
121938
121939 /* Advance the first pCsr->nAdvance entries in the apSegment[] array
121940 ** forward. Then sort the list in order of current term again.
121941 */
121942 for(i=0; i<pCsr->nAdvance; i++){
121943 rc = fts3SegReaderNext(p, apSegment[i], 0);
121944 if( rc!=SQLITE_OK ) return rc;
121945 }
121946 fts3SegReaderSort(apSegment, nSegment, pCsr->nAdvance, fts3SegReaderCmp);
121947 pCsr->nAdvance = 0;
121948
@@ -120902,11 +121977,14 @@
121977 ){
121978 nMerge++;
121979 }
121980
121981 assert( isIgnoreEmpty || (isRequirePos && !isColFilter) );
121982 if( nMerge==1
121983 && !isIgnoreEmpty
121984 && (p->bDescIdx==0 || fts3SegReaderIsPending(apSegment[0])==0)
121985 ){
121986 pCsr->aDoclist = apSegment[0]->aDoclist;
121987 pCsr->nDoclist = apSegment[0]->nDoclist;
121988 rc = SQLITE_ROW;
121989 }else{
121990 int nDoclist = 0; /* Size of doclist */
@@ -120915,56 +121993,66 @@
121993 /* The current term of the first nMerge entries in the array
121994 ** of Fts3SegReader objects is the same. The doclists must be merged
121995 ** and a single term returned with the merged doclist.
121996 */
121997 for(i=0; i<nMerge; i++){
121998 fts3SegReaderFirstDocid(p, apSegment[i]);
121999 }
122000 fts3SegReaderSort(apSegment, nMerge, nMerge, xCmp);
122001 while( apSegment[0]->pOffsetList ){
122002 int j; /* Number of segments that share a docid */
122003 char *pList;
122004 int nList;
122005 int nByte;
122006 sqlite3_int64 iDocid = apSegment[0]->iDocid;
122007 fts3SegReaderNextDocid(p, apSegment[0], &pList, &nList);
122008 j = 1;
122009 while( j<nMerge
122010 && apSegment[j]->pOffsetList
122011 && apSegment[j]->iDocid==iDocid
122012 ){
122013 fts3SegReaderNextDocid(p, apSegment[j], 0, 0);
122014 j++;
122015 }
122016
122017 if( isColFilter ){
122018 fts3ColumnFilter(pFilter->iCol, &pList, &nList);
122019 }
122020
122021 if( !isIgnoreEmpty || nList>0 ){
122022
122023 /* Calculate the 'docid' delta value to write into the merged
122024 ** doclist. */
122025 sqlite3_int64 iDelta;
122026 if( p->bDescIdx && nDoclist>0 ){
122027 iDelta = iPrev - iDocid;
122028 }else{
122029 iDelta = iDocid - iPrev;
122030 }
122031 assert( iDelta>0 || (nDoclist==0 && iDelta==iDocid) );
122032 assert( nDoclist>0 || iDelta==iDocid );
122033
122034 nByte = sqlite3Fts3VarintLen(iDelta) + (isRequirePos?nList+1:0);
122035 if( nDoclist+nByte>pCsr->nBuffer ){
122036 char *aNew;
122037 pCsr->nBuffer = (nDoclist+nByte)*2;
122038 aNew = sqlite3_realloc(pCsr->aBuffer, pCsr->nBuffer);
122039 if( !aNew ){
122040 return SQLITE_NOMEM;
122041 }
122042 pCsr->aBuffer = aNew;
122043 }
122044 nDoclist += sqlite3Fts3PutVarint(&pCsr->aBuffer[nDoclist], iDelta);
 
 
122045 iPrev = iDocid;
122046 if( isRequirePos ){
122047 memcpy(&pCsr->aBuffer[nDoclist], pList, nList);
122048 nDoclist += nList;
122049 pCsr->aBuffer[nDoclist++] = '\0';
122050 }
122051 }
122052
122053 fts3SegReaderSort(apSegment, nMerge, j, xCmp);
122054 }
122055 if( nDoclist>0 ){
122056 pCsr->aDoclist = pCsr->aBuffer;
122057 pCsr->nDoclist = nDoclist;
122058 rc = SQLITE_ROW;
@@ -120973,13 +122061,14 @@
122061 pCsr->nAdvance = nMerge;
122062 }while( rc==SQLITE_OK );
122063
122064 return rc;
122065 }
122066
122067
122068 SQLITE_PRIVATE void sqlite3Fts3SegReaderFinish(
122069 Fts3MultiSegReader *pCsr /* Cursor object */
122070 ){
122071 if( pCsr ){
122072 int i;
122073 for(i=0; i<pCsr->nSegment; i++){
122074 sqlite3Fts3SegReaderFree(pCsr->apSegment[i]);
@@ -121002,47 +122091,60 @@
122091 ** If this function is called with iLevel<0, but there is only one
122092 ** segment in the database, SQLITE_DONE is returned immediately.
122093 ** Otherwise, if successful, SQLITE_OK is returned. If an error occurs,
122094 ** an SQLite error code is returned.
122095 */
122096 static int fts3SegmentMerge(Fts3Table *p, int iIndex, int iLevel){
122097 int rc; /* Return code */
122098 int iIdx = 0; /* Index of new segment */
122099 int iNewLevel = 0; /* Level/index to create new segment at */
122100 SegmentWriter *pWriter = 0; /* Used to write the new, merged, segment */
122101 Fts3SegFilter filter; /* Segment term filter condition */
122102 Fts3MultiSegReader csr; /* Cursor to iterate through level(s) */
122103 int bIgnoreEmpty = 0; /* True to ignore empty segments */
122104
122105 assert( iLevel==FTS3_SEGCURSOR_ALL
122106 || iLevel==FTS3_SEGCURSOR_PENDING
122107 || iLevel>=0
122108 );
122109 assert( iLevel<FTS3_SEGDIR_MAXLEVEL );
122110 assert( iIndex>=0 && iIndex<p->nIndex );
122111
122112 rc = sqlite3Fts3SegReaderCursor(p, iIndex, iLevel, 0, 0, 1, 0, &csr);
122113 if( rc!=SQLITE_OK || csr.nSegment==0 ) goto finished;
122114
122115 if( iLevel==FTS3_SEGCURSOR_ALL ){
122116 /* This call is to merge all segments in the database to a single
122117 ** segment. The level of the new segment is equal to the the numerically
122118 ** greatest segment level currently present in the database for this
122119 ** index. The idx of the new segment is always 0. */
 
122120 if( csr.nSegment==1 ){
122121 rc = SQLITE_DONE;
122122 goto finished;
122123 }
122124 rc = fts3SegmentMaxLevel(p, iIndex, &iNewLevel);
122125 bIgnoreEmpty = 1;
122126
122127 }else if( iLevel==FTS3_SEGCURSOR_PENDING ){
122128 iNewLevel = iIndex * FTS3_SEGDIR_MAXLEVEL;
122129 rc = fts3AllocateSegdirIdx(p, iIndex, 0, &iIdx);
122130 }else{
122131 /* This call is to merge all segments at level iLevel. find the next
122132 ** available segment index at level iLevel+1. The call to
122133 ** fts3AllocateSegdirIdx() will merge the segments at level iLevel+1 to
122134 ** a single iLevel+2 segment if necessary. */
122135 rc = fts3AllocateSegdirIdx(p, iIndex, iLevel+1, &iIdx);
122136 iNewLevel = iIndex * FTS3_SEGDIR_MAXLEVEL + iLevel+1;
122137 }
122138 if( rc!=SQLITE_OK ) goto finished;
122139 assert( csr.nSegment>0 );
122140 assert( iNewLevel>=(iIndex*FTS3_SEGDIR_MAXLEVEL) );
122141 assert( iNewLevel<((iIndex+1)*FTS3_SEGDIR_MAXLEVEL) );
122142
122143 memset(&filter, 0, sizeof(Fts3SegFilter));
122144 filter.flags = FTS3_SEGMENT_REQUIRE_POS;
122145 filter.flags |= (bIgnoreEmpty ? FTS3_SEGMENT_IGNORE_EMPTY : 0);
122146
122147 rc = sqlite3Fts3SegReaderStart(p, &csr, &filter);
122148 while( SQLITE_OK==rc ){
122149 rc = sqlite3Fts3SegReaderStep(p, &csr);
122150 if( rc!=SQLITE_ROW ) break;
@@ -121050,12 +122152,14 @@
122152 csr.zTerm, csr.nTerm, csr.aDoclist, csr.nDoclist);
122153 }
122154 if( rc!=SQLITE_OK ) goto finished;
122155 assert( pWriter );
122156
122157 if( iLevel!=FTS3_SEGCURSOR_PENDING ){
122158 rc = fts3DeleteSegdir(p, iIndex, iLevel, csr.apSegment, csr.nSegment);
122159 if( rc!=SQLITE_OK ) goto finished;
122160 }
122161 rc = fts3SegWriterFlush(p, pWriter, iNewLevel, iIdx);
122162
122163 finished:
122164 fts3SegWriterFree(pWriter);
122165 sqlite3Fts3SegReaderFinish(&csr);
@@ -121062,14 +122166,21 @@
122166 return rc;
122167 }
122168
122169
122170 /*
122171 ** Flush the contents of pendingTerms to level 0 segments.
122172 */
122173 SQLITE_PRIVATE int sqlite3Fts3PendingTermsFlush(Fts3Table *p){
122174 int rc = SQLITE_OK;
122175 int i;
122176 for(i=0; rc==SQLITE_OK && i<p->nIndex; i++){
122177 rc = fts3SegmentMerge(p, i, FTS3_SEGCURSOR_PENDING);
122178 if( rc==SQLITE_DONE ) rc = SQLITE_OK;
122179 }
122180 sqlite3Fts3PendingTermsClear(p);
122181 return rc;
122182 }
122183
122184 /*
122185 ** Encode N integers as varints into a blob.
122186 */
@@ -121215,10 +122326,27 @@
122326 sqlite3_bind_blob(pStmt, 1, pBlob, nBlob, SQLITE_STATIC);
122327 sqlite3_step(pStmt);
122328 *pRC = sqlite3_reset(pStmt);
122329 sqlite3_free(a);
122330 }
122331
122332 static int fts3DoOptimize(Fts3Table *p, int bReturnDone){
122333 int i;
122334 int bSeenDone = 0;
122335 int rc = SQLITE_OK;
122336 for(i=0; rc==SQLITE_OK && i<p->nIndex; i++){
122337 rc = fts3SegmentMerge(p, i, FTS3_SEGCURSOR_ALL);
122338 if( rc==SQLITE_DONE ){
122339 bSeenDone = 1;
122340 rc = SQLITE_OK;
122341 }
122342 }
122343 sqlite3Fts3SegmentsClose(p);
122344 sqlite3Fts3PendingTermsClear(p);
122345
122346 return (rc==SQLITE_OK && bReturnDone && bSeenDone) ? SQLITE_DONE : rc;
122347 }
122348
122349 /*
122350 ** Handle a 'special' INSERT of the form:
122351 **
122352 ** "INSERT INTO tbl(tbl) VALUES(<expr>)"
@@ -121232,16 +122360,11 @@
122360 int nVal = sqlite3_value_bytes(pVal);
122361
122362 if( !zVal ){
122363 return SQLITE_NOMEM;
122364 }else if( nVal==8 && 0==sqlite3_strnicmp(zVal, "optimize", 8) ){
122365 rc = fts3DoOptimize(p, 0);
 
 
 
 
 
122366 #ifdef SQLITE_TEST
122367 }else if( nVal>9 && 0==sqlite3_strnicmp(zVal, "nodesize=", 9) ){
122368 p->nNodeSize = atoi(&zVal[9]);
122369 rc = SQLITE_OK;
122370 }else if( nVal>11 && 0==sqlite3_strnicmp(zVal, "maxpending=", 9) ){
@@ -121250,61 +122373,23 @@
122373 #endif
122374 }else{
122375 rc = SQLITE_ERROR;
122376 }
122377
 
122378 return rc;
122379 }
122380
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
122381 /*
122382 ** Delete all cached deferred doclists. Deferred doclists are cached
122383 ** (allocated) by the sqlite3Fts3CacheDeferredDoclists() function.
122384 */
122385 SQLITE_PRIVATE void sqlite3Fts3FreeDeferredDoclists(Fts3Cursor *pCsr){
122386 Fts3DeferredToken *pDef;
122387 for(pDef=pCsr->pDeferred; pDef; pDef=pDef->pNext){
122388 fts3PendingListDelete(pDef->pList);
122389 pDef->pList = 0;
122390 }
 
 
 
122391 }
122392
122393 /*
122394 ** Free all entries in the pCsr->pDeffered list. Entries are added to
122395 ** this list using sqlite3Fts3DeferToken().
@@ -121312,11 +122397,11 @@
122397 SQLITE_PRIVATE void sqlite3Fts3FreeDeferredTokens(Fts3Cursor *pCsr){
122398 Fts3DeferredToken *pDef;
122399 Fts3DeferredToken *pNext;
122400 for(pDef=pCsr->pDeferred; pDef; pDef=pNext){
122401 pNext = pDef->pNext;
122402 fts3PendingListDelete(pDef->pList);
122403 sqlite3_free(pDef);
122404 }
122405 pCsr->pDeferred = 0;
122406 }
122407
@@ -121376,10 +122461,37 @@
122461 }
122462 }
122463
122464 return rc;
122465 }
122466
122467 SQLITE_PRIVATE int sqlite3Fts3DeferredTokenList(
122468 Fts3DeferredToken *p,
122469 char **ppData,
122470 int *pnData
122471 ){
122472 char *pRet;
122473 int nSkip;
122474 sqlite3_int64 dummy;
122475
122476 *ppData = 0;
122477 *pnData = 0;
122478
122479 if( p->pList==0 ){
122480 return SQLITE_OK;
122481 }
122482
122483 pRet = (char *)sqlite3_malloc(p->pList->nData);
122484 if( !pRet ) return SQLITE_NOMEM;
122485
122486 nSkip = sqlite3Fts3GetVarint(p->pList->aData, &dummy);
122487 *pnData = p->pList->nData - nSkip;
122488 *ppData = pRet;
122489
122490 memcpy(pRet, &p->pList->aData[nSkip], *pnData);
122491 return SQLITE_OK;
122492 }
122493
122494 /*
122495 ** Add an entry for token pToken to the pCsr->pDeferred list.
122496 */
122497 SQLITE_PRIVATE int sqlite3Fts3DeferToken(
@@ -121451,11 +122563,11 @@
122563 ){
122564 Fts3Table *p = (Fts3Table *)pVtab;
122565 int rc = SQLITE_OK; /* Return Code */
122566 int isRemove = 0; /* True for an UPDATE or DELETE */
122567 sqlite3_int64 iRemove = 0; /* Rowid removed by UPDATE or DELETE */
122568 u32 *aSzIns = 0; /* Sizes of inserted documents */
122569 u32 *aSzDel; /* Sizes of deleted documents */
122570 int nChng = 0; /* Net change in number of documents */
122571 int bInsertDone = 0;
122572
122573 assert( p->pSegments==0 );
@@ -121466,16 +122578,20 @@
122578 */
122579 if( nArg>1
122580 && sqlite3_value_type(apVal[0])==SQLITE_NULL
122581 && sqlite3_value_type(apVal[p->nColumn+2])!=SQLITE_NULL
122582 ){
122583 rc = fts3SpecialInsert(p, apVal[p->nColumn+2]);
122584 goto update_out;
122585 }
122586
122587 /* Allocate space to hold the change in document sizes */
122588 aSzIns = sqlite3_malloc( sizeof(aSzIns[0])*(p->nColumn+1)*2 );
122589 if( aSzIns==0 ){
122590 rc = SQLITE_NOMEM;
122591 goto update_out;
122592 }
122593 aSzDel = &aSzIns[p->nColumn+1];
122594 memset(aSzIns, 0, sizeof(aSzIns[0])*(p->nColumn+1)*2);
122595
122596 /* If this is an INSERT operation, or an UPDATE that modifies the rowid
122597 ** value, then this operation requires constraint handling.
@@ -121521,12 +122637,11 @@
122637 bInsertDone = 1;
122638 }
122639 }
122640 }
122641 if( rc!=SQLITE_OK ){
122642 goto update_out;
 
122643 }
122644
122645 /* If this is a DELETE or UPDATE operation, remove the old record. */
122646 if( sqlite3_value_type(apVal[0])!=SQLITE_NULL ){
122647 assert( sqlite3_value_type(apVal[0])==SQLITE_INTEGER );
@@ -121555,10 +122670,11 @@
122670
122671 if( p->bHasStat ){
122672 fts3UpdateDocTotals(&rc, p, aSzIns, aSzDel, nChng);
122673 }
122674
122675 update_out:
122676 sqlite3_free(aSzIns);
122677 sqlite3Fts3SegmentsClose(p);
122678 return rc;
122679 }
122680
@@ -121569,16 +122685,14 @@
122685 */
122686 SQLITE_PRIVATE int sqlite3Fts3Optimize(Fts3Table *p){
122687 int rc;
122688 rc = sqlite3_exec(p->db, "SAVEPOINT fts3", 0, 0, 0);
122689 if( rc==SQLITE_OK ){
122690 rc = fts3DoOptimize(p, 1);
122691 if( rc==SQLITE_OK || rc==SQLITE_DONE ){
122692 int rc2 = sqlite3_exec(p->db, "RELEASE fts3", 0, 0, 0);
122693 if( rc2!=SQLITE_OK ) rc = rc2;
 
 
122694 }else{
122695 sqlite3_exec(p->db, "ROLLBACK TO fts3", 0, 0, 0);
122696 sqlite3_exec(p->db, "RELEASE fts3", 0, 0, 0);
122697 }
122698 }
@@ -121763,76 +122877,24 @@
122877 ){
122878 int iPhrase = 0; /* Variable used as the phrase counter */
122879 return fts3ExprIterate2(pExpr, &iPhrase, x, pCtx);
122880 }
122881
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
122882 /*
122883 ** This is an fts3ExprIterate() callback used while loading the doclists
122884 ** for each phrase into Fts3Expr.aDoclist[]/nDoclist. See also
122885 ** fts3ExprLoadDoclists().
122886 */
122887 static int fts3ExprLoadDoclistsCb(Fts3Expr *pExpr, int iPhrase, void *ctx){
122888 int rc = SQLITE_OK;
122889 Fts3Phrase *pPhrase = pExpr->pPhrase;
122890 LoadDoclistCtx *p = (LoadDoclistCtx *)ctx;
122891
122892 UNUSED_PARAMETER(iPhrase);
122893
122894 p->nPhrase++;
122895 p->nToken += pPhrase->nToken;
 
 
 
 
 
 
 
 
122896
122897 return rc;
122898 }
122899
122900 /*
@@ -122002,11 +123064,11 @@
123064 SnippetPhrase *pPhrase = &p->aPhrase[iPhrase];
123065 char *pCsr;
123066
123067 pPhrase->nToken = pExpr->pPhrase->nToken;
123068
123069 pCsr = sqlite3Fts3EvalPhrasePoslist(p->pCsr, pExpr, p->iCol);
123070 if( pCsr ){
123071 int iFirst = 0;
123072 pPhrase->pList = pCsr;
123073 fts3GetDeltaPosition(&pCsr, &iFirst);
123074 pPhrase->pHead = pCsr;
@@ -122359,30 +123421,10 @@
123421
123422 *ppCollist = pEnd;
123423 return nEntry;
123424 }
123425
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
123426 /*
123427 ** fts3ExprIterate() callback used to collect the "global" matchinfo stats
123428 ** for a single query.
123429 **
123430 ** fts3ExprIterate() callback to load the 'global' elements of a
@@ -122412,52 +123454,13 @@
123454 Fts3Expr *pExpr, /* Phrase expression node */
123455 int iPhrase, /* Phrase number (numbered from zero) */
123456 void *pCtx /* Pointer to MatchInfo structure */
123457 ){
123458 MatchInfo *p = (MatchInfo *)pCtx;
123459 return sqlite3Fts3EvalPhraseStats(
123460 p->pCursor, pExpr, &p->aMatchinfo[3*iPhrase*p->nCol]
123461 );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
123462 }
123463
123464 /*
123465 ** fts3ExprIterate() callback used to collect the "local" part of the
123466 ** FTS3_MATCHINFO_HITS array. The local stats are those elements of the
@@ -122470,18 +123473,17 @@
123473 ){
123474 MatchInfo *p = (MatchInfo *)pCtx;
123475 int iStart = iPhrase * p->nCol * 3;
123476 int i;
123477
123478 for(i=0; i<p->nCol; i++){
 
 
123479 char *pCsr;
123480 pCsr = sqlite3Fts3EvalPhrasePoslist(p->pCursor, pExpr, i);
 
123481 if( pCsr ){
123482 p->aMatchinfo[iStart+i*3] = fts3ColumnlistCount(&pCsr);
123483 }else{
123484 p->aMatchinfo[iStart+i*3] = 0;
123485 }
123486 }
123487
123488 return SQLITE_OK;
123489 }
@@ -122563,13 +123565,12 @@
123565 ** values for a matchinfo() FTS3_MATCHINFO_LCS request.
123566 */
123567 typedef struct LcsIterator LcsIterator;
123568 struct LcsIterator {
123569 Fts3Expr *pExpr; /* Pointer to phrase expression */
 
123570 int iPosOffset; /* Tokens count up to end of this phrase */
123571 char *pRead; /* Cursor used to iterate through aDoclist */
123572 int iPos; /* Current position */
123573 };
123574
123575 /*
123576 ** If LcsIterator.iCol is set to the following value, the iterator has
@@ -122596,21 +123597,14 @@
123597 char *pRead = pIter->pRead;
123598 sqlite3_int64 iRead;
123599 int rc = 0;
123600
123601 pRead += sqlite3Fts3GetVarint(pRead, &iRead);
123602 if( iRead==0 || iRead==1 ){
123603 pRead = 0;
123604 rc = 1;
123605 }else{
 
 
 
 
 
 
 
123606 pIter->iPos += (int)(iRead-2);
123607 }
123608
123609 pIter->pRead = pRead;
123610 return rc;
@@ -122638,46 +123632,38 @@
123632 **/
123633 aIter = sqlite3_malloc(sizeof(LcsIterator) * pCsr->nPhrase);
123634 if( !aIter ) return SQLITE_NOMEM;
123635 memset(aIter, 0, sizeof(LcsIterator) * pCsr->nPhrase);
123636 (void)fts3ExprIterate(pCsr->pExpr, fts3MatchinfoLcsCb, (void*)aIter);
123637
123638 for(i=0; i<pInfo->nPhrase; i++){
123639 LcsIterator *pIter = &aIter[i];
123640 nToken -= pIter->pExpr->pPhrase->nToken;
123641 pIter->iPosOffset = nToken;
 
 
 
 
 
 
 
123642 }
123643
123644 for(iCol=0; iCol<pInfo->nCol; iCol++){
123645 int nLcs = 0; /* LCS value for this column */
123646 int nLive = 0; /* Number of iterators in aIter not at EOF */
123647
 
 
 
123648 for(i=0; i<pInfo->nPhrase; i++){
123649 LcsIterator *pIt = &aIter[i];
123650 pIt->pRead = sqlite3Fts3EvalPhrasePoslist(pCsr, pIt->pExpr, iCol);
123651 if( pIt->pRead ){
123652 pIt->iPos = pIt->iPosOffset;
123653 fts3LcsIteratorAdvance(&aIter[i]);
123654 nLive++;
123655 }
123656 }
123657
 
 
 
 
123658 while( nLive>0 ){
123659 LcsIterator *pAdv = 0; /* The iterator to advance by one position */
123660 int nThisLcs = 0; /* LCS for the current iterator positions */
123661
123662 for(i=0; i<pInfo->nPhrase; i++){
123663 LcsIterator *pIter = &aIter[i];
123664 if( pIter->pRead==0 ){
123665 /* This iterator is already at EOF for this column. */
123666 nThisLcs = 0;
123667 }else{
123668 if( pAdv==0 || pIter->iPos<pAdv->iPos ){
123669 pAdv = pIter;
@@ -123013,11 +123999,11 @@
123999 int iTerm; /* For looping through nTerm phrase terms */
124000 char *pList; /* Pointer to position list for phrase */
124001 int iPos = 0; /* First position in position-list */
124002
124003 UNUSED_PARAMETER(iPhrase);
124004 pList = sqlite3Fts3EvalPhrasePoslist(p->pCsr, pExpr, p->iCol);
124005 nTerm = pExpr->pPhrase->nToken;
124006 if( pList ){
124007 fts3GetDeltaPosition(&pList, &iPos);
124008 assert( iPos>=0 );
124009 }
124010
+1 -1
--- src/sqlite3.h
+++ src/sqlite3.h
@@ -107,11 +107,11 @@
107107
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
108108
** [sqlite_version()] and [sqlite_source_id()].
109109
*/
110110
#define SQLITE_VERSION "3.7.7"
111111
#define SQLITE_VERSION_NUMBER 3007007
112
-#define SQLITE_SOURCE_ID "2011-06-03 14:19:10 0206bc6f87bb9393218a380fc5b18039d334a8d8"
112
+#define SQLITE_SOURCE_ID "2011-06-15 13:11:06 f9750870ee04935f338e4d808900fee5a8b2b389"
113113
114114
/*
115115
** CAPI3REF: Run-Time Library Version Numbers
116116
** KEYWORDS: sqlite3_version, sqlite3_sourceid
117117
**
118118
--- src/sqlite3.h
+++ src/sqlite3.h
@@ -107,11 +107,11 @@
107 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
108 ** [sqlite_version()] and [sqlite_source_id()].
109 */
110 #define SQLITE_VERSION "3.7.7"
111 #define SQLITE_VERSION_NUMBER 3007007
112 #define SQLITE_SOURCE_ID "2011-06-03 14:19:10 0206bc6f87bb9393218a380fc5b18039d334a8d8"
113
114 /*
115 ** CAPI3REF: Run-Time Library Version Numbers
116 ** KEYWORDS: sqlite3_version, sqlite3_sourceid
117 **
118
--- src/sqlite3.h
+++ src/sqlite3.h
@@ -107,11 +107,11 @@
107 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
108 ** [sqlite_version()] and [sqlite_source_id()].
109 */
110 #define SQLITE_VERSION "3.7.7"
111 #define SQLITE_VERSION_NUMBER 3007007
112 #define SQLITE_SOURCE_ID "2011-06-15 13:11:06 f9750870ee04935f338e4d808900fee5a8b2b389"
113
114 /*
115 ** CAPI3REF: Run-Time Library Version Numbers
116 ** KEYWORDS: sqlite3_version, sqlite3_sourceid
117 **
118
+2 -1
--- src/stat.c
+++ src/stat.c
@@ -104,11 +104,12 @@
104104
@ <tr><th>Server&nbsp;ID:</th><td>
105105
@ %h(db_get("server-code",""))
106106
@ </td></tr>
107107
108108
@ <tr><th>Fossil&nbsp;Version:</th><td>
109
- @ %h(MANIFEST_DATE) %h(MANIFEST_VERSION) (%h(COMPILER_NAME))
109
+ @ %h(RELEASE_VERSION) %h(MANIFEST_DATE) %h(MANIFEST_VERSION)
110
+ @ (%h(COMPILER_NAME))
110111
@ </td></tr>
111112
@ <tr><th>SQLite&nbsp;Version:</th><td>
112113
sqlite3_snprintf(sizeof(zBuf), zBuf, "%.19s [%.10s] (%s)",
113114
SQLITE_SOURCE_ID, &SQLITE_SOURCE_ID[20], SQLITE_VERSION);
114115
zDb = db_name("repository");
115116
--- src/stat.c
+++ src/stat.c
@@ -104,11 +104,12 @@
104 @ <tr><th>Server&nbsp;ID:</th><td>
105 @ %h(db_get("server-code",""))
106 @ </td></tr>
107
108 @ <tr><th>Fossil&nbsp;Version:</th><td>
109 @ %h(MANIFEST_DATE) %h(MANIFEST_VERSION) (%h(COMPILER_NAME))
 
110 @ </td></tr>
111 @ <tr><th>SQLite&nbsp;Version:</th><td>
112 sqlite3_snprintf(sizeof(zBuf), zBuf, "%.19s [%.10s] (%s)",
113 SQLITE_SOURCE_ID, &SQLITE_SOURCE_ID[20], SQLITE_VERSION);
114 zDb = db_name("repository");
115
--- src/stat.c
+++ src/stat.c
@@ -104,11 +104,12 @@
104 @ <tr><th>Server&nbsp;ID:</th><td>
105 @ %h(db_get("server-code",""))
106 @ </td></tr>
107
108 @ <tr><th>Fossil&nbsp;Version:</th><td>
109 @ %h(RELEASE_VERSION) %h(MANIFEST_DATE) %h(MANIFEST_VERSION)
110 @ (%h(COMPILER_NAME))
111 @ </td></tr>
112 @ <tr><th>SQLite&nbsp;Version:</th><td>
113 sqlite3_snprintf(sizeof(zBuf), zBuf, "%.19s [%.10s] (%s)",
114 SQLITE_SOURCE_ID, &SQLITE_SOURCE_ID[20], SQLITE_VERSION);
115 zDb = db_name("repository");
116
+2 -1
--- src/style.c
+++ src/style.c
@@ -98,10 +98,11 @@
9898
Th_Store("title", zTitle);
9999
Th_Store("baseurl", g.zBaseURL);
100100
Th_Store("home", g.zTop);
101101
Th_Store("index_page", db_get("index-page","/home"));
102102
Th_Store("current_page", g.zPath);
103
+ Th_Store("release_version", RELEASE_VERSION);
103104
Th_Store("manifest_version", MANIFEST_VERSION);
104105
Th_Store("manifest_date", MANIFEST_DATE);
105106
Th_Store("compiler_name", COMPILER_NAME);
106107
if( g.zLogin ){
107108
Th_Store("login", g.zLogin);
@@ -245,11 +246,11 @@
245246
/*
246247
** The default page footer
247248
*/
248249
const char zDefaultFooter[] =
249250
@ <div class="footer">
250
-@ Fossil version $manifest_version $manifest_date
251
+@ Fossil version $release_version $manifest_version $manifest_date
251252
@ </div>
252253
@ </body></html>
253254
;
254255
255256
/*
256257
--- src/style.c
+++ src/style.c
@@ -98,10 +98,11 @@
98 Th_Store("title", zTitle);
99 Th_Store("baseurl", g.zBaseURL);
100 Th_Store("home", g.zTop);
101 Th_Store("index_page", db_get("index-page","/home"));
102 Th_Store("current_page", g.zPath);
 
103 Th_Store("manifest_version", MANIFEST_VERSION);
104 Th_Store("manifest_date", MANIFEST_DATE);
105 Th_Store("compiler_name", COMPILER_NAME);
106 if( g.zLogin ){
107 Th_Store("login", g.zLogin);
@@ -245,11 +246,11 @@
245 /*
246 ** The default page footer
247 */
248 const char zDefaultFooter[] =
249 @ <div class="footer">
250 @ Fossil version $manifest_version $manifest_date
251 @ </div>
252 @ </body></html>
253 ;
254
255 /*
256
--- src/style.c
+++ src/style.c
@@ -98,10 +98,11 @@
98 Th_Store("title", zTitle);
99 Th_Store("baseurl", g.zBaseURL);
100 Th_Store("home", g.zTop);
101 Th_Store("index_page", db_get("index-page","/home"));
102 Th_Store("current_page", g.zPath);
103 Th_Store("release_version", RELEASE_VERSION);
104 Th_Store("manifest_version", MANIFEST_VERSION);
105 Th_Store("manifest_date", MANIFEST_DATE);
106 Th_Store("compiler_name", COMPILER_NAME);
107 if( g.zLogin ){
108 Th_Store("login", g.zLogin);
@@ -245,11 +246,11 @@
246 /*
247 ** The default page footer
248 */
249 const char zDefaultFooter[] =
250 @ <div class="footer">
251 @ Fossil version $release_version $manifest_version $manifest_date
252 @ </div>
253 @ </body></html>
254 ;
255
256 /*
257
+1 -1
--- src/timeline.c
+++ src/timeline.c
@@ -333,11 +333,11 @@
333333
" (SELECT name FROM filename WHERE fnid=mlink.fnid) AS name,"
334334
" (SELECT uuid FROM blob WHERE rid=fid),"
335335
" (SELECT uuid FROM blob WHERE rid=pid)"
336336
" FROM mlink"
337337
" WHERE mid=:mid AND pid!=fid"
338
- " ORDER BY 3"
338
+ " ORDER BY 3 /*sort*/"
339339
);
340340
fchngQueryInit = 1;
341341
}
342342
db_bind_int(&fchngQuery, ":mid", rid);
343343
while( db_step(&fchngQuery)==SQLITE_ROW ){
344344
--- src/timeline.c
+++ src/timeline.c
@@ -333,11 +333,11 @@
333 " (SELECT name FROM filename WHERE fnid=mlink.fnid) AS name,"
334 " (SELECT uuid FROM blob WHERE rid=fid),"
335 " (SELECT uuid FROM blob WHERE rid=pid)"
336 " FROM mlink"
337 " WHERE mid=:mid AND pid!=fid"
338 " ORDER BY 3"
339 );
340 fchngQueryInit = 1;
341 }
342 db_bind_int(&fchngQuery, ":mid", rid);
343 while( db_step(&fchngQuery)==SQLITE_ROW ){
344
--- src/timeline.c
+++ src/timeline.c
@@ -333,11 +333,11 @@
333 " (SELECT name FROM filename WHERE fnid=mlink.fnid) AS name,"
334 " (SELECT uuid FROM blob WHERE rid=fid),"
335 " (SELECT uuid FROM blob WHERE rid=pid)"
336 " FROM mlink"
337 " WHERE mid=:mid AND pid!=fid"
338 " ORDER BY 3 /*sort*/"
339 );
340 fchngQueryInit = 1;
341 }
342 db_bind_int(&fchngQuery, ":mid", rid);
343 while( db_step(&fchngQuery)==SQLITE_ROW ){
344
+35 -18
--- src/tkt.c
+++ src/tkt.c
@@ -889,10 +889,11 @@
889889
** status, type, severity, priority, resolution,
890890
** foundin, private_contact, resolution, title or comment
891891
** Field names given above are the ones, defined in a standard
892892
** fossil environment. If you have added, deleted columns, you
893893
** change the all your configured columns.
894
+** If you use +FIELD, the VALUE Is appended to the field FIELD.
894895
** You can use more than one field/value pair on the commandline.
895896
** Using -q|--quote enables the special character decoding as
896897
** in "ticket show". So it's possible, to set multiline text or
897898
** text with special characters.
898899
**
@@ -1008,25 +1009,34 @@
10081009
/* read commandline and assign fields in the azValue array */
10091010
while( i<g.argc ){
10101011
char *zFName;
10111012
char *zFValue;
10121013
int j;
1014
+ int append = 0;
10131015
10141016
zFName = g.argv[i++];
10151017
if( i==g.argc ){
10161018
fossil_fatal("missing value for '%s'!",zFName);
10171019
}
10181020
zFValue = g.argv[i++];
1019
- j = fieldId(zFName);
10201021
if( tktEncoding == tktFossilize ){
10211022
zFValue=mprintf("%s",zFValue);
10221023
defossilize(zFValue);
10231024
}
1025
+ append = (zFName[0] == '+');
1026
+ if (append){
1027
+ zFName++;
1028
+ }
1029
+ j = fieldId(zFName);
10241030
if( j == -1 ){
10251031
fossil_fatal("unknown field name '%s'!",zFName);
10261032
}else{
1027
- azValue[j] = zFValue;
1033
+ if (append) {
1034
+ azAppend[j] = zFValue;
1035
+ } else {
1036
+ azValue[j] = zFValue;
1037
+ }
10281038
}
10291039
}
10301040
10311041
/* now add the needed artifacts to the repository */
10321042
blob_zero(&tktchng);
@@ -1037,24 +1047,31 @@
10371047
blob_appendf(&tktchng, "D %s\n", zDate);
10381048
free(zDate);
10391049
}
10401050
/* append defined elements */
10411051
for(i=0; i<nField; i++){
1042
- char *zValue;
1043
-
1044
- zValue = azValue[i];
1045
- if( azValue[i] && azValue[i][0] ){
1046
- if( strncmp(azField[i], "private_", 8)==0 ){
1047
- zValue = db_conceal(zValue, strlen(zValue));
1048
- blob_appendf(&tktchng, "J %s %s\n", azField[i], zValue);
1049
- }else{
1050
- blob_appendf(&tktchng, "J %s %#F\n",
1051
- azField[i], strlen(zValue), zValue);
1052
- }
1053
- if( tktEncoding == tktFossilize ){
1054
- free(azValue[i]);
1055
- }
1052
+ char *zValue = 0;
1053
+ char *zPfx;
1054
+
1055
+ if (azAppend[i] && azAppend[i][0] ){
1056
+ zPfx = " +";
1057
+ zValue = azAppend[i];
1058
+ } else if( azValue[i] && azValue[i][0] ){
1059
+ zPfx = " ";
1060
+ zValue = azValue[i];
1061
+ } else {
1062
+ continue;
1063
+ }
1064
+ if( strncmp(azField[i], "private_", 8)==0 ){
1065
+ zValue = db_conceal(zValue, strlen(zValue));
1066
+ blob_appendf(&tktchng, "J%s%s %s\n", zPfx, azField[i], zValue);
1067
+ }else{
1068
+ blob_appendf(&tktchng, "J%s%s %#F\n", zPfx,
1069
+ azField[i], strlen(zValue), zValue);
1070
+ }
1071
+ if( tktEncoding == tktFossilize ){
1072
+ free(azValue[i]);
10561073
}
10571074
}
10581075
blob_appendf(&tktchng, "K %s\n", zTktUuid);
10591076
blob_appendf(&tktchng, "U %F\n", g.zLogin);
10601077
md5sum_blob(&tktchng, &cksum);
@@ -1065,11 +1082,11 @@
10651082
}
10661083
manifest_crosslink_begin();
10671084
manifest_crosslink(rid, &tktchng);
10681085
manifest_crosslink_end();
10691086
assert( blob_is_reset(&tktchng) );
1070
- printf("ticket %s succeeded for UID %s\n",
1071
- (eCmd==set?"set":"add"),zTktUuid);
1087
+ printf("ticket %s succeeded for UID %s\n",
1088
+ (eCmd==set?"set":"add"),zTktUuid);
10721089
}
10731090
}
10741091
}
10751092
}
10761093
--- src/tkt.c
+++ src/tkt.c
@@ -889,10 +889,11 @@
889 ** status, type, severity, priority, resolution,
890 ** foundin, private_contact, resolution, title or comment
891 ** Field names given above are the ones, defined in a standard
892 ** fossil environment. If you have added, deleted columns, you
893 ** change the all your configured columns.
 
894 ** You can use more than one field/value pair on the commandline.
895 ** Using -q|--quote enables the special character decoding as
896 ** in "ticket show". So it's possible, to set multiline text or
897 ** text with special characters.
898 **
@@ -1008,25 +1009,34 @@
1008 /* read commandline and assign fields in the azValue array */
1009 while( i<g.argc ){
1010 char *zFName;
1011 char *zFValue;
1012 int j;
 
1013
1014 zFName = g.argv[i++];
1015 if( i==g.argc ){
1016 fossil_fatal("missing value for '%s'!",zFName);
1017 }
1018 zFValue = g.argv[i++];
1019 j = fieldId(zFName);
1020 if( tktEncoding == tktFossilize ){
1021 zFValue=mprintf("%s",zFValue);
1022 defossilize(zFValue);
1023 }
 
 
 
 
 
1024 if( j == -1 ){
1025 fossil_fatal("unknown field name '%s'!",zFName);
1026 }else{
1027 azValue[j] = zFValue;
 
 
 
 
1028 }
1029 }
1030
1031 /* now add the needed artifacts to the repository */
1032 blob_zero(&tktchng);
@@ -1037,24 +1047,31 @@
1037 blob_appendf(&tktchng, "D %s\n", zDate);
1038 free(zDate);
1039 }
1040 /* append defined elements */
1041 for(i=0; i<nField; i++){
1042 char *zValue;
1043
1044 zValue = azValue[i];
1045 if( azValue[i] && azValue[i][0] ){
1046 if( strncmp(azField[i], "private_", 8)==0 ){
1047 zValue = db_conceal(zValue, strlen(zValue));
1048 blob_appendf(&tktchng, "J %s %s\n", azField[i], zValue);
1049 }else{
1050 blob_appendf(&tktchng, "J %s %#F\n",
1051 azField[i], strlen(zValue), zValue);
1052 }
1053 if( tktEncoding == tktFossilize ){
1054 free(azValue[i]);
1055 }
 
 
 
 
 
 
 
1056 }
1057 }
1058 blob_appendf(&tktchng, "K %s\n", zTktUuid);
1059 blob_appendf(&tktchng, "U %F\n", g.zLogin);
1060 md5sum_blob(&tktchng, &cksum);
@@ -1065,11 +1082,11 @@
1065 }
1066 manifest_crosslink_begin();
1067 manifest_crosslink(rid, &tktchng);
1068 manifest_crosslink_end();
1069 assert( blob_is_reset(&tktchng) );
1070 printf("ticket %s succeeded for UID %s\n",
1071 (eCmd==set?"set":"add"),zTktUuid);
1072 }
1073 }
1074 }
1075 }
1076
--- src/tkt.c
+++ src/tkt.c
@@ -889,10 +889,11 @@
889 ** status, type, severity, priority, resolution,
890 ** foundin, private_contact, resolution, title or comment
891 ** Field names given above are the ones, defined in a standard
892 ** fossil environment. If you have added, deleted columns, you
893 ** change the all your configured columns.
894 ** If you use +FIELD, the VALUE Is appended to the field FIELD.
895 ** You can use more than one field/value pair on the commandline.
896 ** Using -q|--quote enables the special character decoding as
897 ** in "ticket show". So it's possible, to set multiline text or
898 ** text with special characters.
899 **
@@ -1008,25 +1009,34 @@
1009 /* read commandline and assign fields in the azValue array */
1010 while( i<g.argc ){
1011 char *zFName;
1012 char *zFValue;
1013 int j;
1014 int append = 0;
1015
1016 zFName = g.argv[i++];
1017 if( i==g.argc ){
1018 fossil_fatal("missing value for '%s'!",zFName);
1019 }
1020 zFValue = g.argv[i++];
 
1021 if( tktEncoding == tktFossilize ){
1022 zFValue=mprintf("%s",zFValue);
1023 defossilize(zFValue);
1024 }
1025 append = (zFName[0] == '+');
1026 if (append){
1027 zFName++;
1028 }
1029 j = fieldId(zFName);
1030 if( j == -1 ){
1031 fossil_fatal("unknown field name '%s'!",zFName);
1032 }else{
1033 if (append) {
1034 azAppend[j] = zFValue;
1035 } else {
1036 azValue[j] = zFValue;
1037 }
1038 }
1039 }
1040
1041 /* now add the needed artifacts to the repository */
1042 blob_zero(&tktchng);
@@ -1037,24 +1047,31 @@
1047 blob_appendf(&tktchng, "D %s\n", zDate);
1048 free(zDate);
1049 }
1050 /* append defined elements */
1051 for(i=0; i<nField; i++){
1052 char *zValue = 0;
1053 char *zPfx;
1054
1055 if (azAppend[i] && azAppend[i][0] ){
1056 zPfx = " +";
1057 zValue = azAppend[i];
1058 } else if( azValue[i] && azValue[i][0] ){
1059 zPfx = " ";
1060 zValue = azValue[i];
1061 } else {
1062 continue;
1063 }
1064 if( strncmp(azField[i], "private_", 8)==0 ){
1065 zValue = db_conceal(zValue, strlen(zValue));
1066 blob_appendf(&tktchng, "J%s%s %s\n", zPfx, azField[i], zValue);
1067 }else{
1068 blob_appendf(&tktchng, "J%s%s %#F\n", zPfx,
1069 azField[i], strlen(zValue), zValue);
1070 }
1071 if( tktEncoding == tktFossilize ){
1072 free(azValue[i]);
1073 }
1074 }
1075 blob_appendf(&tktchng, "K %s\n", zTktUuid);
1076 blob_appendf(&tktchng, "U %F\n", g.zLogin);
1077 md5sum_blob(&tktchng, &cksum);
@@ -1065,11 +1082,11 @@
1082 }
1083 manifest_crosslink_begin();
1084 manifest_crosslink(rid, &tktchng);
1085 manifest_crosslink_end();
1086 assert( blob_is_reset(&tktchng) );
1087 printf("ticket %s succeeded for UID %s\n",
1088 (eCmd==set?"set":"add"),zTktUuid);
1089 }
1090 }
1091 }
1092 }
1093
+5 -4
--- src/update.c
+++ src/update.c
@@ -327,11 +327,11 @@
327327
int ridv = db_column_int(&q, 2); /* RecordID for current */
328328
int idt = db_column_int(&q, 3); /* VFILE entry for target */
329329
int ridt = db_column_int(&q, 4); /* RecordID for target */
330330
int chnged = db_column_int(&q, 5); /* Current is edited */
331331
const char *zNewName = db_column_text(&q,6);/* New filename */
332
- int isexe = db_column_int(&q, 6); /* EXE perm for new file */
332
+ int isexe = db_column_int(&q, 7); /* EXE perm for new file */
333333
char *zFullPath; /* Full pathname of the file */
334334
char *zFullNewPath; /* Full pathname of dest */
335335
char nameChng; /* True if the name changed */
336336
337337
zFullPath = mprintf("%s%s", g.zLocalRoot, zName);
@@ -432,12 +432,13 @@
432432
*/
433433
if( nConflict && !nochangeFlag ){
434434
if( internalUpdate ){
435435
internalConflictCnt = nConflict;
436436
}else{
437
- fossil_print("WARNING: %d merge conflicts - see messages above for details.\n",
438
- nConflict);
437
+ fossil_print(
438
+ "WARNING: %d merge conflicts - see messages above for details.\n",
439
+ nConflict);
439440
}
440441
}
441442
442443
/*
443444
** Clean up the mid and pid VFILE entries. Then commit the changes.
@@ -447,11 +448,11 @@
447448
}else{
448449
ensure_empty_dirs_created();
449450
if( g.argc<=3 ){
450451
/* All files updated. Shift the current checkout to the target. */
451452
db_multi_exec("DELETE FROM vfile WHERE vid!=%d", tid);
452
- checkout_set_all_exe(vid);
453
+ checkout_set_all_exe(tid);
453454
manifest_to_disk(tid);
454455
db_lset_int("checkout", tid);
455456
}else{
456457
/* A subset of files have been checked out. Keep the current
457458
** checkout unchanged. */
458459
--- src/update.c
+++ src/update.c
@@ -327,11 +327,11 @@
327 int ridv = db_column_int(&q, 2); /* RecordID for current */
328 int idt = db_column_int(&q, 3); /* VFILE entry for target */
329 int ridt = db_column_int(&q, 4); /* RecordID for target */
330 int chnged = db_column_int(&q, 5); /* Current is edited */
331 const char *zNewName = db_column_text(&q,6);/* New filename */
332 int isexe = db_column_int(&q, 6); /* EXE perm for new file */
333 char *zFullPath; /* Full pathname of the file */
334 char *zFullNewPath; /* Full pathname of dest */
335 char nameChng; /* True if the name changed */
336
337 zFullPath = mprintf("%s%s", g.zLocalRoot, zName);
@@ -432,12 +432,13 @@
432 */
433 if( nConflict && !nochangeFlag ){
434 if( internalUpdate ){
435 internalConflictCnt = nConflict;
436 }else{
437 fossil_print("WARNING: %d merge conflicts - see messages above for details.\n",
438 nConflict);
 
439 }
440 }
441
442 /*
443 ** Clean up the mid and pid VFILE entries. Then commit the changes.
@@ -447,11 +448,11 @@
447 }else{
448 ensure_empty_dirs_created();
449 if( g.argc<=3 ){
450 /* All files updated. Shift the current checkout to the target. */
451 db_multi_exec("DELETE FROM vfile WHERE vid!=%d", tid);
452 checkout_set_all_exe(vid);
453 manifest_to_disk(tid);
454 db_lset_int("checkout", tid);
455 }else{
456 /* A subset of files have been checked out. Keep the current
457 ** checkout unchanged. */
458
--- src/update.c
+++ src/update.c
@@ -327,11 +327,11 @@
327 int ridv = db_column_int(&q, 2); /* RecordID for current */
328 int idt = db_column_int(&q, 3); /* VFILE entry for target */
329 int ridt = db_column_int(&q, 4); /* RecordID for target */
330 int chnged = db_column_int(&q, 5); /* Current is edited */
331 const char *zNewName = db_column_text(&q,6);/* New filename */
332 int isexe = db_column_int(&q, 7); /* EXE perm for new file */
333 char *zFullPath; /* Full pathname of the file */
334 char *zFullNewPath; /* Full pathname of dest */
335 char nameChng; /* True if the name changed */
336
337 zFullPath = mprintf("%s%s", g.zLocalRoot, zName);
@@ -432,12 +432,13 @@
432 */
433 if( nConflict && !nochangeFlag ){
434 if( internalUpdate ){
435 internalConflictCnt = nConflict;
436 }else{
437 fossil_print(
438 "WARNING: %d merge conflicts - see messages above for details.\n",
439 nConflict);
440 }
441 }
442
443 /*
444 ** Clean up the mid and pid VFILE entries. Then commit the changes.
@@ -447,11 +448,11 @@
448 }else{
449 ensure_empty_dirs_created();
450 if( g.argc<=3 ){
451 /* All files updated. Shift the current checkout to the target. */
452 db_multi_exec("DELETE FROM vfile WHERE vid!=%d", tid);
453 checkout_set_all_exe(tid);
454 manifest_to_disk(tid);
455 db_lset_int("checkout", tid);
456 }else{
457 /* A subset of files have been checked out. Keep the current
458 ** checkout unchanged. */
459
+5 -4
--- src/update.c
+++ src/update.c
@@ -327,11 +327,11 @@
327327
int ridv = db_column_int(&q, 2); /* RecordID for current */
328328
int idt = db_column_int(&q, 3); /* VFILE entry for target */
329329
int ridt = db_column_int(&q, 4); /* RecordID for target */
330330
int chnged = db_column_int(&q, 5); /* Current is edited */
331331
const char *zNewName = db_column_text(&q,6);/* New filename */
332
- int isexe = db_column_int(&q, 6); /* EXE perm for new file */
332
+ int isexe = db_column_int(&q, 7); /* EXE perm for new file */
333333
char *zFullPath; /* Full pathname of the file */
334334
char *zFullNewPath; /* Full pathname of dest */
335335
char nameChng; /* True if the name changed */
336336
337337
zFullPath = mprintf("%s%s", g.zLocalRoot, zName);
@@ -432,12 +432,13 @@
432432
*/
433433
if( nConflict && !nochangeFlag ){
434434
if( internalUpdate ){
435435
internalConflictCnt = nConflict;
436436
}else{
437
- fossil_print("WARNING: %d merge conflicts - see messages above for details.\n",
438
- nConflict);
437
+ fossil_print(
438
+ "WARNING: %d merge conflicts - see messages above for details.\n",
439
+ nConflict);
439440
}
440441
}
441442
442443
/*
443444
** Clean up the mid and pid VFILE entries. Then commit the changes.
@@ -447,11 +448,11 @@
447448
}else{
448449
ensure_empty_dirs_created();
449450
if( g.argc<=3 ){
450451
/* All files updated. Shift the current checkout to the target. */
451452
db_multi_exec("DELETE FROM vfile WHERE vid!=%d", tid);
452
- checkout_set_all_exe(vid);
453
+ checkout_set_all_exe(tid);
453454
manifest_to_disk(tid);
454455
db_lset_int("checkout", tid);
455456
}else{
456457
/* A subset of files have been checked out. Keep the current
457458
** checkout unchanged. */
458459
--- src/update.c
+++ src/update.c
@@ -327,11 +327,11 @@
327 int ridv = db_column_int(&q, 2); /* RecordID for current */
328 int idt = db_column_int(&q, 3); /* VFILE entry for target */
329 int ridt = db_column_int(&q, 4); /* RecordID for target */
330 int chnged = db_column_int(&q, 5); /* Current is edited */
331 const char *zNewName = db_column_text(&q,6);/* New filename */
332 int isexe = db_column_int(&q, 6); /* EXE perm for new file */
333 char *zFullPath; /* Full pathname of the file */
334 char *zFullNewPath; /* Full pathname of dest */
335 char nameChng; /* True if the name changed */
336
337 zFullPath = mprintf("%s%s", g.zLocalRoot, zName);
@@ -432,12 +432,13 @@
432 */
433 if( nConflict && !nochangeFlag ){
434 if( internalUpdate ){
435 internalConflictCnt = nConflict;
436 }else{
437 fossil_print("WARNING: %d merge conflicts - see messages above for details.\n",
438 nConflict);
 
439 }
440 }
441
442 /*
443 ** Clean up the mid and pid VFILE entries. Then commit the changes.
@@ -447,11 +448,11 @@
447 }else{
448 ensure_empty_dirs_created();
449 if( g.argc<=3 ){
450 /* All files updated. Shift the current checkout to the target. */
451 db_multi_exec("DELETE FROM vfile WHERE vid!=%d", tid);
452 checkout_set_all_exe(vid);
453 manifest_to_disk(tid);
454 db_lset_int("checkout", tid);
455 }else{
456 /* A subset of files have been checked out. Keep the current
457 ** checkout unchanged. */
458
--- src/update.c
+++ src/update.c
@@ -327,11 +327,11 @@
327 int ridv = db_column_int(&q, 2); /* RecordID for current */
328 int idt = db_column_int(&q, 3); /* VFILE entry for target */
329 int ridt = db_column_int(&q, 4); /* RecordID for target */
330 int chnged = db_column_int(&q, 5); /* Current is edited */
331 const char *zNewName = db_column_text(&q,6);/* New filename */
332 int isexe = db_column_int(&q, 7); /* EXE perm for new file */
333 char *zFullPath; /* Full pathname of the file */
334 char *zFullNewPath; /* Full pathname of dest */
335 char nameChng; /* True if the name changed */
336
337 zFullPath = mprintf("%s%s", g.zLocalRoot, zName);
@@ -432,12 +432,13 @@
432 */
433 if( nConflict && !nochangeFlag ){
434 if( internalUpdate ){
435 internalConflictCnt = nConflict;
436 }else{
437 fossil_print(
438 "WARNING: %d merge conflicts - see messages above for details.\n",
439 nConflict);
440 }
441 }
442
443 /*
444 ** Clean up the mid and pid VFILE entries. Then commit the changes.
@@ -447,11 +448,11 @@
448 }else{
449 ensure_empty_dirs_created();
450 if( g.argc<=3 ){
451 /* All files updated. Shift the current checkout to the target. */
452 db_multi_exec("DELETE FROM vfile WHERE vid!=%d", tid);
453 checkout_set_all_exe(tid);
454 manifest_to_disk(tid);
455 db_lset_int("checkout", tid);
456 }else{
457 /* A subset of files have been checked out. Keep the current
458 ** checkout unchanged. */
459
+7 -2
--- src/vfile.c
+++ src/vfile.c
@@ -70,19 +70,24 @@
7070
if( rid==0 && phantomize ){
7171
rid = content_new(zUuid, phantomize-1);
7272
}
7373
return rid;
7474
}
75
+
7576
7677
/*
77
-** Build a catalog of all files in a checkin.
78
+** Load a vfile from a record ID.
7879
*/
79
-void vfile_build(int vid){
80
+void load_vfile_from_rid(int vid){
8081
int rid, size;
8182
Stmt ins, ridq;
8283
Manifest *p;
8384
ManifestFile *pFile;
85
+
86
+ if( db_exists("SELECT 1 FROM vfile WHERE vid=%d", vid) ){
87
+ return;
88
+ }
8489
8590
db_begin_transaction();
8691
p = manifest_get(vid, CFTYPE_MANIFEST);
8792
if( p==0 ) return;
8893
db_multi_exec("DELETE FROM vfile WHERE vid=%d", vid);
8994
--- src/vfile.c
+++ src/vfile.c
@@ -70,19 +70,24 @@
70 if( rid==0 && phantomize ){
71 rid = content_new(zUuid, phantomize-1);
72 }
73 return rid;
74 }
 
75
76 /*
77 ** Build a catalog of all files in a checkin.
78 */
79 void vfile_build(int vid){
80 int rid, size;
81 Stmt ins, ridq;
82 Manifest *p;
83 ManifestFile *pFile;
 
 
 
 
84
85 db_begin_transaction();
86 p = manifest_get(vid, CFTYPE_MANIFEST);
87 if( p==0 ) return;
88 db_multi_exec("DELETE FROM vfile WHERE vid=%d", vid);
89
--- src/vfile.c
+++ src/vfile.c
@@ -70,19 +70,24 @@
70 if( rid==0 && phantomize ){
71 rid = content_new(zUuid, phantomize-1);
72 }
73 return rid;
74 }
75
76
77 /*
78 ** Load a vfile from a record ID.
79 */
80 void load_vfile_from_rid(int vid){
81 int rid, size;
82 Stmt ins, ridq;
83 Manifest *p;
84 ManifestFile *pFile;
85
86 if( db_exists("SELECT 1 FROM vfile WHERE vid=%d", vid) ){
87 return;
88 }
89
90 db_begin_transaction();
91 p = manifest_get(vid, CFTYPE_MANIFEST);
92 if( p==0 ) return;
93 db_multi_exec("DELETE FROM vfile WHERE vid=%d", vid);
94
--- win/Makefile.PellesCGMake
+++ win/Makefile.PellesCGMake
@@ -126,11 +126,11 @@
126126
# compiling standard fossil utils
127127
$(UTILS_OBJ): %.obj: $(SRCDIR)%.c
128128
$(CC) $(CCFLAGS) $(INCLUDE) "$<" -Fo"$@"
129129
130130
# compile special windows utils
131
-version.obj: $(WINDIR)version.c
131
+version.obj: $(SRCDIR)mkversion.c
132132
$(CC) $(CCFLAGS) $(INCLUDE) "$<" -Fo"$@"
133133
134134
# generate the translated c-source files
135135
$(TRANSLATEDSRC): %_.c: $(SRCDIR)%.c translate.exe
136136
translate.exe $< >$@
137137
--- win/Makefile.PellesCGMake
+++ win/Makefile.PellesCGMake
@@ -126,11 +126,11 @@
126 # compiling standard fossil utils
127 $(UTILS_OBJ): %.obj: $(SRCDIR)%.c
128 $(CC) $(CCFLAGS) $(INCLUDE) "$<" -Fo"$@"
129
130 # compile special windows utils
131 version.obj: $(WINDIR)version.c
132 $(CC) $(CCFLAGS) $(INCLUDE) "$<" -Fo"$@"
133
134 # generate the translated c-source files
135 $(TRANSLATEDSRC): %_.c: $(SRCDIR)%.c translate.exe
136 translate.exe $< >$@
137
--- win/Makefile.PellesCGMake
+++ win/Makefile.PellesCGMake
@@ -126,11 +126,11 @@
126 # compiling standard fossil utils
127 $(UTILS_OBJ): %.obj: $(SRCDIR)%.c
128 $(CC) $(CCFLAGS) $(INCLUDE) "$<" -Fo"$@"
129
130 # compile special windows utils
131 version.obj: $(SRCDIR)mkversion.c
132 $(CC) $(CCFLAGS) $(INCLUDE) "$<" -Fo"$@"
133
134 # generate the translated c-source files
135 $(TRANSLATEDSRC): %_.c: $(SRCDIR)%.c translate.exe
136 translate.exe $< >$@
137
--- win/Makefile.dmc
+++ win/Makefile.dmc
@@ -58,11 +58,11 @@
5858
$(BCC) -o$@ $**
5959
6060
mkindex$E: $(SRCDIR)\mkindex.c
6161
$(BCC) -o$@ $**
6262
63
-version$E: $B\win\version.c
63
+version$E: $B\src\mkversion.c
6464
$(BCC) -o$@ $**
6565
6666
$(OBJDIR)\shell$O : $(SRCDIR)\shell.c
6767
$(TCC) -o$@ -c -Dmain=sqlite3_shell $(SQLITE_OPTIONS) $**
6868
6969
--- win/Makefile.dmc
+++ win/Makefile.dmc
@@ -58,11 +58,11 @@
58 $(BCC) -o$@ $**
59
60 mkindex$E: $(SRCDIR)\mkindex.c
61 $(BCC) -o$@ $**
62
63 version$E: $B\win\version.c
64 $(BCC) -o$@ $**
65
66 $(OBJDIR)\shell$O : $(SRCDIR)\shell.c
67 $(TCC) -o$@ -c -Dmain=sqlite3_shell $(SQLITE_OPTIONS) $**
68
69
--- win/Makefile.dmc
+++ win/Makefile.dmc
@@ -58,11 +58,11 @@
58 $(BCC) -o$@ $**
59
60 mkindex$E: $(SRCDIR)\mkindex.c
61 $(BCC) -o$@ $**
62
63 version$E: $B\src\mkversion.c
64 $(BCC) -o$@ $**
65
66 $(OBJDIR)\shell$O : $(SRCDIR)\shell.c
67 $(TCC) -o$@ -c -Dmain=sqlite3_shell $(SQLITE_OPTIONS) $**
68
69
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -351,12 +351,12 @@
351351
$(BCC) -o $(OBJDIR)/makeheaders $(SRCDIR)/makeheaders.c
352352
353353
$(OBJDIR)/mkindex: $(SRCDIR)/mkindex.c
354354
$(BCC) -o $(OBJDIR)/mkindex $(SRCDIR)/mkindex.c
355355
356
-$(VERSION): $(SRCDIR)/../win/version.c
357
- $(BCC) -o $(OBJDIR)/version $(SRCDIR)/../win/version.c
356
+$(VERSION): $(SRCDIR)/mkversion.c
357
+ $(BCC) -o $(OBJDIR)/version $(SRCDIR)/mkversion.c
358358
359359
# WARNING. DANGER. Running the testsuite modifies the repository the
360360
# build is done from, i.e. the checkout belongs to. Do not sync/push
361361
# the repository after running the tests.
362362
test: $(APPNAME)
363363
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -351,12 +351,12 @@
351 $(BCC) -o $(OBJDIR)/makeheaders $(SRCDIR)/makeheaders.c
352
353 $(OBJDIR)/mkindex: $(SRCDIR)/mkindex.c
354 $(BCC) -o $(OBJDIR)/mkindex $(SRCDIR)/mkindex.c
355
356 $(VERSION): $(SRCDIR)/../win/version.c
357 $(BCC) -o $(OBJDIR)/version $(SRCDIR)/../win/version.c
358
359 # WARNING. DANGER. Running the testsuite modifies the repository the
360 # build is done from, i.e. the checkout belongs to. Do not sync/push
361 # the repository after running the tests.
362 test: $(APPNAME)
363
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -351,12 +351,12 @@
351 $(BCC) -o $(OBJDIR)/makeheaders $(SRCDIR)/makeheaders.c
352
353 $(OBJDIR)/mkindex: $(SRCDIR)/mkindex.c
354 $(BCC) -o $(OBJDIR)/mkindex $(SRCDIR)/mkindex.c
355
356 $(VERSION): $(SRCDIR)/mkversion.c
357 $(BCC) -o $(OBJDIR)/version $(SRCDIR)/mkversion.c
358
359 # WARNING. DANGER. Running the testsuite modifies the repository the
360 # build is done from, i.e. the checkout belongs to. Do not sync/push
361 # the repository after running the tests.
362 test: $(APPNAME)
363
+89 -4
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -47,14 +47,99 @@
4747
4848
all: $(OX) $(APPNAME)
4949
5050
$(APPNAME) : translate$E mkindex$E headers $(OBJ) $(OX)\linkopts
5151
cd $(OX)
52
- link -LINK -OUT:$@ $(LIBDIR) @linkopts
52
+ link /NODEFAULTLIB:msvcrt -OUT:$@ $(LIBDIR) @linkopts
5353
5454
$(OX)\linkopts: $B\win\Makefile.msc
55
- echo add allrepo attach bag bisect blob branch browse captcha cgi checkin checkout clearsign clone comformat configure content db delta deltacmd descendants diff diffcmd doc encode event export file finfo glob graph gzip http http_socket http_ssl http_transport import info leaf login main manifest md5 merge merge3 name path pivot popen pqueue printf rebuild report rss schema search setup sha1 shun skins sqlcmd stash stat style sync tag tar th_main timeline tkt tktsetup undo update url user verify vfile wiki wikiformat winhttp xfer zip sqlite3 th th_lang > $@
55
+ echo $(OX)\add.obj > $@
56
+ echo $(OX)\allrepo.obj >> $@
57
+ echo $(OX)\attach.obj >> $@
58
+ echo $(OX)\bag.obj >> $@
59
+ echo $(OX)\bisect.obj >> $@
60
+ echo $(OX)\blob.obj >> $@
61
+ echo $(OX)\branch.obj >> $@
62
+ echo $(OX)\browse.obj >> $@
63
+ echo $(OX)\captcha.obj >> $@
64
+ echo $(OX)\cgi.obj >> $@
65
+ echo $(OX)\checkin.obj >> $@
66
+ echo $(OX)\checkout.obj >> $@
67
+ echo $(OX)\clearsign.obj >> $@
68
+ echo $(OX)\clone.obj >> $@
69
+ echo $(OX)\comformat.obj >> $@
70
+ echo $(OX)\configure.obj >> $@
71
+ echo $(OX)\content.obj >> $@
72
+ echo $(OX)\db.obj >> $@
73
+ echo $(OX)\delta.obj >> $@
74
+ echo $(OX)\deltacmd.obj >> $@
75
+ echo $(OX)\descendants.obj >> $@
76
+ echo $(OX)\diff.obj >> $@
77
+ echo $(OX)\diffcmd.obj >> $@
78
+ echo $(OX)\doc.obj >> $@
79
+ echo $(OX)\encode.obj >> $@
80
+ echo $(OX)\event.obj >> $@
81
+ echo $(OX)\export.obj >> $@
82
+ echo $(OX)\file.obj >> $@
83
+ echo $(OX)\finfo.obj >> $@
84
+ echo $(OX)\glob.obj >> $@
85
+ echo $(OX)\graph.obj >> $@
86
+ echo $(OX)\gzip.obj >> $@
87
+ echo $(OX)\http.obj >> $@
88
+ echo $(OX)\http_socket.obj >> $@
89
+ echo $(OX)\http_ssl.obj >> $@
90
+ echo $(OX)\http_transport.obj >> $@
91
+ echo $(OX)\import.obj >> $@
92
+ echo $(OX)\info.obj >> $@
93
+ echo $(OX)\leaf.obj >> $@
94
+ echo $(OX)\login.obj >> $@
95
+ echo $(OX)\main.obj >> $@
96
+ echo $(OX)\manifest.obj >> $@
97
+ echo $(OX)\md5.obj >> $@
98
+ echo $(OX)\merge.obj >> $@
99
+ echo $(OX)\merge3.obj >> $@
100
+ echo $(OX)\name.obj >> $@
101
+ echo $(OX)\path.obj >> $@
102
+ echo $(OX)\pivot.obj >> $@
103
+ echo $(OX)\popen.obj >> $@
104
+ echo $(OX)\pqueue.obj >> $@
105
+ echo $(OX)\printf.obj >> $@
106
+ echo $(OX)\rebuild.obj >> $@
107
+ echo $(OX)\report.obj >> $@
108
+ echo $(OX)\rss.obj >> $@
109
+ echo $(OX)\schema.obj >> $@
110
+ echo $(OX)\search.obj >> $@
111
+ echo $(OX)\setup.obj >> $@
112
+ echo $(OX)\sha1.obj >> $@
113
+ echo $(OX)\shell.obj >> $@
114
+ echo $(OX)\shun.obj >> $@
115
+ echo $(OX)\skins.obj >> $@
116
+ echo $(OX)\sqlcmd.obj >> $@
117
+ echo $(OX)\sqlite3.obj >> $@
118
+ echo $(OX)\stash.obj >> $@
119
+ echo $(OX)\stat.obj >> $@
120
+ echo $(OX)\style.obj >> $@
121
+ echo $(OX)\sync.obj >> $@
122
+ echo $(OX)\tag.obj >> $@
123
+ echo $(OX)\tar.obj >> $@
124
+ echo $(OX)\th.obj >> $@
125
+ echo $(OX)\th_lang.obj >> $@
126
+ echo $(OX)\th_main.obj >> $@
127
+ echo $(OX)\timeline.obj >> $@
128
+ echo $(OX)\tkt.obj >> $@
129
+ echo $(OX)\tktsetup.obj >> $@
130
+ echo $(OX)\undo.obj >> $@
131
+ echo $(OX)\update.obj >> $@
132
+ echo $(OX)\url.obj >> $@
133
+ echo $(OX)\user.obj >> $@
134
+ echo $(OX)\verify.obj >> $@
135
+ echo $(OX)\vfile.obj >> $@
136
+ echo $(OX)\wiki.obj >> $@
137
+ echo $(OX)\wikiformat.obj >> $@
138
+ echo $(OX)\winhttp.obj >> $@
139
+ echo $(OX)\xfer.obj >> $@
140
+ echo $(OX)\zip.obj >> $@
56141
echo $(LIBS) >> $@
57142
58143
59144
60145
@@ -68,15 +153,15 @@
68153
$(BCC) $**
69154
70155
mkindex$E: $(SRCDIR)\mkindex.c
71156
$(BCC) $**
72157
73
-version$E: $B\win\version.c
158
+version$E: $B\src\mkversion.c
74159
$(BCC) $**
75160
76161
$(OX)\shell$O : $(SRCDIR)\shell.c
77
- $(TCC) /Fo$@ /Dmain=sqlite3_shell $(SQLITE_OPTIONS) -c shell_.c
162
+ $(TCC) /Fo$@ /Dmain=sqlite3_shell $(SQLITE_OPTIONS) -c $(SRCDIR)\shell.c
78163
79164
$(OX)\sqlite3$O : $(SRCDIR)\sqlite3.c
80165
$(TCC) /Fo$@ -c $(SQLITE_OPTIONS) $**
81166
82167
$(OX)\th$O : $(SRCDIR)\th.c
83168
84169
DELETED win/version.c
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -47,14 +47,99 @@
47
48 all: $(OX) $(APPNAME)
49
50 $(APPNAME) : translate$E mkindex$E headers $(OBJ) $(OX)\linkopts
51 cd $(OX)
52 link -LINK -OUT:$@ $(LIBDIR) @linkopts
53
54 $(OX)\linkopts: $B\win\Makefile.msc
55 echo add allrepo attach bag bisect blob branch browse captcha cgi checkin checkout clearsign clone comformat configure content db delta deltacmd descendants diff diffcmd doc encode event export file finfo glob graph gzip http http_socket http_ssl http_transport import info leaf login main manifest md5 merge merge3 name path pivot popen pqueue printf rebuild report rss schema search setup sha1 shun skins sqlcmd stash stat style sync tag tar th_main timeline tkt tktsetup undo update url user verify vfile wiki wikiformat winhttp xfer zip sqlite3 th th_lang > $@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
56 echo $(LIBS) >> $@
57
58
59
60
@@ -68,15 +153,15 @@
68 $(BCC) $**
69
70 mkindex$E: $(SRCDIR)\mkindex.c
71 $(BCC) $**
72
73 version$E: $B\win\version.c
74 $(BCC) $**
75
76 $(OX)\shell$O : $(SRCDIR)\shell.c
77 $(TCC) /Fo$@ /Dmain=sqlite3_shell $(SQLITE_OPTIONS) -c shell_.c
78
79 $(OX)\sqlite3$O : $(SRCDIR)\sqlite3.c
80 $(TCC) /Fo$@ -c $(SQLITE_OPTIONS) $**
81
82 $(OX)\th$O : $(SRCDIR)\th.c
83
84 ELETED win/version.c
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -47,14 +47,99 @@
47
48 all: $(OX) $(APPNAME)
49
50 $(APPNAME) : translate$E mkindex$E headers $(OBJ) $(OX)\linkopts
51 cd $(OX)
52 link /NODEFAULTLIB:msvcrt -OUT:$@ $(LIBDIR) @linkopts
53
54 $(OX)\linkopts: $B\win\Makefile.msc
55 echo $(OX)\add.obj > $@
56 echo $(OX)\allrepo.obj >> $@
57 echo $(OX)\attach.obj >> $@
58 echo $(OX)\bag.obj >> $@
59 echo $(OX)\bisect.obj >> $@
60 echo $(OX)\blob.obj >> $@
61 echo $(OX)\branch.obj >> $@
62 echo $(OX)\browse.obj >> $@
63 echo $(OX)\captcha.obj >> $@
64 echo $(OX)\cgi.obj >> $@
65 echo $(OX)\checkin.obj >> $@
66 echo $(OX)\checkout.obj >> $@
67 echo $(OX)\clearsign.obj >> $@
68 echo $(OX)\clone.obj >> $@
69 echo $(OX)\comformat.obj >> $@
70 echo $(OX)\configure.obj >> $@
71 echo $(OX)\content.obj >> $@
72 echo $(OX)\db.obj >> $@
73 echo $(OX)\delta.obj >> $@
74 echo $(OX)\deltacmd.obj >> $@
75 echo $(OX)\descendants.obj >> $@
76 echo $(OX)\diff.obj >> $@
77 echo $(OX)\diffcmd.obj >> $@
78 echo $(OX)\doc.obj >> $@
79 echo $(OX)\encode.obj >> $@
80 echo $(OX)\event.obj >> $@
81 echo $(OX)\export.obj >> $@
82 echo $(OX)\file.obj >> $@
83 echo $(OX)\finfo.obj >> $@
84 echo $(OX)\glob.obj >> $@
85 echo $(OX)\graph.obj >> $@
86 echo $(OX)\gzip.obj >> $@
87 echo $(OX)\http.obj >> $@
88 echo $(OX)\http_socket.obj >> $@
89 echo $(OX)\http_ssl.obj >> $@
90 echo $(OX)\http_transport.obj >> $@
91 echo $(OX)\import.obj >> $@
92 echo $(OX)\info.obj >> $@
93 echo $(OX)\leaf.obj >> $@
94 echo $(OX)\login.obj >> $@
95 echo $(OX)\main.obj >> $@
96 echo $(OX)\manifest.obj >> $@
97 echo $(OX)\md5.obj >> $@
98 echo $(OX)\merge.obj >> $@
99 echo $(OX)\merge3.obj >> $@
100 echo $(OX)\name.obj >> $@
101 echo $(OX)\path.obj >> $@
102 echo $(OX)\pivot.obj >> $@
103 echo $(OX)\popen.obj >> $@
104 echo $(OX)\pqueue.obj >> $@
105 echo $(OX)\printf.obj >> $@
106 echo $(OX)\rebuild.obj >> $@
107 echo $(OX)\report.obj >> $@
108 echo $(OX)\rss.obj >> $@
109 echo $(OX)\schema.obj >> $@
110 echo $(OX)\search.obj >> $@
111 echo $(OX)\setup.obj >> $@
112 echo $(OX)\sha1.obj >> $@
113 echo $(OX)\shell.obj >> $@
114 echo $(OX)\shun.obj >> $@
115 echo $(OX)\skins.obj >> $@
116 echo $(OX)\sqlcmd.obj >> $@
117 echo $(OX)\sqlite3.obj >> $@
118 echo $(OX)\stash.obj >> $@
119 echo $(OX)\stat.obj >> $@
120 echo $(OX)\style.obj >> $@
121 echo $(OX)\sync.obj >> $@
122 echo $(OX)\tag.obj >> $@
123 echo $(OX)\tar.obj >> $@
124 echo $(OX)\th.obj >> $@
125 echo $(OX)\th_lang.obj >> $@
126 echo $(OX)\th_main.obj >> $@
127 echo $(OX)\timeline.obj >> $@
128 echo $(OX)\tkt.obj >> $@
129 echo $(OX)\tktsetup.obj >> $@
130 echo $(OX)\undo.obj >> $@
131 echo $(OX)\update.obj >> $@
132 echo $(OX)\url.obj >> $@
133 echo $(OX)\user.obj >> $@
134 echo $(OX)\verify.obj >> $@
135 echo $(OX)\vfile.obj >> $@
136 echo $(OX)\wiki.obj >> $@
137 echo $(OX)\wikiformat.obj >> $@
138 echo $(OX)\winhttp.obj >> $@
139 echo $(OX)\xfer.obj >> $@
140 echo $(OX)\zip.obj >> $@
141 echo $(LIBS) >> $@
142
143
144
145
@@ -68,15 +153,15 @@
153 $(BCC) $**
154
155 mkindex$E: $(SRCDIR)\mkindex.c
156 $(BCC) $**
157
158 version$E: $B\src\mkversion.c
159 $(BCC) $**
160
161 $(OX)\shell$O : $(SRCDIR)\shell.c
162 $(TCC) /Fo$@ /Dmain=sqlite3_shell $(SQLITE_OPTIONS) -c $(SRCDIR)\shell.c
163
164 $(OX)\sqlite3$O : $(SRCDIR)\sqlite3.c
165 $(TCC) /Fo$@ -c $(SQLITE_OPTIONS) $**
166
167 $(OX)\th$O : $(SRCDIR)\th.c
168
169 ELETED win/version.c
D win/version.c
-10
--- a/win/version.c
+++ b/win/version.c
@@ -1,10 +0,0 @@
1
-fopen(argv[1],"gv[1],exists to do the job that AWK would do for the unix
2
-** makefile - to extract information from the "mainfest" and "manifest.uuid"
3
-** files for this p)
4
- d = _MSC_VER / 1 return 0;
5
-}
6
-b2b2,0,sizeof(b2)strcpy(b2b2b2vx[1000]return 0;
7
-}
8
-;
9
- char b[1024b[strlen(b)-1] =0; return 0"gv[1],"fMSC_VER)
10
- fopen(argv[1
--- a/win/version.c
+++ b/win/version.c
@@ -1,10 +0,0 @@
1 fopen(argv[1],"gv[1],exists to do the job that AWK would do for the unix
2 ** makefile - to extract information from the "mainfest" and "manifest.uuid"
3 ** files for this p)
4 d = _MSC_VER / 1 return 0;
5 }
6 b2b2,0,sizeof(b2)strcpy(b2b2b2vx[1000]return 0;
7 }
8 ;
9 char b[1024b[strlen(b)-1] =0; return 0"gv[1],"fMSC_VER)
10 fopen(argv[1
--- a/win/version.c
+++ b/win/version.c
@@ -1,10 +0,0 @@
 
 
 
 
 
 
 
 
 
 

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button