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