Get rid of the special RowSet processing in where.c and move that into
clients. Added the WHERE_DUPLICATES_OK option to eliminate an unnecessary RowSet during DELETE with a WHERE clause containing ORs. (CVS 6546) FossilOrigin-Name: 98606bee9e41b8969fb639fc43864e230185ca43
This commit is contained in:
parent
46619d6787
commit
336a5300de
20
manifest
20
manifest
@ -1,5 +1,5 @@
|
||||
C Make\ssure\sthat\sthe\soptimizer\srealizes\sthat\san\s"x\sIS\sNULL"\scontraint\sdoes\snot\nnecessarily\sgive\sa\ssingle-row\sresult\seven\son\sa\sUNIQUE\sindex.\s\sTicket\s#3824.\s(CVS\s6545)
|
||||
D 2009-04-24T14:51:42
|
||||
C Get\srid\sof\sthe\sspecial\sRowSet\sprocessing\sin\swhere.c\sand\smove\sthat\sinto\nclients.\s\sAdded\sthe\sWHERE_DUPLICATES_OK\soption\sto\seliminate\san\sunnecessary\nRowSet\sduring\sDELETE\swith\sa\sWHERE\sclause\scontaining\sORs.\s(CVS\s6546)
|
||||
D 2009-04-24T15:46:22
|
||||
F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
|
||||
F Makefile.in 583e87706abc3026960ed759aff6371faf84c211
|
||||
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
|
||||
@ -113,7 +113,7 @@ F src/build.c d4c6d22636607aa3c937e619de6781e83db48b6f
|
||||
F src/callback.c 73016376d6848ba987709e8c9048d4f0e0776036
|
||||
F src/complete.c cb14e06dbe79dee031031f0d9e686ff306afe07c
|
||||
F src/date.c d327ec7bb2f64b08d32b1035de82b9ba8675de91
|
||||
F src/delete.c eb1066b2f35489fee46ad765d2b66386fc7d8adf
|
||||
F src/delete.c becfff86a6d1a3606b7215cd79e2e033e3a66225
|
||||
F src/expr.c 015bdfc73af9d867558761cd8dc8652aa6c8cc04
|
||||
F src/fault.c dc88c821842157460750d2d61a8a8b4197d047ff
|
||||
F src/func.c f667fe886309707c7178542073bb0ced00a9fae7
|
||||
@ -158,11 +158,11 @@ F src/printf.c ea2d76000cc5f4579d7e9cb2f5460433eec0d384
|
||||
F src/random.c 676b9d7ac820fe81e6fb2394ac8c10cff7f38628
|
||||
F src/resolve.c 094e44450371fb27869eb8bf679aacbe51fdc56d
|
||||
F src/rowset.c 14d12b5e81b5907b87d511f6f4219805f96a4b55
|
||||
F src/select.c b3d9b7a56e08ec007286aad55cc46f36b13b63dd
|
||||
F src/select.c 40748e8044b79d41ba04ce1014ae45434ed452d3
|
||||
F src/shell.c 0a11f831603f17fea20ca97133c0f64e716af4a7
|
||||
F src/sqlite.h.in 8e0e256079bac2319380bdfebf403fcbe630510f
|
||||
F src/sqlite3ext.h 1db7d63ab5de4b3e6b83dd03d1a4e64fef6d2a17
|
||||
F src/sqliteInt.h 2ce7f412fbc5a56e35befea0625f05c786ddad83
|
||||
F src/sqliteInt.h d34f80cf38227ce8ed5c519e748375bd9b40d8f7
|
||||
F src/sqliteLimit.h ffe93f5a0c4e7bd13e70cd7bf84cfb5c3465f45d
|
||||
F src/status.c 237b193efae0cf6ac3f0817a208de6c6c6ef6d76
|
||||
F src/table.c cc86ad3d6ad54df7c63a3e807b5783c90411a08d
|
||||
@ -199,7 +199,7 @@ F src/test_thread.c b8a1ab7ca1a632f18e8a361880d5d65eeea08eac
|
||||
F src/test_wsd.c 3ae5101de6cbfda2720152ab659ea84079719241
|
||||
F src/tokenize.c 7bd3b6dd56566604ad24ed4aa017e6618166b500
|
||||
F src/trigger.c c029d5262768faa43962080a170bb707afa0b9d7
|
||||
F src/update.c 9617202877aa55c585b55937e0097bf050970c67
|
||||
F src/update.c 5062f0f042f67a4da0aff69949f145e2bc96e3cd
|
||||
F src/utf.c 9541d28f40441812c0b40f00334372a0542c00ff
|
||||
F src/util.c 828c552a22a1d5b650b8a5ea0009546715c45d93
|
||||
F src/vacuum.c 07121a727beeee88f27d704a00313ad6a7c9bef0
|
||||
@ -212,7 +212,7 @@ F src/vdbeblob.c e67757450ae8581a8b354d9d7e467e41502dfe38
|
||||
F src/vdbemem.c 111d8193859d16aefd5d3cb57472808584ea5503
|
||||
F src/vtab.c 6118d71c5137e20a7ac51fb5d9beb0361fbedb89
|
||||
F src/walker.c 7cdf63223c953d4343c6833e940f110281a378ee
|
||||
F src/where.c 5eaf44228221e541911fb530d6dceb1e0e37157f
|
||||
F src/where.c d20e083e5cc549a04f1647ee180d3bc3d2c73c02
|
||||
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
|
||||
F test/alias.test 4529fbc152f190268a15f9384a5651bbbabc9d87
|
||||
F test/all.test 14165b3e32715b700b5f0cbf8f6e3833dda0be45
|
||||
@ -724,7 +724,7 @@ F tool/speedtest16.c c8a9c793df96db7e4933f0852abb7a03d48f2e81
|
||||
F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
|
||||
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
|
||||
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
|
||||
P 577277e84a05707b8c21aa08bc5fc314c1ac38ac
|
||||
R 0206ac4aa85a991e57e63aae8cfedcce
|
||||
P 207335fdbf992a2f5bc5982b3163a38016ba1b21
|
||||
R 321c81c869b57be31c75d6ce8e352af8
|
||||
U drh
|
||||
Z c576963fd7ebe23db6a9694028a5b0e6
|
||||
Z 9a5d55f141a7dc0fff1bfe4c527d36a1
|
||||
|
@ -1 +1 @@
|
||||
207335fdbf992a2f5bc5982b3163a38016ba1b21
|
||||
98606bee9e41b8969fb639fc43864e230185ca43
|
@ -12,7 +12,7 @@
|
||||
** This file contains C code routines that are called by the parser
|
||||
** in order to generate code for DELETE FROM statements.
|
||||
**
|
||||
** $Id: delete.c,v 1.198 2009/03/05 03:48:07 shane Exp $
|
||||
** $Id: delete.c,v 1.199 2009/04/24 15:46:22 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
|
||||
@ -393,13 +393,15 @@ void sqlite3DeleteFrom(
|
||||
{
|
||||
int iRowid = ++pParse->nMem; /* Used for storing rowid values. */
|
||||
int iRowSet = ++pParse->nMem; /* Register for rowset of rows to delete */
|
||||
int regRowid; /* Actual register containing rowids */
|
||||
|
||||
/* Collect rowids of every row to be deleted.
|
||||
*/
|
||||
sqlite3VdbeAddOp2(v, OP_Null, 0, iRowSet);
|
||||
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0,
|
||||
WHERE_FILL_ROWSET, iRowSet);
|
||||
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere,0,WHERE_DUPLICATES_OK);
|
||||
if( pWInfo==0 ) goto delete_from_cleanup;
|
||||
regRowid = sqlite3ExprCodeGetColumn(pParse, pTab, -1, iCur, iRowid, 0);
|
||||
sqlite3VdbeAddOp2(v, OP_RowSetAdd, iRowSet, regRowid);
|
||||
if( db->flags & SQLITE_CountRows ){
|
||||
sqlite3VdbeAddOp2(v, OP_AddImm, memCnt, 1);
|
||||
}
|
||||
|
@ -12,7 +12,7 @@
|
||||
** This file contains C code routines that are called by the parser
|
||||
** to handle SELECT statements in SQLite.
|
||||
**
|
||||
** $Id: select.c,v 1.509 2009/04/23 13:22:43 drh Exp $
|
||||
** $Id: select.c,v 1.510 2009/04/24 15:46:22 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
|
||||
@ -3771,7 +3771,7 @@ int sqlite3Select(
|
||||
/* This case is for non-aggregate queries
|
||||
** Begin the database scan
|
||||
*/
|
||||
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pOrderBy, 0, 0);
|
||||
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pOrderBy, 0);
|
||||
if( pWInfo==0 ) goto select_end;
|
||||
|
||||
/* If sorting index that was created by a prior OP_OpenEphemeral
|
||||
@ -3893,7 +3893,7 @@ int sqlite3Select(
|
||||
** in the right order to begin with.
|
||||
*/
|
||||
sqlite3VdbeAddOp2(v, OP_Gosub, regReset, addrReset);
|
||||
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pGroupBy, 0, 0);
|
||||
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pGroupBy, 0);
|
||||
if( pWInfo==0 ) goto select_end;
|
||||
if( pGroupBy==0 ){
|
||||
/* The optimizer is able to deliver rows in group by order so
|
||||
@ -4151,7 +4151,7 @@ int sqlite3Select(
|
||||
** of output.
|
||||
*/
|
||||
resetAccumulator(pParse, &sAggInfo);
|
||||
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pMinMax, flag, 0);
|
||||
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pMinMax, flag);
|
||||
if( pWInfo==0 ){
|
||||
sqlite3ExprListDelete(db, pDel);
|
||||
goto select_end;
|
||||
|
@ -11,7 +11,7 @@
|
||||
*************************************************************************
|
||||
** Internal interface definitions for SQLite.
|
||||
**
|
||||
** @(#) $Id: sqliteInt.h,v 1.860 2009/04/23 13:22:44 drh Exp $
|
||||
** @(#) $Id: sqliteInt.h,v 1.861 2009/04/24 15:46:22 drh Exp $
|
||||
*/
|
||||
#ifndef _SQLITEINT_H_
|
||||
#define _SQLITEINT_H_
|
||||
@ -1742,16 +1742,17 @@ struct WhereLevel {
|
||||
};
|
||||
|
||||
/*
|
||||
** Flags appropriate for the wctrlFlags parameter of sqlite3WhereBegin().
|
||||
** Flags appropriate for the wctrlFlags parameter of sqlite3WhereBegin()
|
||||
** and the WhereInfo.wctrlFlags member.
|
||||
*/
|
||||
#define WHERE_ORDERBY_NORMAL 0x0000 /* No-op */
|
||||
#define WHERE_ORDERBY_MIN 0x0001 /* ORDER BY processing for min() func */
|
||||
#define WHERE_ORDERBY_MAX 0x0002 /* ORDER BY processing for max() func */
|
||||
#define WHERE_ONEPASS_DESIRED 0x0004 /* Want to do one-pass UPDATE/DELETE */
|
||||
#define WHERE_FILL_ROWSET 0x0008 /* Save results in a RowSet object */
|
||||
#define WHERE_OMIT_OPEN 0x0010 /* Table cursor are already open */
|
||||
#define WHERE_OMIT_CLOSE 0x0020 /* Omit close of table & index cursors */
|
||||
#define WHERE_FILL_ROWTEST 0x0040 /* Save results using OP_RowSetTest */
|
||||
#define WHERE_DUPLICATES_OK 0x0008 /* Ok to return a row more than once */
|
||||
#define WHERE_OMIT_OPEN 0x0010 /* Table cursor are already open */
|
||||
#define WHERE_OMIT_CLOSE 0x0020 /* Omit close of table & index cursors */
|
||||
#define WHERE_FORCE_TABLE 0x0040 /* Do not use an index-only search */
|
||||
|
||||
/*
|
||||
** The WHERE clause processing routine has two halves. The
|
||||
@ -1764,8 +1765,6 @@ struct WhereInfo {
|
||||
Parse *pParse; /* Parsing and code generating context */
|
||||
u16 wctrlFlags; /* Flags originally passed to sqlite3WhereBegin() */
|
||||
u8 okOnePass; /* Ok to use one-pass algorithm for UPDATE or DELETE */
|
||||
int regRowSet; /* Store rowids in this rowset */
|
||||
int iRowidHandler; /* Address of OP_RowSet or OP_RowSetTest */
|
||||
SrcList *pTabList; /* List of tables in the join */
|
||||
int iTop; /* The very beginning of the WHERE loop */
|
||||
int iContinue; /* Jump here to continue with next record */
|
||||
@ -2452,7 +2451,7 @@ Expr *sqlite3LimitWhere(Parse *, SrcList *, Expr *, ExprList *, Expr *, Expr *,
|
||||
#endif
|
||||
void sqlite3DeleteFrom(Parse*, SrcList*, Expr*);
|
||||
void sqlite3Update(Parse*, SrcList*, ExprList*, Expr*, int);
|
||||
WhereInfo *sqlite3WhereBegin(Parse*, SrcList*, Expr*, ExprList**, u8, int);
|
||||
WhereInfo *sqlite3WhereBegin(Parse*, SrcList*, Expr*, ExprList**, u16);
|
||||
void sqlite3WhereEnd(WhereInfo*);
|
||||
int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int, int);
|
||||
void sqlite3ExprCodeMove(Parse*, int, int, int);
|
||||
|
@ -12,7 +12,7 @@
|
||||
** This file contains C code routines that are called by the parser
|
||||
** to handle UPDATE statements.
|
||||
**
|
||||
** $Id: update.c,v 1.197 2009/04/22 17:15:03 drh Exp $
|
||||
** $Id: update.c,v 1.198 2009/04/24 15:46:22 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
|
||||
@ -345,8 +345,7 @@ void sqlite3Update(
|
||||
/* Begin the database scan
|
||||
*/
|
||||
sqlite3VdbeAddOp2(v, OP_Null, 0, regOldRowid);
|
||||
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0,
|
||||
WHERE_ONEPASS_DESIRED, 0);
|
||||
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere,0, WHERE_ONEPASS_DESIRED);
|
||||
if( pWInfo==0 ) goto update_cleanup;
|
||||
okOnePass = pWInfo->okOnePass;
|
||||
|
||||
|
92
src/where.c
92
src/where.c
@ -16,7 +16,7 @@
|
||||
** 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.389 2009/04/24 14:51:42 drh Exp $
|
||||
** $Id: where.c,v 1.390 2009/04/24 15:46:22 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
|
||||
@ -2395,7 +2395,7 @@ static int codeAllEqualityTerms(
|
||||
static Bitmask codeOneLoopStart(
|
||||
WhereInfo *pWInfo, /* Complete information about the WHERE clause */
|
||||
int iLevel, /* Which level of pWInfo->a[] should be coded */
|
||||
u8 wctrlFlags, /* One of the WHERE_* flags defined in sqliteInt.h */
|
||||
u16 wctrlFlags, /* One of the WHERE_* flags defined in sqliteInt.h */
|
||||
Bitmask notReady /* Which tables are currently available */
|
||||
){
|
||||
int j, k; /* Loop counters */
|
||||
@ -2411,21 +2411,6 @@ static Bitmask codeOneLoopStart(
|
||||
struct SrcList_item *pTabItem; /* FROM clause term being coded */
|
||||
int addrBrk; /* Jump here to break out of the loop */
|
||||
int addrCont; /* Jump here to continue with next cycle */
|
||||
int regRowSet; /* Write rowids to this RowSet if non-negative */
|
||||
|
||||
/* Sometimes, this function is required to generate code to do
|
||||
** something with the rowid of each row scanned. Specifically,
|
||||
** If pWInfo->regRowSet is non-zero, then the rowid must be inserted
|
||||
** into the RowSet object stored in register pWInfo->regRowSet.
|
||||
**
|
||||
** Extracting a rowid value from a VDBE cursor is not always a cheap
|
||||
** operation, especially if the rowid is being extracted from an index
|
||||
** cursor. If the rowid value is available as a by-product of the code
|
||||
** generated to create the top of the scan loop, then it can be reused
|
||||
** without extracting it from a cursor. The following two variables are
|
||||
** used to communicate the availability of the rowid value to the C-code
|
||||
** at the end of this function that generates the rowid-handling VDBE code.
|
||||
*/
|
||||
int iRowidReg = 0; /* Rowid is stored in this register, if not zero */
|
||||
int iReleaseReg = 0; /* Temp register to free before returning */
|
||||
|
||||
@ -2437,8 +2422,7 @@ static Bitmask codeOneLoopStart(
|
||||
iCur = pTabItem->iCursor;
|
||||
bRev = (pLevel->plan.wsFlags & WHERE_REVERSE)!=0;
|
||||
omitTable = (pLevel->plan.wsFlags & WHERE_IDX_ONLY)!=0
|
||||
&& (wctrlFlags & WHERE_FILL_ROWTEST)==0;
|
||||
regRowSet = pWInfo->regRowSet;
|
||||
&& (wctrlFlags & WHERE_FORCE_TABLE)==0;
|
||||
|
||||
/* Create labels for the "break" and "continue" instructions
|
||||
** for the current loop. Jump to addrBrk to break out of a loop.
|
||||
@ -2836,14 +2820,13 @@ static Bitmask codeOneLoopStart(
|
||||
** B: <after the loop>
|
||||
**
|
||||
*/
|
||||
const int f = WHERE_OMIT_OPEN | WHERE_OMIT_CLOSE | WHERE_FILL_ROWTEST;
|
||||
|
||||
WhereClause *pOrWc; /* The OR-clause broken out into subterms */
|
||||
WhereTerm *pFinal; /* Final subterm within the OR-clause. */
|
||||
SrcList oneTab; /* Shortened table list */
|
||||
|
||||
int regReturn = ++pParse->nMem; /* Register used with OP_Gosub */
|
||||
int regRowset = ++pParse->nMem; /* Register for RowSet object */
|
||||
int regRowset; /* Register for RowSet object */
|
||||
int regRowid; /* Register holding rowid */
|
||||
int iLoopBody = sqlite3VdbeMakeLabel(v); /* Start of loop body */
|
||||
int iRetInit; /* Address of regReturn init */
|
||||
int ii;
|
||||
@ -2871,7 +2854,11 @@ static Bitmask codeOneLoopStart(
|
||||
** fall through to the next instruction, just as an OP_Next does if
|
||||
** called on an uninitialized cursor.
|
||||
*/
|
||||
sqlite3VdbeAddOp2(v, OP_Null, 0, regRowset);
|
||||
if( (wctrlFlags & WHERE_DUPLICATES_OK)==0 ){
|
||||
regRowset = ++pParse->nMem;
|
||||
regRowid = ++pParse->nMem;
|
||||
sqlite3VdbeAddOp2(v, OP_Null, 0, regRowset);
|
||||
}
|
||||
iRetInit = sqlite3VdbeAddOp2(v, OP_Integer, 0, regReturn);
|
||||
|
||||
for(ii=0; ii<pOrWc->nTerm; ii++){
|
||||
@ -2880,20 +2867,18 @@ static Bitmask codeOneLoopStart(
|
||||
WhereInfo *pSubWInfo; /* Info for single OR-term scan */
|
||||
|
||||
/* Loop through table entries that match term pOrTerm. */
|
||||
pSubWInfo = sqlite3WhereBegin(
|
||||
pParse, &oneTab, pOrTerm->pExpr, 0, f, regRowset);
|
||||
pSubWInfo = sqlite3WhereBegin(pParse, &oneTab, pOrTerm->pExpr, 0,
|
||||
WHERE_OMIT_OPEN | WHERE_OMIT_CLOSE | WHERE_FORCE_TABLE);
|
||||
if( pSubWInfo ){
|
||||
int iSet = ((ii==pOrWc->nTerm-1)?-1:ii);
|
||||
/* The call to sqlite3WhereBegin has coded an OP_RowSetTest
|
||||
** at instruction iRowSet. Set P2 (the jump target) of this
|
||||
** instruction to jump past the OP_Gosub coded below. This way,
|
||||
** if the rowid is already in the hash-table, the body of the
|
||||
** loop is not executed.
|
||||
*/
|
||||
int iRowSet = pSubWInfo->iRowidHandler;
|
||||
assert( iRowSet>0 || pWInfo->pParse->db->mallocFailed );
|
||||
sqlite3VdbeChangeP2(v, iRowSet, sqlite3VdbeCurrentAddr(v) + 1);
|
||||
sqlite3VdbeChangeP4(v, iRowSet, (char *)iSet, P4_INT32);
|
||||
if( (wctrlFlags & WHERE_DUPLICATES_OK)==0 ){
|
||||
int iSet = ((ii==pOrWc->nTerm-1)?-1:ii);
|
||||
int r;
|
||||
r = sqlite3ExprCodeGetColumn(pParse, pTabItem->pTab, -1, iCur,
|
||||
regRowid, 0);
|
||||
sqlite3VdbeAddOp4(v, OP_RowSetTest, regRowset,
|
||||
sqlite3VdbeCurrentAddr(v)+2,
|
||||
r, (char*)iSet, P4_INT32);
|
||||
}
|
||||
sqlite3VdbeAddOp2(v, OP_Gosub, regReturn, iLoopBody);
|
||||
|
||||
/* Finish the loop through table entries that match term pOrTerm. */
|
||||
@ -2902,7 +2887,7 @@ static Bitmask codeOneLoopStart(
|
||||
}
|
||||
}
|
||||
sqlite3VdbeChangeP1(v, iRetInit, sqlite3VdbeCurrentAddr(v));
|
||||
sqlite3VdbeAddOp2(v, OP_Null, 0, regRowset);
|
||||
/* sqlite3VdbeAddOp2(v, OP_Null, 0, regRowset); */
|
||||
sqlite3VdbeAddOp2(v, OP_Goto, 0, pLevel->addrBrk);
|
||||
sqlite3VdbeResolveLabel(v, iLoopBody);
|
||||
|
||||
@ -2965,28 +2950,6 @@ static Bitmask codeOneLoopStart(
|
||||
pTerm->wtFlags |= TERM_CODED;
|
||||
}
|
||||
}
|
||||
|
||||
/* Do the special rowid handling now. */
|
||||
if( regRowSet ){
|
||||
assert( regRowSet>0 );
|
||||
if( iRowidReg==0 ){
|
||||
/* The rowid was not available as a side-effect of the code
|
||||
** genenerated above. So extract it from the cursor now.
|
||||
*/
|
||||
assert( iReleaseReg==0 );
|
||||
iReleaseReg = iRowidReg = sqlite3GetTempReg(pParse);
|
||||
sqlite3VdbeAddOp2(v, OP_Rowid, iCur, iRowidReg);
|
||||
}
|
||||
|
||||
if( pWInfo->wctrlFlags&WHERE_FILL_ROWSET ){
|
||||
sqlite3VdbeAddOp2(v, OP_RowSetAdd, regRowSet, iRowidReg);
|
||||
VVA_ONLY( pWInfo->iRowidHandler = 0; )
|
||||
}else{
|
||||
assert( pWInfo->wctrlFlags&WHERE_FILL_ROWTEST );
|
||||
pWInfo->iRowidHandler =
|
||||
sqlite3VdbeAddOp3(v, OP_RowSetTest, regRowSet, 0, iRowidReg);
|
||||
}
|
||||
}
|
||||
sqlite3ReleaseTempReg(pParse, iReleaseReg);
|
||||
|
||||
return notReady;
|
||||
@ -3120,8 +3083,7 @@ WhereInfo *sqlite3WhereBegin(
|
||||
SrcList *pTabList, /* A list of all tables to be scanned */
|
||||
Expr *pWhere, /* The WHERE clause */
|
||||
ExprList **ppOrderBy, /* An ORDER BY clause, or NULL */
|
||||
u8 wctrlFlags, /* One of the WHERE_* flags defined in sqliteInt.h */
|
||||
int regRowSet /* Register hold RowSet if WHERE_FILL_ROWSET is set */
|
||||
u16 wctrlFlags /* One of the WHERE_* flags defined in sqliteInt.h */
|
||||
){
|
||||
int i; /* Loop counter */
|
||||
int nByteWInfo; /* Num. bytes allocated for WhereInfo struct */
|
||||
@ -3170,11 +3132,9 @@ WhereInfo *sqlite3WhereBegin(
|
||||
pWInfo->pParse = pParse;
|
||||
pWInfo->pTabList = pTabList;
|
||||
pWInfo->iBreak = sqlite3VdbeMakeLabel(v);
|
||||
pWInfo->regRowSet = regRowSet;
|
||||
pWInfo->pWC = pWC = (WhereClause *)&((u8 *)pWInfo)[nByteWInfo];
|
||||
pWInfo->wctrlFlags = wctrlFlags;
|
||||
pMaskSet = (WhereMaskSet*)&pWC[1];
|
||||
assert( regRowSet==0 || (wctrlFlags&(WHERE_FILL_ROWSET|WHERE_FILL_ROWTEST)) );
|
||||
|
||||
/* Split the WHERE clause into separate subexpressions where each
|
||||
** subexpression is separated by an AND operator.
|
||||
@ -3534,7 +3494,11 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
|
||||
if( pLevel->iIdxCur>=0 ){
|
||||
sqlite3VdbeAddOp1(v, OP_NullRow, pLevel->iIdxCur);
|
||||
}
|
||||
sqlite3VdbeAddOp2(v, OP_Goto, 0, pLevel->addrFirst);
|
||||
if( pLevel->op==OP_Return ){
|
||||
sqlite3VdbeAddOp2(v, OP_Gosub, pLevel->p1, pLevel->addrFirst);
|
||||
}else{
|
||||
sqlite3VdbeAddOp2(v, OP_Goto, 0, pLevel->addrFirst);
|
||||
}
|
||||
sqlite3VdbeJumpHere(v, addr);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user