/* Parse a MATCH expression. */
int sqlite3Fts5ExprNew(
Fts5Config *pConfig,
+ int iCol, /* Column on LHS of MATCH operator */
const char *zExpr,
Fts5Expr **ppNew,
char **pzErr
int sqlite3Fts5ExprNew(
Fts5Config *pConfig, /* FTS5 Configuration */
+ int iCol,
const char *zExpr, /* Expression text */
Fts5Expr **ppNew,
char **pzErr
}while( sParse.rc==SQLITE_OK && t!=FTS5_EOF );
sqlite3Fts5ParserFree(pEngine, fts5ParseFree);
+ /* If the LHS of the MATCH expression was a user column, apply the
+ ** implicit column-filter. */
+ if( iCol<pConfig->nCol && sParse.pExpr && sParse.rc==SQLITE_OK ){
+ int n = sizeof(Fts5Colset);
+ Fts5Colset *pColset = (Fts5Colset*)sqlite3Fts5MallocZero(&sParse.rc, n);
+ if( pColset ){
+ pColset->nCol = 1;
+ pColset->aiCol[0] = iCol;
+ sqlite3Fts5ParseSetColset(&sParse, sParse.pExpr, pColset);
+ }
+ }
+
assert( sParse.rc!=SQLITE_OK || sParse.zErr==0 );
if( sParse.rc==SQLITE_OK ){
*ppNew = pNew = sqlite3_malloc(sizeof(Fts5Expr));
rc = sqlite3Fts5ConfigParse(pGlobal, db, nConfig, azConfig, &pConfig, &zErr);
if( rc==SQLITE_OK ){
- rc = sqlite3Fts5ExprNew(pConfig, zExpr, &pExpr, &zErr);
+ rc = sqlite3Fts5ExprNew(pConfig, pConfig->nCol, zExpr, &pExpr, &zErr);
}
if( rc==SQLITE_OK ){
char *zText;
static int fts5BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
Fts5Table *pTab = (Fts5Table*)pVTab;
Fts5Config *pConfig = pTab->pConfig;
+ const int nCol = pConfig->nCol;
int idxFlags = 0; /* Parameter passed through to xFilter() */
int bHasMatch;
int iNext;
int aColMap[3];
aColMap[0] = -1;
- aColMap[1] = pConfig->nCol;
- aColMap[2] = pConfig->nCol+1;
+ aColMap[1] = nCol;
+ aColMap[2] = nCol+1;
/* Set idxFlags flags for all WHERE clause terms that will be used. */
for(i=0; i<pInfo->nConstraint; i++){
struct sqlite3_index_constraint *p = &pInfo->aConstraint[i];
- int j;
- for(j=0; j<ArraySize(aConstraint); j++){
- struct Constraint *pC = &aConstraint[j];
- if( p->iColumn==aColMap[pC->iCol] && p->op & pC->op ){
- if( p->usable ){
+ int iCol = p->iColumn;
+
+ if( (p->op==SQLITE_INDEX_CONSTRAINT_MATCH && iCol>=0 && iCol<=nCol)
+ || (p->op==SQLITE_INDEX_CONSTRAINT_EQ && iCol==nCol)
+ ){
+ /* A MATCH operator or equivalent */
+ if( p->usable ){
+ idxFlags = (idxFlags & 0xFFFF) | FTS5_BI_MATCH | (iCol << 16);
+ aConstraint[0].iConsIndex = i;
+ }else{
+ /* As there exists an unusable MATCH constraint this is an
+ ** unusable plan. Set a prohibitively high cost. */
+ pInfo->estimatedCost = 1e50;
+ return SQLITE_OK;
+ }
+ }else{
+ int j;
+ for(j=1; j<ArraySize(aConstraint); j++){
+ struct Constraint *pC = &aConstraint[j];
+ if( iCol==aColMap[pC->iCol] && p->op & pC->op && p->usable ){
pC->iConsIndex = i;
idxFlags |= pC->fts5op;
- }else if( j==0 ){
- /* As there exists an unusable MATCH constraint this is an
- ** unusable plan. Set a prohibitively high cost. */
- pInfo->estimatedCost = 1e50;
- return SQLITE_OK;
}
}
}
sqlite3_value *pRowidEq = 0; /* rowid = ? expression (or NULL) */
sqlite3_value *pRowidLe = 0; /* rowid <= ? expression (or NULL) */
sqlite3_value *pRowidGe = 0; /* rowid >= ? expression (or NULL) */
+ int iCol; /* Column on LHS of MATCH operator */
char **pzErrmsg = pConfig->pzErrmsg;
UNUSED_PARAM(zUnused);
if( BitFlagTest(idxNum, FTS5_BI_ROWID_EQ) ) pRowidEq = apVal[iVal++];
if( BitFlagTest(idxNum, FTS5_BI_ROWID_LE) ) pRowidLe = apVal[iVal++];
if( BitFlagTest(idxNum, FTS5_BI_ROWID_GE) ) pRowidGe = apVal[iVal++];
+ iCol = (idxNum>>16);
+ assert( iCol>=0 && iCol<=pConfig->nCol );
assert( iVal==nVal );
bOrderByRank = ((idxNum & FTS5_BI_ORDER_RANK) ? 1 : 0);
pCsr->bDesc = bDesc = ((idxNum & FTS5_BI_ORDER_DESC) ? 1 : 0);
rc = fts5SpecialMatch(pTab, pCsr, &zExpr[1]);
}else{
char **pzErr = &pTab->base.zErrMsg;
- rc = sqlite3Fts5ExprNew(pConfig, zExpr, &pCsr->pExpr, pzErr);
+ rc = sqlite3Fts5ExprNew(pConfig, iCol, zExpr, &pCsr->pExpr, pzErr);
if( rc==SQLITE_OK ){
if( bOrderByRank ){
pCsr->ePlan = FTS5_PLAN_SORTED_MATCH;
SELECT rowid FROM t1($q)
} $res
}
+
+ foreach {tn w res} {
+ 0 "a MATCH 'a'" {1}
+ 1 "b MATCH 'a'" {2}
+ 2 "b MATCH '{a b c} : a'" {2}
+ 3 "b MATCH 'a OR b'" {1 2}
+ 4 "b MATCH 'a OR a:b'" {2}
+ 5 "b MATCH 'a OR b:b'" {1 2}
+ } {
+ do_execsql_test 3.$tn "
+ SELECT rowid FROM t1 WHERE $w
+ " $res
+ }
+
+ do_catchsql_test 4.1 {
+ SELECT * FROM t1 WHERE rowid MATCH 'a'
+ } {1 {unable to use function MATCH in the requested context}}
}
SELECT * FROM t1, f1 WHERE f1 MATCH t1.x
} {
0 0 0 {SCAN TABLE t1}
- 0 1 1 {SCAN TABLE f1 VIRTUAL TABLE INDEX 1:}
+ 0 1 1 {SCAN TABLE f1 VIRTUAL TABLE INDEX 65537:}
}
do_eqp_test 1.2 {
do_eqp_test 1.3 {
SELECT * FROM f1 WHERE f1 MATCH ? ORDER BY ff
} {
- 0 0 0 {SCAN TABLE f1 VIRTUAL TABLE INDEX 1:}
+ 0 0 0 {SCAN TABLE f1 VIRTUAL TABLE INDEX 65537:}
0 0 0 {USE TEMP B-TREE FOR ORDER BY}
}
-C Fix\sa\sregression\scaused\sby\sthe\sfix\sfor\sticket\s[6c9b5514077fed34551f98e64c09a1]\s-\ncontrol\scharacters\sallowed\sin\sJSON.
-D 2017-04-13T00:12:32.332
+C Allow\sa\suser\scolumn\sname\sto\sbe\sused\son\sthe\sLHS\sof\sa\sMATCH\soperator\sin\sFTS5.
+D 2017-04-13T09:45:21.225
F Makefile.in 1cc758ce3374a32425e4d130c2fe7b026b20de5b8843243de75f087c0a2661fb
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
F Makefile.msc a4c0613a18663bda56d8cf76079ab6590a7c3602e54befb4bbdef76bcaa38b6a
F ext/fts3/unicode/parseunicode.tcl da577d1384810fb4e2b209bf3313074353193e95
F ext/fts5/extract_api_docs.tcl a36e54ec777172ddd3f9a88daf593b00848368e0
F ext/fts5/fts5.h 62f3e33ceeb9a428db139f9c012186b371da1cc7
-F ext/fts5/fts5Int.h d514c81997be588c2b23b82c77f6449e20a43903c503066f13d3d0ed8746ccde
+F ext/fts5/fts5Int.h 15e7514b46a845937d7c62e5c69e935091f0dbb72eb61aa4c8bcfbd39fdea158
F ext/fts5/fts5_aux.c 67acf8d51723cf28ffc3828210ba662df4b8d267
F ext/fts5/fts5_buffer.c 4c1502d4c956cd092c89ce4480867f9d8bf325cd
F ext/fts5/fts5_config.c 5af9c360e99669d29f06492c370892394aba0857
-F ext/fts5/fts5_expr.c e5522f89e599e7e53c0014003b66480f676d2eff8b9cdb2c03c32d859b4b7cb3
+F ext/fts5/fts5_expr.c f2825f714d91bbe62ab5820aee9ad12e0c94205b2a01725eaa9072415ae9ff1c
F ext/fts5/fts5_hash.c 880998e596b60f078348d48732ca4ad9a90caad2
F ext/fts5/fts5_index.c 551add2b7762a2857336747def3b9d4fa304df476e188fb323492e2fd851772b
-F ext/fts5/fts5_main.c 24cafdc44c06b9665d73c34b75966f6223e9299cc9fd10184c6bf888e3ff563f
+F ext/fts5/fts5_main.c 1ba0e7806886c1bc16e20d0dde1c2b535d1aeb98cbbb937c4c3e064af5ac6f03
F ext/fts5/fts5_storage.c 7750986004f3f0c94619a85ecb5dd6cbef53e5e3853488e8a906c269d4d11db6
F ext/fts5/fts5_tcl.c 4a901f00c8553740dba63511603f5527d741c26a
F ext/fts5/fts5_test_mi.c 783b86697ebf773c18fc109992426c0173a055bc
F ext/fts5/test/fts5auxdata.test 141a7cbffcceb1bd2799b4b29c183ff8780d586e
F ext/fts5/test/fts5bigpl.test 04ee0d7eebbebf17c31f5a0b5c5f9494eac3a0cb
F ext/fts5/test/fts5bigtok.test 017a9397b14e7598883a6328ead4a6539b42d59a
-F ext/fts5/test/fts5colset.test 5d6cc35a7cdf39b2709a36620c3f398f6f8c88de39e1485f367e5294ffc7c153
+F ext/fts5/test/fts5colset.test 97084e7fd3183a3c148ade1d4ad980b7e764cb2711ac77c3176680c3e75ea2b9
F ext/fts5/test/fts5columnsize.test a8cfef21ffa1c264b9f670a7d94eeaccb5341c07
F ext/fts5/test/fts5config.test 7788b9c058074d640dfcdd81d97b6a9480000368
F ext/fts5/test/fts5conflict.test 26f4e46c4d31e16221794832a990dc4e30e18de5
F ext/fts5/test/fts5onepass.test 7ed9608e258132cb8d55e7c479b08676ad68810c
F ext/fts5/test/fts5optimize.test 9d3ac53bb9cae58cb070d795db86bcb2f9fec105
F ext/fts5/test/fts5phrase.test f6d1d464da5beb25dc56277aa4f1d6102f0d9a2f
-F ext/fts5/test/fts5plan.test 6a55ecbac9890765b0e16f8c421c7e0888cfe436
+F ext/fts5/test/fts5plan.test fb0ee60c9a092b17bb958dd742f01e3731b520d50b5d61b288c49c7acdc286cb
F ext/fts5/test/fts5porter.test 7cdc07bef301d70eebbfa75dcaf45c3680e1d0e1
F ext/fts5/test/fts5porter2.test 2e65633d58a1c525d5af0f6c01e5a59155bb3487
F ext/fts5/test/fts5prefix.test 6ef7e875738412907b17687d25db39a25cbdaba4
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P c847543f8bb1376fef52bca72b4191162a32eb7e6c5f0cd1aa0ab116b3183396
-R 0115b666e9627edf0663b399afd00fa5
-U drh
-Z d4923dfb1fc052664f2f0021f04650c5
+P 8e7b611863247a3bf46a96ec4b47d24c0ae0d60c9cee968a1cfd1da157e7c9bb
+R c8c7d138fdb377c6e26ca103486be93e
+U dan
+Z 1fddd5a6b11f63b38f6de23209c4c2b7
-8e7b611863247a3bf46a96ec4b47d24c0ae0d60c9cee968a1cfd1da157e7c9bb
\ No newline at end of file
+6f54ffd151b0eca6f9ef57ac54802584a839cfc7373f10c100fc18c855edcc0a
\ No newline at end of file