| 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 |