-C Add\ssupport\sfor\sthe\sMATCH\soperator.\s(CVS\s3231)
-D 2006-06-13T15:37:26
+C The\soptimizer\srecognizes\sMATCH\soperators\sand\sallows\svirtual-tables\sto\smake\nuse\sof\sthem.\s(CVS\s3232)
+D 2006-06-13T17:39:00
F Makefile.in 56fd6261e83f60724e6dcd764e06ab68cbd53909
F Makefile.linux-gcc 74ba0eadf88748a9ce3fd03d2a3ede2e6715baec
F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028
F src/delete.c f9a8c7837adb4bb4810a698a041a88d5ec7bfa9a
F src/experimental.c 1b2d1a6cd62ecc39610e97670332ca073c50792b
F src/expr.c 8c873e05436ca8ee0ac4c7825d35ff898abb9c89
-F src/func.c acbbf533b55221f26760798d99b37de3ac5678fe
+F src/func.c 16eaca47b4d5c66f750e0b2d8814387d70f0d5b2
F src/hash.c 449f3d6620193aa557f5d86cbc5cc6b87702b185
F src/hash.h 1b3f7e2609141fd571f62199fc38687d262e9564
F src/insert.c 2c3eeb4bcde13c1006824ef14953c2fdad31cf36
F src/vdbefifo.c 9efb94c8c3f4c979ebd0028219483f88e57584f5
F src/vdbemem.c 5f0afe3b92bb2c037f8d5d697f7c151fa50783a3
F src/vtab.c 12d83f7de893d06592d6d37c285defefebbd2d48
-F src/where.c 0b1fcf590040175e20c6d8f2e13485b683d3d03c
+F src/where.c 7e614b0278c688aec94c79d42f602b24e9e4119f
F tclinstaller.tcl 046e3624671962dc50f0481d7c25b38ef803eb42
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
F test/all.test 5df90d015ca63fcef2a4b62c24f7316b66c4bfd4
F test/expr.test 7b4b349abdb05ab1862c1cfcf7607e3731efc5d2
F test/fkey1.test 153004438d51e6769fb1ce165f6313972d6263ce
F test/format4.test 9f31d41d4f926cab97b2ebe6be00a6ab12dece87
-F test/func.test 27d02fd00b7c2a6b5c8c302d02f9f20876ce5cc8
+F test/func.test 7d8dd2e7d92fb17974d84c0cf02dfb7f9885b5b2
F test/hook.test 7e7645fd9a033f79cce8fdff151e32715e7ec50a
F test/in.test 369cb2aa1eab02296b4ec470732fe8c131260b1d
F test/index.test e65df12bed94b2903ee89987115e1578687e9266
F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
F www/whentouse.tcl 97e2b5cd296f7d8057e11f44427dea8a4c2db513
-P ea4bc5a0be6cfc81ef1e9405f396c43205fe9cd8
-R 3c35da63c52751c585cf9cb6b2473575
+P 815b84d5273b42978edcee0d4afe7f91a7933f4e
+R fa210e05061370c7e0ab1d80526752c9
U drh
-Z a4bc00b43637d2bd30e6651aa4a937df
+Z 0393cac6dbaee2c659fa623848ca0a40
** sqliteRegisterBuildinFunctions() found at the bottom of the file.
** All other code has file scope.
**
-** $Id: func.c,v 1.128 2006/05/11 13:25:39 drh Exp $
+** $Id: func.c,v 1.129 2006/06/13 17:39:00 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
sqlite3_result_text(context, sqlite3_version, -1, SQLITE_STATIC);
}
+/*
+** The MATCH() function is unimplemented. If anybody tries to use it,
+** return an error.
+*/
+static void matchStub(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ static const char zErr[] = "MATCH is not implemented";
+ sqlite3_result_error(context, zErr, sizeof(zErr)-1);
+}
+
/*
** EXPERIMENTAL - This is not an official function. The interface may
{ "last_insert_rowid", 0, 1, SQLITE_UTF8, 0, last_insert_rowid },
{ "changes", 0, 1, SQLITE_UTF8, 0, changes },
{ "total_changes", 0, 1, SQLITE_UTF8, 0, total_changes },
+ { "match", 2, 0, SQLITE_UTF8, 0, matchStub },
#ifdef SQLITE_SOUNDEX
{ "soundex", 1, 0, SQLITE_UTF8, 0, soundexFunc},
#endif
** so is applicable. Because this module is responsible for selecting
** indices, you might also think of this module as the "query optimizer".
**
-** $Id: where.c,v 1.214 2006/06/13 15:00:55 danielk1977 Exp $
+** $Id: where.c,v 1.215 2006/06/13 17:39:01 drh Exp $
*/
#include "sqliteInt.h"
#define WO_LE (WO_EQ<<(TK_LE-TK_EQ))
#define WO_GT (WO_EQ<<(TK_GT-TK_EQ))
#define WO_GE (WO_EQ<<(TK_GE-TK_EQ))
+#define WO_MATCH 64
/*
** Value for flags returned by bestIndex()
}
#endif /* SQLITE_OMIT_LIKE_OPTIMIZATION */
+/*
+** Check to see if the given expression is of the form
+**
+** column MATCH expr
+**
+** If it is then return TRUE. If not, return FALSE.
+*/
+static int isMatchOfColumn(
+ Expr *pExpr /* Test this expression */
+){
+ ExprList *pList;
+
+ if( pExpr->op!=TK_FUNCTION ){
+ return 0;
+ }
+ if( pExpr->token.n!=5 || sqlite3StrNICmp(pExpr->token.z,"match",5)!=0 ){
+ return 0;
+ }
+ pList = pExpr->pList;
+ if( pList->nExpr!=2 ){
+ return 0;
+ }
+ if( pList->a[1].pExpr->op != TK_COLUMN ){
+ return 0;
+ }
+ return 1;
+}
+
/*
** If the pBase expression originated in the ON or USING clause of
** a join, then transfer the appropriate markings over to derived.
}
}
#endif /* SQLITE_OMIT_LIKE_OPTIMIZATION */
+
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ /* Add a WO_MATCH auxiliary term to the constraint set if the
+ ** current expression is of the form: column MATCH expr.
+ ** This information is used by the xBestIndex methods of
+ ** virtual tables. The native query optimizer does not attempt
+ ** to do anything with MATCH functions.
+ */
+ if( isMatchOfColumn(pExpr) ){
+ int idxNew;
+ Expr *pRight, *pLeft;
+ WhereTerm *pNewTerm;
+ Bitmask prereqColumn, prereqExpr;
+
+ pRight = pExpr->pList->a[0].pExpr;
+ pLeft = pExpr->pList->a[1].pExpr;
+ prereqExpr = exprTableUsage(pMaskSet, pRight);
+ prereqColumn = exprTableUsage(pMaskSet, pLeft);
+ if( (prereqExpr & prereqColumn)==0 ){
+ idxNew = whereClauseInsert(pWC, pExpr, TERM_VIRTUAL);
+ pNewTerm = &pWC->a[idxNew];
+ pNewTerm->prereqRight = prereqExpr;
+ pNewTerm->leftCursor = pLeft->iTable;
+ pNewTerm->leftColumn = pLeft->iColumn;
+ pNewTerm->eOperator = WO_MATCH;
+ pNewTerm->iParent = idxTerm;
+ pTerm = &pWC->a[idxNew];
+ pTerm->nChild = 1;
+ pTerm->flags |= TERM_COPIED;
+ pNewTerm->prereqAll = pTerm->prereqAll;
+ }
+ }
+#endif /* SQLITE_OMIT_VIRTUALTABLE */
}
#ifndef SQLITE_OMIT_VIRTUALTABLE
/*
-** Compute the best index for a virtual table
+** Compute the best index for a virtual table.
+**
+** The best index is computed by the xBestIndex method of the virtual
+** table module. This routine is really just a wrapper that sets up
+** the sqlite3_index_info structure that is used to communicate with
+** xBestIndex.
+**
+** In a join, this routine might be called multiple times for the
+** same virtual table. The sqlite3_index_info structure is created
+** and initialized on the first invocation and reused on all subsequent
+** invocations. The sqlite3_index_info structure is also used when
+** code is generated to access the virtual table. The whereInfoDelete()
+** routine takes care of freeing the sqlite3_index_info structure after
+** everybody has finished with it.
*/
static double bestVirtualIndex(
Parse *pParse, /* The parsing context */
pIdxCons[j].iColumn = pTerm->leftColumn;
pIdxCons[j].iTermOffset = i;
pIdxCons[j].op = pTerm->eOperator;
+ /* The direct assignment in the previous line is possible only because
+ ** the WO_ and SQLITE_INDEX_CONSTRAINT_ codes are identical. The
+ ** following asserts verify this fact. */
assert( WO_EQ==SQLITE_INDEX_CONSTRAINT_EQ );
assert( WO_LT==SQLITE_INDEX_CONSTRAINT_LT );
assert( WO_LE==SQLITE_INDEX_CONSTRAINT_LE );
assert( WO_GT==SQLITE_INDEX_CONSTRAINT_GT );
assert( WO_GE==SQLITE_INDEX_CONSTRAINT_GE );
- assert( pTerm->eOperator & (WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE) );
+ assert( WO_MATCH==SQLITE_INDEX_CONSTRAINT_MATCH );
+ assert( pTerm->eOperator & (WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE|WO_MATCH) );
j++;
}
for(i=0; i<nOrderBy; i++){
}
}
+ /* At this point, the sqlite3_index_info structure that pIdxInfo points
+ ** to will have been initialized, either during the current invocation or
+ ** during some prior invocation. Now we just have to customize the
+ ** details of pIdxInfo for the current invocation and pass it to
+ ** xBestIndex.
+ */
+
/* The module name must be defined */
assert( pTab->azModuleArg && pTab->azModuleArg[0] );
if( pTab->pVtab==0 ){
}
/* Set the aConstraint[].usable fields and initialize all
- ** output variables
+ ** output variables to zero.
+ **
+ ** aConstraint[].usable is true for constraints where the right-hand
+ ** side contains only references to tables to the left of the current
+ ** table. In other words, if the constraint is of the form:
+ **
+ ** column = expr
+ **
+ ** and we are evaluating a join, then the constraint on column is
+ ** only valid if all tables referenced in expr occur to the left
+ ** of the table containing column.
+ **
+ ** The aConstraints[] array contains entries for all constraints
+ ** on the current table. That way we only have to compute it once
+ ** even though we might try to pick the best index multiple times.
+ ** For each attempt at picking an index, the order of tables in the
+ ** join might be different so we have to recompute the usable flag
+ ** each time.
*/
pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint;
pUsage = pIdxInfo->aConstraintUsage;
#ifndef SQLITE_OMIT_VIRTUALTABLE
if( pLevel->pIdxInfo ){
+ /* Case 0: The table is a virtual-table. Use the VFilter and VNext
+ ** to access the data.
+ */
char *zSpace; /* Space for OP_VFilter to marshall it's arguments */
- /* Case 0: That table is a virtual-table. Use the VFilter and VNext.
- */
sqlite3_index_info *pIdxInfo = pLevel->pIdxInfo;
for(i=1; i<=pIdxInfo->nConstraint; i++){
int j;