mirror of
https://github.com/sqlite/sqlite.git
synced 2025-11-16 23:02:26 +03:00
Add experimental support for LIKE, GLOB and REGEXP to the virtual table interface.
FossilOrigin-Name: 277a5b4027d4c2caba8143228a4f7d6df899dbb4
This commit is contained in:
@@ -5709,12 +5709,15 @@ struct sqlite3_index_info {
|
||||
** an operator that is part of a constraint term in the wHERE clause of
|
||||
** a query that uses a [virtual table].
|
||||
*/
|
||||
#define SQLITE_INDEX_CONSTRAINT_EQ 2
|
||||
#define SQLITE_INDEX_CONSTRAINT_GT 4
|
||||
#define SQLITE_INDEX_CONSTRAINT_LE 8
|
||||
#define SQLITE_INDEX_CONSTRAINT_LT 16
|
||||
#define SQLITE_INDEX_CONSTRAINT_GE 32
|
||||
#define SQLITE_INDEX_CONSTRAINT_MATCH 64
|
||||
#define SQLITE_INDEX_CONSTRAINT_EQ 2
|
||||
#define SQLITE_INDEX_CONSTRAINT_GT 4
|
||||
#define SQLITE_INDEX_CONSTRAINT_LE 8
|
||||
#define SQLITE_INDEX_CONSTRAINT_LT 16
|
||||
#define SQLITE_INDEX_CONSTRAINT_GE 32
|
||||
#define SQLITE_INDEX_CONSTRAINT_MATCH 64
|
||||
#define SQLITE_INDEX_CONSTRAINT_LIKE 65
|
||||
#define SQLITE_INDEX_CONSTRAINT_GLOB 66
|
||||
#define SQLITE_INDEX_CONSTRAINT_REGEXP 67
|
||||
|
||||
/*
|
||||
** CAPI3REF: Register A Virtual Table Implementation
|
||||
|
||||
@@ -849,6 +849,12 @@ static int echoBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
|
||||
zOp = ">="; break;
|
||||
case SQLITE_INDEX_CONSTRAINT_MATCH:
|
||||
zOp = "LIKE"; break;
|
||||
case SQLITE_INDEX_CONSTRAINT_LIKE:
|
||||
zOp = "like"; break;
|
||||
case SQLITE_INDEX_CONSTRAINT_GLOB:
|
||||
zOp = "glob"; break;
|
||||
case SQLITE_INDEX_CONSTRAINT_REGEXP:
|
||||
zOp = "regexp"; break;
|
||||
}
|
||||
if( zOp[0]=='L' ){
|
||||
zNew = sqlite3_mprintf(" %s %s LIKE (SELECT '%%'||?||'%%')",
|
||||
|
||||
@@ -893,6 +893,9 @@ static sqlite3_index_info *allocateIndexInfo(
|
||||
pIdxCons[j].iTermOffset = i;
|
||||
op = (u8)pTerm->eOperator & WO_ALL;
|
||||
if( op==WO_IN ) op = WO_EQ;
|
||||
if( op==WO_MATCH ){
|
||||
op = pTerm->eMatchOp;
|
||||
}
|
||||
pIdxCons[j].op = op;
|
||||
/* The direct assignment in the previous line is possible only because
|
||||
** the WO_ and SQLITE_INDEX_CONSTRAINT_ codes are identical. The
|
||||
|
||||
@@ -253,6 +253,7 @@ struct WhereTerm {
|
||||
u16 eOperator; /* A WO_xx value describing <op> */
|
||||
u16 wtFlags; /* TERM_xxx bit flags. See below */
|
||||
u8 nChild; /* Number of children that must disable us */
|
||||
u8 eMatchOp; /* Op for vtab MATCH/LIKE/GLOB/REGEXP terms */
|
||||
WhereClause *pWC; /* The clause this term is part of */
|
||||
Bitmask prereqRight; /* Bitmask of tables used by pExpr->pRight */
|
||||
Bitmask prereqAll; /* Bitmask of tables referenced by pExpr */
|
||||
|
||||
@@ -282,16 +282,24 @@ static int isLikeOrGlob(
|
||||
** If it is then return TRUE. If not, return FALSE.
|
||||
*/
|
||||
static int isMatchOfColumn(
|
||||
Expr *pExpr /* Test this expression */
|
||||
Expr *pExpr, /* Test this expression */
|
||||
unsigned char *peOp2 /* OUT: 0 for MATCH, or else an op2 value */
|
||||
){
|
||||
struct Op2 {
|
||||
const char *zOp;
|
||||
unsigned char eOp2;
|
||||
} aOp[] = {
|
||||
{ "match", SQLITE_INDEX_CONSTRAINT_MATCH },
|
||||
{ "glob", SQLITE_INDEX_CONSTRAINT_GLOB },
|
||||
{ "like", SQLITE_INDEX_CONSTRAINT_LIKE },
|
||||
{ "regex", SQLITE_INDEX_CONSTRAINT_REGEXP }
|
||||
};
|
||||
ExprList *pList;
|
||||
int i;
|
||||
|
||||
if( pExpr->op!=TK_FUNCTION ){
|
||||
return 0;
|
||||
}
|
||||
if( sqlite3StrICmp(pExpr->u.zToken,"match")!=0 ){
|
||||
return 0;
|
||||
}
|
||||
pList = pExpr->x.pList;
|
||||
if( pList->nExpr!=2 ){
|
||||
return 0;
|
||||
@@ -299,7 +307,13 @@ static int isMatchOfColumn(
|
||||
if( pList->a[1].pExpr->op != TK_COLUMN ){
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
for(i=0; i<ArraySize(aOp); i++){
|
||||
if( sqlite3StrICmp(pExpr->u.zToken, aOp[i].zOp)==0 ){
|
||||
*peOp2 = aOp[i].eOp2;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif /* SQLITE_OMIT_VIRTUALTABLE */
|
||||
|
||||
@@ -876,6 +890,7 @@ static void exprAnalyze(
|
||||
int op; /* Top-level operator. pExpr->op */
|
||||
Parse *pParse = pWInfo->pParse; /* Parsing context */
|
||||
sqlite3 *db = pParse->db; /* Database connection */
|
||||
unsigned char eOp2; /* op2 value for LIKE/REGEXP/GLOB */
|
||||
|
||||
if( db->mallocFailed ){
|
||||
return;
|
||||
@@ -1099,7 +1114,7 @@ static void exprAnalyze(
|
||||
** virtual tables. The native query optimizer does not attempt
|
||||
** to do anything with MATCH functions.
|
||||
*/
|
||||
if( isMatchOfColumn(pExpr) ){
|
||||
if( isMatchOfColumn(pExpr, &eOp2) ){
|
||||
int idxNew;
|
||||
Expr *pRight, *pLeft;
|
||||
WhereTerm *pNewTerm;
|
||||
@@ -1120,6 +1135,7 @@ static void exprAnalyze(
|
||||
pNewTerm->leftCursor = pLeft->iTable;
|
||||
pNewTerm->u.leftColumn = pLeft->iColumn;
|
||||
pNewTerm->eOperator = WO_MATCH;
|
||||
pNewTerm->eMatchOp = eOp2;
|
||||
markTermAsChild(pWC, idxNew, idxTerm);
|
||||
pTerm = &pWC->a[idxTerm];
|
||||
pTerm->wtFlags |= TERM_COPIED;
|
||||
|
||||
Reference in New Issue
Block a user