OLD | NEW |
1 /* | 1 /* |
2 ** 2006 Oct 10 | 2 ** 2006 Oct 10 |
3 ** | 3 ** |
4 ** The author disclaims copyright to this source code. In place of | 4 ** The author disclaims copyright to this source code. In place of |
5 ** a legal notice, here is a blessing: | 5 ** a legal notice, here is a blessing: |
6 ** | 6 ** |
7 ** May you do good and not evil. | 7 ** May you do good and not evil. |
8 ** May you find forgiveness for yourself and forgive others. | 8 ** May you find forgiveness for yourself and forgive others. |
9 ** May you share freely, never taking more than you give. | 9 ** May you share freely, never taking more than you give. |
10 ** | 10 ** |
(...skipping 295 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
306 #ifndef SQLITE_CORE | 306 #ifndef SQLITE_CORE |
307 # include "sqlite3ext.h" | 307 # include "sqlite3ext.h" |
308 SQLITE_EXTENSION_INIT1 | 308 SQLITE_EXTENSION_INIT1 |
309 #endif | 309 #endif |
310 | 310 |
311 static int fts3EvalNext(Fts3Cursor *pCsr); | 311 static int fts3EvalNext(Fts3Cursor *pCsr); |
312 static int fts3EvalStart(Fts3Cursor *pCsr); | 312 static int fts3EvalStart(Fts3Cursor *pCsr); |
313 static int fts3TermSegReaderCursor( | 313 static int fts3TermSegReaderCursor( |
314 Fts3Cursor *, const char *, int, int, Fts3MultiSegReader **); | 314 Fts3Cursor *, const char *, int, int, Fts3MultiSegReader **); |
315 | 315 |
| 316 #ifndef SQLITE_AMALGAMATION |
| 317 # if defined(SQLITE_DEBUG) |
| 318 int sqlite3Fts3Always(int b) { assert( b ); return b; } |
| 319 int sqlite3Fts3Never(int b) { assert( !b ); return b; } |
| 320 # endif |
| 321 #endif |
| 322 |
316 /* | 323 /* |
317 ** Write a 64-bit variable-length integer to memory starting at p[0]. | 324 ** Write a 64-bit variable-length integer to memory starting at p[0]. |
318 ** The length of data written will be between 1 and FTS3_VARINT_MAX bytes. | 325 ** The length of data written will be between 1 and FTS3_VARINT_MAX bytes. |
319 ** The number of bytes written is returned. | 326 ** The number of bytes written is returned. |
320 */ | 327 */ |
321 int sqlite3Fts3PutVarint(char *p, sqlite_int64 v){ | 328 int sqlite3Fts3PutVarint(char *p, sqlite_int64 v){ |
322 unsigned char *q = (unsigned char *) p; | 329 unsigned char *q = (unsigned char *) p; |
323 sqlite_uint64 vu = v; | 330 sqlite_uint64 vu = v; |
324 do{ | 331 do{ |
325 *q++ = (unsigned char) ((vu & 0x7f) | 0x80); | 332 *q++ = (unsigned char) ((vu & 0x7f) | 0x80); |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
415 char quote; /* Quote character (if any ) */ | 422 char quote; /* Quote character (if any ) */ |
416 | 423 |
417 quote = z[0]; | 424 quote = z[0]; |
418 if( quote=='[' || quote=='\'' || quote=='"' || quote=='`' ){ | 425 if( quote=='[' || quote=='\'' || quote=='"' || quote=='`' ){ |
419 int iIn = 1; /* Index of next byte to read from input */ | 426 int iIn = 1; /* Index of next byte to read from input */ |
420 int iOut = 0; /* Index of next byte to write to output */ | 427 int iOut = 0; /* Index of next byte to write to output */ |
421 | 428 |
422 /* If the first byte was a '[', then the close-quote character is a ']' */ | 429 /* If the first byte was a '[', then the close-quote character is a ']' */ |
423 if( quote=='[' ) quote = ']'; | 430 if( quote=='[' ) quote = ']'; |
424 | 431 |
425 while( ALWAYS(z[iIn]) ){ | 432 while( z[iIn] ){ |
426 if( z[iIn]==quote ){ | 433 if( z[iIn]==quote ){ |
427 if( z[iIn+1]!=quote ) break; | 434 if( z[iIn+1]!=quote ) break; |
428 z[iOut++] = quote; | 435 z[iOut++] = quote; |
429 iIn += 2; | 436 iIn += 2; |
430 }else{ | 437 }else{ |
431 z[iOut++] = z[iIn++]; | 438 z[iOut++] = z[iIn++]; |
432 } | 439 } |
433 } | 440 } |
434 z[iOut] = '\0'; | 441 z[iOut] = '\0'; |
435 } | 442 } |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
495 sqlite3_free(p->zLanguageid); | 502 sqlite3_free(p->zLanguageid); |
496 | 503 |
497 /* Invoke the tokenizer destructor to free the tokenizer. */ | 504 /* Invoke the tokenizer destructor to free the tokenizer. */ |
498 p->pTokenizer->pModule->xDestroy(p->pTokenizer); | 505 p->pTokenizer->pModule->xDestroy(p->pTokenizer); |
499 | 506 |
500 sqlite3_free(p); | 507 sqlite3_free(p); |
501 return SQLITE_OK; | 508 return SQLITE_OK; |
502 } | 509 } |
503 | 510 |
504 /* | 511 /* |
| 512 ** Write an error message into *pzErr |
| 513 */ |
| 514 void sqlite3Fts3ErrMsg(char **pzErr, const char *zFormat, ...){ |
| 515 va_list ap; |
| 516 sqlite3_free(*pzErr); |
| 517 va_start(ap, zFormat); |
| 518 *pzErr = sqlite3_vmprintf(zFormat, ap); |
| 519 va_end(ap); |
| 520 } |
| 521 |
| 522 /* |
505 ** Construct one or more SQL statements from the format string given | 523 ** Construct one or more SQL statements from the format string given |
506 ** and then evaluate those statements. The success code is written | 524 ** and then evaluate those statements. The success code is written |
507 ** into *pRc. | 525 ** into *pRc. |
508 ** | 526 ** |
509 ** If *pRc is initially non-zero then this routine is a no-op. | 527 ** If *pRc is initially non-zero then this routine is a no-op. |
510 */ | 528 */ |
511 static void fts3DbExec( | 529 static void fts3DbExec( |
512 int *pRc, /* Success code */ | 530 int *pRc, /* Success code */ |
513 sqlite3 *db, /* Database in which to run SQL */ | 531 sqlite3 *db, /* Database in which to run SQL */ |
514 const char *zFormat, /* Format string for SQL */ | 532 const char *zFormat, /* Format string for SQL */ |
(...skipping 388 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
903 ** the integer value. | 921 ** the integer value. |
904 ** | 922 ** |
905 ** Only decimal digits ('0'..'9') may be part of an integer value. | 923 ** Only decimal digits ('0'..'9') may be part of an integer value. |
906 ** | 924 ** |
907 ** If *pp does not being with a decimal digit SQLITE_ERROR is returned and | 925 ** If *pp does not being with a decimal digit SQLITE_ERROR is returned and |
908 ** the output value undefined. Otherwise SQLITE_OK is returned. | 926 ** the output value undefined. Otherwise SQLITE_OK is returned. |
909 ** | 927 ** |
910 ** This function is used when parsing the "prefix=" FTS4 parameter. | 928 ** This function is used when parsing the "prefix=" FTS4 parameter. |
911 */ | 929 */ |
912 static int fts3GobbleInt(const char **pp, int *pnOut){ | 930 static int fts3GobbleInt(const char **pp, int *pnOut){ |
| 931 const int MAX_NPREFIX = 10000000; |
913 const char *p; /* Iterator pointer */ | 932 const char *p; /* Iterator pointer */ |
914 int nInt = 0; /* Output value */ | 933 int nInt = 0; /* Output value */ |
915 | 934 |
916 for(p=*pp; p[0]>='0' && p[0]<='9'; p++){ | 935 for(p=*pp; p[0]>='0' && p[0]<='9'; p++){ |
917 nInt = nInt * 10 + (p[0] - '0'); | 936 nInt = nInt * 10 + (p[0] - '0'); |
| 937 if( nInt>MAX_NPREFIX ){ |
| 938 nInt = 0; |
| 939 break; |
| 940 } |
918 } | 941 } |
919 if( p==*pp ) return SQLITE_ERROR; | 942 if( p==*pp ) return SQLITE_ERROR; |
920 *pnOut = nInt; | 943 *pnOut = nInt; |
921 *pp = p; | 944 *pp = p; |
922 return SQLITE_OK; | 945 return SQLITE_OK; |
923 } | 946 } |
924 | 947 |
925 /* | 948 /* |
926 ** This function is called to allocate an array of Fts3Index structures | 949 ** This function is called to allocate an array of Fts3Index structures |
927 ** representing the indexes maintained by the current FTS table. FTS tables | 950 ** representing the indexes maintained by the current FTS table. FTS tables |
(...skipping 22 matching lines...) Expand all Loading... |
950 if( zParam && zParam[0] ){ | 973 if( zParam && zParam[0] ){ |
951 const char *p; | 974 const char *p; |
952 nIndex++; | 975 nIndex++; |
953 for(p=zParam; *p; p++){ | 976 for(p=zParam; *p; p++){ |
954 if( *p==',' ) nIndex++; | 977 if( *p==',' ) nIndex++; |
955 } | 978 } |
956 } | 979 } |
957 | 980 |
958 aIndex = sqlite3_malloc(sizeof(struct Fts3Index) * nIndex); | 981 aIndex = sqlite3_malloc(sizeof(struct Fts3Index) * nIndex); |
959 *apIndex = aIndex; | 982 *apIndex = aIndex; |
960 *pnIndex = nIndex; | |
961 if( !aIndex ){ | 983 if( !aIndex ){ |
962 return SQLITE_NOMEM; | 984 return SQLITE_NOMEM; |
963 } | 985 } |
964 | 986 |
965 memset(aIndex, 0, sizeof(struct Fts3Index) * nIndex); | 987 memset(aIndex, 0, sizeof(struct Fts3Index) * nIndex); |
966 if( zParam ){ | 988 if( zParam ){ |
967 const char *p = zParam; | 989 const char *p = zParam; |
968 int i; | 990 int i; |
969 for(i=1; i<nIndex; i++){ | 991 for(i=1; i<nIndex; i++){ |
970 int nPrefix; | 992 int nPrefix = 0; |
971 if( fts3GobbleInt(&p, &nPrefix) ) return SQLITE_ERROR; | 993 if( fts3GobbleInt(&p, &nPrefix) ) return SQLITE_ERROR; |
972 aIndex[i].nPrefix = nPrefix; | 994 assert( nPrefix>=0 ); |
| 995 if( nPrefix==0 ){ |
| 996 nIndex--; |
| 997 i--; |
| 998 }else{ |
| 999 aIndex[i].nPrefix = nPrefix; |
| 1000 } |
973 p++; | 1001 p++; |
974 } | 1002 } |
975 } | 1003 } |
976 | 1004 |
| 1005 *pnIndex = nIndex; |
977 return SQLITE_OK; | 1006 return SQLITE_OK; |
978 } | 1007 } |
979 | 1008 |
980 /* | 1009 /* |
981 ** This function is called when initializing an FTS4 table that uses the | 1010 ** This function is called when initializing an FTS4 table that uses the |
982 ** content=xxx option. It determines the number of and names of the columns | 1011 ** content=xxx option. It determines the number of and names of the columns |
983 ** of the new FTS4 table. | 1012 ** of the new FTS4 table. |
984 ** | 1013 ** |
985 ** The third argument passed to this function is the value passed to the | 1014 ** The third argument passed to this function is the value passed to the |
986 ** config=xxx option (i.e. "xxx"). This function queries the database for | 1015 ** config=xxx option (i.e. "xxx"). This function queries the database for |
(...skipping 14 matching lines...) Expand all Loading... |
1001 ** If the table cannot be found, an error code is returned and the output | 1030 ** If the table cannot be found, an error code is returned and the output |
1002 ** variables are undefined. Or, if an OOM is encountered, SQLITE_NOMEM is | 1031 ** variables are undefined. Or, if an OOM is encountered, SQLITE_NOMEM is |
1003 ** returned (and the output variables are undefined). | 1032 ** returned (and the output variables are undefined). |
1004 */ | 1033 */ |
1005 static int fts3ContentColumns( | 1034 static int fts3ContentColumns( |
1006 sqlite3 *db, /* Database handle */ | 1035 sqlite3 *db, /* Database handle */ |
1007 const char *zDb, /* Name of db (i.e. "main", "temp" etc.) */ | 1036 const char *zDb, /* Name of db (i.e. "main", "temp" etc.) */ |
1008 const char *zTbl, /* Name of content table */ | 1037 const char *zTbl, /* Name of content table */ |
1009 const char ***pazCol, /* OUT: Malloc'd array of column names */ | 1038 const char ***pazCol, /* OUT: Malloc'd array of column names */ |
1010 int *pnCol, /* OUT: Size of array *pazCol */ | 1039 int *pnCol, /* OUT: Size of array *pazCol */ |
1011 int *pnStr /* OUT: Bytes of string content */ | 1040 int *pnStr, /* OUT: Bytes of string content */ |
| 1041 char **pzErr /* OUT: error message */ |
1012 ){ | 1042 ){ |
1013 int rc = SQLITE_OK; /* Return code */ | 1043 int rc = SQLITE_OK; /* Return code */ |
1014 char *zSql; /* "SELECT *" statement on zTbl */ | 1044 char *zSql; /* "SELECT *" statement on zTbl */ |
1015 sqlite3_stmt *pStmt = 0; /* Compiled version of zSql */ | 1045 sqlite3_stmt *pStmt = 0; /* Compiled version of zSql */ |
1016 | 1046 |
1017 zSql = sqlite3_mprintf("SELECT * FROM %Q.%Q", zDb, zTbl); | 1047 zSql = sqlite3_mprintf("SELECT * FROM %Q.%Q", zDb, zTbl); |
1018 if( !zSql ){ | 1048 if( !zSql ){ |
1019 rc = SQLITE_NOMEM; | 1049 rc = SQLITE_NOMEM; |
1020 }else{ | 1050 }else{ |
1021 rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0); | 1051 rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0); |
| 1052 if( rc!=SQLITE_OK ){ |
| 1053 sqlite3Fts3ErrMsg(pzErr, "%s", sqlite3_errmsg(db)); |
| 1054 } |
1022 } | 1055 } |
1023 sqlite3_free(zSql); | 1056 sqlite3_free(zSql); |
1024 | 1057 |
1025 if( rc==SQLITE_OK ){ | 1058 if( rc==SQLITE_OK ){ |
1026 const char **azCol; /* Output array */ | 1059 const char **azCol; /* Output array */ |
1027 int nStr = 0; /* Size of all column names (incl. 0x00) */ | 1060 int nStr = 0; /* Size of all column names (incl. 0x00) */ |
1028 int nCol; /* Number of table columns */ | 1061 int nCol; /* Number of table columns */ |
1029 int i; /* Used to iterate through columns */ | 1062 int i; /* Used to iterate through columns */ |
1030 | 1063 |
1031 /* Loop through the returned columns. Set nStr to the number of bytes of | 1064 /* Loop through the returned columns. Set nStr to the number of bytes of |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1090 int iCol; /* Column index */ | 1123 int iCol; /* Column index */ |
1091 int nString = 0; /* Bytes required to hold all column names */ | 1124 int nString = 0; /* Bytes required to hold all column names */ |
1092 int nCol = 0; /* Number of columns in the FTS table */ | 1125 int nCol = 0; /* Number of columns in the FTS table */ |
1093 char *zCsr; /* Space for holding column names */ | 1126 char *zCsr; /* Space for holding column names */ |
1094 int nDb; /* Bytes required to hold database name */ | 1127 int nDb; /* Bytes required to hold database name */ |
1095 int nName; /* Bytes required to hold table name */ | 1128 int nName; /* Bytes required to hold table name */ |
1096 int isFts4 = (argv[0][3]=='4'); /* True for FTS4, false for FTS3 */ | 1129 int isFts4 = (argv[0][3]=='4'); /* True for FTS4, false for FTS3 */ |
1097 const char **aCol; /* Array of column names */ | 1130 const char **aCol; /* Array of column names */ |
1098 sqlite3_tokenizer *pTokenizer = 0; /* Tokenizer for this table */ | 1131 sqlite3_tokenizer *pTokenizer = 0; /* Tokenizer for this table */ |
1099 | 1132 |
1100 int nIndex; /* Size of aIndex[] array */ | 1133 int nIndex = 0; /* Size of aIndex[] array */ |
1101 struct Fts3Index *aIndex = 0; /* Array of indexes for this table */ | 1134 struct Fts3Index *aIndex = 0; /* Array of indexes for this table */ |
1102 | 1135 |
1103 /* The results of parsing supported FTS4 key=value options: */ | 1136 /* The results of parsing supported FTS4 key=value options: */ |
1104 int bNoDocsize = 0; /* True to omit %_docsize table */ | 1137 int bNoDocsize = 0; /* True to omit %_docsize table */ |
1105 int bDescIdx = 0; /* True to store descending indexes */ | 1138 int bDescIdx = 0; /* True to store descending indexes */ |
1106 char *zPrefix = 0; /* Prefix parameter value (or NULL) */ | 1139 char *zPrefix = 0; /* Prefix parameter value (or NULL) */ |
1107 char *zCompress = 0; /* compress=? parameter (or NULL) */ | 1140 char *zCompress = 0; /* compress=? parameter (or NULL) */ |
1108 char *zUncompress = 0; /* uncompress=? parameter (or NULL) */ | 1141 char *zUncompress = 0; /* uncompress=? parameter (or NULL) */ |
1109 char *zContent = 0; /* content=? parameter (or NULL) */ | 1142 char *zContent = 0; /* content=? parameter (or NULL) */ |
1110 char *zLanguageid = 0; /* languageid=? parameter (or NULL) */ | 1143 char *zLanguageid = 0; /* languageid=? parameter (or NULL) */ |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1178 if( !zVal ){ | 1211 if( !zVal ){ |
1179 rc = SQLITE_NOMEM; | 1212 rc = SQLITE_NOMEM; |
1180 }else{ | 1213 }else{ |
1181 for(iOpt=0; iOpt<SizeofArray(aFts4Opt); iOpt++){ | 1214 for(iOpt=0; iOpt<SizeofArray(aFts4Opt); iOpt++){ |
1182 struct Fts4Option *pOp = &aFts4Opt[iOpt]; | 1215 struct Fts4Option *pOp = &aFts4Opt[iOpt]; |
1183 if( nKey==pOp->nOpt && !sqlite3_strnicmp(z, pOp->zOpt, pOp->nOpt) ){ | 1216 if( nKey==pOp->nOpt && !sqlite3_strnicmp(z, pOp->zOpt, pOp->nOpt) ){ |
1184 break; | 1217 break; |
1185 } | 1218 } |
1186 } | 1219 } |
1187 if( iOpt==SizeofArray(aFts4Opt) ){ | 1220 if( iOpt==SizeofArray(aFts4Opt) ){ |
1188 *pzErr = sqlite3_mprintf("unrecognized parameter: %s", z); | 1221 sqlite3Fts3ErrMsg(pzErr, "unrecognized parameter: %s", z); |
1189 rc = SQLITE_ERROR; | 1222 rc = SQLITE_ERROR; |
1190 }else{ | 1223 }else{ |
1191 switch( iOpt ){ | 1224 switch( iOpt ){ |
1192 case 0: /* MATCHINFO */ | 1225 case 0: /* MATCHINFO */ |
1193 if( strlen(zVal)!=4 || sqlite3_strnicmp(zVal, "fts3", 4) ){ | 1226 if( strlen(zVal)!=4 || sqlite3_strnicmp(zVal, "fts3", 4) ){ |
1194 *pzErr = sqlite3_mprintf("unrecognized matchinfo: %s", zVal); | 1227 sqlite3Fts3ErrMsg(pzErr, "unrecognized matchinfo: %s", zVal); |
1195 rc = SQLITE_ERROR; | 1228 rc = SQLITE_ERROR; |
1196 } | 1229 } |
1197 bNoDocsize = 1; | 1230 bNoDocsize = 1; |
1198 break; | 1231 break; |
1199 | 1232 |
1200 case 1: /* PREFIX */ | 1233 case 1: /* PREFIX */ |
1201 sqlite3_free(zPrefix); | 1234 sqlite3_free(zPrefix); |
1202 zPrefix = zVal; | 1235 zPrefix = zVal; |
1203 zVal = 0; | 1236 zVal = 0; |
1204 break; | 1237 break; |
1205 | 1238 |
1206 case 2: /* COMPRESS */ | 1239 case 2: /* COMPRESS */ |
1207 sqlite3_free(zCompress); | 1240 sqlite3_free(zCompress); |
1208 zCompress = zVal; | 1241 zCompress = zVal; |
1209 zVal = 0; | 1242 zVal = 0; |
1210 break; | 1243 break; |
1211 | 1244 |
1212 case 3: /* UNCOMPRESS */ | 1245 case 3: /* UNCOMPRESS */ |
1213 sqlite3_free(zUncompress); | 1246 sqlite3_free(zUncompress); |
1214 zUncompress = zVal; | 1247 zUncompress = zVal; |
1215 zVal = 0; | 1248 zVal = 0; |
1216 break; | 1249 break; |
1217 | 1250 |
1218 case 4: /* ORDER */ | 1251 case 4: /* ORDER */ |
1219 if( (strlen(zVal)!=3 || sqlite3_strnicmp(zVal, "asc", 3)) | 1252 if( (strlen(zVal)!=3 || sqlite3_strnicmp(zVal, "asc", 3)) |
1220 && (strlen(zVal)!=4 || sqlite3_strnicmp(zVal, "desc", 4)) | 1253 && (strlen(zVal)!=4 || sqlite3_strnicmp(zVal, "desc", 4)) |
1221 ){ | 1254 ){ |
1222 *pzErr = sqlite3_mprintf("unrecognized order: %s", zVal); | 1255 sqlite3Fts3ErrMsg(pzErr, "unrecognized order: %s", zVal); |
1223 rc = SQLITE_ERROR; | 1256 rc = SQLITE_ERROR; |
1224 } | 1257 } |
1225 bDescIdx = (zVal[0]=='d' || zVal[0]=='D'); | 1258 bDescIdx = (zVal[0]=='d' || zVal[0]=='D'); |
1226 break; | 1259 break; |
1227 | 1260 |
1228 case 5: /* CONTENT */ | 1261 case 5: /* CONTENT */ |
1229 sqlite3_free(zContent); | 1262 sqlite3_free(zContent); |
1230 zContent = zVal; | 1263 zContent = zVal; |
1231 zVal = 0; | 1264 zVal = 0; |
1232 break; | 1265 break; |
(...skipping 30 matching lines...) Expand all Loading... |
1263 ** TABLE statement, use all columns from the content table. | 1296 ** TABLE statement, use all columns from the content table. |
1264 */ | 1297 */ |
1265 if( rc==SQLITE_OK && zContent ){ | 1298 if( rc==SQLITE_OK && zContent ){ |
1266 sqlite3_free(zCompress); | 1299 sqlite3_free(zCompress); |
1267 sqlite3_free(zUncompress); | 1300 sqlite3_free(zUncompress); |
1268 zCompress = 0; | 1301 zCompress = 0; |
1269 zUncompress = 0; | 1302 zUncompress = 0; |
1270 if( nCol==0 ){ | 1303 if( nCol==0 ){ |
1271 sqlite3_free((void*)aCol); | 1304 sqlite3_free((void*)aCol); |
1272 aCol = 0; | 1305 aCol = 0; |
1273 rc = fts3ContentColumns(db, argv[1], zContent, &aCol, &nCol, &nString); | 1306 rc = fts3ContentColumns(db, argv[1], zContent,&aCol,&nCol,&nString,pzErr); |
1274 | 1307 |
1275 /* If a languageid= option was specified, remove the language id | 1308 /* If a languageid= option was specified, remove the language id |
1276 ** column from the aCol[] array. */ | 1309 ** column from the aCol[] array. */ |
1277 if( rc==SQLITE_OK && zLanguageid ){ | 1310 if( rc==SQLITE_OK && zLanguageid ){ |
1278 int j; | 1311 int j; |
1279 for(j=0; j<nCol; j++){ | 1312 for(j=0; j<nCol; j++){ |
1280 if( sqlite3_stricmp(zLanguageid, aCol[j])==0 ){ | 1313 if( sqlite3_stricmp(zLanguageid, aCol[j])==0 ){ |
1281 int k; | 1314 int k; |
1282 for(k=j; k<nCol; k++) aCol[k] = aCol[k+1]; | 1315 for(k=j; k<nCol; k++) aCol[k] = aCol[k+1]; |
1283 nCol--; | 1316 nCol--; |
(...skipping 14 matching lines...) Expand all Loading... |
1298 | 1331 |
1299 if( pTokenizer==0 ){ | 1332 if( pTokenizer==0 ){ |
1300 rc = sqlite3Fts3InitTokenizer(pHash, "simple", &pTokenizer, pzErr); | 1333 rc = sqlite3Fts3InitTokenizer(pHash, "simple", &pTokenizer, pzErr); |
1301 if( rc!=SQLITE_OK ) goto fts3_init_out; | 1334 if( rc!=SQLITE_OK ) goto fts3_init_out; |
1302 } | 1335 } |
1303 assert( pTokenizer ); | 1336 assert( pTokenizer ); |
1304 | 1337 |
1305 rc = fts3PrefixParameter(zPrefix, &nIndex, &aIndex); | 1338 rc = fts3PrefixParameter(zPrefix, &nIndex, &aIndex); |
1306 if( rc==SQLITE_ERROR ){ | 1339 if( rc==SQLITE_ERROR ){ |
1307 assert( zPrefix ); | 1340 assert( zPrefix ); |
1308 *pzErr = sqlite3_mprintf("error parsing prefix parameter: %s", zPrefix); | 1341 sqlite3Fts3ErrMsg(pzErr, "error parsing prefix parameter: %s", zPrefix); |
1309 } | 1342 } |
1310 if( rc!=SQLITE_OK ) goto fts3_init_out; | 1343 if( rc!=SQLITE_OK ) goto fts3_init_out; |
1311 | 1344 |
1312 /* Allocate and populate the Fts3Table structure. */ | 1345 /* Allocate and populate the Fts3Table structure. */ |
1313 nByte = sizeof(Fts3Table) + /* Fts3Table */ | 1346 nByte = sizeof(Fts3Table) + /* Fts3Table */ |
1314 nCol * sizeof(char *) + /* azColumn */ | 1347 nCol * sizeof(char *) + /* azColumn */ |
1315 nIndex * sizeof(struct Fts3Index) + /* aIndex */ | 1348 nIndex * sizeof(struct Fts3Index) + /* aIndex */ |
1316 nCol * sizeof(u8) + /* abNotindexed */ | 1349 nCol * sizeof(u8) + /* abNotindexed */ |
1317 nName + /* zName */ | 1350 nName + /* zName */ |
1318 nDb + /* zDb */ | 1351 nDb + /* zDb */ |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1380 && 0==sqlite3_strnicmp(p->azColumn[iCol], zNot, n) | 1413 && 0==sqlite3_strnicmp(p->azColumn[iCol], zNot, n) |
1381 ){ | 1414 ){ |
1382 p->abNotindexed[iCol] = 1; | 1415 p->abNotindexed[iCol] = 1; |
1383 sqlite3_free(zNot); | 1416 sqlite3_free(zNot); |
1384 azNotindexed[i] = 0; | 1417 azNotindexed[i] = 0; |
1385 } | 1418 } |
1386 } | 1419 } |
1387 } | 1420 } |
1388 for(i=0; i<nNotindexed; i++){ | 1421 for(i=0; i<nNotindexed; i++){ |
1389 if( azNotindexed[i] ){ | 1422 if( azNotindexed[i] ){ |
1390 *pzErr = sqlite3_mprintf("no such column: %s", azNotindexed[i]); | 1423 sqlite3Fts3ErrMsg(pzErr, "no such column: %s", azNotindexed[i]); |
1391 rc = SQLITE_ERROR; | 1424 rc = SQLITE_ERROR; |
1392 } | 1425 } |
1393 } | 1426 } |
1394 | 1427 |
1395 if( rc==SQLITE_OK && (zCompress==0)!=(zUncompress==0) ){ | 1428 if( rc==SQLITE_OK && (zCompress==0)!=(zUncompress==0) ){ |
1396 char const *zMiss = (zCompress==0 ? "compress" : "uncompress"); | 1429 char const *zMiss = (zCompress==0 ? "compress" : "uncompress"); |
1397 rc = SQLITE_ERROR; | 1430 rc = SQLITE_ERROR; |
1398 *pzErr = sqlite3_mprintf("missing %s parameter in fts4 constructor", zMiss); | 1431 sqlite3Fts3ErrMsg(pzErr, "missing %s parameter in fts4 constructor", zMiss); |
1399 } | 1432 } |
1400 p->zReadExprlist = fts3ReadExprList(p, zUncompress, &rc); | 1433 p->zReadExprlist = fts3ReadExprList(p, zUncompress, &rc); |
1401 p->zWriteExprlist = fts3WriteExprList(p, zCompress, &rc); | 1434 p->zWriteExprlist = fts3WriteExprList(p, zCompress, &rc); |
1402 if( rc!=SQLITE_OK ) goto fts3_init_out; | 1435 if( rc!=SQLITE_OK ) goto fts3_init_out; |
1403 | 1436 |
1404 /* If this is an xCreate call, create the underlying tables in the | 1437 /* If this is an xCreate call, create the underlying tables in the |
1405 ** database. TODO: For xConnect(), it could verify that said tables exist. | 1438 ** database. TODO: For xConnect(), it could verify that said tables exist. |
1406 */ | 1439 */ |
1407 if( isCreate ){ | 1440 if( isCreate ){ |
1408 rc = fts3CreateTables(p); | 1441 rc = fts3CreateTables(p); |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1477 ** support estimatedRows. In that case this function is a no-op. | 1510 ** support estimatedRows. In that case this function is a no-op. |
1478 */ | 1511 */ |
1479 static void fts3SetEstimatedRows(sqlite3_index_info *pIdxInfo, i64 nRow){ | 1512 static void fts3SetEstimatedRows(sqlite3_index_info *pIdxInfo, i64 nRow){ |
1480 #if SQLITE_VERSION_NUMBER>=3008002 | 1513 #if SQLITE_VERSION_NUMBER>=3008002 |
1481 if( sqlite3_libversion_number()>=3008002 ){ | 1514 if( sqlite3_libversion_number()>=3008002 ){ |
1482 pIdxInfo->estimatedRows = nRow; | 1515 pIdxInfo->estimatedRows = nRow; |
1483 } | 1516 } |
1484 #endif | 1517 #endif |
1485 } | 1518 } |
1486 | 1519 |
| 1520 /* |
| 1521 ** Set the SQLITE_INDEX_SCAN_UNIQUE flag in pIdxInfo->flags. Unless this |
| 1522 ** extension is currently being used by a version of SQLite too old to |
| 1523 ** support index-info flags. In that case this function is a no-op. |
| 1524 */ |
| 1525 static void fts3SetUniqueFlag(sqlite3_index_info *pIdxInfo){ |
| 1526 #if SQLITE_VERSION_NUMBER>=3008012 |
| 1527 if( sqlite3_libversion_number()>=3008012 ){ |
| 1528 pIdxInfo->idxFlags |= SQLITE_INDEX_SCAN_UNIQUE; |
| 1529 } |
| 1530 #endif |
| 1531 } |
| 1532 |
1487 /* | 1533 /* |
1488 ** Implementation of the xBestIndex method for FTS3 tables. There | 1534 ** Implementation of the xBestIndex method for FTS3 tables. There |
1489 ** are three possible strategies, in order of preference: | 1535 ** are three possible strategies, in order of preference: |
1490 ** | 1536 ** |
1491 ** 1. Direct lookup by rowid or docid. | 1537 ** 1. Direct lookup by rowid or docid. |
1492 ** 2. Full-text search using a MATCH operator on a non-docid column. | 1538 ** 2. Full-text search using a MATCH operator on a non-docid column. |
1493 ** 3. Linear scan of %_content table. | 1539 ** 3. Linear scan of %_content table. |
1494 */ | 1540 */ |
1495 static int fts3BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){ | 1541 static int fts3BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){ |
1496 Fts3Table *p = (Fts3Table *)pVTab; | 1542 Fts3Table *p = (Fts3Table *)pVTab; |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1567 break; | 1613 break; |
1568 | 1614 |
1569 case SQLITE_INDEX_CONSTRAINT_LE: | 1615 case SQLITE_INDEX_CONSTRAINT_LE: |
1570 case SQLITE_INDEX_CONSTRAINT_LT: | 1616 case SQLITE_INDEX_CONSTRAINT_LT: |
1571 iDocidLe = i; | 1617 iDocidLe = i; |
1572 break; | 1618 break; |
1573 } | 1619 } |
1574 } | 1620 } |
1575 } | 1621 } |
1576 | 1622 |
| 1623 /* If using a docid=? or rowid=? strategy, set the UNIQUE flag. */ |
| 1624 if( pInfo->idxNum==FTS3_DOCID_SEARCH ) fts3SetUniqueFlag(pInfo); |
| 1625 |
1577 iIdx = 1; | 1626 iIdx = 1; |
1578 if( iCons>=0 ){ | 1627 if( iCons>=0 ){ |
1579 pInfo->aConstraintUsage[iCons].argvIndex = iIdx++; | 1628 pInfo->aConstraintUsage[iCons].argvIndex = iIdx++; |
1580 pInfo->aConstraintUsage[iCons].omit = 1; | 1629 pInfo->aConstraintUsage[iCons].omit = 1; |
1581 } | 1630 } |
1582 if( iLangidCons>=0 ){ | 1631 if( iLangidCons>=0 ){ |
1583 pInfo->idxNum |= FTS3_HAVE_LANGID; | 1632 pInfo->idxNum |= FTS3_HAVE_LANGID; |
1584 pInfo->aConstraintUsage[iLangidCons].argvIndex = iIdx++; | 1633 pInfo->aConstraintUsage[iLangidCons].argvIndex = iIdx++; |
1585 } | 1634 } |
1586 if( iDocidGe>=0 ){ | 1635 if( iDocidGe>=0 ){ |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1635 ** Close the cursor. For additional information see the documentation | 1684 ** Close the cursor. For additional information see the documentation |
1636 ** on the xClose method of the virtual table interface. | 1685 ** on the xClose method of the virtual table interface. |
1637 */ | 1686 */ |
1638 static int fts3CloseMethod(sqlite3_vtab_cursor *pCursor){ | 1687 static int fts3CloseMethod(sqlite3_vtab_cursor *pCursor){ |
1639 Fts3Cursor *pCsr = (Fts3Cursor *)pCursor; | 1688 Fts3Cursor *pCsr = (Fts3Cursor *)pCursor; |
1640 assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 ); | 1689 assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 ); |
1641 sqlite3_finalize(pCsr->pStmt); | 1690 sqlite3_finalize(pCsr->pStmt); |
1642 sqlite3Fts3ExprFree(pCsr->pExpr); | 1691 sqlite3Fts3ExprFree(pCsr->pExpr); |
1643 sqlite3Fts3FreeDeferredTokens(pCsr); | 1692 sqlite3Fts3FreeDeferredTokens(pCsr); |
1644 sqlite3_free(pCsr->aDoclist); | 1693 sqlite3_free(pCsr->aDoclist); |
1645 sqlite3_free(pCsr->aMatchinfo); | 1694 sqlite3Fts3MIBufferFree(pCsr->pMIBuffer); |
1646 assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 ); | 1695 assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 ); |
1647 sqlite3_free(pCsr); | 1696 sqlite3_free(pCsr); |
1648 return SQLITE_OK; | 1697 return SQLITE_OK; |
1649 } | 1698 } |
1650 | 1699 |
1651 /* | 1700 /* |
1652 ** If pCsr->pStmt has not been prepared (i.e. if pCsr->pStmt==0), then | 1701 ** If pCsr->pStmt has not been prepared (i.e. if pCsr->pStmt==0), then |
1653 ** compose and prepare an SQL statement of the form: | 1702 ** compose and prepare an SQL statement of the form: |
1654 ** | 1703 ** |
1655 ** "SELECT <columns> FROM %_content WHERE rowid = ?" | 1704 ** "SELECT <columns> FROM %_content WHERE rowid = ?" |
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1846 */ | 1895 */ |
1847 static int fts3SelectLeaf( | 1896 static int fts3SelectLeaf( |
1848 Fts3Table *p, /* Virtual table handle */ | 1897 Fts3Table *p, /* Virtual table handle */ |
1849 const char *zTerm, /* Term to select leaves for */ | 1898 const char *zTerm, /* Term to select leaves for */ |
1850 int nTerm, /* Size of term zTerm in bytes */ | 1899 int nTerm, /* Size of term zTerm in bytes */ |
1851 const char *zNode, /* Buffer containing segment interior node */ | 1900 const char *zNode, /* Buffer containing segment interior node */ |
1852 int nNode, /* Size of buffer at zNode */ | 1901 int nNode, /* Size of buffer at zNode */ |
1853 sqlite3_int64 *piLeaf, /* Selected leaf node */ | 1902 sqlite3_int64 *piLeaf, /* Selected leaf node */ |
1854 sqlite3_int64 *piLeaf2 /* Selected leaf node */ | 1903 sqlite3_int64 *piLeaf2 /* Selected leaf node */ |
1855 ){ | 1904 ){ |
1856 int rc; /* Return code */ | 1905 int rc = SQLITE_OK; /* Return code */ |
1857 int iHeight; /* Height of this node in tree */ | 1906 int iHeight; /* Height of this node in tree */ |
1858 | 1907 |
1859 assert( piLeaf || piLeaf2 ); | 1908 assert( piLeaf || piLeaf2 ); |
1860 | 1909 |
1861 fts3GetVarint32(zNode, &iHeight); | 1910 fts3GetVarint32(zNode, &iHeight); |
1862 rc = fts3ScanInteriorNode(zTerm, nTerm, zNode, nNode, piLeaf, piLeaf2); | 1911 rc = fts3ScanInteriorNode(zTerm, nTerm, zNode, nNode, piLeaf, piLeaf2); |
1863 assert( !piLeaf2 || !piLeaf || rc!=SQLITE_OK || (*piLeaf<=*piLeaf2) ); | 1912 assert( !piLeaf2 || !piLeaf || rc!=SQLITE_OK || (*piLeaf<=*piLeaf2) ); |
1864 | 1913 |
1865 if( rc==SQLITE_OK && iHeight>1 ){ | 1914 if( rc==SQLITE_OK && iHeight>1 ){ |
1866 char *zBlob = 0; /* Blob read from %_segments table */ | 1915 char *zBlob = 0; /* Blob read from %_segments table */ |
1867 int nBlob; /* Size of zBlob in bytes */ | 1916 int nBlob = 0; /* Size of zBlob in bytes */ |
1868 | 1917 |
1869 if( piLeaf && piLeaf2 && (*piLeaf!=*piLeaf2) ){ | 1918 if( piLeaf && piLeaf2 && (*piLeaf!=*piLeaf2) ){ |
1870 rc = sqlite3Fts3ReadBlock(p, *piLeaf, &zBlob, &nBlob, 0); | 1919 rc = sqlite3Fts3ReadBlock(p, *piLeaf, &zBlob, &nBlob, 0); |
1871 if( rc==SQLITE_OK ){ | 1920 if( rc==SQLITE_OK ){ |
1872 rc = fts3SelectLeaf(p, zTerm, nTerm, zBlob, nBlob, piLeaf, 0); | 1921 rc = fts3SelectLeaf(p, zTerm, nTerm, zBlob, nBlob, piLeaf, 0); |
1873 } | 1922 } |
1874 sqlite3_free(zBlob); | 1923 sqlite3_free(zBlob); |
1875 piLeaf = 0; | 1924 piLeaf = 0; |
1876 zBlob = 0; | 1925 zBlob = 0; |
1877 } | 1926 } |
(...skipping 606 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2484 ** the output contains a copy of each position from the right-hand input | 2533 ** the output contains a copy of each position from the right-hand input |
2485 ** doclist for which there is a position in the left-hand input doclist | 2534 ** doclist for which there is a position in the left-hand input doclist |
2486 ** exactly nDist tokens before it. | 2535 ** exactly nDist tokens before it. |
2487 ** | 2536 ** |
2488 ** If the docids in the input doclists are sorted in ascending order, | 2537 ** If the docids in the input doclists are sorted in ascending order, |
2489 ** parameter bDescDoclist should be false. If they are sorted in ascending | 2538 ** parameter bDescDoclist should be false. If they are sorted in ascending |
2490 ** order, it should be passed a non-zero value. | 2539 ** order, it should be passed a non-zero value. |
2491 ** | 2540 ** |
2492 ** The right-hand input doclist is overwritten by this function. | 2541 ** The right-hand input doclist is overwritten by this function. |
2493 */ | 2542 */ |
2494 static void fts3DoclistPhraseMerge( | 2543 static int fts3DoclistPhraseMerge( |
2495 int bDescDoclist, /* True if arguments are desc */ | 2544 int bDescDoclist, /* True if arguments are desc */ |
2496 int nDist, /* Distance from left to right (1=adjacent) */ | 2545 int nDist, /* Distance from left to right (1=adjacent) */ |
2497 char *aLeft, int nLeft, /* Left doclist */ | 2546 char *aLeft, int nLeft, /* Left doclist */ |
2498 char *aRight, int *pnRight /* IN/OUT: Right/output doclist */ | 2547 char **paRight, int *pnRight /* IN/OUT: Right/output doclist */ |
2499 ){ | 2548 ){ |
2500 sqlite3_int64 i1 = 0; | 2549 sqlite3_int64 i1 = 0; |
2501 sqlite3_int64 i2 = 0; | 2550 sqlite3_int64 i2 = 0; |
2502 sqlite3_int64 iPrev = 0; | 2551 sqlite3_int64 iPrev = 0; |
| 2552 char *aRight = *paRight; |
2503 char *pEnd1 = &aLeft[nLeft]; | 2553 char *pEnd1 = &aLeft[nLeft]; |
2504 char *pEnd2 = &aRight[*pnRight]; | 2554 char *pEnd2 = &aRight[*pnRight]; |
2505 char *p1 = aLeft; | 2555 char *p1 = aLeft; |
2506 char *p2 = aRight; | 2556 char *p2 = aRight; |
2507 char *p; | 2557 char *p; |
2508 int bFirstOut = 0; | 2558 int bFirstOut = 0; |
2509 char *aOut = aRight; | 2559 char *aOut; |
2510 | 2560 |
2511 assert( nDist>0 ); | 2561 assert( nDist>0 ); |
| 2562 if( bDescDoclist ){ |
| 2563 aOut = sqlite3_malloc(*pnRight + FTS3_VARINT_MAX); |
| 2564 if( aOut==0 ) return SQLITE_NOMEM; |
| 2565 }else{ |
| 2566 aOut = aRight; |
| 2567 } |
| 2568 p = aOut; |
2512 | 2569 |
2513 p = aOut; | |
2514 fts3GetDeltaVarint3(&p1, pEnd1, 0, &i1); | 2570 fts3GetDeltaVarint3(&p1, pEnd1, 0, &i1); |
2515 fts3GetDeltaVarint3(&p2, pEnd2, 0, &i2); | 2571 fts3GetDeltaVarint3(&p2, pEnd2, 0, &i2); |
2516 | 2572 |
2517 while( p1 && p2 ){ | 2573 while( p1 && p2 ){ |
2518 sqlite3_int64 iDiff = DOCID_CMP(i1, i2); | 2574 sqlite3_int64 iDiff = DOCID_CMP(i1, i2); |
2519 if( iDiff==0 ){ | 2575 if( iDiff==0 ){ |
2520 char *pSave = p; | 2576 char *pSave = p; |
2521 sqlite3_int64 iPrevSave = iPrev; | 2577 sqlite3_int64 iPrevSave = iPrev; |
2522 int bFirstOutSave = bFirstOut; | 2578 int bFirstOutSave = bFirstOut; |
2523 | 2579 |
2524 fts3PutDeltaVarint3(&p, bDescDoclist, &iPrev, &bFirstOut, i1); | 2580 fts3PutDeltaVarint3(&p, bDescDoclist, &iPrev, &bFirstOut, i1); |
2525 if( 0==fts3PoslistPhraseMerge(&p, nDist, 0, 1, &p1, &p2) ){ | 2581 if( 0==fts3PoslistPhraseMerge(&p, nDist, 0, 1, &p1, &p2) ){ |
2526 p = pSave; | 2582 p = pSave; |
2527 iPrev = iPrevSave; | 2583 iPrev = iPrevSave; |
2528 bFirstOut = bFirstOutSave; | 2584 bFirstOut = bFirstOutSave; |
2529 } | 2585 } |
2530 fts3GetDeltaVarint3(&p1, pEnd1, bDescDoclist, &i1); | 2586 fts3GetDeltaVarint3(&p1, pEnd1, bDescDoclist, &i1); |
2531 fts3GetDeltaVarint3(&p2, pEnd2, bDescDoclist, &i2); | 2587 fts3GetDeltaVarint3(&p2, pEnd2, bDescDoclist, &i2); |
2532 }else if( iDiff<0 ){ | 2588 }else if( iDiff<0 ){ |
2533 fts3PoslistCopy(0, &p1); | 2589 fts3PoslistCopy(0, &p1); |
2534 fts3GetDeltaVarint3(&p1, pEnd1, bDescDoclist, &i1); | 2590 fts3GetDeltaVarint3(&p1, pEnd1, bDescDoclist, &i1); |
2535 }else{ | 2591 }else{ |
2536 fts3PoslistCopy(0, &p2); | 2592 fts3PoslistCopy(0, &p2); |
2537 fts3GetDeltaVarint3(&p2, pEnd2, bDescDoclist, &i2); | 2593 fts3GetDeltaVarint3(&p2, pEnd2, bDescDoclist, &i2); |
2538 } | 2594 } |
2539 } | 2595 } |
2540 | 2596 |
2541 *pnRight = (int)(p - aOut); | 2597 *pnRight = (int)(p - aOut); |
| 2598 if( bDescDoclist ){ |
| 2599 sqlite3_free(aRight); |
| 2600 *paRight = aOut; |
| 2601 } |
| 2602 |
| 2603 return SQLITE_OK; |
2542 } | 2604 } |
2543 | 2605 |
2544 /* | 2606 /* |
2545 ** Argument pList points to a position list nList bytes in size. This | 2607 ** Argument pList points to a position list nList bytes in size. This |
2546 ** function checks to see if the position list contains any entries for | 2608 ** function checks to see if the position list contains any entries for |
2547 ** a token in position 0 (of any column). If so, it writes argument iDelta | 2609 ** a token in position 0 (of any column). If so, it writes argument iDelta |
2548 ** to the output buffer pOut, followed by a position list consisting only | 2610 ** to the output buffer pOut, followed by a position list consisting only |
2549 ** of the entries from pList at position 0, and terminated by an 0x00 byte. | 2611 ** of the entries from pList at position 0, and terminated by an 0x00 byte. |
2550 ** The value returned is the number of bytes written to pOut (if any). | 2612 ** The value returned is the number of bytes written to pOut (if any). |
2551 */ | 2613 */ |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2656 ** SQLite error code (SQLITE_NOMEM) if an error occurs. | 2718 ** SQLite error code (SQLITE_NOMEM) if an error occurs. |
2657 */ | 2719 */ |
2658 static int fts3TermSelectMerge( | 2720 static int fts3TermSelectMerge( |
2659 Fts3Table *p, /* FTS table handle */ | 2721 Fts3Table *p, /* FTS table handle */ |
2660 TermSelect *pTS, /* TermSelect object to merge into */ | 2722 TermSelect *pTS, /* TermSelect object to merge into */ |
2661 char *aDoclist, /* Pointer to doclist */ | 2723 char *aDoclist, /* Pointer to doclist */ |
2662 int nDoclist /* Size of aDoclist in bytes */ | 2724 int nDoclist /* Size of aDoclist in bytes */ |
2663 ){ | 2725 ){ |
2664 if( pTS->aaOutput[0]==0 ){ | 2726 if( pTS->aaOutput[0]==0 ){ |
2665 /* If this is the first term selected, copy the doclist to the output | 2727 /* If this is the first term selected, copy the doclist to the output |
2666 ** buffer using memcpy(). */ | 2728 ** buffer using memcpy(). |
2667 pTS->aaOutput[0] = sqlite3_malloc(nDoclist); | 2729 ** |
| 2730 ** Add FTS3_VARINT_MAX bytes of unused space to the end of the |
| 2731 ** allocation. This is so as to ensure that the buffer is big enough |
| 2732 ** to hold the current doclist AND'd with any other doclist. If the |
| 2733 ** doclists are stored in order=ASC order, this padding would not be |
| 2734 ** required (since the size of [doclistA AND doclistB] is always less |
| 2735 ** than or equal to the size of [doclistA] in that case). But this is |
| 2736 ** not true for order=DESC. For example, a doclist containing (1, -1) |
| 2737 ** may be smaller than (-1), as in the first example the -1 may be stored |
| 2738 ** as a single-byte delta, whereas in the second it must be stored as a |
| 2739 ** FTS3_VARINT_MAX byte varint. |
| 2740 ** |
| 2741 ** Similar padding is added in the fts3DoclistOrMerge() function. |
| 2742 */ |
| 2743 pTS->aaOutput[0] = sqlite3_malloc(nDoclist + FTS3_VARINT_MAX + 1); |
2668 pTS->anOutput[0] = nDoclist; | 2744 pTS->anOutput[0] = nDoclist; |
2669 if( pTS->aaOutput[0] ){ | 2745 if( pTS->aaOutput[0] ){ |
2670 memcpy(pTS->aaOutput[0], aDoclist, nDoclist); | 2746 memcpy(pTS->aaOutput[0], aDoclist, nDoclist); |
2671 }else{ | 2747 }else{ |
2672 return SQLITE_NOMEM; | 2748 return SQLITE_NOMEM; |
2673 } | 2749 } |
2674 }else{ | 2750 }else{ |
2675 char *aMerge = aDoclist; | 2751 char *aMerge = aDoclist; |
2676 int nMerge = nDoclist; | 2752 int nMerge = nDoclist; |
2677 int iOut; | 2753 int iOut; |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2754 int rc2; /* Result of sqlite3_reset() */ | 2830 int rc2; /* Result of sqlite3_reset() */ |
2755 | 2831 |
2756 /* If iLevel is less than 0 and this is not a scan, include a seg-reader | 2832 /* If iLevel is less than 0 and this is not a scan, include a seg-reader |
2757 ** for the pending-terms. If this is a scan, then this call must be being | 2833 ** for the pending-terms. If this is a scan, then this call must be being |
2758 ** made by an fts4aux module, not an FTS table. In this case calling | 2834 ** made by an fts4aux module, not an FTS table. In this case calling |
2759 ** Fts3SegReaderPending might segfault, as the data structures used by | 2835 ** Fts3SegReaderPending might segfault, as the data structures used by |
2760 ** fts4aux are not completely populated. So it's easiest to filter these | 2836 ** fts4aux are not completely populated. So it's easiest to filter these |
2761 ** calls out here. */ | 2837 ** calls out here. */ |
2762 if( iLevel<0 && p->aIndex ){ | 2838 if( iLevel<0 && p->aIndex ){ |
2763 Fts3SegReader *pSeg = 0; | 2839 Fts3SegReader *pSeg = 0; |
2764 rc = sqlite3Fts3SegReaderPending(p, iIndex, zTerm, nTerm, isPrefix, &pSeg); | 2840 rc = sqlite3Fts3SegReaderPending(p, iIndex, zTerm, nTerm, isPrefix||isScan,
&pSeg); |
2765 if( rc==SQLITE_OK && pSeg ){ | 2841 if( rc==SQLITE_OK && pSeg ){ |
2766 rc = fts3SegReaderCursorAppend(pCsr, pSeg); | 2842 rc = fts3SegReaderCursorAppend(pCsr, pSeg); |
2767 } | 2843 } |
2768 } | 2844 } |
2769 | 2845 |
2770 if( iLevel!=FTS3_SEGCURSOR_PENDING ){ | 2846 if( iLevel!=FTS3_SEGCURSOR_PENDING ){ |
2771 if( rc==SQLITE_OK ){ | 2847 if( rc==SQLITE_OK ){ |
2772 rc = sqlite3Fts3AllSegdirs(p, iLangid, iIndex, iLevel, &pStmt); | 2848 rc = sqlite3Fts3AllSegdirs(p, iLangid, iIndex, iLevel, &pStmt); |
2773 } | 2849 } |
2774 | 2850 |
(...skipping 304 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3079 ** number idxNum-FTS3_FULLTEXT_SEARCH, 0 indexed. argv[0] is the right-hand | 3155 ** number idxNum-FTS3_FULLTEXT_SEARCH, 0 indexed. argv[0] is the right-hand |
3080 ** side of the MATCH operator. | 3156 ** side of the MATCH operator. |
3081 */ | 3157 */ |
3082 static int fts3FilterMethod( | 3158 static int fts3FilterMethod( |
3083 sqlite3_vtab_cursor *pCursor, /* The cursor used for this query */ | 3159 sqlite3_vtab_cursor *pCursor, /* The cursor used for this query */ |
3084 int idxNum, /* Strategy index */ | 3160 int idxNum, /* Strategy index */ |
3085 const char *idxStr, /* Unused */ | 3161 const char *idxStr, /* Unused */ |
3086 int nVal, /* Number of elements in apVal */ | 3162 int nVal, /* Number of elements in apVal */ |
3087 sqlite3_value **apVal /* Arguments for the indexing scheme */ | 3163 sqlite3_value **apVal /* Arguments for the indexing scheme */ |
3088 ){ | 3164 ){ |
3089 int rc; | 3165 int rc = SQLITE_OK; |
3090 char *zSql; /* SQL statement used to access %_content */ | 3166 char *zSql; /* SQL statement used to access %_content */ |
3091 int eSearch; | 3167 int eSearch; |
3092 Fts3Table *p = (Fts3Table *)pCursor->pVtab; | 3168 Fts3Table *p = (Fts3Table *)pCursor->pVtab; |
3093 Fts3Cursor *pCsr = (Fts3Cursor *)pCursor; | 3169 Fts3Cursor *pCsr = (Fts3Cursor *)pCursor; |
3094 | 3170 |
3095 sqlite3_value *pCons = 0; /* The MATCH or rowid constraint, if any */ | 3171 sqlite3_value *pCons = 0; /* The MATCH or rowid constraint, if any */ |
3096 sqlite3_value *pLangid = 0; /* The "langid = ?" constraint, if any */ | 3172 sqlite3_value *pLangid = 0; /* The "langid = ?" constraint, if any */ |
3097 sqlite3_value *pDocidGe = 0; /* The "docid >= ?" constraint, if any */ | 3173 sqlite3_value *pDocidGe = 0; /* The "docid >= ?" constraint, if any */ |
3098 sqlite3_value *pDocidLe = 0; /* The "docid <= ?" constraint, if any */ | 3174 sqlite3_value *pDocidLe = 0; /* The "docid <= ?" constraint, if any */ |
3099 int iIdx; | 3175 int iIdx; |
3100 | 3176 |
3101 UNUSED_PARAMETER(idxStr); | 3177 UNUSED_PARAMETER(idxStr); |
3102 UNUSED_PARAMETER(nVal); | 3178 UNUSED_PARAMETER(nVal); |
3103 | 3179 |
3104 eSearch = (idxNum & 0x0000FFFF); | 3180 eSearch = (idxNum & 0x0000FFFF); |
3105 assert( eSearch>=0 && eSearch<=(FTS3_FULLTEXT_SEARCH+p->nColumn) ); | 3181 assert( eSearch>=0 && eSearch<=(FTS3_FULLTEXT_SEARCH+p->nColumn) ); |
3106 assert( p->pSegments==0 ); | 3182 assert( p->pSegments==0 ); |
3107 | 3183 |
3108 /* Collect arguments into local variables */ | 3184 /* Collect arguments into local variables */ |
3109 iIdx = 0; | 3185 iIdx = 0; |
3110 if( eSearch!=FTS3_FULLSCAN_SEARCH ) pCons = apVal[iIdx++]; | 3186 if( eSearch!=FTS3_FULLSCAN_SEARCH ) pCons = apVal[iIdx++]; |
3111 if( idxNum & FTS3_HAVE_LANGID ) pLangid = apVal[iIdx++]; | 3187 if( idxNum & FTS3_HAVE_LANGID ) pLangid = apVal[iIdx++]; |
3112 if( idxNum & FTS3_HAVE_DOCID_GE ) pDocidGe = apVal[iIdx++]; | 3188 if( idxNum & FTS3_HAVE_DOCID_GE ) pDocidGe = apVal[iIdx++]; |
3113 if( idxNum & FTS3_HAVE_DOCID_LE ) pDocidLe = apVal[iIdx++]; | 3189 if( idxNum & FTS3_HAVE_DOCID_LE ) pDocidLe = apVal[iIdx++]; |
3114 assert( iIdx==nVal ); | 3190 assert( iIdx==nVal ); |
3115 | 3191 |
3116 /* In case the cursor has been used before, clear it now. */ | 3192 /* In case the cursor has been used before, clear it now. */ |
3117 sqlite3_finalize(pCsr->pStmt); | 3193 sqlite3_finalize(pCsr->pStmt); |
3118 sqlite3_free(pCsr->aDoclist); | 3194 sqlite3_free(pCsr->aDoclist); |
3119 sqlite3_free(pCsr->aMatchinfo); | 3195 sqlite3Fts3MIBufferFree(pCsr->pMIBuffer); |
3120 sqlite3Fts3ExprFree(pCsr->pExpr); | 3196 sqlite3Fts3ExprFree(pCsr->pExpr); |
3121 memset(&pCursor[1], 0, sizeof(Fts3Cursor)-sizeof(sqlite3_vtab_cursor)); | 3197 memset(&pCursor[1], 0, sizeof(Fts3Cursor)-sizeof(sqlite3_vtab_cursor)); |
3122 | 3198 |
3123 /* Set the lower and upper bounds on docids to return */ | 3199 /* Set the lower and upper bounds on docids to return */ |
3124 pCsr->iMinDocid = fts3DocidRange(pDocidGe, SMALLEST_INT64); | 3200 pCsr->iMinDocid = fts3DocidRange(pDocidGe, SMALLEST_INT64); |
3125 pCsr->iMaxDocid = fts3DocidRange(pDocidLe, LARGEST_INT64); | 3201 pCsr->iMaxDocid = fts3DocidRange(pDocidLe, LARGEST_INT64); |
3126 | 3202 |
3127 if( idxStr ){ | 3203 if( idxStr ){ |
3128 pCsr->bDesc = (idxStr[0]=='D'); | 3204 pCsr->bDesc = (idxStr[0]=='D'); |
3129 }else{ | 3205 }else{ |
(...skipping 27 matching lines...) Expand all Loading... |
3157 pCsr->pNextId = pCsr->aDoclist; | 3233 pCsr->pNextId = pCsr->aDoclist; |
3158 pCsr->iPrevId = 0; | 3234 pCsr->iPrevId = 0; |
3159 } | 3235 } |
3160 | 3236 |
3161 /* Compile a SELECT statement for this cursor. For a full-table-scan, the | 3237 /* Compile a SELECT statement for this cursor. For a full-table-scan, the |
3162 ** statement loops through all rows of the %_content table. For a | 3238 ** statement loops through all rows of the %_content table. For a |
3163 ** full-text query or docid lookup, the statement retrieves a single | 3239 ** full-text query or docid lookup, the statement retrieves a single |
3164 ** row by docid. | 3240 ** row by docid. |
3165 */ | 3241 */ |
3166 if( eSearch==FTS3_FULLSCAN_SEARCH ){ | 3242 if( eSearch==FTS3_FULLSCAN_SEARCH ){ |
3167 zSql = sqlite3_mprintf( | 3243 if( pDocidGe || pDocidLe ){ |
3168 "SELECT %s ORDER BY rowid %s", | 3244 zSql = sqlite3_mprintf( |
3169 p->zReadExprlist, (pCsr->bDesc ? "DESC" : "ASC") | 3245 "SELECT %s WHERE rowid BETWEEN %lld AND %lld ORDER BY rowid %s", |
3170 ); | 3246 p->zReadExprlist, pCsr->iMinDocid, pCsr->iMaxDocid, |
| 3247 (pCsr->bDesc ? "DESC" : "ASC") |
| 3248 ); |
| 3249 }else{ |
| 3250 zSql = sqlite3_mprintf("SELECT %s ORDER BY rowid %s", |
| 3251 p->zReadExprlist, (pCsr->bDesc ? "DESC" : "ASC") |
| 3252 ); |
| 3253 } |
3171 if( zSql ){ | 3254 if( zSql ){ |
3172 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pCsr->pStmt, 0); | 3255 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pCsr->pStmt, 0); |
3173 sqlite3_free(zSql); | 3256 sqlite3_free(zSql); |
3174 }else{ | 3257 }else{ |
3175 rc = SQLITE_NOMEM; | 3258 rc = SQLITE_NOMEM; |
3176 } | 3259 } |
3177 }else if( eSearch==FTS3_DOCID_SEARCH ){ | 3260 }else if( eSearch==FTS3_DOCID_SEARCH ){ |
3178 rc = fts3CursorSeekStmt(pCsr, &pCsr->pStmt); | 3261 rc = fts3CursorSeekStmt(pCsr, &pCsr->pStmt); |
3179 if( rc==SQLITE_OK ){ | 3262 if( rc==SQLITE_OK ){ |
3180 rc = sqlite3_bind_value(pCsr->pStmt, 1, pCons); | 3263 rc = sqlite3_bind_value(pCsr->pStmt, 1, pCons); |
(...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3396 /* | 3479 /* |
3397 ** When called, *ppPoslist must point to the byte immediately following the | 3480 ** When called, *ppPoslist must point to the byte immediately following the |
3398 ** end of a position-list. i.e. ( (*ppPoslist)[-1]==POS_END ). This function | 3481 ** end of a position-list. i.e. ( (*ppPoslist)[-1]==POS_END ). This function |
3399 ** moves *ppPoslist so that it instead points to the first byte of the | 3482 ** moves *ppPoslist so that it instead points to the first byte of the |
3400 ** same position list. | 3483 ** same position list. |
3401 */ | 3484 */ |
3402 static void fts3ReversePoslist(char *pStart, char **ppPoslist){ | 3485 static void fts3ReversePoslist(char *pStart, char **ppPoslist){ |
3403 char *p = &(*ppPoslist)[-2]; | 3486 char *p = &(*ppPoslist)[-2]; |
3404 char c = 0; | 3487 char c = 0; |
3405 | 3488 |
| 3489 /* Skip backwards passed any trailing 0x00 bytes added by NearTrim() */ |
3406 while( p>pStart && (c=*p--)==0 ); | 3490 while( p>pStart && (c=*p--)==0 ); |
| 3491 |
| 3492 /* Search backwards for a varint with value zero (the end of the previous |
| 3493 ** poslist). This is an 0x00 byte preceded by some byte that does not |
| 3494 ** have the 0x80 bit set. */ |
3407 while( p>pStart && (*p & 0x80) | c ){ | 3495 while( p>pStart && (*p & 0x80) | c ){ |
3408 c = *p--; | 3496 c = *p--; |
3409 } | 3497 } |
3410 if( p>pStart ){ p = &p[2]; } | 3498 assert( p==pStart || c==0 ); |
| 3499 |
| 3500 /* At this point p points to that preceding byte without the 0x80 bit |
| 3501 ** set. So to find the start of the poslist, skip forward 2 bytes then |
| 3502 ** over a varint. |
| 3503 ** |
| 3504 ** Normally. The other case is that p==pStart and the poslist to return |
| 3505 ** is the first in the doclist. In this case do not skip forward 2 bytes. |
| 3506 ** The second part of the if condition (c==0 && *ppPoslist>&p[2]) |
| 3507 ** is required for cases where the first byte of a doclist and the |
| 3508 ** doclist is empty. For example, if the first docid is 10, a doclist |
| 3509 ** that begins with: |
| 3510 ** |
| 3511 ** 0x0A 0x00 <next docid delta varint> |
| 3512 */ |
| 3513 if( p>pStart || (c==0 && *ppPoslist>&p[2]) ){ p = &p[2]; } |
3411 while( *p++&0x80 ); | 3514 while( *p++&0x80 ); |
3412 *ppPoslist = p; | 3515 *ppPoslist = p; |
3413 } | 3516 } |
3414 | 3517 |
3415 /* | 3518 /* |
3416 ** Helper function used by the implementation of the overloaded snippet(), | 3519 ** Helper function used by the implementation of the overloaded snippet(), |
3417 ** offsets() and optimize() SQL functions. | 3520 ** offsets() and optimize() SQL functions. |
3418 ** | 3521 ** |
3419 ** If the value passed as the third argument is a blob of size | 3522 ** If the value passed as the third argument is a blob of size |
3420 ** sizeof(Fts3Cursor*), then the blob contents are copied to the | 3523 ** sizeof(Fts3Cursor*), then the blob contents are copied to the |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3471 | 3574 |
3472 switch( nVal ){ | 3575 switch( nVal ){ |
3473 case 6: nToken = sqlite3_value_int(apVal[5]); | 3576 case 6: nToken = sqlite3_value_int(apVal[5]); |
3474 case 5: iCol = sqlite3_value_int(apVal[4]); | 3577 case 5: iCol = sqlite3_value_int(apVal[4]); |
3475 case 4: zEllipsis = (const char*)sqlite3_value_text(apVal[3]); | 3578 case 4: zEllipsis = (const char*)sqlite3_value_text(apVal[3]); |
3476 case 3: zEnd = (const char*)sqlite3_value_text(apVal[2]); | 3579 case 3: zEnd = (const char*)sqlite3_value_text(apVal[2]); |
3477 case 2: zStart = (const char*)sqlite3_value_text(apVal[1]); | 3580 case 2: zStart = (const char*)sqlite3_value_text(apVal[1]); |
3478 } | 3581 } |
3479 if( !zEllipsis || !zEnd || !zStart ){ | 3582 if( !zEllipsis || !zEnd || !zStart ){ |
3480 sqlite3_result_error_nomem(pContext); | 3583 sqlite3_result_error_nomem(pContext); |
| 3584 }else if( nToken==0 ){ |
| 3585 sqlite3_result_text(pContext, "", -1, SQLITE_STATIC); |
3481 }else if( SQLITE_OK==fts3CursorSeek(pContext, pCsr) ){ | 3586 }else if( SQLITE_OK==fts3CursorSeek(pContext, pCsr) ){ |
3482 sqlite3Fts3Snippet(pContext, pCsr, zStart, zEnd, zEllipsis, iCol, nToken); | 3587 sqlite3Fts3Snippet(pContext, pCsr, zStart, zEnd, zEllipsis, iCol, nToken); |
3483 } | 3588 } |
3484 } | 3589 } |
3485 | 3590 |
3486 /* | 3591 /* |
3487 ** Implementation of the offsets() function for FTS3 | 3592 ** Implementation of the offsets() function for FTS3 |
3488 */ | 3593 */ |
3489 static void fts3OffsetsFunc( | 3594 static void fts3OffsetsFunc( |
3490 sqlite3_context *pContext, /* SQLite function call context */ | 3595 sqlite3_context *pContext, /* SQLite function call context */ |
(...skipping 415 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3906 } | 4011 } |
3907 } | 4012 } |
3908 | 4013 |
3909 /* | 4014 /* |
3910 ** Arguments pList/nList contain the doclist for token iToken of phrase p. | 4015 ** Arguments pList/nList contain the doclist for token iToken of phrase p. |
3911 ** It is merged into the main doclist stored in p->doclist.aAll/nAll. | 4016 ** It is merged into the main doclist stored in p->doclist.aAll/nAll. |
3912 ** | 4017 ** |
3913 ** This function assumes that pList points to a buffer allocated using | 4018 ** This function assumes that pList points to a buffer allocated using |
3914 ** sqlite3_malloc(). This function takes responsibility for eventually | 4019 ** sqlite3_malloc(). This function takes responsibility for eventually |
3915 ** freeing the buffer. | 4020 ** freeing the buffer. |
| 4021 ** |
| 4022 ** SQLITE_OK is returned if successful, or SQLITE_NOMEM if an error occurs. |
3916 */ | 4023 */ |
3917 static void fts3EvalPhraseMergeToken( | 4024 static int fts3EvalPhraseMergeToken( |
3918 Fts3Table *pTab, /* FTS Table pointer */ | 4025 Fts3Table *pTab, /* FTS Table pointer */ |
3919 Fts3Phrase *p, /* Phrase to merge pList/nList into */ | 4026 Fts3Phrase *p, /* Phrase to merge pList/nList into */ |
3920 int iToken, /* Token pList/nList corresponds to */ | 4027 int iToken, /* Token pList/nList corresponds to */ |
3921 char *pList, /* Pointer to doclist */ | 4028 char *pList, /* Pointer to doclist */ |
3922 int nList /* Number of bytes in pList */ | 4029 int nList /* Number of bytes in pList */ |
3923 ){ | 4030 ){ |
| 4031 int rc = SQLITE_OK; |
3924 assert( iToken!=p->iDoclistToken ); | 4032 assert( iToken!=p->iDoclistToken ); |
3925 | 4033 |
3926 if( pList==0 ){ | 4034 if( pList==0 ){ |
3927 sqlite3_free(p->doclist.aAll); | 4035 sqlite3_free(p->doclist.aAll); |
3928 p->doclist.aAll = 0; | 4036 p->doclist.aAll = 0; |
3929 p->doclist.nAll = 0; | 4037 p->doclist.nAll = 0; |
3930 } | 4038 } |
3931 | 4039 |
3932 else if( p->iDoclistToken<0 ){ | 4040 else if( p->iDoclistToken<0 ){ |
3933 p->doclist.aAll = pList; | 4041 p->doclist.aAll = pList; |
(...skipping 18 matching lines...) Expand all Loading... |
3952 nRight = nList; | 4060 nRight = nList; |
3953 nDiff = iToken - p->iDoclistToken; | 4061 nDiff = iToken - p->iDoclistToken; |
3954 }else{ | 4062 }else{ |
3955 pRight = p->doclist.aAll; | 4063 pRight = p->doclist.aAll; |
3956 nRight = p->doclist.nAll; | 4064 nRight = p->doclist.nAll; |
3957 pLeft = pList; | 4065 pLeft = pList; |
3958 nLeft = nList; | 4066 nLeft = nList; |
3959 nDiff = p->iDoclistToken - iToken; | 4067 nDiff = p->iDoclistToken - iToken; |
3960 } | 4068 } |
3961 | 4069 |
3962 fts3DoclistPhraseMerge(pTab->bDescIdx, nDiff, pLeft, nLeft, pRight,&nRight); | 4070 rc = fts3DoclistPhraseMerge( |
| 4071 pTab->bDescIdx, nDiff, pLeft, nLeft, &pRight, &nRight |
| 4072 ); |
3963 sqlite3_free(pLeft); | 4073 sqlite3_free(pLeft); |
3964 p->doclist.aAll = pRight; | 4074 p->doclist.aAll = pRight; |
3965 p->doclist.nAll = nRight; | 4075 p->doclist.nAll = nRight; |
3966 } | 4076 } |
3967 | 4077 |
3968 if( iToken>p->iDoclistToken ) p->iDoclistToken = iToken; | 4078 if( iToken>p->iDoclistToken ) p->iDoclistToken = iToken; |
| 4079 return rc; |
3969 } | 4080 } |
3970 | 4081 |
3971 /* | 4082 /* |
3972 ** Load the doclist for phrase p into p->doclist.aAll/nAll. The loaded doclist | 4083 ** Load the doclist for phrase p into p->doclist.aAll/nAll. The loaded doclist |
3973 ** does not take deferred tokens into account. | 4084 ** does not take deferred tokens into account. |
3974 ** | 4085 ** |
3975 ** SQLITE_OK is returned if no error occurs, otherwise an SQLite error code. | 4086 ** SQLITE_OK is returned if no error occurs, otherwise an SQLite error code. |
3976 */ | 4087 */ |
3977 static int fts3EvalPhraseLoad( | 4088 static int fts3EvalPhraseLoad( |
3978 Fts3Cursor *pCsr, /* FTS Cursor handle */ | 4089 Fts3Cursor *pCsr, /* FTS Cursor handle */ |
3979 Fts3Phrase *p /* Phrase object */ | 4090 Fts3Phrase *p /* Phrase object */ |
3980 ){ | 4091 ){ |
3981 Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab; | 4092 Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab; |
3982 int iToken; | 4093 int iToken; |
3983 int rc = SQLITE_OK; | 4094 int rc = SQLITE_OK; |
3984 | 4095 |
3985 for(iToken=0; rc==SQLITE_OK && iToken<p->nToken; iToken++){ | 4096 for(iToken=0; rc==SQLITE_OK && iToken<p->nToken; iToken++){ |
3986 Fts3PhraseToken *pToken = &p->aToken[iToken]; | 4097 Fts3PhraseToken *pToken = &p->aToken[iToken]; |
3987 assert( pToken->pDeferred==0 || pToken->pSegcsr==0 ); | 4098 assert( pToken->pDeferred==0 || pToken->pSegcsr==0 ); |
3988 | 4099 |
3989 if( pToken->pSegcsr ){ | 4100 if( pToken->pSegcsr ){ |
3990 int nThis = 0; | 4101 int nThis = 0; |
3991 char *pThis = 0; | 4102 char *pThis = 0; |
3992 rc = fts3TermSelect(pTab, pToken, p->iColumn, &nThis, &pThis); | 4103 rc = fts3TermSelect(pTab, pToken, p->iColumn, &nThis, &pThis); |
3993 if( rc==SQLITE_OK ){ | 4104 if( rc==SQLITE_OK ){ |
3994 fts3EvalPhraseMergeToken(pTab, p, iToken, pThis, nThis); | 4105 rc = fts3EvalPhraseMergeToken(pTab, p, iToken, pThis, nThis); |
3995 } | 4106 } |
3996 } | 4107 } |
3997 assert( pToken->pSegcsr==0 ); | 4108 assert( pToken->pSegcsr==0 ); |
3998 } | 4109 } |
3999 | 4110 |
4000 return rc; | 4111 return rc; |
4001 } | 4112 } |
4002 | 4113 |
4003 /* | 4114 /* |
4004 ** This function is called on each phrase after the position lists for | 4115 ** This function is called on each phrase after the position lists for |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4129 | 4240 |
4130 /* Determine if doclists may be loaded from disk incrementally. This is | 4241 /* Determine if doclists may be loaded from disk incrementally. This is |
4131 ** possible if the bOptOk argument is true, the FTS doclists will be | 4242 ** possible if the bOptOk argument is true, the FTS doclists will be |
4132 ** scanned in forward order, and the phrase consists of | 4243 ** scanned in forward order, and the phrase consists of |
4133 ** MAX_INCR_PHRASE_TOKENS or fewer tokens, none of which are are "^first" | 4244 ** MAX_INCR_PHRASE_TOKENS or fewer tokens, none of which are are "^first" |
4134 ** tokens or prefix tokens that cannot use a prefix-index. */ | 4245 ** tokens or prefix tokens that cannot use a prefix-index. */ |
4135 int bHaveIncr = 0; | 4246 int bHaveIncr = 0; |
4136 int bIncrOk = (bOptOk | 4247 int bIncrOk = (bOptOk |
4137 && pCsr->bDesc==pTab->bDescIdx | 4248 && pCsr->bDesc==pTab->bDescIdx |
4138 && p->nToken<=MAX_INCR_PHRASE_TOKENS && p->nToken>0 | 4249 && p->nToken<=MAX_INCR_PHRASE_TOKENS && p->nToken>0 |
4139 && p->nToken<=MAX_INCR_PHRASE_TOKENS && p->nToken>0 | |
4140 #ifdef SQLITE_TEST | 4250 #ifdef SQLITE_TEST |
4141 && pTab->bNoIncrDoclist==0 | 4251 && pTab->bNoIncrDoclist==0 |
4142 #endif | 4252 #endif |
4143 ); | 4253 ); |
4144 for(i=0; bIncrOk==1 && i<p->nToken; i++){ | 4254 for(i=0; bIncrOk==1 && i<p->nToken; i++){ |
4145 Fts3PhraseToken *pToken = &p->aToken[i]; | 4255 Fts3PhraseToken *pToken = &p->aToken[i]; |
4146 if( pToken->bFirst || (pToken->pSegcsr!=0 && !pToken->pSegcsr->bLookup) ){ | 4256 if( pToken->bFirst || (pToken->pSegcsr!=0 && !pToken->pSegcsr->bLookup) ){ |
4147 bIncrOk = 0; | 4257 bIncrOk = 0; |
4148 } | 4258 } |
4149 if( pToken->pSegcsr ) bHaveIncr = 1; | 4259 if( pToken->pSegcsr ) bHaveIncr = 1; |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4249 assert( nDoclist>0 ); | 4359 assert( nDoclist>0 ); |
4250 assert( *pbEof==0 ); | 4360 assert( *pbEof==0 ); |
4251 assert( p || *piDocid==0 ); | 4361 assert( p || *piDocid==0 ); |
4252 assert( !p || (p>=aDoclist && p<=&aDoclist[nDoclist]) ); | 4362 assert( !p || (p>=aDoclist && p<=&aDoclist[nDoclist]) ); |
4253 | 4363 |
4254 if( p==0 ){ | 4364 if( p==0 ){ |
4255 p = aDoclist; | 4365 p = aDoclist; |
4256 p += sqlite3Fts3GetVarint(p, piDocid); | 4366 p += sqlite3Fts3GetVarint(p, piDocid); |
4257 }else{ | 4367 }else{ |
4258 fts3PoslistCopy(0, &p); | 4368 fts3PoslistCopy(0, &p); |
| 4369 while( p<&aDoclist[nDoclist] && *p==0 ) p++; |
4259 if( p>=&aDoclist[nDoclist] ){ | 4370 if( p>=&aDoclist[nDoclist] ){ |
4260 *pbEof = 1; | 4371 *pbEof = 1; |
4261 }else{ | 4372 }else{ |
4262 sqlite3_int64 iVar; | 4373 sqlite3_int64 iVar; |
4263 p += sqlite3Fts3GetVarint(p, &iVar); | 4374 p += sqlite3Fts3GetVarint(p, &iVar); |
4264 *piDocid += ((bDescIdx ? -1 : 1) * iVar); | 4375 *piDocid += ((bDescIdx ? -1 : 1) * iVar); |
4265 } | 4376 } |
4266 } | 4377 } |
4267 | 4378 |
4268 *ppIter = p; | 4379 *ppIter = p; |
(...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4526 ** If an error occurs within this function, *pRc is set to an SQLite error | 4637 ** If an error occurs within this function, *pRc is set to an SQLite error |
4527 ** code before returning. | 4638 ** code before returning. |
4528 */ | 4639 */ |
4529 static void fts3EvalStartReaders( | 4640 static void fts3EvalStartReaders( |
4530 Fts3Cursor *pCsr, /* FTS Cursor handle */ | 4641 Fts3Cursor *pCsr, /* FTS Cursor handle */ |
4531 Fts3Expr *pExpr, /* Expression to initialize phrases in */ | 4642 Fts3Expr *pExpr, /* Expression to initialize phrases in */ |
4532 int *pRc /* IN/OUT: Error code */ | 4643 int *pRc /* IN/OUT: Error code */ |
4533 ){ | 4644 ){ |
4534 if( pExpr && SQLITE_OK==*pRc ){ | 4645 if( pExpr && SQLITE_OK==*pRc ){ |
4535 if( pExpr->eType==FTSQUERY_PHRASE ){ | 4646 if( pExpr->eType==FTSQUERY_PHRASE ){ |
4536 int i; | |
4537 int nToken = pExpr->pPhrase->nToken; | 4647 int nToken = pExpr->pPhrase->nToken; |
4538 for(i=0; i<nToken; i++){ | 4648 if( nToken ){ |
4539 if( pExpr->pPhrase->aToken[i].pDeferred==0 ) break; | 4649 int i; |
| 4650 for(i=0; i<nToken; i++){ |
| 4651 if( pExpr->pPhrase->aToken[i].pDeferred==0 ) break; |
| 4652 } |
| 4653 pExpr->bDeferred = (i==nToken); |
4540 } | 4654 } |
4541 pExpr->bDeferred = (i==nToken); | |
4542 *pRc = fts3EvalPhraseStart(pCsr, 1, pExpr->pPhrase); | 4655 *pRc = fts3EvalPhraseStart(pCsr, 1, pExpr->pPhrase); |
4543 }else{ | 4656 }else{ |
4544 fts3EvalStartReaders(pCsr, pExpr->pLeft, pRc); | 4657 fts3EvalStartReaders(pCsr, pExpr->pLeft, pRc); |
4545 fts3EvalStartReaders(pCsr, pExpr->pRight, pRc); | 4658 fts3EvalStartReaders(pCsr, pExpr->pRight, pRc); |
4546 pExpr->bDeferred = (pExpr->pLeft->bDeferred && pExpr->pRight->bDeferred); | 4659 pExpr->bDeferred = (pExpr->pLeft->bDeferred && pExpr->pRight->bDeferred); |
4547 } | 4660 } |
4548 } | 4661 } |
4549 } | 4662 } |
4550 | 4663 |
4551 /* | 4664 /* |
(...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4787 if( ii==0 || (pTC->pPhrase->nToken>1 && ii!=nToken-1) ){ | 4900 if( ii==0 || (pTC->pPhrase->nToken>1 && ii!=nToken-1) ){ |
4788 /* Either this is the cheapest token in the entire query, or it is | 4901 /* Either this is the cheapest token in the entire query, or it is |
4789 ** part of a multi-token phrase. Either way, the entire doclist will | 4902 ** part of a multi-token phrase. Either way, the entire doclist will |
4790 ** (eventually) be loaded into memory. It may as well be now. */ | 4903 ** (eventually) be loaded into memory. It may as well be now. */ |
4791 Fts3PhraseToken *pToken = pTC->pToken; | 4904 Fts3PhraseToken *pToken = pTC->pToken; |
4792 int nList = 0; | 4905 int nList = 0; |
4793 char *pList = 0; | 4906 char *pList = 0; |
4794 rc = fts3TermSelect(pTab, pToken, pTC->iCol, &nList, &pList); | 4907 rc = fts3TermSelect(pTab, pToken, pTC->iCol, &nList, &pList); |
4795 assert( rc==SQLITE_OK || pList==0 ); | 4908 assert( rc==SQLITE_OK || pList==0 ); |
4796 if( rc==SQLITE_OK ){ | 4909 if( rc==SQLITE_OK ){ |
| 4910 rc = fts3EvalPhraseMergeToken( |
| 4911 pTab, pTC->pPhrase, pTC->iToken,pList,nList |
| 4912 ); |
| 4913 } |
| 4914 if( rc==SQLITE_OK ){ |
4797 int nCount; | 4915 int nCount; |
4798 fts3EvalPhraseMergeToken(pTab, pTC->pPhrase, pTC->iToken,pList,nList); | |
4799 nCount = fts3DoclistCountDocids( | 4916 nCount = fts3DoclistCountDocids( |
4800 pTC->pPhrase->doclist.aAll, pTC->pPhrase->doclist.nAll | 4917 pTC->pPhrase->doclist.aAll, pTC->pPhrase->doclist.nAll |
4801 ); | 4918 ); |
4802 if( ii==0 || nCount<nMinEst ) nMinEst = nCount; | 4919 if( ii==0 || nCount<nMinEst ) nMinEst = nCount; |
4803 } | 4920 } |
4804 } | 4921 } |
4805 } | 4922 } |
4806 pTC->pToken = 0; | 4923 pTC->pToken = 0; |
4807 } | 4924 } |
4808 | 4925 |
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4966 ** more non-deferred tokens, then the expression is advanced to the | 5083 ** more non-deferred tokens, then the expression is advanced to the |
4967 ** next possible match, considering only non-deferred tokens. In other | 5084 ** next possible match, considering only non-deferred tokens. In other |
4968 ** words, if the phrase is "A B C", and "B" is deferred, the expression | 5085 ** words, if the phrase is "A B C", and "B" is deferred, the expression |
4969 ** is advanced to the next row that contains an instance of "A * C", | 5086 ** is advanced to the next row that contains an instance of "A * C", |
4970 ** where "*" may match any single token. The position list in this case | 5087 ** where "*" may match any single token. The position list in this case |
4971 ** is populated as for "A * C" before returning. | 5088 ** is populated as for "A * C" before returning. |
4972 ** | 5089 ** |
4973 ** 2. NEAR is treated as AND. If the expression is "x NEAR y", it is | 5090 ** 2. NEAR is treated as AND. If the expression is "x NEAR y", it is |
4974 ** advanced to point to the next row that matches "x AND y". | 5091 ** advanced to point to the next row that matches "x AND y". |
4975 ** | 5092 ** |
4976 ** See fts3EvalTestDeferredAndNear() for details on testing if a row is | 5093 ** See sqlite3Fts3EvalTestDeferred() for details on testing if a row is |
4977 ** really a match, taking into account deferred tokens and NEAR operators. | 5094 ** really a match, taking into account deferred tokens and NEAR operators. |
4978 */ | 5095 */ |
4979 static void fts3EvalNextRow( | 5096 static void fts3EvalNextRow( |
4980 Fts3Cursor *pCsr, /* FTS Cursor handle */ | 5097 Fts3Cursor *pCsr, /* FTS Cursor handle */ |
4981 Fts3Expr *pExpr, /* Expr. to advance to next matching row */ | 5098 Fts3Expr *pExpr, /* Expr. to advance to next matching row */ |
4982 int *pRc /* IN/OUT: Error code */ | 5099 int *pRc /* IN/OUT: Error code */ |
4983 ){ | 5100 ){ |
4984 if( *pRc==SQLITE_OK ){ | 5101 if( *pRc==SQLITE_OK ){ |
4985 int bDescDoclist = pCsr->bDesc; /* Used by DOCID_CMP() macro */ | 5102 int bDescDoclist = pCsr->bDesc; /* Used by DOCID_CMP() macro */ |
4986 assert( pExpr->bEof==0 ); | 5103 assert( pExpr->bEof==0 ); |
(...skipping 26 matching lines...) Expand all Loading... |
5013 sqlite3_int64 iDiff = DOCID_CMP(pLeft->iDocid, pRight->iDocid); | 5130 sqlite3_int64 iDiff = DOCID_CMP(pLeft->iDocid, pRight->iDocid); |
5014 if( iDiff==0 ) break; | 5131 if( iDiff==0 ) break; |
5015 if( iDiff<0 ){ | 5132 if( iDiff<0 ){ |
5016 fts3EvalNextRow(pCsr, pLeft, pRc); | 5133 fts3EvalNextRow(pCsr, pLeft, pRc); |
5017 }else{ | 5134 }else{ |
5018 fts3EvalNextRow(pCsr, pRight, pRc); | 5135 fts3EvalNextRow(pCsr, pRight, pRc); |
5019 } | 5136 } |
5020 } | 5137 } |
5021 pExpr->iDocid = pLeft->iDocid; | 5138 pExpr->iDocid = pLeft->iDocid; |
5022 pExpr->bEof = (pLeft->bEof || pRight->bEof); | 5139 pExpr->bEof = (pLeft->bEof || pRight->bEof); |
| 5140 if( pExpr->eType==FTSQUERY_NEAR && pExpr->bEof ){ |
| 5141 if( pRight->pPhrase && pRight->pPhrase->doclist.aAll ){ |
| 5142 Fts3Doclist *pDl = &pRight->pPhrase->doclist; |
| 5143 while( *pRc==SQLITE_OK && pRight->bEof==0 ){ |
| 5144 memset(pDl->pList, 0, pDl->nList); |
| 5145 fts3EvalNextRow(pCsr, pRight, pRc); |
| 5146 } |
| 5147 } |
| 5148 if( pLeft->pPhrase && pLeft->pPhrase->doclist.aAll ){ |
| 5149 Fts3Doclist *pDl = &pLeft->pPhrase->doclist; |
| 5150 while( *pRc==SQLITE_OK && pLeft->bEof==0 ){ |
| 5151 memset(pDl->pList, 0, pDl->nList); |
| 5152 fts3EvalNextRow(pCsr, pLeft, pRc); |
| 5153 } |
| 5154 } |
| 5155 } |
5023 } | 5156 } |
5024 break; | 5157 break; |
5025 } | 5158 } |
5026 | 5159 |
5027 case FTSQUERY_OR: { | 5160 case FTSQUERY_OR: { |
5028 Fts3Expr *pLeft = pExpr->pLeft; | 5161 Fts3Expr *pLeft = pExpr->pLeft; |
5029 Fts3Expr *pRight = pExpr->pRight; | 5162 Fts3Expr *pRight = pExpr->pRight; |
5030 sqlite3_int64 iCmp = DOCID_CMP(pLeft->iDocid, pRight->iDocid); | 5163 sqlite3_int64 iCmp = DOCID_CMP(pLeft->iDocid, pRight->iDocid); |
5031 | 5164 |
5032 assert( pLeft->bStart || pLeft->iDocid==pRight->iDocid ); | 5165 assert( pLeft->bStart || pLeft->iDocid==pRight->iDocid ); |
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5170 } | 5303 } |
5171 | 5304 |
5172 sqlite3_free(aTmp); | 5305 sqlite3_free(aTmp); |
5173 } | 5306 } |
5174 } | 5307 } |
5175 | 5308 |
5176 return res; | 5309 return res; |
5177 } | 5310 } |
5178 | 5311 |
5179 /* | 5312 /* |
5180 ** This function is a helper function for fts3EvalTestDeferredAndNear(). | 5313 ** This function is a helper function for sqlite3Fts3EvalTestDeferred(). |
5181 ** Assuming no error occurs or has occurred, It returns non-zero if the | 5314 ** Assuming no error occurs or has occurred, It returns non-zero if the |
5182 ** expression passed as the second argument matches the row that pCsr | 5315 ** expression passed as the second argument matches the row that pCsr |
5183 ** currently points to, or zero if it does not. | 5316 ** currently points to, or zero if it does not. |
5184 ** | 5317 ** |
5185 ** If *pRc is not SQLITE_OK when this function is called, it is a no-op. | 5318 ** If *pRc is not SQLITE_OK when this function is called, it is a no-op. |
5186 ** If an error occurs during execution of this function, *pRc is set to | 5319 ** If an error occurs during execution of this function, *pRc is set to |
5187 ** the appropriate SQLite error code. In this case the returned value is | 5320 ** the appropriate SQLite error code. In this case the returned value is |
5188 ** undefined. | 5321 ** undefined. |
5189 */ | 5322 */ |
5190 static int fts3EvalTestExpr( | 5323 static int fts3EvalTestExpr( |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5291 ** expression. It returns 1 if both of the following are true: | 5424 ** expression. It returns 1 if both of the following are true: |
5292 ** | 5425 ** |
5293 ** 1. *pRc is SQLITE_OK when this function returns, and | 5426 ** 1. *pRc is SQLITE_OK when this function returns, and |
5294 ** | 5427 ** |
5295 ** 2. After scanning the current FTS table row for the deferred tokens, | 5428 ** 2. After scanning the current FTS table row for the deferred tokens, |
5296 ** it is determined that the row does *not* match the query. | 5429 ** it is determined that the row does *not* match the query. |
5297 ** | 5430 ** |
5298 ** Or, if no error occurs and it seems the current row does match the FTS | 5431 ** Or, if no error occurs and it seems the current row does match the FTS |
5299 ** query, return 0. | 5432 ** query, return 0. |
5300 */ | 5433 */ |
5301 static int fts3EvalTestDeferredAndNear(Fts3Cursor *pCsr, int *pRc){ | 5434 int sqlite3Fts3EvalTestDeferred(Fts3Cursor *pCsr, int *pRc){ |
5302 int rc = *pRc; | 5435 int rc = *pRc; |
5303 int bMiss = 0; | 5436 int bMiss = 0; |
5304 if( rc==SQLITE_OK ){ | 5437 if( rc==SQLITE_OK ){ |
5305 | 5438 |
5306 /* If there are one or more deferred tokens, load the current row into | 5439 /* If there are one or more deferred tokens, load the current row into |
5307 ** memory and scan it to determine the position list for each deferred | 5440 ** memory and scan it to determine the position list for each deferred |
5308 ** token. Then, see if this row is really a match, considering deferred | 5441 ** token. Then, see if this row is really a match, considering deferred |
5309 ** tokens and NEAR operators (neither of which were taken into account | 5442 ** tokens and NEAR operators (neither of which were taken into account |
5310 ** earlier, by fts3EvalNextRow()). | 5443 ** earlier, by fts3EvalNextRow()). |
5311 */ | 5444 */ |
(...skipping 26 matching lines...) Expand all Loading... |
5338 do { | 5471 do { |
5339 if( pCsr->isRequireSeek==0 ){ | 5472 if( pCsr->isRequireSeek==0 ){ |
5340 sqlite3_reset(pCsr->pStmt); | 5473 sqlite3_reset(pCsr->pStmt); |
5341 } | 5474 } |
5342 assert( sqlite3_data_count(pCsr->pStmt)==0 ); | 5475 assert( sqlite3_data_count(pCsr->pStmt)==0 ); |
5343 fts3EvalNextRow(pCsr, pExpr, &rc); | 5476 fts3EvalNextRow(pCsr, pExpr, &rc); |
5344 pCsr->isEof = pExpr->bEof; | 5477 pCsr->isEof = pExpr->bEof; |
5345 pCsr->isRequireSeek = 1; | 5478 pCsr->isRequireSeek = 1; |
5346 pCsr->isMatchinfoNeeded = 1; | 5479 pCsr->isMatchinfoNeeded = 1; |
5347 pCsr->iPrevId = pExpr->iDocid; | 5480 pCsr->iPrevId = pExpr->iDocid; |
5348 }while( pCsr->isEof==0 && fts3EvalTestDeferredAndNear(pCsr, &rc) ); | 5481 }while( pCsr->isEof==0 && sqlite3Fts3EvalTestDeferred(pCsr, &rc) ); |
5349 } | 5482 } |
5350 | 5483 |
5351 /* Check if the cursor is past the end of the docid range specified | 5484 /* Check if the cursor is past the end of the docid range specified |
5352 ** by Fts3Cursor.iMinDocid/iMaxDocid. If so, set the EOF flag. */ | 5485 ** by Fts3Cursor.iMinDocid/iMaxDocid. If so, set the EOF flag. */ |
5353 if( rc==SQLITE_OK && ( | 5486 if( rc==SQLITE_OK && ( |
5354 (pCsr->bDesc==0 && pCsr->iPrevId>pCsr->iMaxDocid) | 5487 (pCsr->bDesc==0 && pCsr->iPrevId>pCsr->iMaxDocid) |
5355 || (pCsr->bDesc!=0 && pCsr->iPrevId<pCsr->iMinDocid) | 5488 || (pCsr->bDesc!=0 && pCsr->iPrevId<pCsr->iMinDocid) |
5356 )){ | 5489 )){ |
5357 pCsr->isEof = 1; | 5490 pCsr->isEof = 1; |
5358 } | 5491 } |
(...skipping 26 matching lines...) Expand all Loading... |
5385 Fts3PhraseToken *pToken = &pPhrase->aToken[i]; | 5518 Fts3PhraseToken *pToken = &pPhrase->aToken[i]; |
5386 assert( pToken->pDeferred==0 ); | 5519 assert( pToken->pDeferred==0 ); |
5387 if( pToken->pSegcsr ){ | 5520 if( pToken->pSegcsr ){ |
5388 sqlite3Fts3MsrIncrRestart(pToken->pSegcsr); | 5521 sqlite3Fts3MsrIncrRestart(pToken->pSegcsr); |
5389 } | 5522 } |
5390 } | 5523 } |
5391 *pRc = fts3EvalPhraseStart(pCsr, 0, pPhrase); | 5524 *pRc = fts3EvalPhraseStart(pCsr, 0, pPhrase); |
5392 } | 5525 } |
5393 pPhrase->doclist.pNextDocid = 0; | 5526 pPhrase->doclist.pNextDocid = 0; |
5394 pPhrase->doclist.iDocid = 0; | 5527 pPhrase->doclist.iDocid = 0; |
| 5528 pPhrase->pOrPoslist = 0; |
5395 } | 5529 } |
5396 | 5530 |
5397 pExpr->iDocid = 0; | 5531 pExpr->iDocid = 0; |
5398 pExpr->bEof = 0; | 5532 pExpr->bEof = 0; |
5399 pExpr->bStart = 0; | 5533 pExpr->bStart = 0; |
5400 | 5534 |
5401 fts3EvalRestart(pCsr, pExpr->pLeft, pRc); | 5535 fts3EvalRestart(pCsr, pExpr->pLeft, pRc); |
5402 fts3EvalRestart(pCsr, pExpr->pRight, pRc); | 5536 fts3EvalRestart(pCsr, pExpr->pRight, pRc); |
5403 } | 5537 } |
5404 } | 5538 } |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5498 assert( sqlite3_data_count(pCsr->pStmt)==0 ); | 5632 assert( sqlite3_data_count(pCsr->pStmt)==0 ); |
5499 | 5633 |
5500 /* Advance to the next document */ | 5634 /* Advance to the next document */ |
5501 fts3EvalNextRow(pCsr, pRoot, &rc); | 5635 fts3EvalNextRow(pCsr, pRoot, &rc); |
5502 pCsr->isEof = pRoot->bEof; | 5636 pCsr->isEof = pRoot->bEof; |
5503 pCsr->isRequireSeek = 1; | 5637 pCsr->isRequireSeek = 1; |
5504 pCsr->isMatchinfoNeeded = 1; | 5638 pCsr->isMatchinfoNeeded = 1; |
5505 pCsr->iPrevId = pRoot->iDocid; | 5639 pCsr->iPrevId = pRoot->iDocid; |
5506 }while( pCsr->isEof==0 | 5640 }while( pCsr->isEof==0 |
5507 && pRoot->eType==FTSQUERY_NEAR | 5641 && pRoot->eType==FTSQUERY_NEAR |
5508 && fts3EvalTestDeferredAndNear(pCsr, &rc) | 5642 && sqlite3Fts3EvalTestDeferred(pCsr, &rc) |
5509 ); | 5643 ); |
5510 | 5644 |
5511 if( rc==SQLITE_OK && pCsr->isEof==0 ){ | 5645 if( rc==SQLITE_OK && pCsr->isEof==0 ){ |
5512 fts3EvalUpdateCounts(pRoot); | 5646 fts3EvalUpdateCounts(pRoot); |
5513 } | 5647 } |
5514 } | 5648 } |
5515 | 5649 |
5516 pCsr->isEof = 0; | 5650 pCsr->isEof = 0; |
5517 pCsr->iPrevId = iPrevId; | 5651 pCsr->iPrevId = iPrevId; |
5518 | 5652 |
5519 if( bEof ){ | 5653 if( bEof ){ |
5520 pRoot->bEof = bEof; | 5654 pRoot->bEof = bEof; |
5521 }else{ | 5655 }else{ |
5522 /* Caution: pRoot may iterate through docids in ascending or descending | 5656 /* Caution: pRoot may iterate through docids in ascending or descending |
5523 ** order. For this reason, even though it seems more defensive, the | 5657 ** order. For this reason, even though it seems more defensive, the |
5524 ** do loop can not be written: | 5658 ** do loop can not be written: |
5525 ** | 5659 ** |
5526 ** do {...} while( pRoot->iDocid<iDocid && rc==SQLITE_OK ); | 5660 ** do {...} while( pRoot->iDocid<iDocid && rc==SQLITE_OK ); |
5527 */ | 5661 */ |
5528 fts3EvalRestart(pCsr, pRoot, &rc); | 5662 fts3EvalRestart(pCsr, pRoot, &rc); |
5529 do { | 5663 do { |
5530 fts3EvalNextRow(pCsr, pRoot, &rc); | 5664 fts3EvalNextRow(pCsr, pRoot, &rc); |
5531 assert( pRoot->bEof==0 ); | 5665 assert( pRoot->bEof==0 ); |
5532 }while( pRoot->iDocid!=iDocid && rc==SQLITE_OK ); | 5666 }while( pRoot->iDocid!=iDocid && rc==SQLITE_OK ); |
5533 fts3EvalTestDeferredAndNear(pCsr, &rc); | |
5534 } | 5667 } |
5535 } | 5668 } |
5536 return rc; | 5669 return rc; |
5537 } | 5670 } |
5538 | 5671 |
5539 /* | 5672 /* |
5540 ** This function is used by the matchinfo() module to query a phrase | 5673 ** This function is used by the matchinfo() module to query a phrase |
5541 ** expression node for the following information: | 5674 ** expression node for the following information: |
5542 ** | 5675 ** |
5543 ** 1. The total number of occurrences of the phrase in each column of | 5676 ** 1. The total number of occurrences of the phrase in each column of |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5630 ** column iCol, return a NULL pointer. */ | 5763 ** column iCol, return a NULL pointer. */ |
5631 *ppOut = 0; | 5764 *ppOut = 0; |
5632 assert( iCol>=0 && iCol<pTab->nColumn ); | 5765 assert( iCol>=0 && iCol<pTab->nColumn ); |
5633 if( (pPhrase->iColumn<pTab->nColumn && pPhrase->iColumn!=iCol) ){ | 5766 if( (pPhrase->iColumn<pTab->nColumn && pPhrase->iColumn!=iCol) ){ |
5634 return SQLITE_OK; | 5767 return SQLITE_OK; |
5635 } | 5768 } |
5636 | 5769 |
5637 iDocid = pExpr->iDocid; | 5770 iDocid = pExpr->iDocid; |
5638 pIter = pPhrase->doclist.pList; | 5771 pIter = pPhrase->doclist.pList; |
5639 if( iDocid!=pCsr->iPrevId || pExpr->bEof ){ | 5772 if( iDocid!=pCsr->iPrevId || pExpr->bEof ){ |
| 5773 int rc = SQLITE_OK; |
5640 int bDescDoclist = pTab->bDescIdx; /* For DOCID_CMP macro */ | 5774 int bDescDoclist = pTab->bDescIdx; /* For DOCID_CMP macro */ |
5641 int iMul; /* +1 if csr dir matches index dir, else -1 */ | |
5642 int bOr = 0; | 5775 int bOr = 0; |
5643 u8 bEof = 0; | |
5644 u8 bTreeEof = 0; | 5776 u8 bTreeEof = 0; |
5645 Fts3Expr *p; /* Used to iterate from pExpr to root */ | 5777 Fts3Expr *p; /* Used to iterate from pExpr to root */ |
5646 Fts3Expr *pNear; /* Most senior NEAR ancestor (or pExpr) */ | 5778 Fts3Expr *pNear; /* Most senior NEAR ancestor (or pExpr) */ |
| 5779 int bMatch; |
5647 | 5780 |
5648 /* Check if this phrase descends from an OR expression node. If not, | 5781 /* Check if this phrase descends from an OR expression node. If not, |
5649 ** return NULL. Otherwise, the entry that corresponds to docid | 5782 ** return NULL. Otherwise, the entry that corresponds to docid |
5650 ** pCsr->iPrevId may lie earlier in the doclist buffer. Or, if the | 5783 ** pCsr->iPrevId may lie earlier in the doclist buffer. Or, if the |
5651 ** tree that the node is part of has been marked as EOF, but the node | 5784 ** tree that the node is part of has been marked as EOF, but the node |
5652 ** itself is not EOF, then it may point to an earlier entry. */ | 5785 ** itself is not EOF, then it may point to an earlier entry. */ |
5653 pNear = pExpr; | 5786 pNear = pExpr; |
5654 for(p=pExpr->pParent; p; p=p->pParent){ | 5787 for(p=pExpr->pParent; p; p=p->pParent){ |
5655 if( p->eType==FTSQUERY_OR ) bOr = 1; | 5788 if( p->eType==FTSQUERY_OR ) bOr = 1; |
5656 if( p->eType==FTSQUERY_NEAR ) pNear = p; | 5789 if( p->eType==FTSQUERY_NEAR ) pNear = p; |
5657 if( p->bEof ) bTreeEof = 1; | 5790 if( p->bEof ) bTreeEof = 1; |
5658 } | 5791 } |
5659 if( bOr==0 ) return SQLITE_OK; | 5792 if( bOr==0 ) return SQLITE_OK; |
5660 | 5793 |
5661 /* This is the descendent of an OR node. In this case we cannot use | 5794 /* This is the descendent of an OR node. In this case we cannot use |
5662 ** an incremental phrase. Load the entire doclist for the phrase | 5795 ** an incremental phrase. Load the entire doclist for the phrase |
5663 ** into memory in this case. */ | 5796 ** into memory in this case. */ |
5664 if( pPhrase->bIncr ){ | 5797 if( pPhrase->bIncr ){ |
5665 int rc = SQLITE_OK; | 5798 int bEofSave = pNear->bEof; |
5666 int bEofSave = pExpr->bEof; | 5799 fts3EvalRestart(pCsr, pNear, &rc); |
5667 fts3EvalRestart(pCsr, pExpr, &rc); | 5800 while( rc==SQLITE_OK && !pNear->bEof ){ |
5668 while( rc==SQLITE_OK && !pExpr->bEof ){ | 5801 fts3EvalNextRow(pCsr, pNear, &rc); |
5669 fts3EvalNextRow(pCsr, pExpr, &rc); | 5802 if( bEofSave==0 && pNear->iDocid==iDocid ) break; |
5670 if( bEofSave==0 && pExpr->iDocid==iDocid ) break; | |
5671 } | 5803 } |
5672 pIter = pPhrase->doclist.pList; | |
5673 assert( rc!=SQLITE_OK || pPhrase->bIncr==0 ); | 5804 assert( rc!=SQLITE_OK || pPhrase->bIncr==0 ); |
5674 if( rc!=SQLITE_OK ) return rc; | |
5675 } | 5805 } |
5676 | 5806 if( bTreeEof ){ |
5677 iMul = ((pCsr->bDesc==bDescDoclist) ? 1 : -1); | 5807 while( rc==SQLITE_OK && !pNear->bEof ){ |
5678 while( bTreeEof==1 | 5808 fts3EvalNextRow(pCsr, pNear, &rc); |
5679 && pNear->bEof==0 | 5809 } |
5680 && (DOCID_CMP(pNear->iDocid, pCsr->iPrevId) * iMul)<0 | |
5681 ){ | |
5682 int rc = SQLITE_OK; | |
5683 fts3EvalNextRow(pCsr, pExpr, &rc); | |
5684 if( rc!=SQLITE_OK ) return rc; | |
5685 iDocid = pExpr->iDocid; | |
5686 pIter = pPhrase->doclist.pList; | |
5687 } | 5810 } |
| 5811 if( rc!=SQLITE_OK ) return rc; |
5688 | 5812 |
5689 bEof = (pPhrase->doclist.nAll==0); | 5813 bMatch = 1; |
5690 assert( bDescDoclist==0 || bDescDoclist==1 ); | 5814 for(p=pNear; p; p=p->pLeft){ |
5691 assert( pCsr->bDesc==0 || pCsr->bDesc==1 ); | 5815 u8 bEof = 0; |
| 5816 Fts3Expr *pTest = p; |
| 5817 Fts3Phrase *pPh; |
| 5818 assert( pTest->eType==FTSQUERY_NEAR || pTest->eType==FTSQUERY_PHRASE ); |
| 5819 if( pTest->eType==FTSQUERY_NEAR ) pTest = pTest->pRight; |
| 5820 assert( pTest->eType==FTSQUERY_PHRASE ); |
| 5821 pPh = pTest->pPhrase; |
5692 | 5822 |
5693 if( bEof==0 ){ | 5823 pIter = pPh->pOrPoslist; |
| 5824 iDocid = pPh->iOrDocid; |
5694 if( pCsr->bDesc==bDescDoclist ){ | 5825 if( pCsr->bDesc==bDescDoclist ){ |
5695 int dummy; | 5826 bEof = !pPh->doclist.nAll || |
5696 if( pNear->bEof ){ | 5827 (pIter >= (pPh->doclist.aAll + pPh->doclist.nAll)); |
5697 /* This expression is already at EOF. So position it to point to the | 5828 while( (pIter==0 || DOCID_CMP(iDocid, pCsr->iPrevId)<0 ) && bEof==0 ){ |
5698 ** last entry in the doclist at pPhrase->doclist.aAll[]. Variable | 5829 sqlite3Fts3DoclistNext( |
5699 ** iDocid is already set for this entry, so all that is required is | 5830 bDescDoclist, pPh->doclist.aAll, pPh->doclist.nAll, |
5700 ** to set pIter to point to the first byte of the last position-list | 5831 &pIter, &iDocid, &bEof |
5701 ** in the doclist. | |
5702 ** | |
5703 ** It would also be correct to set pIter and iDocid to zero. In | |
5704 ** this case, the first call to sqltie3Fts4DoclistPrev() below | |
5705 ** would also move the iterator to point to the last entry in the | |
5706 ** doclist. However, this is expensive, as to do so it has to | |
5707 ** iterate through the entire doclist from start to finish (since | |
5708 ** it does not know the docid for the last entry). */ | |
5709 pIter = &pPhrase->doclist.aAll[pPhrase->doclist.nAll-1]; | |
5710 fts3ReversePoslist(pPhrase->doclist.aAll, &pIter); | |
5711 } | |
5712 while( (pIter==0 || DOCID_CMP(iDocid, pCsr->iPrevId)>0 ) && bEof==0 ){ | |
5713 sqlite3Fts3DoclistPrev( | |
5714 bDescDoclist, pPhrase->doclist.aAll, pPhrase->doclist.nAll, | |
5715 &pIter, &iDocid, &dummy, &bEof | |
5716 ); | 5832 ); |
5717 } | 5833 } |
5718 }else{ | 5834 }else{ |
5719 if( pNear->bEof ){ | 5835 bEof = !pPh->doclist.nAll || (pIter && pIter<=pPh->doclist.aAll); |
5720 pIter = 0; | 5836 while( (pIter==0 || DOCID_CMP(iDocid, pCsr->iPrevId)>0 ) && bEof==0 ){ |
5721 iDocid = 0; | 5837 int dummy; |
5722 } | 5838 sqlite3Fts3DoclistPrev( |
5723 while( (pIter==0 || DOCID_CMP(iDocid, pCsr->iPrevId)<0 ) && bEof==0 ){ | 5839 bDescDoclist, pPh->doclist.aAll, pPh->doclist.nAll, |
5724 sqlite3Fts3DoclistNext( | 5840 &pIter, &iDocid, &dummy, &bEof |
5725 bDescDoclist, pPhrase->doclist.aAll, pPhrase->doclist.nAll, | 5841 ); |
5726 &pIter, &iDocid, &bEof | |
5727 ); | |
5728 } | 5842 } |
5729 } | 5843 } |
| 5844 pPh->pOrPoslist = pIter; |
| 5845 pPh->iOrDocid = iDocid; |
| 5846 if( bEof || iDocid!=pCsr->iPrevId ) bMatch = 0; |
5730 } | 5847 } |
5731 | 5848 |
5732 if( bEof || iDocid!=pCsr->iPrevId ) pIter = 0; | 5849 if( bMatch ){ |
| 5850 pIter = pPhrase->pOrPoslist; |
| 5851 }else{ |
| 5852 pIter = 0; |
| 5853 } |
5733 } | 5854 } |
5734 if( pIter==0 ) return SQLITE_OK; | 5855 if( pIter==0 ) return SQLITE_OK; |
5735 | 5856 |
5736 if( *pIter==0x01 ){ | 5857 if( *pIter==0x01 ){ |
5737 pIter++; | 5858 pIter++; |
5738 pIter += fts3GetVarint32(pIter, &iThis); | 5859 pIter += fts3GetVarint32(pIter, &iThis); |
5739 }else{ | 5860 }else{ |
5740 iThis = 0; | 5861 iThis = 0; |
5741 } | 5862 } |
5742 while( iThis<iCol ){ | 5863 while( iThis<iCol ){ |
5743 fts3ColumnlistCopy(0, &pIter); | 5864 fts3ColumnlistCopy(0, &pIter); |
5744 if( *pIter==0x00 ) return 0; | 5865 if( *pIter==0x00 ) return SQLITE_OK; |
5745 pIter++; | 5866 pIter++; |
5746 pIter += fts3GetVarint32(pIter, &iThis); | 5867 pIter += fts3GetVarint32(pIter, &iThis); |
5747 } | 5868 } |
| 5869 if( *pIter==0x00 ){ |
| 5870 pIter = 0; |
| 5871 } |
5748 | 5872 |
5749 *ppOut = ((iCol==iThis)?pIter:0); | 5873 *ppOut = ((iCol==iThis)?pIter:0); |
5750 return SQLITE_OK; | 5874 return SQLITE_OK; |
5751 } | 5875 } |
5752 | 5876 |
5753 /* | 5877 /* |
5754 ** Free all components of the Fts3Phrase structure that were allocated by | 5878 ** Free all components of the Fts3Phrase structure that were allocated by |
5755 ** the eval module. Specifically, this means to free: | 5879 ** the eval module. Specifically, this means to free: |
5756 ** | 5880 ** |
5757 ** * the contents of pPhrase->doclist, and | 5881 ** * the contents of pPhrase->doclist, and |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5791 sqlite3 *db, | 5915 sqlite3 *db, |
5792 char **pzErrMsg, | 5916 char **pzErrMsg, |
5793 const sqlite3_api_routines *pApi | 5917 const sqlite3_api_routines *pApi |
5794 ){ | 5918 ){ |
5795 SQLITE_EXTENSION_INIT2(pApi) | 5919 SQLITE_EXTENSION_INIT2(pApi) |
5796 return sqlite3Fts3Init(db); | 5920 return sqlite3Fts3Init(db); |
5797 } | 5921 } |
5798 #endif | 5922 #endif |
5799 | 5923 |
5800 #endif | 5924 #endif |
OLD | NEW |