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 296 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
307 #ifndef SQLITE_CORE | 307 #ifndef SQLITE_CORE |
308 # include "sqlite3ext.h" | 308 # include "sqlite3ext.h" |
309 SQLITE_EXTENSION_INIT1 | 309 SQLITE_EXTENSION_INIT1 |
310 #endif | 310 #endif |
311 | 311 |
312 static int fts3EvalNext(Fts3Cursor *pCsr); | 312 static int fts3EvalNext(Fts3Cursor *pCsr); |
313 static int fts3EvalStart(Fts3Cursor *pCsr); | 313 static int fts3EvalStart(Fts3Cursor *pCsr); |
314 static int fts3TermSegReaderCursor( | 314 static int fts3TermSegReaderCursor( |
315 Fts3Cursor *, const char *, int, int, Fts3MultiSegReader **); | 315 Fts3Cursor *, const char *, int, int, Fts3MultiSegReader **); |
316 | 316 |
| 317 #ifndef SQLITE_AMALGAMATION |
| 318 # if defined(SQLITE_DEBUG) |
| 319 int sqlite3Fts3Always(int b) { assert( b ); return b; } |
| 320 int sqlite3Fts3Never(int b) { assert( !b ); return b; } |
| 321 # endif |
| 322 #endif |
| 323 |
317 /* | 324 /* |
318 ** Write a 64-bit variable-length integer to memory starting at p[0]. | 325 ** Write a 64-bit variable-length integer to memory starting at p[0]. |
319 ** The length of data written will be between 1 and FTS3_VARINT_MAX bytes. | 326 ** The length of data written will be between 1 and FTS3_VARINT_MAX bytes. |
320 ** The number of bytes written is returned. | 327 ** The number of bytes written is returned. |
321 */ | 328 */ |
322 int sqlite3Fts3PutVarint(char *p, sqlite_int64 v){ | 329 int sqlite3Fts3PutVarint(char *p, sqlite_int64 v){ |
323 unsigned char *q = (unsigned char *) p; | 330 unsigned char *q = (unsigned char *) p; |
324 sqlite_uint64 vu = v; | 331 sqlite_uint64 vu = v; |
325 do{ | 332 do{ |
326 *q++ = (unsigned char) ((vu & 0x7f) | 0x80); | 333 *q++ = (unsigned char) ((vu & 0x7f) | 0x80); |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
416 char quote; /* Quote character (if any ) */ | 423 char quote; /* Quote character (if any ) */ |
417 | 424 |
418 quote = z[0]; | 425 quote = z[0]; |
419 if( quote=='[' || quote=='\'' || quote=='"' || quote=='`' ){ | 426 if( quote=='[' || quote=='\'' || quote=='"' || quote=='`' ){ |
420 int iIn = 1; /* Index of next byte to read from input */ | 427 int iIn = 1; /* Index of next byte to read from input */ |
421 int iOut = 0; /* Index of next byte to write to output */ | 428 int iOut = 0; /* Index of next byte to write to output */ |
422 | 429 |
423 /* If the first byte was a '[', then the close-quote character is a ']' */ | 430 /* If the first byte was a '[', then the close-quote character is a ']' */ |
424 if( quote=='[' ) quote = ']'; | 431 if( quote=='[' ) quote = ']'; |
425 | 432 |
426 while( ALWAYS(z[iIn]) ){ | 433 while( z[iIn] ){ |
427 if( z[iIn]==quote ){ | 434 if( z[iIn]==quote ){ |
428 if( z[iIn+1]!=quote ) break; | 435 if( z[iIn+1]!=quote ) break; |
429 z[iOut++] = quote; | 436 z[iOut++] = quote; |
430 iIn += 2; | 437 iIn += 2; |
431 }else{ | 438 }else{ |
432 z[iOut++] = z[iIn++]; | 439 z[iOut++] = z[iIn++]; |
433 } | 440 } |
434 } | 441 } |
435 z[iOut] = '\0'; | 442 z[iOut] = '\0'; |
436 } | 443 } |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
496 sqlite3_free(p->zLanguageid); | 503 sqlite3_free(p->zLanguageid); |
497 | 504 |
498 /* Invoke the tokenizer destructor to free the tokenizer. */ | 505 /* Invoke the tokenizer destructor to free the tokenizer. */ |
499 p->pTokenizer->pModule->xDestroy(p->pTokenizer); | 506 p->pTokenizer->pModule->xDestroy(p->pTokenizer); |
500 | 507 |
501 sqlite3_free(p); | 508 sqlite3_free(p); |
502 return SQLITE_OK; | 509 return SQLITE_OK; |
503 } | 510 } |
504 | 511 |
505 /* | 512 /* |
| 513 ** Write an error message into *pzErr |
| 514 */ |
| 515 void sqlite3Fts3ErrMsg(char **pzErr, const char *zFormat, ...){ |
| 516 va_list ap; |
| 517 sqlite3_free(*pzErr); |
| 518 va_start(ap, zFormat); |
| 519 *pzErr = sqlite3_vmprintf(zFormat, ap); |
| 520 va_end(ap); |
| 521 } |
| 522 |
| 523 /* |
506 ** Construct one or more SQL statements from the format string given | 524 ** Construct one or more SQL statements from the format string given |
507 ** and then evaluate those statements. The success code is written | 525 ** and then evaluate those statements. The success code is written |
508 ** into *pRc. | 526 ** into *pRc. |
509 ** | 527 ** |
510 ** If *pRc is initially non-zero then this routine is a no-op. | 528 ** If *pRc is initially non-zero then this routine is a no-op. |
511 */ | 529 */ |
512 static void fts3DbExec( | 530 static void fts3DbExec( |
513 int *pRc, /* Success code */ | 531 int *pRc, /* Success code */ |
514 sqlite3 *db, /* Database in which to run SQL */ | 532 sqlite3 *db, /* Database in which to run SQL */ |
515 const char *zFormat, /* Format string for SQL */ | 533 const char *zFormat, /* Format string for SQL */ |
(...skipping 388 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
904 ** the integer value. | 922 ** the integer value. |
905 ** | 923 ** |
906 ** Only decimal digits ('0'..'9') may be part of an integer value. | 924 ** Only decimal digits ('0'..'9') may be part of an integer value. |
907 ** | 925 ** |
908 ** If *pp does not being with a decimal digit SQLITE_ERROR is returned and | 926 ** If *pp does not being with a decimal digit SQLITE_ERROR is returned and |
909 ** the output value undefined. Otherwise SQLITE_OK is returned. | 927 ** the output value undefined. Otherwise SQLITE_OK is returned. |
910 ** | 928 ** |
911 ** This function is used when parsing the "prefix=" FTS4 parameter. | 929 ** This function is used when parsing the "prefix=" FTS4 parameter. |
912 */ | 930 */ |
913 static int fts3GobbleInt(const char **pp, int *pnOut){ | 931 static int fts3GobbleInt(const char **pp, int *pnOut){ |
| 932 const int MAX_NPREFIX = 10000000; |
914 const char *p; /* Iterator pointer */ | 933 const char *p; /* Iterator pointer */ |
915 int nInt = 0; /* Output value */ | 934 int nInt = 0; /* Output value */ |
916 | 935 |
917 for(p=*pp; p[0]>='0' && p[0]<='9'; p++){ | 936 for(p=*pp; p[0]>='0' && p[0]<='9'; p++){ |
918 nInt = nInt * 10 + (p[0] - '0'); | 937 nInt = nInt * 10 + (p[0] - '0'); |
| 938 if( nInt>MAX_NPREFIX ){ |
| 939 nInt = 0; |
| 940 break; |
| 941 } |
919 } | 942 } |
920 if( p==*pp ) return SQLITE_ERROR; | 943 if( p==*pp ) return SQLITE_ERROR; |
921 *pnOut = nInt; | 944 *pnOut = nInt; |
922 *pp = p; | 945 *pp = p; |
923 return SQLITE_OK; | 946 return SQLITE_OK; |
924 } | 947 } |
925 | 948 |
926 /* | 949 /* |
927 ** This function is called to allocate an array of Fts3Index structures | 950 ** This function is called to allocate an array of Fts3Index structures |
928 ** representing the indexes maintained by the current FTS table. FTS tables | 951 ** representing the indexes maintained by the current FTS table. FTS tables |
(...skipping 22 matching lines...) Expand all Loading... |
951 if( zParam && zParam[0] ){ | 974 if( zParam && zParam[0] ){ |
952 const char *p; | 975 const char *p; |
953 nIndex++; | 976 nIndex++; |
954 for(p=zParam; *p; p++){ | 977 for(p=zParam; *p; p++){ |
955 if( *p==',' ) nIndex++; | 978 if( *p==',' ) nIndex++; |
956 } | 979 } |
957 } | 980 } |
958 | 981 |
959 aIndex = sqlite3_malloc(sizeof(struct Fts3Index) * nIndex); | 982 aIndex = sqlite3_malloc(sizeof(struct Fts3Index) * nIndex); |
960 *apIndex = aIndex; | 983 *apIndex = aIndex; |
961 *pnIndex = nIndex; | |
962 if( !aIndex ){ | 984 if( !aIndex ){ |
963 return SQLITE_NOMEM; | 985 return SQLITE_NOMEM; |
964 } | 986 } |
965 | 987 |
966 memset(aIndex, 0, sizeof(struct Fts3Index) * nIndex); | 988 memset(aIndex, 0, sizeof(struct Fts3Index) * nIndex); |
967 if( zParam ){ | 989 if( zParam ){ |
968 const char *p = zParam; | 990 const char *p = zParam; |
969 int i; | 991 int i; |
970 for(i=1; i<nIndex; i++){ | 992 for(i=1; i<nIndex; i++){ |
971 int nPrefix; | 993 int nPrefix = 0; |
972 if( fts3GobbleInt(&p, &nPrefix) ) return SQLITE_ERROR; | 994 if( fts3GobbleInt(&p, &nPrefix) ) return SQLITE_ERROR; |
973 aIndex[i].nPrefix = nPrefix; | 995 assert( nPrefix>=0 ); |
| 996 if( nPrefix==0 ){ |
| 997 nIndex--; |
| 998 i--; |
| 999 }else{ |
| 1000 aIndex[i].nPrefix = nPrefix; |
| 1001 } |
974 p++; | 1002 p++; |
975 } | 1003 } |
976 } | 1004 } |
977 | 1005 |
| 1006 *pnIndex = nIndex; |
978 return SQLITE_OK; | 1007 return SQLITE_OK; |
979 } | 1008 } |
980 | 1009 |
981 /* | 1010 /* |
982 ** This function is called when initializing an FTS4 table that uses the | 1011 ** This function is called when initializing an FTS4 table that uses the |
983 ** content=xxx option. It determines the number of and names of the columns | 1012 ** content=xxx option. It determines the number of and names of the columns |
984 ** of the new FTS4 table. | 1013 ** of the new FTS4 table. |
985 ** | 1014 ** |
986 ** The third argument passed to this function is the value passed to the | 1015 ** The third argument passed to this function is the value passed to the |
987 ** config=xxx option (i.e. "xxx"). This function queries the database for | 1016 ** config=xxx option (i.e. "xxx"). This function queries the database for |
(...skipping 14 matching lines...) Expand all Loading... |
1002 ** If the table cannot be found, an error code is returned and the output | 1031 ** If the table cannot be found, an error code is returned and the output |
1003 ** variables are undefined. Or, if an OOM is encountered, SQLITE_NOMEM is | 1032 ** variables are undefined. Or, if an OOM is encountered, SQLITE_NOMEM is |
1004 ** returned (and the output variables are undefined). | 1033 ** returned (and the output variables are undefined). |
1005 */ | 1034 */ |
1006 static int fts3ContentColumns( | 1035 static int fts3ContentColumns( |
1007 sqlite3 *db, /* Database handle */ | 1036 sqlite3 *db, /* Database handle */ |
1008 const char *zDb, /* Name of db (i.e. "main", "temp" etc.) */ | 1037 const char *zDb, /* Name of db (i.e. "main", "temp" etc.) */ |
1009 const char *zTbl, /* Name of content table */ | 1038 const char *zTbl, /* Name of content table */ |
1010 const char ***pazCol, /* OUT: Malloc'd array of column names */ | 1039 const char ***pazCol, /* OUT: Malloc'd array of column names */ |
1011 int *pnCol, /* OUT: Size of array *pazCol */ | 1040 int *pnCol, /* OUT: Size of array *pazCol */ |
1012 int *pnStr /* OUT: Bytes of string content */ | 1041 int *pnStr, /* OUT: Bytes of string content */ |
| 1042 char **pzErr /* OUT: error message */ |
1013 ){ | 1043 ){ |
1014 int rc = SQLITE_OK; /* Return code */ | 1044 int rc = SQLITE_OK; /* Return code */ |
1015 char *zSql; /* "SELECT *" statement on zTbl */ | 1045 char *zSql; /* "SELECT *" statement on zTbl */ |
1016 sqlite3_stmt *pStmt = 0; /* Compiled version of zSql */ | 1046 sqlite3_stmt *pStmt = 0; /* Compiled version of zSql */ |
1017 | 1047 |
1018 zSql = sqlite3_mprintf("SELECT * FROM %Q.%Q", zDb, zTbl); | 1048 zSql = sqlite3_mprintf("SELECT * FROM %Q.%Q", zDb, zTbl); |
1019 if( !zSql ){ | 1049 if( !zSql ){ |
1020 rc = SQLITE_NOMEM; | 1050 rc = SQLITE_NOMEM; |
1021 }else{ | 1051 }else{ |
1022 rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0); | 1052 rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0); |
| 1053 if( rc!=SQLITE_OK ){ |
| 1054 sqlite3Fts3ErrMsg(pzErr, "%s", sqlite3_errmsg(db)); |
| 1055 } |
1023 } | 1056 } |
1024 sqlite3_free(zSql); | 1057 sqlite3_free(zSql); |
1025 | 1058 |
1026 if( rc==SQLITE_OK ){ | 1059 if( rc==SQLITE_OK ){ |
1027 const char **azCol; /* Output array */ | 1060 const char **azCol; /* Output array */ |
1028 int nStr = 0; /* Size of all column names (incl. 0x00) */ | 1061 int nStr = 0; /* Size of all column names (incl. 0x00) */ |
1029 int nCol; /* Number of table columns */ | 1062 int nCol; /* Number of table columns */ |
1030 int i; /* Used to iterate through columns */ | 1063 int i; /* Used to iterate through columns */ |
1031 | 1064 |
1032 /* Loop through the returned columns. Set nStr to the number of bytes of | 1065 /* 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... |
1091 int iCol; /* Column index */ | 1124 int iCol; /* Column index */ |
1092 int nString = 0; /* Bytes required to hold all column names */ | 1125 int nString = 0; /* Bytes required to hold all column names */ |
1093 int nCol = 0; /* Number of columns in the FTS table */ | 1126 int nCol = 0; /* Number of columns in the FTS table */ |
1094 char *zCsr; /* Space for holding column names */ | 1127 char *zCsr; /* Space for holding column names */ |
1095 int nDb; /* Bytes required to hold database name */ | 1128 int nDb; /* Bytes required to hold database name */ |
1096 int nName; /* Bytes required to hold table name */ | 1129 int nName; /* Bytes required to hold table name */ |
1097 int isFts4 = (argv[0][3]=='4'); /* True for FTS4, false for FTS3 */ | 1130 int isFts4 = (argv[0][3]=='4'); /* True for FTS4, false for FTS3 */ |
1098 const char **aCol; /* Array of column names */ | 1131 const char **aCol; /* Array of column names */ |
1099 sqlite3_tokenizer *pTokenizer = 0; /* Tokenizer for this table */ | 1132 sqlite3_tokenizer *pTokenizer = 0; /* Tokenizer for this table */ |
1100 | 1133 |
1101 int nIndex; /* Size of aIndex[] array */ | 1134 int nIndex = 0; /* Size of aIndex[] array */ |
1102 struct Fts3Index *aIndex = 0; /* Array of indexes for this table */ | 1135 struct Fts3Index *aIndex = 0; /* Array of indexes for this table */ |
1103 | 1136 |
1104 /* The results of parsing supported FTS4 key=value options: */ | 1137 /* The results of parsing supported FTS4 key=value options: */ |
1105 int bNoDocsize = 0; /* True to omit %_docsize table */ | 1138 int bNoDocsize = 0; /* True to omit %_docsize table */ |
1106 int bDescIdx = 0; /* True to store descending indexes */ | 1139 int bDescIdx = 0; /* True to store descending indexes */ |
1107 char *zPrefix = 0; /* Prefix parameter value (or NULL) */ | 1140 char *zPrefix = 0; /* Prefix parameter value (or NULL) */ |
1108 char *zCompress = 0; /* compress=? parameter (or NULL) */ | 1141 char *zCompress = 0; /* compress=? parameter (or NULL) */ |
1109 char *zUncompress = 0; /* uncompress=? parameter (or NULL) */ | 1142 char *zUncompress = 0; /* uncompress=? parameter (or NULL) */ |
1110 char *zContent = 0; /* content=? parameter (or NULL) */ | 1143 char *zContent = 0; /* content=? parameter (or NULL) */ |
1111 char *zLanguageid = 0; /* languageid=? parameter (or NULL) */ | 1144 char *zLanguageid = 0; /* languageid=? parameter (or NULL) */ |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1179 if( !zVal ){ | 1212 if( !zVal ){ |
1180 rc = SQLITE_NOMEM; | 1213 rc = SQLITE_NOMEM; |
1181 }else{ | 1214 }else{ |
1182 for(iOpt=0; iOpt<SizeofArray(aFts4Opt); iOpt++){ | 1215 for(iOpt=0; iOpt<SizeofArray(aFts4Opt); iOpt++){ |
1183 struct Fts4Option *pOp = &aFts4Opt[iOpt]; | 1216 struct Fts4Option *pOp = &aFts4Opt[iOpt]; |
1184 if( nKey==pOp->nOpt && !sqlite3_strnicmp(z, pOp->zOpt, pOp->nOpt) ){ | 1217 if( nKey==pOp->nOpt && !sqlite3_strnicmp(z, pOp->zOpt, pOp->nOpt) ){ |
1185 break; | 1218 break; |
1186 } | 1219 } |
1187 } | 1220 } |
1188 if( iOpt==SizeofArray(aFts4Opt) ){ | 1221 if( iOpt==SizeofArray(aFts4Opt) ){ |
1189 *pzErr = sqlite3_mprintf("unrecognized parameter: %s", z); | 1222 sqlite3Fts3ErrMsg(pzErr, "unrecognized parameter: %s", z); |
1190 rc = SQLITE_ERROR; | 1223 rc = SQLITE_ERROR; |
1191 }else{ | 1224 }else{ |
1192 switch( iOpt ){ | 1225 switch( iOpt ){ |
1193 case 0: /* MATCHINFO */ | 1226 case 0: /* MATCHINFO */ |
1194 if( strlen(zVal)!=4 || sqlite3_strnicmp(zVal, "fts3", 4) ){ | 1227 if( strlen(zVal)!=4 || sqlite3_strnicmp(zVal, "fts3", 4) ){ |
1195 *pzErr = sqlite3_mprintf("unrecognized matchinfo: %s", zVal); | 1228 sqlite3Fts3ErrMsg(pzErr, "unrecognized matchinfo: %s", zVal); |
1196 rc = SQLITE_ERROR; | 1229 rc = SQLITE_ERROR; |
1197 } | 1230 } |
1198 bNoDocsize = 1; | 1231 bNoDocsize = 1; |
1199 break; | 1232 break; |
1200 | 1233 |
1201 case 1: /* PREFIX */ | 1234 case 1: /* PREFIX */ |
1202 sqlite3_free(zPrefix); | 1235 sqlite3_free(zPrefix); |
1203 zPrefix = zVal; | 1236 zPrefix = zVal; |
1204 zVal = 0; | 1237 zVal = 0; |
1205 break; | 1238 break; |
1206 | 1239 |
1207 case 2: /* COMPRESS */ | 1240 case 2: /* COMPRESS */ |
1208 sqlite3_free(zCompress); | 1241 sqlite3_free(zCompress); |
1209 zCompress = zVal; | 1242 zCompress = zVal; |
1210 zVal = 0; | 1243 zVal = 0; |
1211 break; | 1244 break; |
1212 | 1245 |
1213 case 3: /* UNCOMPRESS */ | 1246 case 3: /* UNCOMPRESS */ |
1214 sqlite3_free(zUncompress); | 1247 sqlite3_free(zUncompress); |
1215 zUncompress = zVal; | 1248 zUncompress = zVal; |
1216 zVal = 0; | 1249 zVal = 0; |
1217 break; | 1250 break; |
1218 | 1251 |
1219 case 4: /* ORDER */ | 1252 case 4: /* ORDER */ |
1220 if( (strlen(zVal)!=3 || sqlite3_strnicmp(zVal, "asc", 3)) | 1253 if( (strlen(zVal)!=3 || sqlite3_strnicmp(zVal, "asc", 3)) |
1221 && (strlen(zVal)!=4 || sqlite3_strnicmp(zVal, "desc", 4)) | 1254 && (strlen(zVal)!=4 || sqlite3_strnicmp(zVal, "desc", 4)) |
1222 ){ | 1255 ){ |
1223 *pzErr = sqlite3_mprintf("unrecognized order: %s", zVal); | 1256 sqlite3Fts3ErrMsg(pzErr, "unrecognized order: %s", zVal); |
1224 rc = SQLITE_ERROR; | 1257 rc = SQLITE_ERROR; |
1225 } | 1258 } |
1226 bDescIdx = (zVal[0]=='d' || zVal[0]=='D'); | 1259 bDescIdx = (zVal[0]=='d' || zVal[0]=='D'); |
1227 break; | 1260 break; |
1228 | 1261 |
1229 case 5: /* CONTENT */ | 1262 case 5: /* CONTENT */ |
1230 sqlite3_free(zContent); | 1263 sqlite3_free(zContent); |
1231 zContent = zVal; | 1264 zContent = zVal; |
1232 zVal = 0; | 1265 zVal = 0; |
1233 break; | 1266 break; |
(...skipping 30 matching lines...) Expand all Loading... |
1264 ** TABLE statement, use all columns from the content table. | 1297 ** TABLE statement, use all columns from the content table. |
1265 */ | 1298 */ |
1266 if( rc==SQLITE_OK && zContent ){ | 1299 if( rc==SQLITE_OK && zContent ){ |
1267 sqlite3_free(zCompress); | 1300 sqlite3_free(zCompress); |
1268 sqlite3_free(zUncompress); | 1301 sqlite3_free(zUncompress); |
1269 zCompress = 0; | 1302 zCompress = 0; |
1270 zUncompress = 0; | 1303 zUncompress = 0; |
1271 if( nCol==0 ){ | 1304 if( nCol==0 ){ |
1272 sqlite3_free((void*)aCol); | 1305 sqlite3_free((void*)aCol); |
1273 aCol = 0; | 1306 aCol = 0; |
1274 rc = fts3ContentColumns(db, argv[1], zContent, &aCol, &nCol, &nString); | 1307 rc = fts3ContentColumns(db, argv[1], zContent,&aCol,&nCol,&nString,pzErr); |
1275 | 1308 |
1276 /* If a languageid= option was specified, remove the language id | 1309 /* If a languageid= option was specified, remove the language id |
1277 ** column from the aCol[] array. */ | 1310 ** column from the aCol[] array. */ |
1278 if( rc==SQLITE_OK && zLanguageid ){ | 1311 if( rc==SQLITE_OK && zLanguageid ){ |
1279 int j; | 1312 int j; |
1280 for(j=0; j<nCol; j++){ | 1313 for(j=0; j<nCol; j++){ |
1281 if( sqlite3_stricmp(zLanguageid, aCol[j])==0 ){ | 1314 if( sqlite3_stricmp(zLanguageid, aCol[j])==0 ){ |
1282 int k; | 1315 int k; |
1283 for(k=j; k<nCol; k++) aCol[k] = aCol[k+1]; | 1316 for(k=j; k<nCol; k++) aCol[k] = aCol[k+1]; |
1284 nCol--; | 1317 nCol--; |
(...skipping 14 matching lines...) Expand all Loading... |
1299 | 1332 |
1300 if( pTokenizer==0 ){ | 1333 if( pTokenizer==0 ){ |
1301 rc = sqlite3Fts3InitTokenizer(pHash, "simple", &pTokenizer, pzErr); | 1334 rc = sqlite3Fts3InitTokenizer(pHash, "simple", &pTokenizer, pzErr); |
1302 if( rc!=SQLITE_OK ) goto fts3_init_out; | 1335 if( rc!=SQLITE_OK ) goto fts3_init_out; |
1303 } | 1336 } |
1304 assert( pTokenizer ); | 1337 assert( pTokenizer ); |
1305 | 1338 |
1306 rc = fts3PrefixParameter(zPrefix, &nIndex, &aIndex); | 1339 rc = fts3PrefixParameter(zPrefix, &nIndex, &aIndex); |
1307 if( rc==SQLITE_ERROR ){ | 1340 if( rc==SQLITE_ERROR ){ |
1308 assert( zPrefix ); | 1341 assert( zPrefix ); |
1309 *pzErr = sqlite3_mprintf("error parsing prefix parameter: %s", zPrefix); | 1342 sqlite3Fts3ErrMsg(pzErr, "error parsing prefix parameter: %s", zPrefix); |
1310 } | 1343 } |
1311 if( rc!=SQLITE_OK ) goto fts3_init_out; | 1344 if( rc!=SQLITE_OK ) goto fts3_init_out; |
1312 | 1345 |
1313 /* Allocate and populate the Fts3Table structure. */ | 1346 /* Allocate and populate the Fts3Table structure. */ |
1314 nByte = sizeof(Fts3Table) + /* Fts3Table */ | 1347 nByte = sizeof(Fts3Table) + /* Fts3Table */ |
1315 nCol * sizeof(char *) + /* azColumn */ | 1348 nCol * sizeof(char *) + /* azColumn */ |
1316 nIndex * sizeof(struct Fts3Index) + /* aIndex */ | 1349 nIndex * sizeof(struct Fts3Index) + /* aIndex */ |
1317 nCol * sizeof(u8) + /* abNotindexed */ | 1350 nCol * sizeof(u8) + /* abNotindexed */ |
1318 nName + /* zName */ | 1351 nName + /* zName */ |
1319 nDb + /* zDb */ | 1352 nDb + /* zDb */ |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1381 && 0==sqlite3_strnicmp(p->azColumn[iCol], zNot, n) | 1414 && 0==sqlite3_strnicmp(p->azColumn[iCol], zNot, n) |
1382 ){ | 1415 ){ |
1383 p->abNotindexed[iCol] = 1; | 1416 p->abNotindexed[iCol] = 1; |
1384 sqlite3_free(zNot); | 1417 sqlite3_free(zNot); |
1385 azNotindexed[i] = 0; | 1418 azNotindexed[i] = 0; |
1386 } | 1419 } |
1387 } | 1420 } |
1388 } | 1421 } |
1389 for(i=0; i<nNotindexed; i++){ | 1422 for(i=0; i<nNotindexed; i++){ |
1390 if( azNotindexed[i] ){ | 1423 if( azNotindexed[i] ){ |
1391 *pzErr = sqlite3_mprintf("no such column: %s", azNotindexed[i]); | 1424 sqlite3Fts3ErrMsg(pzErr, "no such column: %s", azNotindexed[i]); |
1392 rc = SQLITE_ERROR; | 1425 rc = SQLITE_ERROR; |
1393 } | 1426 } |
1394 } | 1427 } |
1395 | 1428 |
1396 if( rc==SQLITE_OK && (zCompress==0)!=(zUncompress==0) ){ | 1429 if( rc==SQLITE_OK && (zCompress==0)!=(zUncompress==0) ){ |
1397 char const *zMiss = (zCompress==0 ? "compress" : "uncompress"); | 1430 char const *zMiss = (zCompress==0 ? "compress" : "uncompress"); |
1398 rc = SQLITE_ERROR; | 1431 rc = SQLITE_ERROR; |
1399 *pzErr = sqlite3_mprintf("missing %s parameter in fts4 constructor", zMiss); | 1432 sqlite3Fts3ErrMsg(pzErr, "missing %s parameter in fts4 constructor", zMiss); |
1400 } | 1433 } |
1401 p->zReadExprlist = fts3ReadExprList(p, zUncompress, &rc); | 1434 p->zReadExprlist = fts3ReadExprList(p, zUncompress, &rc); |
1402 p->zWriteExprlist = fts3WriteExprList(p, zCompress, &rc); | 1435 p->zWriteExprlist = fts3WriteExprList(p, zCompress, &rc); |
1403 if( rc!=SQLITE_OK ) goto fts3_init_out; | 1436 if( rc!=SQLITE_OK ) goto fts3_init_out; |
1404 | 1437 |
1405 /* If this is an xCreate call, create the underlying tables in the | 1438 /* If this is an xCreate call, create the underlying tables in the |
1406 ** database. TODO: For xConnect(), it could verify that said tables exist. | 1439 ** database. TODO: For xConnect(), it could verify that said tables exist. |
1407 */ | 1440 */ |
1408 if( isCreate ){ | 1441 if( isCreate ){ |
1409 rc = fts3CreateTables(p); | 1442 rc = fts3CreateTables(p); |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1478 ** support estimatedRows. In that case this function is a no-op. | 1511 ** support estimatedRows. In that case this function is a no-op. |
1479 */ | 1512 */ |
1480 static void fts3SetEstimatedRows(sqlite3_index_info *pIdxInfo, i64 nRow){ | 1513 static void fts3SetEstimatedRows(sqlite3_index_info *pIdxInfo, i64 nRow){ |
1481 #if SQLITE_VERSION_NUMBER>=3008002 | 1514 #if SQLITE_VERSION_NUMBER>=3008002 |
1482 if( sqlite3_libversion_number()>=3008002 ){ | 1515 if( sqlite3_libversion_number()>=3008002 ){ |
1483 pIdxInfo->estimatedRows = nRow; | 1516 pIdxInfo->estimatedRows = nRow; |
1484 } | 1517 } |
1485 #endif | 1518 #endif |
1486 } | 1519 } |
1487 | 1520 |
| 1521 /* |
| 1522 ** Set the SQLITE_INDEX_SCAN_UNIQUE flag in pIdxInfo->flags. Unless this |
| 1523 ** extension is currently being used by a version of SQLite too old to |
| 1524 ** support index-info flags. In that case this function is a no-op. |
| 1525 */ |
| 1526 static void fts3SetUniqueFlag(sqlite3_index_info *pIdxInfo){ |
| 1527 #if SQLITE_VERSION_NUMBER>=3008012 |
| 1528 if( sqlite3_libversion_number()>=3008012 ){ |
| 1529 pIdxInfo->idxFlags |= SQLITE_INDEX_SCAN_UNIQUE; |
| 1530 } |
| 1531 #endif |
| 1532 } |
| 1533 |
1488 /* | 1534 /* |
1489 ** Implementation of the xBestIndex method for FTS3 tables. There | 1535 ** Implementation of the xBestIndex method for FTS3 tables. There |
1490 ** are three possible strategies, in order of preference: | 1536 ** are three possible strategies, in order of preference: |
1491 ** | 1537 ** |
1492 ** 1. Direct lookup by rowid or docid. | 1538 ** 1. Direct lookup by rowid or docid. |
1493 ** 2. Full-text search using a MATCH operator on a non-docid column. | 1539 ** 2. Full-text search using a MATCH operator on a non-docid column. |
1494 ** 3. Linear scan of %_content table. | 1540 ** 3. Linear scan of %_content table. |
1495 */ | 1541 */ |
1496 static int fts3BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){ | 1542 static int fts3BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){ |
1497 Fts3Table *p = (Fts3Table *)pVTab; | 1543 Fts3Table *p = (Fts3Table *)pVTab; |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1568 break; | 1614 break; |
1569 | 1615 |
1570 case SQLITE_INDEX_CONSTRAINT_LE: | 1616 case SQLITE_INDEX_CONSTRAINT_LE: |
1571 case SQLITE_INDEX_CONSTRAINT_LT: | 1617 case SQLITE_INDEX_CONSTRAINT_LT: |
1572 iDocidLe = i; | 1618 iDocidLe = i; |
1573 break; | 1619 break; |
1574 } | 1620 } |
1575 } | 1621 } |
1576 } | 1622 } |
1577 | 1623 |
| 1624 /* If using a docid=? or rowid=? strategy, set the UNIQUE flag. */ |
| 1625 if( pInfo->idxNum==FTS3_DOCID_SEARCH ) fts3SetUniqueFlag(pInfo); |
| 1626 |
1578 iIdx = 1; | 1627 iIdx = 1; |
1579 if( iCons>=0 ){ | 1628 if( iCons>=0 ){ |
1580 pInfo->aConstraintUsage[iCons].argvIndex = iIdx++; | 1629 pInfo->aConstraintUsage[iCons].argvIndex = iIdx++; |
1581 pInfo->aConstraintUsage[iCons].omit = 1; | 1630 pInfo->aConstraintUsage[iCons].omit = 1; |
1582 } | 1631 } |
1583 if( iLangidCons>=0 ){ | 1632 if( iLangidCons>=0 ){ |
1584 pInfo->idxNum |= FTS3_HAVE_LANGID; | 1633 pInfo->idxNum |= FTS3_HAVE_LANGID; |
1585 pInfo->aConstraintUsage[iLangidCons].argvIndex = iIdx++; | 1634 pInfo->aConstraintUsage[iLangidCons].argvIndex = iIdx++; |
1586 } | 1635 } |
1587 if( iDocidGe>=0 ){ | 1636 if( iDocidGe>=0 ){ |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1636 ** Close the cursor. For additional information see the documentation | 1685 ** Close the cursor. For additional information see the documentation |
1637 ** on the xClose method of the virtual table interface. | 1686 ** on the xClose method of the virtual table interface. |
1638 */ | 1687 */ |
1639 static int fts3CloseMethod(sqlite3_vtab_cursor *pCursor){ | 1688 static int fts3CloseMethod(sqlite3_vtab_cursor *pCursor){ |
1640 Fts3Cursor *pCsr = (Fts3Cursor *)pCursor; | 1689 Fts3Cursor *pCsr = (Fts3Cursor *)pCursor; |
1641 assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 ); | 1690 assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 ); |
1642 sqlite3_finalize(pCsr->pStmt); | 1691 sqlite3_finalize(pCsr->pStmt); |
1643 sqlite3Fts3ExprFree(pCsr->pExpr); | 1692 sqlite3Fts3ExprFree(pCsr->pExpr); |
1644 sqlite3Fts3FreeDeferredTokens(pCsr); | 1693 sqlite3Fts3FreeDeferredTokens(pCsr); |
1645 sqlite3_free(pCsr->aDoclist); | 1694 sqlite3_free(pCsr->aDoclist); |
1646 sqlite3_free(pCsr->aMatchinfo); | 1695 sqlite3Fts3MIBufferFree(pCsr->pMIBuffer); |
1647 assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 ); | 1696 assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 ); |
1648 sqlite3_free(pCsr); | 1697 sqlite3_free(pCsr); |
1649 return SQLITE_OK; | 1698 return SQLITE_OK; |
1650 } | 1699 } |
1651 | 1700 |
1652 /* | 1701 /* |
1653 ** If pCsr->pStmt has not been prepared (i.e. if pCsr->pStmt==0), then | 1702 ** If pCsr->pStmt has not been prepared (i.e. if pCsr->pStmt==0), then |
1654 ** compose and prepare an SQL statement of the form: | 1703 ** compose and prepare an SQL statement of the form: |
1655 ** | 1704 ** |
1656 ** "SELECT <columns> FROM %_content WHERE rowid = ?" | 1705 ** "SELECT <columns> FROM %_content WHERE rowid = ?" |
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1853 */ | 1902 */ |
1854 static int fts3SelectLeaf( | 1903 static int fts3SelectLeaf( |
1855 Fts3Table *p, /* Virtual table handle */ | 1904 Fts3Table *p, /* Virtual table handle */ |
1856 const char *zTerm, /* Term to select leaves for */ | 1905 const char *zTerm, /* Term to select leaves for */ |
1857 int nTerm, /* Size of term zTerm in bytes */ | 1906 int nTerm, /* Size of term zTerm in bytes */ |
1858 const char *zNode, /* Buffer containing segment interior node */ | 1907 const char *zNode, /* Buffer containing segment interior node */ |
1859 int nNode, /* Size of buffer at zNode */ | 1908 int nNode, /* Size of buffer at zNode */ |
1860 sqlite3_int64 *piLeaf, /* Selected leaf node */ | 1909 sqlite3_int64 *piLeaf, /* Selected leaf node */ |
1861 sqlite3_int64 *piLeaf2 /* Selected leaf node */ | 1910 sqlite3_int64 *piLeaf2 /* Selected leaf node */ |
1862 ){ | 1911 ){ |
1863 int rc; /* Return code */ | 1912 int rc = SQLITE_OK; /* Return code */ |
1864 int iHeight; /* Height of this node in tree */ | 1913 int iHeight; /* Height of this node in tree */ |
1865 | 1914 |
1866 assert( piLeaf || piLeaf2 ); | 1915 assert( piLeaf || piLeaf2 ); |
1867 | 1916 |
1868 fts3GetVarint32(zNode, &iHeight); | 1917 fts3GetVarint32(zNode, &iHeight); |
1869 rc = fts3ScanInteriorNode(zTerm, nTerm, zNode, nNode, piLeaf, piLeaf2); | 1918 rc = fts3ScanInteriorNode(zTerm, nTerm, zNode, nNode, piLeaf, piLeaf2); |
1870 assert( !piLeaf2 || !piLeaf || rc!=SQLITE_OK || (*piLeaf<=*piLeaf2) ); | 1919 assert( !piLeaf2 || !piLeaf || rc!=SQLITE_OK || (*piLeaf<=*piLeaf2) ); |
1871 | 1920 |
1872 if( rc==SQLITE_OK && iHeight>1 ){ | 1921 if( rc==SQLITE_OK && iHeight>1 ){ |
1873 char *zBlob = 0; /* Blob read from %_segments table */ | 1922 char *zBlob = 0; /* Blob read from %_segments table */ |
1874 int nBlob; /* Size of zBlob in bytes */ | 1923 int nBlob = 0; /* Size of zBlob in bytes */ |
1875 | 1924 |
1876 if( piLeaf && piLeaf2 && (*piLeaf!=*piLeaf2) ){ | 1925 if( piLeaf && piLeaf2 && (*piLeaf!=*piLeaf2) ){ |
1877 rc = sqlite3Fts3ReadBlock(p, *piLeaf, &zBlob, &nBlob, 0); | 1926 rc = sqlite3Fts3ReadBlock(p, *piLeaf, &zBlob, &nBlob, 0); |
1878 if( rc==SQLITE_OK ){ | 1927 if( rc==SQLITE_OK ){ |
1879 rc = fts3SelectLeaf(p, zTerm, nTerm, zBlob, nBlob, piLeaf, 0); | 1928 rc = fts3SelectLeaf(p, zTerm, nTerm, zBlob, nBlob, piLeaf, 0); |
1880 } | 1929 } |
1881 sqlite3_free(zBlob); | 1930 sqlite3_free(zBlob); |
1882 piLeaf = 0; | 1931 piLeaf = 0; |
1883 zBlob = 0; | 1932 zBlob = 0; |
1884 } | 1933 } |
(...skipping 606 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2491 ** the output contains a copy of each position from the right-hand input | 2540 ** the output contains a copy of each position from the right-hand input |
2492 ** doclist for which there is a position in the left-hand input doclist | 2541 ** doclist for which there is a position in the left-hand input doclist |
2493 ** exactly nDist tokens before it. | 2542 ** exactly nDist tokens before it. |
2494 ** | 2543 ** |
2495 ** If the docids in the input doclists are sorted in ascending order, | 2544 ** If the docids in the input doclists are sorted in ascending order, |
2496 ** parameter bDescDoclist should be false. If they are sorted in ascending | 2545 ** parameter bDescDoclist should be false. If they are sorted in ascending |
2497 ** order, it should be passed a non-zero value. | 2546 ** order, it should be passed a non-zero value. |
2498 ** | 2547 ** |
2499 ** The right-hand input doclist is overwritten by this function. | 2548 ** The right-hand input doclist is overwritten by this function. |
2500 */ | 2549 */ |
2501 static void fts3DoclistPhraseMerge( | 2550 static int fts3DoclistPhraseMerge( |
2502 int bDescDoclist, /* True if arguments are desc */ | 2551 int bDescDoclist, /* True if arguments are desc */ |
2503 int nDist, /* Distance from left to right (1=adjacent) */ | 2552 int nDist, /* Distance from left to right (1=adjacent) */ |
2504 char *aLeft, int nLeft, /* Left doclist */ | 2553 char *aLeft, int nLeft, /* Left doclist */ |
2505 char *aRight, int *pnRight /* IN/OUT: Right/output doclist */ | 2554 char **paRight, int *pnRight /* IN/OUT: Right/output doclist */ |
2506 ){ | 2555 ){ |
2507 sqlite3_int64 i1 = 0; | 2556 sqlite3_int64 i1 = 0; |
2508 sqlite3_int64 i2 = 0; | 2557 sqlite3_int64 i2 = 0; |
2509 sqlite3_int64 iPrev = 0; | 2558 sqlite3_int64 iPrev = 0; |
| 2559 char *aRight = *paRight; |
2510 char *pEnd1 = &aLeft[nLeft]; | 2560 char *pEnd1 = &aLeft[nLeft]; |
2511 char *pEnd2 = &aRight[*pnRight]; | 2561 char *pEnd2 = &aRight[*pnRight]; |
2512 char *p1 = aLeft; | 2562 char *p1 = aLeft; |
2513 char *p2 = aRight; | 2563 char *p2 = aRight; |
2514 char *p; | 2564 char *p; |
2515 int bFirstOut = 0; | 2565 int bFirstOut = 0; |
2516 char *aOut = aRight; | 2566 char *aOut; |
2517 | 2567 |
2518 assert( nDist>0 ); | 2568 assert( nDist>0 ); |
| 2569 if( bDescDoclist ){ |
| 2570 aOut = sqlite3_malloc(*pnRight + FTS3_VARINT_MAX); |
| 2571 if( aOut==0 ) return SQLITE_NOMEM; |
| 2572 }else{ |
| 2573 aOut = aRight; |
| 2574 } |
| 2575 p = aOut; |
2519 | 2576 |
2520 p = aOut; | |
2521 fts3GetDeltaVarint3(&p1, pEnd1, 0, &i1); | 2577 fts3GetDeltaVarint3(&p1, pEnd1, 0, &i1); |
2522 fts3GetDeltaVarint3(&p2, pEnd2, 0, &i2); | 2578 fts3GetDeltaVarint3(&p2, pEnd2, 0, &i2); |
2523 | 2579 |
2524 while( p1 && p2 ){ | 2580 while( p1 && p2 ){ |
2525 sqlite3_int64 iDiff = DOCID_CMP(i1, i2); | 2581 sqlite3_int64 iDiff = DOCID_CMP(i1, i2); |
2526 if( iDiff==0 ){ | 2582 if( iDiff==0 ){ |
2527 char *pSave = p; | 2583 char *pSave = p; |
2528 sqlite3_int64 iPrevSave = iPrev; | 2584 sqlite3_int64 iPrevSave = iPrev; |
2529 int bFirstOutSave = bFirstOut; | 2585 int bFirstOutSave = bFirstOut; |
2530 | 2586 |
2531 fts3PutDeltaVarint3(&p, bDescDoclist, &iPrev, &bFirstOut, i1); | 2587 fts3PutDeltaVarint3(&p, bDescDoclist, &iPrev, &bFirstOut, i1); |
2532 if( 0==fts3PoslistPhraseMerge(&p, nDist, 0, 1, &p1, &p2) ){ | 2588 if( 0==fts3PoslistPhraseMerge(&p, nDist, 0, 1, &p1, &p2) ){ |
2533 p = pSave; | 2589 p = pSave; |
2534 iPrev = iPrevSave; | 2590 iPrev = iPrevSave; |
2535 bFirstOut = bFirstOutSave; | 2591 bFirstOut = bFirstOutSave; |
2536 } | 2592 } |
2537 fts3GetDeltaVarint3(&p1, pEnd1, bDescDoclist, &i1); | 2593 fts3GetDeltaVarint3(&p1, pEnd1, bDescDoclist, &i1); |
2538 fts3GetDeltaVarint3(&p2, pEnd2, bDescDoclist, &i2); | 2594 fts3GetDeltaVarint3(&p2, pEnd2, bDescDoclist, &i2); |
2539 }else if( iDiff<0 ){ | 2595 }else if( iDiff<0 ){ |
2540 fts3PoslistCopy(0, &p1); | 2596 fts3PoslistCopy(0, &p1); |
2541 fts3GetDeltaVarint3(&p1, pEnd1, bDescDoclist, &i1); | 2597 fts3GetDeltaVarint3(&p1, pEnd1, bDescDoclist, &i1); |
2542 }else{ | 2598 }else{ |
2543 fts3PoslistCopy(0, &p2); | 2599 fts3PoslistCopy(0, &p2); |
2544 fts3GetDeltaVarint3(&p2, pEnd2, bDescDoclist, &i2); | 2600 fts3GetDeltaVarint3(&p2, pEnd2, bDescDoclist, &i2); |
2545 } | 2601 } |
2546 } | 2602 } |
2547 | 2603 |
2548 *pnRight = (int)(p - aOut); | 2604 *pnRight = (int)(p - aOut); |
| 2605 if( bDescDoclist ){ |
| 2606 sqlite3_free(aRight); |
| 2607 *paRight = aOut; |
| 2608 } |
| 2609 |
| 2610 return SQLITE_OK; |
2549 } | 2611 } |
2550 | 2612 |
2551 /* | 2613 /* |
2552 ** Argument pList points to a position list nList bytes in size. This | 2614 ** Argument pList points to a position list nList bytes in size. This |
2553 ** function checks to see if the position list contains any entries for | 2615 ** function checks to see if the position list contains any entries for |
2554 ** a token in position 0 (of any column). If so, it writes argument iDelta | 2616 ** a token in position 0 (of any column). If so, it writes argument iDelta |
2555 ** to the output buffer pOut, followed by a position list consisting only | 2617 ** to the output buffer pOut, followed by a position list consisting only |
2556 ** of the entries from pList at position 0, and terminated by an 0x00 byte. | 2618 ** of the entries from pList at position 0, and terminated by an 0x00 byte. |
2557 ** The value returned is the number of bytes written to pOut (if any). | 2619 ** The value returned is the number of bytes written to pOut (if any). |
2558 */ | 2620 */ |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2663 ** SQLite error code (SQLITE_NOMEM) if an error occurs. | 2725 ** SQLite error code (SQLITE_NOMEM) if an error occurs. |
2664 */ | 2726 */ |
2665 static int fts3TermSelectMerge( | 2727 static int fts3TermSelectMerge( |
2666 Fts3Table *p, /* FTS table handle */ | 2728 Fts3Table *p, /* FTS table handle */ |
2667 TermSelect *pTS, /* TermSelect object to merge into */ | 2729 TermSelect *pTS, /* TermSelect object to merge into */ |
2668 char *aDoclist, /* Pointer to doclist */ | 2730 char *aDoclist, /* Pointer to doclist */ |
2669 int nDoclist /* Size of aDoclist in bytes */ | 2731 int nDoclist /* Size of aDoclist in bytes */ |
2670 ){ | 2732 ){ |
2671 if( pTS->aaOutput[0]==0 ){ | 2733 if( pTS->aaOutput[0]==0 ){ |
2672 /* If this is the first term selected, copy the doclist to the output | 2734 /* If this is the first term selected, copy the doclist to the output |
2673 ** buffer using memcpy(). */ | 2735 ** buffer using memcpy(). |
2674 pTS->aaOutput[0] = sqlite3_malloc(nDoclist); | 2736 ** |
| 2737 ** Add FTS3_VARINT_MAX bytes of unused space to the end of the |
| 2738 ** allocation. This is so as to ensure that the buffer is big enough |
| 2739 ** to hold the current doclist AND'd with any other doclist. If the |
| 2740 ** doclists are stored in order=ASC order, this padding would not be |
| 2741 ** required (since the size of [doclistA AND doclistB] is always less |
| 2742 ** than or equal to the size of [doclistA] in that case). But this is |
| 2743 ** not true for order=DESC. For example, a doclist containing (1, -1) |
| 2744 ** may be smaller than (-1), as in the first example the -1 may be stored |
| 2745 ** as a single-byte delta, whereas in the second it must be stored as a |
| 2746 ** FTS3_VARINT_MAX byte varint. |
| 2747 ** |
| 2748 ** Similar padding is added in the fts3DoclistOrMerge() function. |
| 2749 */ |
| 2750 pTS->aaOutput[0] = sqlite3_malloc(nDoclist + FTS3_VARINT_MAX + 1); |
2675 pTS->anOutput[0] = nDoclist; | 2751 pTS->anOutput[0] = nDoclist; |
2676 if( pTS->aaOutput[0] ){ | 2752 if( pTS->aaOutput[0] ){ |
2677 memcpy(pTS->aaOutput[0], aDoclist, nDoclist); | 2753 memcpy(pTS->aaOutput[0], aDoclist, nDoclist); |
2678 }else{ | 2754 }else{ |
2679 return SQLITE_NOMEM; | 2755 return SQLITE_NOMEM; |
2680 } | 2756 } |
2681 }else{ | 2757 }else{ |
2682 char *aMerge = aDoclist; | 2758 char *aMerge = aDoclist; |
2683 int nMerge = nDoclist; | 2759 int nMerge = nDoclist; |
2684 int iOut; | 2760 int iOut; |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2761 int rc2; /* Result of sqlite3_reset() */ | 2837 int rc2; /* Result of sqlite3_reset() */ |
2762 | 2838 |
2763 /* If iLevel is less than 0 and this is not a scan, include a seg-reader | 2839 /* If iLevel is less than 0 and this is not a scan, include a seg-reader |
2764 ** for the pending-terms. If this is a scan, then this call must be being | 2840 ** for the pending-terms. If this is a scan, then this call must be being |
2765 ** made by an fts4aux module, not an FTS table. In this case calling | 2841 ** made by an fts4aux module, not an FTS table. In this case calling |
2766 ** Fts3SegReaderPending might segfault, as the data structures used by | 2842 ** Fts3SegReaderPending might segfault, as the data structures used by |
2767 ** fts4aux are not completely populated. So it's easiest to filter these | 2843 ** fts4aux are not completely populated. So it's easiest to filter these |
2768 ** calls out here. */ | 2844 ** calls out here. */ |
2769 if( iLevel<0 && p->aIndex ){ | 2845 if( iLevel<0 && p->aIndex ){ |
2770 Fts3SegReader *pSeg = 0; | 2846 Fts3SegReader *pSeg = 0; |
2771 rc = sqlite3Fts3SegReaderPending(p, iIndex, zTerm, nTerm, isPrefix, &pSeg); | 2847 rc = sqlite3Fts3SegReaderPending(p, iIndex, zTerm, nTerm, isPrefix||isScan,
&pSeg); |
2772 if( rc==SQLITE_OK && pSeg ){ | 2848 if( rc==SQLITE_OK && pSeg ){ |
2773 rc = fts3SegReaderCursorAppend(pCsr, pSeg); | 2849 rc = fts3SegReaderCursorAppend(pCsr, pSeg); |
2774 } | 2850 } |
2775 } | 2851 } |
2776 | 2852 |
2777 if( iLevel!=FTS3_SEGCURSOR_PENDING ){ | 2853 if( iLevel!=FTS3_SEGCURSOR_PENDING ){ |
2778 if( rc==SQLITE_OK ){ | 2854 if( rc==SQLITE_OK ){ |
2779 rc = sqlite3Fts3AllSegdirs(p, iLangid, iIndex, iLevel, &pStmt); | 2855 rc = sqlite3Fts3AllSegdirs(p, iLangid, iIndex, iLevel, &pStmt); |
2780 } | 2856 } |
2781 | 2857 |
(...skipping 304 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3086 ** number idxNum-FTS3_FULLTEXT_SEARCH, 0 indexed. argv[0] is the right-hand | 3162 ** number idxNum-FTS3_FULLTEXT_SEARCH, 0 indexed. argv[0] is the right-hand |
3087 ** side of the MATCH operator. | 3163 ** side of the MATCH operator. |
3088 */ | 3164 */ |
3089 static int fts3FilterMethod( | 3165 static int fts3FilterMethod( |
3090 sqlite3_vtab_cursor *pCursor, /* The cursor used for this query */ | 3166 sqlite3_vtab_cursor *pCursor, /* The cursor used for this query */ |
3091 int idxNum, /* Strategy index */ | 3167 int idxNum, /* Strategy index */ |
3092 const char *idxStr, /* Unused */ | 3168 const char *idxStr, /* Unused */ |
3093 int nVal, /* Number of elements in apVal */ | 3169 int nVal, /* Number of elements in apVal */ |
3094 sqlite3_value **apVal /* Arguments for the indexing scheme */ | 3170 sqlite3_value **apVal /* Arguments for the indexing scheme */ |
3095 ){ | 3171 ){ |
3096 int rc; | 3172 int rc = SQLITE_OK; |
3097 char *zSql; /* SQL statement used to access %_content */ | 3173 char *zSql; /* SQL statement used to access %_content */ |
3098 int eSearch; | 3174 int eSearch; |
3099 Fts3Table *p = (Fts3Table *)pCursor->pVtab; | 3175 Fts3Table *p = (Fts3Table *)pCursor->pVtab; |
3100 Fts3Cursor *pCsr = (Fts3Cursor *)pCursor; | 3176 Fts3Cursor *pCsr = (Fts3Cursor *)pCursor; |
3101 | 3177 |
3102 sqlite3_value *pCons = 0; /* The MATCH or rowid constraint, if any */ | 3178 sqlite3_value *pCons = 0; /* The MATCH or rowid constraint, if any */ |
3103 sqlite3_value *pLangid = 0; /* The "langid = ?" constraint, if any */ | 3179 sqlite3_value *pLangid = 0; /* The "langid = ?" constraint, if any */ |
3104 sqlite3_value *pDocidGe = 0; /* The "docid >= ?" constraint, if any */ | 3180 sqlite3_value *pDocidGe = 0; /* The "docid >= ?" constraint, if any */ |
3105 sqlite3_value *pDocidLe = 0; /* The "docid <= ?" constraint, if any */ | 3181 sqlite3_value *pDocidLe = 0; /* The "docid <= ?" constraint, if any */ |
3106 int iIdx; | 3182 int iIdx; |
3107 | 3183 |
3108 UNUSED_PARAMETER(idxStr); | 3184 UNUSED_PARAMETER(idxStr); |
3109 UNUSED_PARAMETER(nVal); | 3185 UNUSED_PARAMETER(nVal); |
3110 | 3186 |
3111 eSearch = (idxNum & 0x0000FFFF); | 3187 eSearch = (idxNum & 0x0000FFFF); |
3112 assert( eSearch>=0 && eSearch<=(FTS3_FULLTEXT_SEARCH+p->nColumn) ); | 3188 assert( eSearch>=0 && eSearch<=(FTS3_FULLTEXT_SEARCH+p->nColumn) ); |
3113 assert( p->pSegments==0 ); | 3189 assert( p->pSegments==0 ); |
3114 | 3190 |
3115 /* Collect arguments into local variables */ | 3191 /* Collect arguments into local variables */ |
3116 iIdx = 0; | 3192 iIdx = 0; |
3117 if( eSearch!=FTS3_FULLSCAN_SEARCH ) pCons = apVal[iIdx++]; | 3193 if( eSearch!=FTS3_FULLSCAN_SEARCH ) pCons = apVal[iIdx++]; |
3118 if( idxNum & FTS3_HAVE_LANGID ) pLangid = apVal[iIdx++]; | 3194 if( idxNum & FTS3_HAVE_LANGID ) pLangid = apVal[iIdx++]; |
3119 if( idxNum & FTS3_HAVE_DOCID_GE ) pDocidGe = apVal[iIdx++]; | 3195 if( idxNum & FTS3_HAVE_DOCID_GE ) pDocidGe = apVal[iIdx++]; |
3120 if( idxNum & FTS3_HAVE_DOCID_LE ) pDocidLe = apVal[iIdx++]; | 3196 if( idxNum & FTS3_HAVE_DOCID_LE ) pDocidLe = apVal[iIdx++]; |
3121 assert( iIdx==nVal ); | 3197 assert( iIdx==nVal ); |
3122 | 3198 |
3123 /* In case the cursor has been used before, clear it now. */ | 3199 /* In case the cursor has been used before, clear it now. */ |
3124 sqlite3_finalize(pCsr->pStmt); | 3200 sqlite3_finalize(pCsr->pStmt); |
3125 sqlite3_free(pCsr->aDoclist); | 3201 sqlite3_free(pCsr->aDoclist); |
3126 sqlite3_free(pCsr->aMatchinfo); | 3202 sqlite3Fts3MIBufferFree(pCsr->pMIBuffer); |
3127 sqlite3Fts3ExprFree(pCsr->pExpr); | 3203 sqlite3Fts3ExprFree(pCsr->pExpr); |
3128 memset(&pCursor[1], 0, sizeof(Fts3Cursor)-sizeof(sqlite3_vtab_cursor)); | 3204 memset(&pCursor[1], 0, sizeof(Fts3Cursor)-sizeof(sqlite3_vtab_cursor)); |
3129 | 3205 |
3130 /* Set the lower and upper bounds on docids to return */ | 3206 /* Set the lower and upper bounds on docids to return */ |
3131 pCsr->iMinDocid = fts3DocidRange(pDocidGe, SMALLEST_INT64); | 3207 pCsr->iMinDocid = fts3DocidRange(pDocidGe, SMALLEST_INT64); |
3132 pCsr->iMaxDocid = fts3DocidRange(pDocidLe, LARGEST_INT64); | 3208 pCsr->iMaxDocid = fts3DocidRange(pDocidLe, LARGEST_INT64); |
3133 | 3209 |
3134 if( idxStr ){ | 3210 if( idxStr ){ |
3135 pCsr->bDesc = (idxStr[0]=='D'); | 3211 pCsr->bDesc = (idxStr[0]=='D'); |
3136 }else{ | 3212 }else{ |
(...skipping 27 matching lines...) Expand all Loading... |
3164 pCsr->pNextId = pCsr->aDoclist; | 3240 pCsr->pNextId = pCsr->aDoclist; |
3165 pCsr->iPrevId = 0; | 3241 pCsr->iPrevId = 0; |
3166 } | 3242 } |
3167 | 3243 |
3168 /* Compile a SELECT statement for this cursor. For a full-table-scan, the | 3244 /* Compile a SELECT statement for this cursor. For a full-table-scan, the |
3169 ** statement loops through all rows of the %_content table. For a | 3245 ** statement loops through all rows of the %_content table. For a |
3170 ** full-text query or docid lookup, the statement retrieves a single | 3246 ** full-text query or docid lookup, the statement retrieves a single |
3171 ** row by docid. | 3247 ** row by docid. |
3172 */ | 3248 */ |
3173 if( eSearch==FTS3_FULLSCAN_SEARCH ){ | 3249 if( eSearch==FTS3_FULLSCAN_SEARCH ){ |
3174 zSql = sqlite3_mprintf( | 3250 if( pDocidGe || pDocidLe ){ |
3175 "SELECT %s ORDER BY rowid %s", | 3251 zSql = sqlite3_mprintf( |
3176 p->zReadExprlist, (pCsr->bDesc ? "DESC" : "ASC") | 3252 "SELECT %s WHERE rowid BETWEEN %lld AND %lld ORDER BY rowid %s", |
3177 ); | 3253 p->zReadExprlist, pCsr->iMinDocid, pCsr->iMaxDocid, |
| 3254 (pCsr->bDesc ? "DESC" : "ASC") |
| 3255 ); |
| 3256 }else{ |
| 3257 zSql = sqlite3_mprintf("SELECT %s ORDER BY rowid %s", |
| 3258 p->zReadExprlist, (pCsr->bDesc ? "DESC" : "ASC") |
| 3259 ); |
| 3260 } |
3178 if( zSql ){ | 3261 if( zSql ){ |
3179 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pCsr->pStmt, 0); | 3262 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pCsr->pStmt, 0); |
3180 sqlite3_free(zSql); | 3263 sqlite3_free(zSql); |
3181 }else{ | 3264 }else{ |
3182 rc = SQLITE_NOMEM; | 3265 rc = SQLITE_NOMEM; |
3183 } | 3266 } |
3184 }else if( eSearch==FTS3_DOCID_SEARCH ){ | 3267 }else if( eSearch==FTS3_DOCID_SEARCH ){ |
3185 rc = fts3CursorSeekStmt(pCsr, &pCsr->pStmt); | 3268 rc = fts3CursorSeekStmt(pCsr, &pCsr->pStmt); |
3186 if( rc==SQLITE_OK ){ | 3269 if( rc==SQLITE_OK ){ |
3187 rc = sqlite3_bind_value(pCsr->pStmt, 1, pCons); | 3270 rc = sqlite3_bind_value(pCsr->pStmt, 1, pCons); |
(...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3403 /* | 3486 /* |
3404 ** When called, *ppPoslist must point to the byte immediately following the | 3487 ** When called, *ppPoslist must point to the byte immediately following the |
3405 ** end of a position-list. i.e. ( (*ppPoslist)[-1]==POS_END ). This function | 3488 ** end of a position-list. i.e. ( (*ppPoslist)[-1]==POS_END ). This function |
3406 ** moves *ppPoslist so that it instead points to the first byte of the | 3489 ** moves *ppPoslist so that it instead points to the first byte of the |
3407 ** same position list. | 3490 ** same position list. |
3408 */ | 3491 */ |
3409 static void fts3ReversePoslist(char *pStart, char **ppPoslist){ | 3492 static void fts3ReversePoslist(char *pStart, char **ppPoslist){ |
3410 char *p = &(*ppPoslist)[-2]; | 3493 char *p = &(*ppPoslist)[-2]; |
3411 char c = 0; | 3494 char c = 0; |
3412 | 3495 |
| 3496 /* Skip backwards passed any trailing 0x00 bytes added by NearTrim() */ |
3413 while( p>pStart && (c=*p--)==0 ); | 3497 while( p>pStart && (c=*p--)==0 ); |
| 3498 |
| 3499 /* Search backwards for a varint with value zero (the end of the previous |
| 3500 ** poslist). This is an 0x00 byte preceded by some byte that does not |
| 3501 ** have the 0x80 bit set. */ |
3414 while( p>pStart && (*p & 0x80) | c ){ | 3502 while( p>pStart && (*p & 0x80) | c ){ |
3415 c = *p--; | 3503 c = *p--; |
3416 } | 3504 } |
3417 if( p>pStart ){ p = &p[2]; } | 3505 assert( p==pStart || c==0 ); |
| 3506 |
| 3507 /* At this point p points to that preceding byte without the 0x80 bit |
| 3508 ** set. So to find the start of the poslist, skip forward 2 bytes then |
| 3509 ** over a varint. |
| 3510 ** |
| 3511 ** Normally. The other case is that p==pStart and the poslist to return |
| 3512 ** is the first in the doclist. In this case do not skip forward 2 bytes. |
| 3513 ** The second part of the if condition (c==0 && *ppPoslist>&p[2]) |
| 3514 ** is required for cases where the first byte of a doclist and the |
| 3515 ** doclist is empty. For example, if the first docid is 10, a doclist |
| 3516 ** that begins with: |
| 3517 ** |
| 3518 ** 0x0A 0x00 <next docid delta varint> |
| 3519 */ |
| 3520 if( p>pStart || (c==0 && *ppPoslist>&p[2]) ){ p = &p[2]; } |
3418 while( *p++&0x80 ); | 3521 while( *p++&0x80 ); |
3419 *ppPoslist = p; | 3522 *ppPoslist = p; |
3420 } | 3523 } |
3421 | 3524 |
3422 /* | 3525 /* |
3423 ** Helper function used by the implementation of the overloaded snippet(), | 3526 ** Helper function used by the implementation of the overloaded snippet(), |
3424 ** offsets() and optimize() SQL functions. | 3527 ** offsets() and optimize() SQL functions. |
3425 ** | 3528 ** |
3426 ** If the value passed as the third argument is a blob of size | 3529 ** If the value passed as the third argument is a blob of size |
3427 ** sizeof(Fts3Cursor*), then the blob contents are copied to the | 3530 ** sizeof(Fts3Cursor*), then the blob contents are copied to the |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3478 | 3581 |
3479 switch( nVal ){ | 3582 switch( nVal ){ |
3480 case 6: nToken = sqlite3_value_int(apVal[5]); | 3583 case 6: nToken = sqlite3_value_int(apVal[5]); |
3481 case 5: iCol = sqlite3_value_int(apVal[4]); | 3584 case 5: iCol = sqlite3_value_int(apVal[4]); |
3482 case 4: zEllipsis = (const char*)sqlite3_value_text(apVal[3]); | 3585 case 4: zEllipsis = (const char*)sqlite3_value_text(apVal[3]); |
3483 case 3: zEnd = (const char*)sqlite3_value_text(apVal[2]); | 3586 case 3: zEnd = (const char*)sqlite3_value_text(apVal[2]); |
3484 case 2: zStart = (const char*)sqlite3_value_text(apVal[1]); | 3587 case 2: zStart = (const char*)sqlite3_value_text(apVal[1]); |
3485 } | 3588 } |
3486 if( !zEllipsis || !zEnd || !zStart ){ | 3589 if( !zEllipsis || !zEnd || !zStart ){ |
3487 sqlite3_result_error_nomem(pContext); | 3590 sqlite3_result_error_nomem(pContext); |
| 3591 }else if( nToken==0 ){ |
| 3592 sqlite3_result_text(pContext, "", -1, SQLITE_STATIC); |
3488 }else if( SQLITE_OK==fts3CursorSeek(pContext, pCsr) ){ | 3593 }else if( SQLITE_OK==fts3CursorSeek(pContext, pCsr) ){ |
3489 sqlite3Fts3Snippet(pContext, pCsr, zStart, zEnd, zEllipsis, iCol, nToken); | 3594 sqlite3Fts3Snippet(pContext, pCsr, zStart, zEnd, zEllipsis, iCol, nToken); |
3490 } | 3595 } |
3491 } | 3596 } |
3492 | 3597 |
3493 /* | 3598 /* |
3494 ** Implementation of the offsets() function for FTS3 | 3599 ** Implementation of the offsets() function for FTS3 |
3495 */ | 3600 */ |
3496 static void fts3OffsetsFunc( | 3601 static void fts3OffsetsFunc( |
3497 sqlite3_context *pContext, /* SQLite function call context */ | 3602 sqlite3_context *pContext, /* SQLite function call context */ |
(...skipping 423 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3921 } | 4026 } |
3922 } | 4027 } |
3923 | 4028 |
3924 /* | 4029 /* |
3925 ** Arguments pList/nList contain the doclist for token iToken of phrase p. | 4030 ** Arguments pList/nList contain the doclist for token iToken of phrase p. |
3926 ** It is merged into the main doclist stored in p->doclist.aAll/nAll. | 4031 ** It is merged into the main doclist stored in p->doclist.aAll/nAll. |
3927 ** | 4032 ** |
3928 ** This function assumes that pList points to a buffer allocated using | 4033 ** This function assumes that pList points to a buffer allocated using |
3929 ** sqlite3_malloc(). This function takes responsibility for eventually | 4034 ** sqlite3_malloc(). This function takes responsibility for eventually |
3930 ** freeing the buffer. | 4035 ** freeing the buffer. |
| 4036 ** |
| 4037 ** SQLITE_OK is returned if successful, or SQLITE_NOMEM if an error occurs. |
3931 */ | 4038 */ |
3932 static void fts3EvalPhraseMergeToken( | 4039 static int fts3EvalPhraseMergeToken( |
3933 Fts3Table *pTab, /* FTS Table pointer */ | 4040 Fts3Table *pTab, /* FTS Table pointer */ |
3934 Fts3Phrase *p, /* Phrase to merge pList/nList into */ | 4041 Fts3Phrase *p, /* Phrase to merge pList/nList into */ |
3935 int iToken, /* Token pList/nList corresponds to */ | 4042 int iToken, /* Token pList/nList corresponds to */ |
3936 char *pList, /* Pointer to doclist */ | 4043 char *pList, /* Pointer to doclist */ |
3937 int nList /* Number of bytes in pList */ | 4044 int nList /* Number of bytes in pList */ |
3938 ){ | 4045 ){ |
| 4046 int rc = SQLITE_OK; |
3939 assert( iToken!=p->iDoclistToken ); | 4047 assert( iToken!=p->iDoclistToken ); |
3940 | 4048 |
3941 if( pList==0 ){ | 4049 if( pList==0 ){ |
3942 sqlite3_free(p->doclist.aAll); | 4050 sqlite3_free(p->doclist.aAll); |
3943 p->doclist.aAll = 0; | 4051 p->doclist.aAll = 0; |
3944 p->doclist.nAll = 0; | 4052 p->doclist.nAll = 0; |
3945 } | 4053 } |
3946 | 4054 |
3947 else if( p->iDoclistToken<0 ){ | 4055 else if( p->iDoclistToken<0 ){ |
3948 p->doclist.aAll = pList; | 4056 p->doclist.aAll = pList; |
(...skipping 18 matching lines...) Expand all Loading... |
3967 nRight = nList; | 4075 nRight = nList; |
3968 nDiff = iToken - p->iDoclistToken; | 4076 nDiff = iToken - p->iDoclistToken; |
3969 }else{ | 4077 }else{ |
3970 pRight = p->doclist.aAll; | 4078 pRight = p->doclist.aAll; |
3971 nRight = p->doclist.nAll; | 4079 nRight = p->doclist.nAll; |
3972 pLeft = pList; | 4080 pLeft = pList; |
3973 nLeft = nList; | 4081 nLeft = nList; |
3974 nDiff = p->iDoclistToken - iToken; | 4082 nDiff = p->iDoclistToken - iToken; |
3975 } | 4083 } |
3976 | 4084 |
3977 fts3DoclistPhraseMerge(pTab->bDescIdx, nDiff, pLeft, nLeft, pRight,&nRight); | 4085 rc = fts3DoclistPhraseMerge( |
| 4086 pTab->bDescIdx, nDiff, pLeft, nLeft, &pRight, &nRight |
| 4087 ); |
3978 sqlite3_free(pLeft); | 4088 sqlite3_free(pLeft); |
3979 p->doclist.aAll = pRight; | 4089 p->doclist.aAll = pRight; |
3980 p->doclist.nAll = nRight; | 4090 p->doclist.nAll = nRight; |
3981 } | 4091 } |
3982 | 4092 |
3983 if( iToken>p->iDoclistToken ) p->iDoclistToken = iToken; | 4093 if( iToken>p->iDoclistToken ) p->iDoclistToken = iToken; |
| 4094 return rc; |
3984 } | 4095 } |
3985 | 4096 |
3986 /* | 4097 /* |
3987 ** Load the doclist for phrase p into p->doclist.aAll/nAll. The loaded doclist | 4098 ** Load the doclist for phrase p into p->doclist.aAll/nAll. The loaded doclist |
3988 ** does not take deferred tokens into account. | 4099 ** does not take deferred tokens into account. |
3989 ** | 4100 ** |
3990 ** SQLITE_OK is returned if no error occurs, otherwise an SQLite error code. | 4101 ** SQLITE_OK is returned if no error occurs, otherwise an SQLite error code. |
3991 */ | 4102 */ |
3992 static int fts3EvalPhraseLoad( | 4103 static int fts3EvalPhraseLoad( |
3993 Fts3Cursor *pCsr, /* FTS Cursor handle */ | 4104 Fts3Cursor *pCsr, /* FTS Cursor handle */ |
3994 Fts3Phrase *p /* Phrase object */ | 4105 Fts3Phrase *p /* Phrase object */ |
3995 ){ | 4106 ){ |
3996 Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab; | 4107 Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab; |
3997 int iToken; | 4108 int iToken; |
3998 int rc = SQLITE_OK; | 4109 int rc = SQLITE_OK; |
3999 | 4110 |
4000 for(iToken=0; rc==SQLITE_OK && iToken<p->nToken; iToken++){ | 4111 for(iToken=0; rc==SQLITE_OK && iToken<p->nToken; iToken++){ |
4001 Fts3PhraseToken *pToken = &p->aToken[iToken]; | 4112 Fts3PhraseToken *pToken = &p->aToken[iToken]; |
4002 assert( pToken->pDeferred==0 || pToken->pSegcsr==0 ); | 4113 assert( pToken->pDeferred==0 || pToken->pSegcsr==0 ); |
4003 | 4114 |
4004 if( pToken->pSegcsr ){ | 4115 if( pToken->pSegcsr ){ |
4005 int nThis = 0; | 4116 int nThis = 0; |
4006 char *pThis = 0; | 4117 char *pThis = 0; |
4007 rc = fts3TermSelect(pTab, pToken, p->iColumn, &nThis, &pThis); | 4118 rc = fts3TermSelect(pTab, pToken, p->iColumn, &nThis, &pThis); |
4008 if( rc==SQLITE_OK ){ | 4119 if( rc==SQLITE_OK ){ |
4009 fts3EvalPhraseMergeToken(pTab, p, iToken, pThis, nThis); | 4120 rc = fts3EvalPhraseMergeToken(pTab, p, iToken, pThis, nThis); |
4010 } | 4121 } |
4011 } | 4122 } |
4012 assert( pToken->pSegcsr==0 ); | 4123 assert( pToken->pSegcsr==0 ); |
4013 } | 4124 } |
4014 | 4125 |
4015 return rc; | 4126 return rc; |
4016 } | 4127 } |
4017 | 4128 |
4018 /* | 4129 /* |
4019 ** This function is called on each phrase after the position lists for | 4130 ** 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... |
4144 | 4255 |
4145 /* Determine if doclists may be loaded from disk incrementally. This is | 4256 /* Determine if doclists may be loaded from disk incrementally. This is |
4146 ** possible if the bOptOk argument is true, the FTS doclists will be | 4257 ** possible if the bOptOk argument is true, the FTS doclists will be |
4147 ** scanned in forward order, and the phrase consists of | 4258 ** scanned in forward order, and the phrase consists of |
4148 ** MAX_INCR_PHRASE_TOKENS or fewer tokens, none of which are are "^first" | 4259 ** MAX_INCR_PHRASE_TOKENS or fewer tokens, none of which are are "^first" |
4149 ** tokens or prefix tokens that cannot use a prefix-index. */ | 4260 ** tokens or prefix tokens that cannot use a prefix-index. */ |
4150 int bHaveIncr = 0; | 4261 int bHaveIncr = 0; |
4151 int bIncrOk = (bOptOk | 4262 int bIncrOk = (bOptOk |
4152 && pCsr->bDesc==pTab->bDescIdx | 4263 && pCsr->bDesc==pTab->bDescIdx |
4153 && p->nToken<=MAX_INCR_PHRASE_TOKENS && p->nToken>0 | 4264 && p->nToken<=MAX_INCR_PHRASE_TOKENS && p->nToken>0 |
4154 && p->nToken<=MAX_INCR_PHRASE_TOKENS && p->nToken>0 | |
4155 #ifdef SQLITE_TEST | 4265 #ifdef SQLITE_TEST |
4156 && pTab->bNoIncrDoclist==0 | 4266 && pTab->bNoIncrDoclist==0 |
4157 #endif | 4267 #endif |
4158 ); | 4268 ); |
4159 for(i=0; bIncrOk==1 && i<p->nToken; i++){ | 4269 for(i=0; bIncrOk==1 && i<p->nToken; i++){ |
4160 Fts3PhraseToken *pToken = &p->aToken[i]; | 4270 Fts3PhraseToken *pToken = &p->aToken[i]; |
4161 if( pToken->bFirst || (pToken->pSegcsr!=0 && !pToken->pSegcsr->bLookup) ){ | 4271 if( pToken->bFirst || (pToken->pSegcsr!=0 && !pToken->pSegcsr->bLookup) ){ |
4162 bIncrOk = 0; | 4272 bIncrOk = 0; |
4163 } | 4273 } |
4164 if( pToken->pSegcsr ) bHaveIncr = 1; | 4274 if( pToken->pSegcsr ) bHaveIncr = 1; |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4264 assert( nDoclist>0 ); | 4374 assert( nDoclist>0 ); |
4265 assert( *pbEof==0 ); | 4375 assert( *pbEof==0 ); |
4266 assert( p || *piDocid==0 ); | 4376 assert( p || *piDocid==0 ); |
4267 assert( !p || (p>=aDoclist && p<=&aDoclist[nDoclist]) ); | 4377 assert( !p || (p>=aDoclist && p<=&aDoclist[nDoclist]) ); |
4268 | 4378 |
4269 if( p==0 ){ | 4379 if( p==0 ){ |
4270 p = aDoclist; | 4380 p = aDoclist; |
4271 p += sqlite3Fts3GetVarint(p, piDocid); | 4381 p += sqlite3Fts3GetVarint(p, piDocid); |
4272 }else{ | 4382 }else{ |
4273 fts3PoslistCopy(0, &p); | 4383 fts3PoslistCopy(0, &p); |
| 4384 while( p<&aDoclist[nDoclist] && *p==0 ) p++; |
4274 if( p>=&aDoclist[nDoclist] ){ | 4385 if( p>=&aDoclist[nDoclist] ){ |
4275 *pbEof = 1; | 4386 *pbEof = 1; |
4276 }else{ | 4387 }else{ |
4277 sqlite3_int64 iVar; | 4388 sqlite3_int64 iVar; |
4278 p += sqlite3Fts3GetVarint(p, &iVar); | 4389 p += sqlite3Fts3GetVarint(p, &iVar); |
4279 *piDocid += ((bDescIdx ? -1 : 1) * iVar); | 4390 *piDocid += ((bDescIdx ? -1 : 1) * iVar); |
4280 } | 4391 } |
4281 } | 4392 } |
4282 | 4393 |
4283 *ppIter = p; | 4394 *ppIter = p; |
(...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4541 ** If an error occurs within this function, *pRc is set to an SQLite error | 4652 ** If an error occurs within this function, *pRc is set to an SQLite error |
4542 ** code before returning. | 4653 ** code before returning. |
4543 */ | 4654 */ |
4544 static void fts3EvalStartReaders( | 4655 static void fts3EvalStartReaders( |
4545 Fts3Cursor *pCsr, /* FTS Cursor handle */ | 4656 Fts3Cursor *pCsr, /* FTS Cursor handle */ |
4546 Fts3Expr *pExpr, /* Expression to initialize phrases in */ | 4657 Fts3Expr *pExpr, /* Expression to initialize phrases in */ |
4547 int *pRc /* IN/OUT: Error code */ | 4658 int *pRc /* IN/OUT: Error code */ |
4548 ){ | 4659 ){ |
4549 if( pExpr && SQLITE_OK==*pRc ){ | 4660 if( pExpr && SQLITE_OK==*pRc ){ |
4550 if( pExpr->eType==FTSQUERY_PHRASE ){ | 4661 if( pExpr->eType==FTSQUERY_PHRASE ){ |
4551 int i; | |
4552 int nToken = pExpr->pPhrase->nToken; | 4662 int nToken = pExpr->pPhrase->nToken; |
4553 for(i=0; i<nToken; i++){ | 4663 if( nToken ){ |
4554 if( pExpr->pPhrase->aToken[i].pDeferred==0 ) break; | 4664 int i; |
| 4665 for(i=0; i<nToken; i++){ |
| 4666 if( pExpr->pPhrase->aToken[i].pDeferred==0 ) break; |
| 4667 } |
| 4668 pExpr->bDeferred = (i==nToken); |
4555 } | 4669 } |
4556 pExpr->bDeferred = (i==nToken); | |
4557 *pRc = fts3EvalPhraseStart(pCsr, 1, pExpr->pPhrase); | 4670 *pRc = fts3EvalPhraseStart(pCsr, 1, pExpr->pPhrase); |
4558 }else{ | 4671 }else{ |
4559 fts3EvalStartReaders(pCsr, pExpr->pLeft, pRc); | 4672 fts3EvalStartReaders(pCsr, pExpr->pLeft, pRc); |
4560 fts3EvalStartReaders(pCsr, pExpr->pRight, pRc); | 4673 fts3EvalStartReaders(pCsr, pExpr->pRight, pRc); |
4561 pExpr->bDeferred = (pExpr->pLeft->bDeferred && pExpr->pRight->bDeferred); | 4674 pExpr->bDeferred = (pExpr->pLeft->bDeferred && pExpr->pRight->bDeferred); |
4562 } | 4675 } |
4563 } | 4676 } |
4564 } | 4677 } |
4565 | 4678 |
4566 /* | 4679 /* |
(...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4802 if( ii==0 || (pTC->pPhrase->nToken>1 && ii!=nToken-1) ){ | 4915 if( ii==0 || (pTC->pPhrase->nToken>1 && ii!=nToken-1) ){ |
4803 /* Either this is the cheapest token in the entire query, or it is | 4916 /* Either this is the cheapest token in the entire query, or it is |
4804 ** part of a multi-token phrase. Either way, the entire doclist will | 4917 ** part of a multi-token phrase. Either way, the entire doclist will |
4805 ** (eventually) be loaded into memory. It may as well be now. */ | 4918 ** (eventually) be loaded into memory. It may as well be now. */ |
4806 Fts3PhraseToken *pToken = pTC->pToken; | 4919 Fts3PhraseToken *pToken = pTC->pToken; |
4807 int nList = 0; | 4920 int nList = 0; |
4808 char *pList = 0; | 4921 char *pList = 0; |
4809 rc = fts3TermSelect(pTab, pToken, pTC->iCol, &nList, &pList); | 4922 rc = fts3TermSelect(pTab, pToken, pTC->iCol, &nList, &pList); |
4810 assert( rc==SQLITE_OK || pList==0 ); | 4923 assert( rc==SQLITE_OK || pList==0 ); |
4811 if( rc==SQLITE_OK ){ | 4924 if( rc==SQLITE_OK ){ |
| 4925 rc = fts3EvalPhraseMergeToken( |
| 4926 pTab, pTC->pPhrase, pTC->iToken,pList,nList |
| 4927 ); |
| 4928 } |
| 4929 if( rc==SQLITE_OK ){ |
4812 int nCount; | 4930 int nCount; |
4813 fts3EvalPhraseMergeToken(pTab, pTC->pPhrase, pTC->iToken,pList,nList); | |
4814 nCount = fts3DoclistCountDocids( | 4931 nCount = fts3DoclistCountDocids( |
4815 pTC->pPhrase->doclist.aAll, pTC->pPhrase->doclist.nAll | 4932 pTC->pPhrase->doclist.aAll, pTC->pPhrase->doclist.nAll |
4816 ); | 4933 ); |
4817 if( ii==0 || nCount<nMinEst ) nMinEst = nCount; | 4934 if( ii==0 || nCount<nMinEst ) nMinEst = nCount; |
4818 } | 4935 } |
4819 } | 4936 } |
4820 } | 4937 } |
4821 pTC->pToken = 0; | 4938 pTC->pToken = 0; |
4822 } | 4939 } |
4823 | 4940 |
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4981 ** more non-deferred tokens, then the expression is advanced to the | 5098 ** more non-deferred tokens, then the expression is advanced to the |
4982 ** next possible match, considering only non-deferred tokens. In other | 5099 ** next possible match, considering only non-deferred tokens. In other |
4983 ** words, if the phrase is "A B C", and "B" is deferred, the expression | 5100 ** words, if the phrase is "A B C", and "B" is deferred, the expression |
4984 ** is advanced to the next row that contains an instance of "A * C", | 5101 ** is advanced to the next row that contains an instance of "A * C", |
4985 ** where "*" may match any single token. The position list in this case | 5102 ** where "*" may match any single token. The position list in this case |
4986 ** is populated as for "A * C" before returning. | 5103 ** is populated as for "A * C" before returning. |
4987 ** | 5104 ** |
4988 ** 2. NEAR is treated as AND. If the expression is "x NEAR y", it is | 5105 ** 2. NEAR is treated as AND. If the expression is "x NEAR y", it is |
4989 ** advanced to point to the next row that matches "x AND y". | 5106 ** advanced to point to the next row that matches "x AND y". |
4990 ** | 5107 ** |
4991 ** See fts3EvalTestDeferredAndNear() for details on testing if a row is | 5108 ** See sqlite3Fts3EvalTestDeferred() for details on testing if a row is |
4992 ** really a match, taking into account deferred tokens and NEAR operators. | 5109 ** really a match, taking into account deferred tokens and NEAR operators. |
4993 */ | 5110 */ |
4994 static void fts3EvalNextRow( | 5111 static void fts3EvalNextRow( |
4995 Fts3Cursor *pCsr, /* FTS Cursor handle */ | 5112 Fts3Cursor *pCsr, /* FTS Cursor handle */ |
4996 Fts3Expr *pExpr, /* Expr. to advance to next matching row */ | 5113 Fts3Expr *pExpr, /* Expr. to advance to next matching row */ |
4997 int *pRc /* IN/OUT: Error code */ | 5114 int *pRc /* IN/OUT: Error code */ |
4998 ){ | 5115 ){ |
4999 if( *pRc==SQLITE_OK ){ | 5116 if( *pRc==SQLITE_OK ){ |
5000 int bDescDoclist = pCsr->bDesc; /* Used by DOCID_CMP() macro */ | 5117 int bDescDoclist = pCsr->bDesc; /* Used by DOCID_CMP() macro */ |
5001 assert( pExpr->bEof==0 ); | 5118 assert( pExpr->bEof==0 ); |
(...skipping 26 matching lines...) Expand all Loading... |
5028 sqlite3_int64 iDiff = DOCID_CMP(pLeft->iDocid, pRight->iDocid); | 5145 sqlite3_int64 iDiff = DOCID_CMP(pLeft->iDocid, pRight->iDocid); |
5029 if( iDiff==0 ) break; | 5146 if( iDiff==0 ) break; |
5030 if( iDiff<0 ){ | 5147 if( iDiff<0 ){ |
5031 fts3EvalNextRow(pCsr, pLeft, pRc); | 5148 fts3EvalNextRow(pCsr, pLeft, pRc); |
5032 }else{ | 5149 }else{ |
5033 fts3EvalNextRow(pCsr, pRight, pRc); | 5150 fts3EvalNextRow(pCsr, pRight, pRc); |
5034 } | 5151 } |
5035 } | 5152 } |
5036 pExpr->iDocid = pLeft->iDocid; | 5153 pExpr->iDocid = pLeft->iDocid; |
5037 pExpr->bEof = (pLeft->bEof || pRight->bEof); | 5154 pExpr->bEof = (pLeft->bEof || pRight->bEof); |
| 5155 if( pExpr->eType==FTSQUERY_NEAR && pExpr->bEof ){ |
| 5156 if( pRight->pPhrase && pRight->pPhrase->doclist.aAll ){ |
| 5157 Fts3Doclist *pDl = &pRight->pPhrase->doclist; |
| 5158 while( *pRc==SQLITE_OK && pRight->bEof==0 ){ |
| 5159 memset(pDl->pList, 0, pDl->nList); |
| 5160 fts3EvalNextRow(pCsr, pRight, pRc); |
| 5161 } |
| 5162 } |
| 5163 if( pLeft->pPhrase && pLeft->pPhrase->doclist.aAll ){ |
| 5164 Fts3Doclist *pDl = &pLeft->pPhrase->doclist; |
| 5165 while( *pRc==SQLITE_OK && pLeft->bEof==0 ){ |
| 5166 memset(pDl->pList, 0, pDl->nList); |
| 5167 fts3EvalNextRow(pCsr, pLeft, pRc); |
| 5168 } |
| 5169 } |
| 5170 } |
5038 } | 5171 } |
5039 break; | 5172 break; |
5040 } | 5173 } |
5041 | 5174 |
5042 case FTSQUERY_OR: { | 5175 case FTSQUERY_OR: { |
5043 Fts3Expr *pLeft = pExpr->pLeft; | 5176 Fts3Expr *pLeft = pExpr->pLeft; |
5044 Fts3Expr *pRight = pExpr->pRight; | 5177 Fts3Expr *pRight = pExpr->pRight; |
5045 sqlite3_int64 iCmp = DOCID_CMP(pLeft->iDocid, pRight->iDocid); | 5178 sqlite3_int64 iCmp = DOCID_CMP(pLeft->iDocid, pRight->iDocid); |
5046 | 5179 |
5047 assert( pLeft->bStart || pLeft->iDocid==pRight->iDocid ); | 5180 assert( pLeft->bStart || pLeft->iDocid==pRight->iDocid ); |
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5185 } | 5318 } |
5186 | 5319 |
5187 sqlite3_free(aTmp); | 5320 sqlite3_free(aTmp); |
5188 } | 5321 } |
5189 } | 5322 } |
5190 | 5323 |
5191 return res; | 5324 return res; |
5192 } | 5325 } |
5193 | 5326 |
5194 /* | 5327 /* |
5195 ** This function is a helper function for fts3EvalTestDeferredAndNear(). | 5328 ** This function is a helper function for sqlite3Fts3EvalTestDeferred(). |
5196 ** Assuming no error occurs or has occurred, It returns non-zero if the | 5329 ** Assuming no error occurs or has occurred, It returns non-zero if the |
5197 ** expression passed as the second argument matches the row that pCsr | 5330 ** expression passed as the second argument matches the row that pCsr |
5198 ** currently points to, or zero if it does not. | 5331 ** currently points to, or zero if it does not. |
5199 ** | 5332 ** |
5200 ** If *pRc is not SQLITE_OK when this function is called, it is a no-op. | 5333 ** If *pRc is not SQLITE_OK when this function is called, it is a no-op. |
5201 ** If an error occurs during execution of this function, *pRc is set to | 5334 ** If an error occurs during execution of this function, *pRc is set to |
5202 ** the appropriate SQLite error code. In this case the returned value is | 5335 ** the appropriate SQLite error code. In this case the returned value is |
5203 ** undefined. | 5336 ** undefined. |
5204 */ | 5337 */ |
5205 static int fts3EvalTestExpr( | 5338 static int fts3EvalTestExpr( |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5306 ** expression. It returns 1 if both of the following are true: | 5439 ** expression. It returns 1 if both of the following are true: |
5307 ** | 5440 ** |
5308 ** 1. *pRc is SQLITE_OK when this function returns, and | 5441 ** 1. *pRc is SQLITE_OK when this function returns, and |
5309 ** | 5442 ** |
5310 ** 2. After scanning the current FTS table row for the deferred tokens, | 5443 ** 2. After scanning the current FTS table row for the deferred tokens, |
5311 ** it is determined that the row does *not* match the query. | 5444 ** it is determined that the row does *not* match the query. |
5312 ** | 5445 ** |
5313 ** Or, if no error occurs and it seems the current row does match the FTS | 5446 ** Or, if no error occurs and it seems the current row does match the FTS |
5314 ** query, return 0. | 5447 ** query, return 0. |
5315 */ | 5448 */ |
5316 static int fts3EvalTestDeferredAndNear(Fts3Cursor *pCsr, int *pRc){ | 5449 int sqlite3Fts3EvalTestDeferred(Fts3Cursor *pCsr, int *pRc){ |
5317 int rc = *pRc; | 5450 int rc = *pRc; |
5318 int bMiss = 0; | 5451 int bMiss = 0; |
5319 if( rc==SQLITE_OK ){ | 5452 if( rc==SQLITE_OK ){ |
5320 | 5453 |
5321 /* If there are one or more deferred tokens, load the current row into | 5454 /* If there are one or more deferred tokens, load the current row into |
5322 ** memory and scan it to determine the position list for each deferred | 5455 ** memory and scan it to determine the position list for each deferred |
5323 ** token. Then, see if this row is really a match, considering deferred | 5456 ** token. Then, see if this row is really a match, considering deferred |
5324 ** tokens and NEAR operators (neither of which were taken into account | 5457 ** tokens and NEAR operators (neither of which were taken into account |
5325 ** earlier, by fts3EvalNextRow()). | 5458 ** earlier, by fts3EvalNextRow()). |
5326 */ | 5459 */ |
(...skipping 26 matching lines...) Expand all Loading... |
5353 do { | 5486 do { |
5354 if( pCsr->isRequireSeek==0 ){ | 5487 if( pCsr->isRequireSeek==0 ){ |
5355 sqlite3_reset(pCsr->pStmt); | 5488 sqlite3_reset(pCsr->pStmt); |
5356 } | 5489 } |
5357 assert( sqlite3_data_count(pCsr->pStmt)==0 ); | 5490 assert( sqlite3_data_count(pCsr->pStmt)==0 ); |
5358 fts3EvalNextRow(pCsr, pExpr, &rc); | 5491 fts3EvalNextRow(pCsr, pExpr, &rc); |
5359 pCsr->isEof = pExpr->bEof; | 5492 pCsr->isEof = pExpr->bEof; |
5360 pCsr->isRequireSeek = 1; | 5493 pCsr->isRequireSeek = 1; |
5361 pCsr->isMatchinfoNeeded = 1; | 5494 pCsr->isMatchinfoNeeded = 1; |
5362 pCsr->iPrevId = pExpr->iDocid; | 5495 pCsr->iPrevId = pExpr->iDocid; |
5363 }while( pCsr->isEof==0 && fts3EvalTestDeferredAndNear(pCsr, &rc) ); | 5496 }while( pCsr->isEof==0 && sqlite3Fts3EvalTestDeferred(pCsr, &rc) ); |
5364 } | 5497 } |
5365 | 5498 |
5366 /* Check if the cursor is past the end of the docid range specified | 5499 /* Check if the cursor is past the end of the docid range specified |
5367 ** by Fts3Cursor.iMinDocid/iMaxDocid. If so, set the EOF flag. */ | 5500 ** by Fts3Cursor.iMinDocid/iMaxDocid. If so, set the EOF flag. */ |
5368 if( rc==SQLITE_OK && ( | 5501 if( rc==SQLITE_OK && ( |
5369 (pCsr->bDesc==0 && pCsr->iPrevId>pCsr->iMaxDocid) | 5502 (pCsr->bDesc==0 && pCsr->iPrevId>pCsr->iMaxDocid) |
5370 || (pCsr->bDesc!=0 && pCsr->iPrevId<pCsr->iMinDocid) | 5503 || (pCsr->bDesc!=0 && pCsr->iPrevId<pCsr->iMinDocid) |
5371 )){ | 5504 )){ |
5372 pCsr->isEof = 1; | 5505 pCsr->isEof = 1; |
5373 } | 5506 } |
(...skipping 26 matching lines...) Expand all Loading... |
5400 Fts3PhraseToken *pToken = &pPhrase->aToken[i]; | 5533 Fts3PhraseToken *pToken = &pPhrase->aToken[i]; |
5401 assert( pToken->pDeferred==0 ); | 5534 assert( pToken->pDeferred==0 ); |
5402 if( pToken->pSegcsr ){ | 5535 if( pToken->pSegcsr ){ |
5403 sqlite3Fts3MsrIncrRestart(pToken->pSegcsr); | 5536 sqlite3Fts3MsrIncrRestart(pToken->pSegcsr); |
5404 } | 5537 } |
5405 } | 5538 } |
5406 *pRc = fts3EvalPhraseStart(pCsr, 0, pPhrase); | 5539 *pRc = fts3EvalPhraseStart(pCsr, 0, pPhrase); |
5407 } | 5540 } |
5408 pPhrase->doclist.pNextDocid = 0; | 5541 pPhrase->doclist.pNextDocid = 0; |
5409 pPhrase->doclist.iDocid = 0; | 5542 pPhrase->doclist.iDocid = 0; |
| 5543 pPhrase->pOrPoslist = 0; |
5410 } | 5544 } |
5411 | 5545 |
5412 pExpr->iDocid = 0; | 5546 pExpr->iDocid = 0; |
5413 pExpr->bEof = 0; | 5547 pExpr->bEof = 0; |
5414 pExpr->bStart = 0; | 5548 pExpr->bStart = 0; |
5415 | 5549 |
5416 fts3EvalRestart(pCsr, pExpr->pLeft, pRc); | 5550 fts3EvalRestart(pCsr, pExpr->pLeft, pRc); |
5417 fts3EvalRestart(pCsr, pExpr->pRight, pRc); | 5551 fts3EvalRestart(pCsr, pExpr->pRight, pRc); |
5418 } | 5552 } |
5419 } | 5553 } |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5513 assert( sqlite3_data_count(pCsr->pStmt)==0 ); | 5647 assert( sqlite3_data_count(pCsr->pStmt)==0 ); |
5514 | 5648 |
5515 /* Advance to the next document */ | 5649 /* Advance to the next document */ |
5516 fts3EvalNextRow(pCsr, pRoot, &rc); | 5650 fts3EvalNextRow(pCsr, pRoot, &rc); |
5517 pCsr->isEof = pRoot->bEof; | 5651 pCsr->isEof = pRoot->bEof; |
5518 pCsr->isRequireSeek = 1; | 5652 pCsr->isRequireSeek = 1; |
5519 pCsr->isMatchinfoNeeded = 1; | 5653 pCsr->isMatchinfoNeeded = 1; |
5520 pCsr->iPrevId = pRoot->iDocid; | 5654 pCsr->iPrevId = pRoot->iDocid; |
5521 }while( pCsr->isEof==0 | 5655 }while( pCsr->isEof==0 |
5522 && pRoot->eType==FTSQUERY_NEAR | 5656 && pRoot->eType==FTSQUERY_NEAR |
5523 && fts3EvalTestDeferredAndNear(pCsr, &rc) | 5657 && sqlite3Fts3EvalTestDeferred(pCsr, &rc) |
5524 ); | 5658 ); |
5525 | 5659 |
5526 if( rc==SQLITE_OK && pCsr->isEof==0 ){ | 5660 if( rc==SQLITE_OK && pCsr->isEof==0 ){ |
5527 fts3EvalUpdateCounts(pRoot); | 5661 fts3EvalUpdateCounts(pRoot); |
5528 } | 5662 } |
5529 } | 5663 } |
5530 | 5664 |
5531 pCsr->isEof = 0; | 5665 pCsr->isEof = 0; |
5532 pCsr->iPrevId = iPrevId; | 5666 pCsr->iPrevId = iPrevId; |
5533 | 5667 |
5534 if( bEof ){ | 5668 if( bEof ){ |
5535 pRoot->bEof = bEof; | 5669 pRoot->bEof = bEof; |
5536 }else{ | 5670 }else{ |
5537 /* Caution: pRoot may iterate through docids in ascending or descending | 5671 /* Caution: pRoot may iterate through docids in ascending or descending |
5538 ** order. For this reason, even though it seems more defensive, the | 5672 ** order. For this reason, even though it seems more defensive, the |
5539 ** do loop can not be written: | 5673 ** do loop can not be written: |
5540 ** | 5674 ** |
5541 ** do {...} while( pRoot->iDocid<iDocid && rc==SQLITE_OK ); | 5675 ** do {...} while( pRoot->iDocid<iDocid && rc==SQLITE_OK ); |
5542 */ | 5676 */ |
5543 fts3EvalRestart(pCsr, pRoot, &rc); | 5677 fts3EvalRestart(pCsr, pRoot, &rc); |
5544 do { | 5678 do { |
5545 fts3EvalNextRow(pCsr, pRoot, &rc); | 5679 fts3EvalNextRow(pCsr, pRoot, &rc); |
5546 assert( pRoot->bEof==0 ); | 5680 assert( pRoot->bEof==0 ); |
5547 }while( pRoot->iDocid!=iDocid && rc==SQLITE_OK ); | 5681 }while( pRoot->iDocid!=iDocid && rc==SQLITE_OK ); |
5548 fts3EvalTestDeferredAndNear(pCsr, &rc); | |
5549 } | 5682 } |
5550 } | 5683 } |
5551 return rc; | 5684 return rc; |
5552 } | 5685 } |
5553 | 5686 |
5554 /* | 5687 /* |
5555 ** This function is used by the matchinfo() module to query a phrase | 5688 ** This function is used by the matchinfo() module to query a phrase |
5556 ** expression node for the following information: | 5689 ** expression node for the following information: |
5557 ** | 5690 ** |
5558 ** 1. The total number of occurrences of the phrase in each column of | 5691 ** 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... |
5645 ** column iCol, return a NULL pointer. */ | 5778 ** column iCol, return a NULL pointer. */ |
5646 *ppOut = 0; | 5779 *ppOut = 0; |
5647 assert( iCol>=0 && iCol<pTab->nColumn ); | 5780 assert( iCol>=0 && iCol<pTab->nColumn ); |
5648 if( (pPhrase->iColumn<pTab->nColumn && pPhrase->iColumn!=iCol) ){ | 5781 if( (pPhrase->iColumn<pTab->nColumn && pPhrase->iColumn!=iCol) ){ |
5649 return SQLITE_OK; | 5782 return SQLITE_OK; |
5650 } | 5783 } |
5651 | 5784 |
5652 iDocid = pExpr->iDocid; | 5785 iDocid = pExpr->iDocid; |
5653 pIter = pPhrase->doclist.pList; | 5786 pIter = pPhrase->doclist.pList; |
5654 if( iDocid!=pCsr->iPrevId || pExpr->bEof ){ | 5787 if( iDocid!=pCsr->iPrevId || pExpr->bEof ){ |
| 5788 int rc = SQLITE_OK; |
5655 int bDescDoclist = pTab->bDescIdx; /* For DOCID_CMP macro */ | 5789 int bDescDoclist = pTab->bDescIdx; /* For DOCID_CMP macro */ |
5656 int iMul; /* +1 if csr dir matches index dir, else -1 */ | |
5657 int bOr = 0; | 5790 int bOr = 0; |
5658 u8 bEof = 0; | |
5659 u8 bTreeEof = 0; | 5791 u8 bTreeEof = 0; |
5660 Fts3Expr *p; /* Used to iterate from pExpr to root */ | 5792 Fts3Expr *p; /* Used to iterate from pExpr to root */ |
5661 Fts3Expr *pNear; /* Most senior NEAR ancestor (or pExpr) */ | 5793 Fts3Expr *pNear; /* Most senior NEAR ancestor (or pExpr) */ |
| 5794 int bMatch; |
5662 | 5795 |
5663 /* Check if this phrase descends from an OR expression node. If not, | 5796 /* Check if this phrase descends from an OR expression node. If not, |
5664 ** return NULL. Otherwise, the entry that corresponds to docid | 5797 ** return NULL. Otherwise, the entry that corresponds to docid |
5665 ** pCsr->iPrevId may lie earlier in the doclist buffer. Or, if the | 5798 ** pCsr->iPrevId may lie earlier in the doclist buffer. Or, if the |
5666 ** tree that the node is part of has been marked as EOF, but the node | 5799 ** tree that the node is part of has been marked as EOF, but the node |
5667 ** itself is not EOF, then it may point to an earlier entry. */ | 5800 ** itself is not EOF, then it may point to an earlier entry. */ |
5668 pNear = pExpr; | 5801 pNear = pExpr; |
5669 for(p=pExpr->pParent; p; p=p->pParent){ | 5802 for(p=pExpr->pParent; p; p=p->pParent){ |
5670 if( p->eType==FTSQUERY_OR ) bOr = 1; | 5803 if( p->eType==FTSQUERY_OR ) bOr = 1; |
5671 if( p->eType==FTSQUERY_NEAR ) pNear = p; | 5804 if( p->eType==FTSQUERY_NEAR ) pNear = p; |
5672 if( p->bEof ) bTreeEof = 1; | 5805 if( p->bEof ) bTreeEof = 1; |
5673 } | 5806 } |
5674 if( bOr==0 ) return SQLITE_OK; | 5807 if( bOr==0 ) return SQLITE_OK; |
5675 | 5808 |
5676 /* This is the descendent of an OR node. In this case we cannot use | 5809 /* This is the descendent of an OR node. In this case we cannot use |
5677 ** an incremental phrase. Load the entire doclist for the phrase | 5810 ** an incremental phrase. Load the entire doclist for the phrase |
5678 ** into memory in this case. */ | 5811 ** into memory in this case. */ |
5679 if( pPhrase->bIncr ){ | 5812 if( pPhrase->bIncr ){ |
5680 int rc = SQLITE_OK; | 5813 int bEofSave = pNear->bEof; |
5681 int bEofSave = pExpr->bEof; | 5814 fts3EvalRestart(pCsr, pNear, &rc); |
5682 fts3EvalRestart(pCsr, pExpr, &rc); | 5815 while( rc==SQLITE_OK && !pNear->bEof ){ |
5683 while( rc==SQLITE_OK && !pExpr->bEof ){ | 5816 fts3EvalNextRow(pCsr, pNear, &rc); |
5684 fts3EvalNextRow(pCsr, pExpr, &rc); | 5817 if( bEofSave==0 && pNear->iDocid==iDocid ) break; |
5685 if( bEofSave==0 && pExpr->iDocid==iDocid ) break; | |
5686 } | 5818 } |
5687 pIter = pPhrase->doclist.pList; | |
5688 assert( rc!=SQLITE_OK || pPhrase->bIncr==0 ); | 5819 assert( rc!=SQLITE_OK || pPhrase->bIncr==0 ); |
5689 if( rc!=SQLITE_OK ) return rc; | |
5690 } | 5820 } |
5691 | 5821 if( bTreeEof ){ |
5692 iMul = ((pCsr->bDesc==bDescDoclist) ? 1 : -1); | 5822 while( rc==SQLITE_OK && !pNear->bEof ){ |
5693 while( bTreeEof==1 | 5823 fts3EvalNextRow(pCsr, pNear, &rc); |
5694 && pNear->bEof==0 | 5824 } |
5695 && (DOCID_CMP(pNear->iDocid, pCsr->iPrevId) * iMul)<0 | |
5696 ){ | |
5697 int rc = SQLITE_OK; | |
5698 fts3EvalNextRow(pCsr, pExpr, &rc); | |
5699 if( rc!=SQLITE_OK ) return rc; | |
5700 iDocid = pExpr->iDocid; | |
5701 pIter = pPhrase->doclist.pList; | |
5702 } | 5825 } |
| 5826 if( rc!=SQLITE_OK ) return rc; |
5703 | 5827 |
5704 bEof = (pPhrase->doclist.nAll==0); | 5828 bMatch = 1; |
5705 assert( bDescDoclist==0 || bDescDoclist==1 ); | 5829 for(p=pNear; p; p=p->pLeft){ |
5706 assert( pCsr->bDesc==0 || pCsr->bDesc==1 ); | 5830 u8 bEof = 0; |
| 5831 Fts3Expr *pTest = p; |
| 5832 Fts3Phrase *pPh; |
| 5833 assert( pTest->eType==FTSQUERY_NEAR || pTest->eType==FTSQUERY_PHRASE ); |
| 5834 if( pTest->eType==FTSQUERY_NEAR ) pTest = pTest->pRight; |
| 5835 assert( pTest->eType==FTSQUERY_PHRASE ); |
| 5836 pPh = pTest->pPhrase; |
5707 | 5837 |
5708 if( bEof==0 ){ | 5838 pIter = pPh->pOrPoslist; |
| 5839 iDocid = pPh->iOrDocid; |
5709 if( pCsr->bDesc==bDescDoclist ){ | 5840 if( pCsr->bDesc==bDescDoclist ){ |
5710 int dummy; | 5841 bEof = !pPh->doclist.nAll || |
5711 if( pNear->bEof ){ | 5842 (pIter >= (pPh->doclist.aAll + pPh->doclist.nAll)); |
5712 /* This expression is already at EOF. So position it to point to the | 5843 while( (pIter==0 || DOCID_CMP(iDocid, pCsr->iPrevId)<0 ) && bEof==0 ){ |
5713 ** last entry in the doclist at pPhrase->doclist.aAll[]. Variable | 5844 sqlite3Fts3DoclistNext( |
5714 ** iDocid is already set for this entry, so all that is required is | 5845 bDescDoclist, pPh->doclist.aAll, pPh->doclist.nAll, |
5715 ** to set pIter to point to the first byte of the last position-list | 5846 &pIter, &iDocid, &bEof |
5716 ** in the doclist. | |
5717 ** | |
5718 ** It would also be correct to set pIter and iDocid to zero. In | |
5719 ** this case, the first call to sqltie3Fts4DoclistPrev() below | |
5720 ** would also move the iterator to point to the last entry in the | |
5721 ** doclist. However, this is expensive, as to do so it has to | |
5722 ** iterate through the entire doclist from start to finish (since | |
5723 ** it does not know the docid for the last entry). */ | |
5724 pIter = &pPhrase->doclist.aAll[pPhrase->doclist.nAll-1]; | |
5725 fts3ReversePoslist(pPhrase->doclist.aAll, &pIter); | |
5726 } | |
5727 while( (pIter==0 || DOCID_CMP(iDocid, pCsr->iPrevId)>0 ) && bEof==0 ){ | |
5728 sqlite3Fts3DoclistPrev( | |
5729 bDescDoclist, pPhrase->doclist.aAll, pPhrase->doclist.nAll, | |
5730 &pIter, &iDocid, &dummy, &bEof | |
5731 ); | 5847 ); |
5732 } | 5848 } |
5733 }else{ | 5849 }else{ |
5734 if( pNear->bEof ){ | 5850 bEof = !pPh->doclist.nAll || (pIter && pIter<=pPh->doclist.aAll); |
5735 pIter = 0; | 5851 while( (pIter==0 || DOCID_CMP(iDocid, pCsr->iPrevId)>0 ) && bEof==0 ){ |
5736 iDocid = 0; | 5852 int dummy; |
5737 } | 5853 sqlite3Fts3DoclistPrev( |
5738 while( (pIter==0 || DOCID_CMP(iDocid, pCsr->iPrevId)<0 ) && bEof==0 ){ | 5854 bDescDoclist, pPh->doclist.aAll, pPh->doclist.nAll, |
5739 sqlite3Fts3DoclistNext( | 5855 &pIter, &iDocid, &dummy, &bEof |
5740 bDescDoclist, pPhrase->doclist.aAll, pPhrase->doclist.nAll, | 5856 ); |
5741 &pIter, &iDocid, &bEof | |
5742 ); | |
5743 } | 5857 } |
5744 } | 5858 } |
| 5859 pPh->pOrPoslist = pIter; |
| 5860 pPh->iOrDocid = iDocid; |
| 5861 if( bEof || iDocid!=pCsr->iPrevId ) bMatch = 0; |
5745 } | 5862 } |
5746 | 5863 |
5747 if( bEof || iDocid!=pCsr->iPrevId ) pIter = 0; | 5864 if( bMatch ){ |
| 5865 pIter = pPhrase->pOrPoslist; |
| 5866 }else{ |
| 5867 pIter = 0; |
| 5868 } |
5748 } | 5869 } |
5749 if( pIter==0 ) return SQLITE_OK; | 5870 if( pIter==0 ) return SQLITE_OK; |
5750 | 5871 |
5751 if( *pIter==0x01 ){ | 5872 if( *pIter==0x01 ){ |
5752 pIter++; | 5873 pIter++; |
5753 pIter += fts3GetVarint32(pIter, &iThis); | 5874 pIter += fts3GetVarint32(pIter, &iThis); |
5754 }else{ | 5875 }else{ |
5755 iThis = 0; | 5876 iThis = 0; |
5756 } | 5877 } |
5757 while( iThis<iCol ){ | 5878 while( iThis<iCol ){ |
5758 fts3ColumnlistCopy(0, &pIter); | 5879 fts3ColumnlistCopy(0, &pIter); |
5759 if( *pIter==0x00 ) return 0; | 5880 if( *pIter==0x00 ) return SQLITE_OK; |
5760 pIter++; | 5881 pIter++; |
5761 pIter += fts3GetVarint32(pIter, &iThis); | 5882 pIter += fts3GetVarint32(pIter, &iThis); |
5762 } | 5883 } |
| 5884 if( *pIter==0x00 ){ |
| 5885 pIter = 0; |
| 5886 } |
5763 | 5887 |
5764 *ppOut = ((iCol==iThis)?pIter:0); | 5888 *ppOut = ((iCol==iThis)?pIter:0); |
5765 return SQLITE_OK; | 5889 return SQLITE_OK; |
5766 } | 5890 } |
5767 | 5891 |
5768 /* | 5892 /* |
5769 ** Free all components of the Fts3Phrase structure that were allocated by | 5893 ** Free all components of the Fts3Phrase structure that were allocated by |
5770 ** the eval module. Specifically, this means to free: | 5894 ** the eval module. Specifically, this means to free: |
5771 ** | 5895 ** |
5772 ** * the contents of pPhrase->doclist, and | 5896 ** * the contents of pPhrase->doclist, and |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5806 sqlite3 *db, | 5930 sqlite3 *db, |
5807 char **pzErrMsg, | 5931 char **pzErrMsg, |
5808 const sqlite3_api_routines *pApi | 5932 const sqlite3_api_routines *pApi |
5809 ){ | 5933 ){ |
5810 SQLITE_EXTENSION_INIT2(pApi) | 5934 SQLITE_EXTENSION_INIT2(pApi) |
5811 return sqlite3Fts3Init(db); | 5935 return sqlite3Fts3Init(db); |
5812 } | 5936 } |
5813 #endif | 5937 #endif |
5814 | 5938 |
5815 #endif | 5939 #endif |
OLD | NEW |