mirror of
https://github.com/sqlite/sqlite.git
synced 2025-11-08 03:22:21 +03:00
First cut at optimizing single-row updates to use a one-pass algorithm. (CVS 4973)
FossilOrigin-Name: fba97f7874d723111e873d1470fc1a95e64f922d
This commit is contained in:
20
manifest
20
manifest
@@ -1,5 +1,5 @@
|
|||||||
C Add\sthree\snew\stest\scases\sto\sspeed4p.test.\s\sTwo\sof\sthe\sthree\sdo\ssingle-row\nupdates\sbased\son\srowid\sand\son\sprimary\skey.\s(CVS\s4972)
|
C First\scut\sat\soptimizing\ssingle-row\supdates\sto\suse\sa\sone-pass\salgorithm.\s(CVS\s4973)
|
||||||
D 2008-04-10T13:32:37
|
D 2008-04-10T13:33:18
|
||||||
F Makefile.arm-wince-mingw32ce-gcc ac5f7b2cef0cd850d6f755ba6ee4ab961b1fadf7
|
F Makefile.arm-wince-mingw32ce-gcc ac5f7b2cef0cd850d6f755ba6ee4ab961b1fadf7
|
||||||
F Makefile.in b861627d91df5ee422c54237aa38296954dc0151
|
F Makefile.in b861627d91df5ee422c54237aa38296954dc0151
|
||||||
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
|
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
|
||||||
@@ -135,12 +135,12 @@ F src/pragma.c e659c9e443d11854cff2fd250012365ae0ca81ba
|
|||||||
F src/prepare.c adc7e1fc08dfbab63cd213d4c0aff8f3fa70d477
|
F src/prepare.c adc7e1fc08dfbab63cd213d4c0aff8f3fa70d477
|
||||||
F src/printf.c 05d2b44d7b5b80c8a4a09108ddad9c20e254370d
|
F src/printf.c 05d2b44d7b5b80c8a4a09108ddad9c20e254370d
|
||||||
F src/random.c 2b2db2de4ab491f5a14d3480466f8f4b5a5db74a
|
F src/random.c 2b2db2de4ab491f5a14d3480466f8f4b5a5db74a
|
||||||
F src/select.c 53bfb7c4da43b2d20f27b5bf0ceab94d53835080
|
F src/select.c 1abe53c844f536a79cc11b19127c8e6d47a87b20
|
||||||
F src/server.c 087b92a39d883e3fa113cae259d64e4c7438bc96
|
F src/server.c 087b92a39d883e3fa113cae259d64e4c7438bc96
|
||||||
F src/shell.c 22297fffa6f00a6c6d44020fa13b1184a1bb372d
|
F src/shell.c 22297fffa6f00a6c6d44020fa13b1184a1bb372d
|
||||||
F src/sqlite.h.in 5364513316e0c36cb02b27c479643b400dbde9c7
|
F src/sqlite.h.in 5364513316e0c36cb02b27c479643b400dbde9c7
|
||||||
F src/sqlite3ext.h faacd0e6a81aabee0861c6d7883c9172e74ef5b3
|
F src/sqlite3ext.h faacd0e6a81aabee0861c6d7883c9172e74ef5b3
|
||||||
F src/sqliteInt.h 0f571303e19ccd61b2112d9d2613cd36e2166e89
|
F src/sqliteInt.h 52c381c2f15054a5199e5359cf5deb6d48624ede
|
||||||
F src/sqliteLimit.h f435e728c6b620ef7312814d660a81f9356eb5c8
|
F src/sqliteLimit.h f435e728c6b620ef7312814d660a81f9356eb5c8
|
||||||
F src/table.c 2c48c575dd59b3a6c5c306bc55f51a9402cf429a
|
F src/table.c 2c48c575dd59b3a6c5c306bc55f51a9402cf429a
|
||||||
F src/tclsqlite.c d272cbd208f87712f67ae7462d2d6cffbb28a676
|
F src/tclsqlite.c d272cbd208f87712f67ae7462d2d6cffbb28a676
|
||||||
@@ -170,7 +170,7 @@ F src/test_tclvar.c b2d1115e4d489179d3f029e765211b2ad527ba59
|
|||||||
F src/test_thread.c e297dd41db0b249646e69f97d36ec13e56e8b730
|
F src/test_thread.c e297dd41db0b249646e69f97d36ec13e56e8b730
|
||||||
F src/tokenize.c a96abe15a8db6fea2e964cdce2acba9ed17bc26f
|
F src/tokenize.c a96abe15a8db6fea2e964cdce2acba9ed17bc26f
|
||||||
F src/trigger.c 9bd3b6fa0beff4a02d262c96466f752ec15a7fc3
|
F src/trigger.c 9bd3b6fa0beff4a02d262c96466f752ec15a7fc3
|
||||||
F src/update.c 6d5f7728ec254c4a36a06a744f45b232b2eef857
|
F src/update.c d6f214aad7eab5aaec5f966058b0828b3f7d6706
|
||||||
F src/utf.c 8c94fa10efc78c2568d08d436acc59df4df7191b
|
F src/utf.c 8c94fa10efc78c2568d08d436acc59df4df7191b
|
||||||
F src/util.c 02c57c302ef738ff5b554953c12d8f919e501583
|
F src/util.c 02c57c302ef738ff5b554953c12d8f919e501583
|
||||||
F src/vacuum.c 3524411bfb58aac0d87eadd3e5b7cd532772af30
|
F src/vacuum.c 3524411bfb58aac0d87eadd3e5b7cd532772af30
|
||||||
@@ -183,7 +183,7 @@ F src/vdbeblob.c cc713c142c3d4952b380c98ee035f850830ddbdb
|
|||||||
F src/vdbefifo.c a30c237b2a3577e1415fb6e288cbb6b8ed1e5736
|
F src/vdbefifo.c a30c237b2a3577e1415fb6e288cbb6b8ed1e5736
|
||||||
F src/vdbemem.c 095e18f84b3171a5f2d71fa93a4bfc64220c1cfe
|
F src/vdbemem.c 095e18f84b3171a5f2d71fa93a4bfc64220c1cfe
|
||||||
F src/vtab.c 00cd16317b29495c185ff40e4b227917d5a371b2
|
F src/vtab.c 00cd16317b29495c185ff40e4b227917d5a371b2
|
||||||
F src/where.c 86b042dcd57f8428a75ddb59e6289eded6f6af09
|
F src/where.c a686f1e04f1ce5515a801fb3f3a358ef2cbb6ed2
|
||||||
F tclinstaller.tcl 4356d9d94d2b5ed5e68f9f0c80c4df3048dd7617
|
F tclinstaller.tcl 4356d9d94d2b5ed5e68f9f0c80c4df3048dd7617
|
||||||
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
|
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
|
||||||
F test/all.test d56a3ca8acdf761204aff0a2e7aa5eb8e11b31e6
|
F test/all.test d56a3ca8acdf761204aff0a2e7aa5eb8e11b31e6
|
||||||
@@ -522,7 +522,7 @@ F test/vacuum.test f67853a15caa120af591f819670f01a11fcc2bfc
|
|||||||
F test/vacuum2.test d3b9691541fe6ed5c711f547a1c7d70e9760ac6f
|
F test/vacuum2.test d3b9691541fe6ed5c711f547a1c7d70e9760ac6f
|
||||||
F test/vacuum3.test 72fbc903b085cd5f8b3a513b23f8ce44f7e0b06f
|
F test/vacuum3.test 72fbc903b085cd5f8b3a513b23f8ce44f7e0b06f
|
||||||
F test/varint.test ab7b110089a08b9926ed7390e7e97bdefeb74102
|
F test/varint.test ab7b110089a08b9926ed7390e7e97bdefeb74102
|
||||||
F test/veryquick.test 9bba6886026bb58a7332b6c96fd8270469f02177
|
F test/veryquick.test 93fd0500c367e6c03ea757071cfe4ca749533946
|
||||||
F test/view.test 4864e3841ab3213a95297718b94d5d6a8d3bc78b
|
F test/view.test 4864e3841ab3213a95297718b94d5d6a8d3bc78b
|
||||||
F test/vtab1.test bd905d1d43637a700308da6ffcc4e014c27e2f0a
|
F test/vtab1.test bd905d1d43637a700308da6ffcc4e014c27e2f0a
|
||||||
F test/vtab2.test 1da49b015582965a8fc386aa23d051a5a622b08e
|
F test/vtab2.test 1da49b015582965a8fc386aa23d051a5a622b08e
|
||||||
@@ -625,7 +625,7 @@ F www/tclsqlite.tcl 8be95ee6dba05eabcd27a9d91331c803f2ce2130
|
|||||||
F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
|
F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
|
||||||
F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
|
F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
|
||||||
F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5
|
F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5
|
||||||
P 80311594149af093f1719ec433a633c332a5955e
|
P a2da7f9ac24ed17329ce9bde2e521a5b945e4ec2
|
||||||
R 91477f9b363e3127fe8f0174bc0a918e
|
R 7e441dc4d958d560f1e90cd3d12b42d2
|
||||||
U drh
|
U drh
|
||||||
Z a1e09e21b5d00d19682913f02726b0e4
|
Z cff67db9b3badb72e8bf8a1dd2f2e574
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
a2da7f9ac24ed17329ce9bde2e521a5b945e4ec2
|
fba97f7874d723111e873d1470fc1a95e64f922d
|
||||||
20
src/select.c
20
src/select.c
@@ -12,7 +12,7 @@
|
|||||||
** This file contains C code routines that are called by the parser
|
** This file contains C code routines that are called by the parser
|
||||||
** to handle SELECT statements in SQLite.
|
** to handle SELECT statements in SQLite.
|
||||||
**
|
**
|
||||||
** $Id: select.c,v 1.425 2008/04/01 05:07:15 drh Exp $
|
** $Id: select.c,v 1.426 2008/04/10 13:33:18 drh Exp $
|
||||||
*/
|
*/
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
|
|
||||||
@@ -2677,7 +2677,7 @@ static int flattenSubquery(
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
** Analyze the SELECT statement passed as an argument to see if it
|
** Analyze the SELECT statement passed as an argument to see if it
|
||||||
** is a min() or max() query. Return ORDERBY_MIN or ORDERBY_MAX if
|
** is a min() or max() query. Return WHERE_ORDERBY_MIN or WHERE_ORDERBY_MAX if
|
||||||
** it is, or 0 otherwise. At present, a query is considered to be
|
** it is, or 0 otherwise. At present, a query is considered to be
|
||||||
** a min()/max() query if:
|
** a min()/max() query if:
|
||||||
**
|
**
|
||||||
@@ -2690,18 +2690,18 @@ static int minMaxQuery(Parse *pParse, Select *p){
|
|||||||
Expr *pExpr;
|
Expr *pExpr;
|
||||||
ExprList *pEList = p->pEList;
|
ExprList *pEList = p->pEList;
|
||||||
|
|
||||||
if( pEList->nExpr!=1 ) return ORDERBY_NORMAL;
|
if( pEList->nExpr!=1 ) return WHERE_ORDERBY_NORMAL;
|
||||||
pExpr = pEList->a[0].pExpr;
|
pExpr = pEList->a[0].pExpr;
|
||||||
pEList = pExpr->pList;
|
pEList = pExpr->pList;
|
||||||
if( pExpr->op!=TK_AGG_FUNCTION || pEList==0 || pEList->nExpr!=1 ) return 0;
|
if( pExpr->op!=TK_AGG_FUNCTION || pEList==0 || pEList->nExpr!=1 ) return 0;
|
||||||
if( pEList->a[0].pExpr->op!=TK_AGG_COLUMN ) return ORDERBY_NORMAL;
|
if( pEList->a[0].pExpr->op!=TK_AGG_COLUMN ) return WHERE_ORDERBY_NORMAL;
|
||||||
if( pExpr->token.n!=3 ) return ORDERBY_NORMAL;
|
if( pExpr->token.n!=3 ) return WHERE_ORDERBY_NORMAL;
|
||||||
if( sqlite3StrNICmp((char*)pExpr->token.z,"min",3)==0 ){
|
if( sqlite3StrNICmp((char*)pExpr->token.z,"min",3)==0 ){
|
||||||
return ORDERBY_MIN;
|
return WHERE_ORDERBY_MIN;
|
||||||
}else if( sqlite3StrNICmp((char*)pExpr->token.z,"max",3)==0 ){
|
}else if( sqlite3StrNICmp((char*)pExpr->token.z,"max",3)==0 ){
|
||||||
return ORDERBY_MAX;
|
return WHERE_ORDERBY_MAX;
|
||||||
}
|
}
|
||||||
return ORDERBY_NORMAL;
|
return WHERE_ORDERBY_NORMAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -3559,7 +3559,7 @@ int sqlite3Select(
|
|||||||
if( flag ){
|
if( flag ){
|
||||||
pDel = pMinMax = sqlite3ExprListDup(db, p->pEList->a[0].pExpr->pList);
|
pDel = pMinMax = sqlite3ExprListDup(db, p->pEList->a[0].pExpr->pList);
|
||||||
if( pMinMax && !db->mallocFailed ){
|
if( pMinMax && !db->mallocFailed ){
|
||||||
pMinMax->a[0].sortOrder = ((flag==ORDERBY_MIN)?0:1);
|
pMinMax->a[0].sortOrder = ((flag==WHERE_ORDERBY_MIN)?0:1);
|
||||||
pMinMax->a[0].pExpr->op = TK_COLUMN;
|
pMinMax->a[0].pExpr->op = TK_COLUMN;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3577,7 +3577,7 @@ int sqlite3Select(
|
|||||||
updateAccumulator(pParse, &sAggInfo);
|
updateAccumulator(pParse, &sAggInfo);
|
||||||
if( !pMinMax && flag ){
|
if( !pMinMax && flag ){
|
||||||
sqlite3VdbeAddOp2(v, OP_Goto, 0, pWInfo->iBreak);
|
sqlite3VdbeAddOp2(v, OP_Goto, 0, pWInfo->iBreak);
|
||||||
VdbeComment((v, "%s() by index", (flag==ORDERBY_MIN?"min":"max")));
|
VdbeComment((v, "%s() by index", (flag==WHERE_ORDERBY_MIN?"min":"max")));
|
||||||
}
|
}
|
||||||
sqlite3WhereEnd(pWInfo);
|
sqlite3WhereEnd(pWInfo);
|
||||||
finalizeAggFunctions(pParse, &sAggInfo);
|
finalizeAggFunctions(pParse, &sAggInfo);
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
*************************************************************************
|
*************************************************************************
|
||||||
** Internal interface definitions for SQLite.
|
** Internal interface definitions for SQLite.
|
||||||
**
|
**
|
||||||
** @(#) $Id: sqliteInt.h,v 1.689 2008/04/05 18:41:43 drh Exp $
|
** @(#) $Id: sqliteInt.h,v 1.690 2008/04/10 13:33:18 drh Exp $
|
||||||
*/
|
*/
|
||||||
#ifndef _SQLITEINT_H_
|
#ifndef _SQLITEINT_H_
|
||||||
#define _SQLITEINT_H_
|
#define _SQLITEINT_H_
|
||||||
@@ -1311,9 +1311,13 @@ struct WhereLevel {
|
|||||||
sqlite3_index_info *pIdxInfo; /* Index info for n-th source table */
|
sqlite3_index_info *pIdxInfo; /* Index info for n-th source table */
|
||||||
};
|
};
|
||||||
|
|
||||||
#define ORDERBY_NORMAL 0
|
/*
|
||||||
#define ORDERBY_MIN 1
|
** Flags appropriate for the wflags parameter of sqlite3WhereBegin().
|
||||||
#define ORDERBY_MAX 2
|
*/
|
||||||
|
#define WHERE_ORDERBY_NORMAL 0 /* No-op */
|
||||||
|
#define WHERE_ORDERBY_MIN 1 /* ORDER BY processing for min() func */
|
||||||
|
#define WHERE_ORDERBY_MAX 2 /* ORDER BY processing for max() func */
|
||||||
|
#define WHERE_ONEPASS_DESIRED 4 /* Want to do one-pass UPDATE/DELETE */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** The WHERE clause processing routine has two halves. The
|
** The WHERE clause processing routine has two halves. The
|
||||||
@@ -1323,7 +1327,8 @@ struct WhereLevel {
|
|||||||
** into the second half to give some continuity.
|
** into the second half to give some continuity.
|
||||||
*/
|
*/
|
||||||
struct WhereInfo {
|
struct WhereInfo {
|
||||||
Parse *pParse;
|
Parse *pParse; /* Parsing and code generating context */
|
||||||
|
u8 okOnePass; /* Ok to use one-pass algorithm for UPDATE or DELETE */
|
||||||
SrcList *pTabList; /* List of tables in the join */
|
SrcList *pTabList; /* List of tables in the join */
|
||||||
int iTop; /* The very beginning of the WHERE loop */
|
int iTop; /* The very beginning of the WHERE loop */
|
||||||
int iContinue; /* Jump here to continue with next record */
|
int iContinue; /* Jump here to continue with next record */
|
||||||
|
|||||||
18
src/update.c
18
src/update.c
@@ -12,7 +12,7 @@
|
|||||||
** This file contains C code routines that are called by the parser
|
** This file contains C code routines that are called by the parser
|
||||||
** to handle UPDATE statements.
|
** to handle UPDATE statements.
|
||||||
**
|
**
|
||||||
** $Id: update.c,v 1.175 2008/04/01 05:07:15 drh Exp $
|
** $Id: update.c,v 1.176 2008/04/10 13:33:18 drh Exp $
|
||||||
*/
|
*/
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
|
|
||||||
@@ -103,6 +103,7 @@ void sqlite3Update(
|
|||||||
NameContext sNC; /* The name-context to resolve expressions in */
|
NameContext sNC; /* The name-context to resolve expressions in */
|
||||||
int iDb; /* Database containing the table being updated */
|
int iDb; /* Database containing the table being updated */
|
||||||
int j1; /* Addresses of jump instructions */
|
int j1; /* Addresses of jump instructions */
|
||||||
|
int okOnePass; /* True for one-pass algorithm without the FIFO */
|
||||||
|
|
||||||
#ifndef SQLITE_OMIT_TRIGGER
|
#ifndef SQLITE_OMIT_TRIGGER
|
||||||
int isView; /* Trying to update a view */
|
int isView; /* Trying to update a view */
|
||||||
@@ -341,13 +342,16 @@ void sqlite3Update(
|
|||||||
|
|
||||||
/* Begin the database scan
|
/* Begin the database scan
|
||||||
*/
|
*/
|
||||||
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0);
|
sqlite3VdbeAddOp2(v, OP_Null, 0, regOldRowid);
|
||||||
|
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0,
|
||||||
|
WHERE_ONEPASS_DESIRED);
|
||||||
if( pWInfo==0 ) goto update_cleanup;
|
if( pWInfo==0 ) goto update_cleanup;
|
||||||
|
okOnePass = pWInfo->okOnePass;
|
||||||
|
|
||||||
/* Remember the rowid of every item to be updated.
|
/* Remember the rowid of every item to be updated.
|
||||||
*/
|
*/
|
||||||
sqlite3VdbeAddOp2(v, IsVirtual(pTab)?OP_VRowid:OP_Rowid, iCur, regOldRowid);
|
sqlite3VdbeAddOp2(v, IsVirtual(pTab)?OP_VRowid:OP_Rowid, iCur, regOldRowid);
|
||||||
sqlite3VdbeAddOp2(v, OP_FifoWrite, regOldRowid, 0);
|
if( !okOnePass ) sqlite3VdbeAddOp2(v, OP_FifoWrite, regOldRowid, 0);
|
||||||
|
|
||||||
/* End the database scan loop.
|
/* End the database scan loop.
|
||||||
*/
|
*/
|
||||||
@@ -367,7 +371,7 @@ void sqlite3Update(
|
|||||||
** action, then we need to open all indices because we might need
|
** action, then we need to open all indices because we might need
|
||||||
** to be deleting some records.
|
** to be deleting some records.
|
||||||
*/
|
*/
|
||||||
sqlite3OpenTable(pParse, iCur, iDb, pTab, OP_OpenWrite);
|
if( !okOnePass ) sqlite3OpenTable(pParse, iCur, iDb, pTab, OP_OpenWrite);
|
||||||
if( onError==OE_Replace ){
|
if( onError==OE_Replace ){
|
||||||
openAll = 1;
|
openAll = 1;
|
||||||
}else{
|
}else{
|
||||||
@@ -395,7 +399,13 @@ void sqlite3Update(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Top of the update loop */
|
/* Top of the update loop */
|
||||||
|
if( okOnePass ){
|
||||||
|
int a1 = sqlite3VdbeAddOp1(v, OP_NotNull, regOldRowid);
|
||||||
|
addr = sqlite3VdbeAddOp0(v, OP_Goto);
|
||||||
|
sqlite3VdbeJumpHere(v, a1);
|
||||||
|
}else{
|
||||||
addr = sqlite3VdbeAddOp2(v, OP_FifoRead, regOldRowid, 0);
|
addr = sqlite3VdbeAddOp2(v, OP_FifoRead, regOldRowid, 0);
|
||||||
|
}
|
||||||
|
|
||||||
if( triggers_exist ){
|
if( triggers_exist ){
|
||||||
int regRowid;
|
int regRowid;
|
||||||
|
|||||||
26
src/where.c
26
src/where.c
@@ -16,7 +16,7 @@
|
|||||||
** so is applicable. Because this module is responsible for selecting
|
** so is applicable. Because this module is responsible for selecting
|
||||||
** indices, you might also think of this module as the "query optimizer".
|
** indices, you might also think of this module as the "query optimizer".
|
||||||
**
|
**
|
||||||
** $Id: where.c,v 1.297 2008/04/01 05:07:15 drh Exp $
|
** $Id: where.c,v 1.298 2008/04/10 13:33:18 drh Exp $
|
||||||
*/
|
*/
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
|
|
||||||
@@ -2002,7 +2002,7 @@ WhereInfo *sqlite3WhereBegin(
|
|||||||
SrcList *pTabList, /* A list of all tables to be scanned */
|
SrcList *pTabList, /* A list of all tables to be scanned */
|
||||||
Expr *pWhere, /* The WHERE clause */
|
Expr *pWhere, /* The WHERE clause */
|
||||||
ExprList **ppOrderBy, /* An ORDER BY clause, or NULL */
|
ExprList **ppOrderBy, /* An ORDER BY clause, or NULL */
|
||||||
u8 obflag /* One of ORDERBY_MIN, ORDERBY_MAX or ORDERBY_NORMAL */
|
u8 wflags /* One of the WHERE_* flags defined in sqliteInt.h */
|
||||||
){
|
){
|
||||||
int i; /* Loop counter */
|
int i; /* Loop counter */
|
||||||
WhereInfo *pWInfo; /* Will become the return value of this function */
|
WhereInfo *pWInfo; /* Will become the return value of this function */
|
||||||
@@ -2210,6 +2210,17 @@ WhereInfo *sqlite3WhereBegin(
|
|||||||
*ppOrderBy = 0;
|
*ppOrderBy = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If the caller is an UPDATE or DELETE statement that is requesting
|
||||||
|
** to use a one-pass algorithm, determine if this is appropriate.
|
||||||
|
** The one-pass algorithm only works if the WHERE clause constraints
|
||||||
|
** the statement to update a single row.
|
||||||
|
*/
|
||||||
|
assert( (wflags & WHERE_ONEPASS_DESIRED)==0 || pWInfo->nLevel==1 );
|
||||||
|
if( (wflags & WHERE_ONEPASS_DESIRED)!=0 && (andFlags & WHERE_UNIQUE)!=0 ){
|
||||||
|
pWInfo->okOnePass = 1;
|
||||||
|
pWInfo->a[0].flags &= ~WHERE_IDX_ONLY;
|
||||||
|
}
|
||||||
|
|
||||||
/* Open all tables in the pTabList and any indices selected for
|
/* Open all tables in the pTabList and any indices selected for
|
||||||
** searching those tables.
|
** searching those tables.
|
||||||
*/
|
*/
|
||||||
@@ -2258,8 +2269,9 @@ WhereInfo *sqlite3WhereBegin(
|
|||||||
}else
|
}else
|
||||||
#endif
|
#endif
|
||||||
if( (pLevel->flags & WHERE_IDX_ONLY)==0 ){
|
if( (pLevel->flags & WHERE_IDX_ONLY)==0 ){
|
||||||
sqlite3OpenTable(pParse, pTabItem->iCursor, iDb, pTab, OP_OpenRead);
|
int op = pWInfo->okOnePass ? OP_OpenWrite : OP_OpenRead;
|
||||||
if( pTab->nCol<(sizeof(Bitmask)*8) ){
|
sqlite3OpenTable(pParse, pTabItem->iCursor, iDb, pTab, op);
|
||||||
|
if( !pWInfo->okOnePass && pTab->nCol<(sizeof(Bitmask)*8) ){
|
||||||
Bitmask b = pTabItem->colUsed;
|
Bitmask b = pTabItem->colUsed;
|
||||||
int n = 0;
|
int n = 0;
|
||||||
for(; b; b=b>>1, n++){}
|
for(; b; b=b>>1, n++){}
|
||||||
@@ -2496,7 +2508,7 @@ WhereInfo *sqlite3WhereBegin(
|
|||||||
** the first one after the nEq equality constraints in the index,
|
** the first one after the nEq equality constraints in the index,
|
||||||
** this requires some special handling.
|
** this requires some special handling.
|
||||||
*/
|
*/
|
||||||
if( (obflag==ORDERBY_MIN)
|
if( (wflags&WHERE_ORDERBY_MIN)!=0
|
||||||
&& (pLevel->flags&WHERE_ORDERBY)
|
&& (pLevel->flags&WHERE_ORDERBY)
|
||||||
&& (pIdx->nColumn>nEq)
|
&& (pIdx->nColumn>nEq)
|
||||||
&& (pOrderBy->a[0].pExpr->iColumn==pIdx->aiColumn[nEq])
|
&& (pOrderBy->a[0].pExpr->iColumn==pIdx->aiColumn[nEq])
|
||||||
@@ -2635,7 +2647,7 @@ WhereInfo *sqlite3WhereBegin(
|
|||||||
regBase = codeAllEqualityTerms(pParse, pLevel, &wc, notReady, 1);
|
regBase = codeAllEqualityTerms(pParse, pLevel, &wc, notReady, 1);
|
||||||
nxt = pLevel->nxt;
|
nxt = pLevel->nxt;
|
||||||
|
|
||||||
if( (obflag==ORDERBY_MIN)
|
if( (wflags&WHERE_ORDERBY_MIN)!=0
|
||||||
&& (pLevel->flags&WHERE_ORDERBY)
|
&& (pLevel->flags&WHERE_ORDERBY)
|
||||||
&& (pIdx->nColumn>nEq)
|
&& (pIdx->nColumn>nEq)
|
||||||
&& (pOrderBy->a[0].pExpr->iColumn==pIdx->aiColumn[nEq])
|
&& (pOrderBy->a[0].pExpr->iColumn==pIdx->aiColumn[nEq])
|
||||||
@@ -2853,7 +2865,7 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
|
|||||||
Table *pTab = pTabItem->pTab;
|
Table *pTab = pTabItem->pTab;
|
||||||
assert( pTab!=0 );
|
assert( pTab!=0 );
|
||||||
if( pTab->isEphem || pTab->pSelect ) continue;
|
if( pTab->isEphem || pTab->pSelect ) continue;
|
||||||
if( (pLevel->flags & WHERE_IDX_ONLY)==0 ){
|
if( !pWInfo->okOnePass && (pLevel->flags & WHERE_IDX_ONLY)==0 ){
|
||||||
sqlite3VdbeAddOp1(v, OP_Close, pTabItem->iCursor);
|
sqlite3VdbeAddOp1(v, OP_Close, pTabItem->iCursor);
|
||||||
}
|
}
|
||||||
if( pLevel->pIdx!=0 ){
|
if( pLevel->pIdx!=0 ){
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
#***********************************************************************
|
#***********************************************************************
|
||||||
# This file runs all tests.
|
# This file runs all tests.
|
||||||
#
|
#
|
||||||
# $Id: veryquick.test,v 1.1 2008/03/31 23:51:35 drh Exp $
|
# $Id: veryquick.test,v 1.2 2008/04/10 13:33:18 drh Exp $
|
||||||
|
|
||||||
proc lshift {lvar} {
|
proc lshift {lvar} {
|
||||||
upvar $lvar l
|
upvar $lvar l
|
||||||
@@ -95,6 +95,7 @@ set EXCLUDE {
|
|||||||
speed4.test
|
speed4.test
|
||||||
speed4p.test
|
speed4p.test
|
||||||
sqllimits1.test
|
sqllimits1.test
|
||||||
|
vacuum3.test
|
||||||
|
|
||||||
tkt2686.test
|
tkt2686.test
|
||||||
thread001.test
|
thread001.test
|
||||||
|
|||||||
Reference in New Issue
Block a user