mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-01 06:27:03 +03:00
Registerification of the WHERE clause logic. (CVS 4716)
FossilOrigin-Name: b3a141b2b0c09bf3c7704deeade290d71b7c9b77
This commit is contained in:
44
manifest
44
manifest
@ -1,5 +1,5 @@
|
||||
C Use\s1<<$x\sinstead\sof\spow(2,$x)\sin\sthe\stest\ssuite\scode.\s(CVS\s4715)
|
||||
D 2008-01-16T18:20:42
|
||||
C Registerification\sof\sthe\sWHERE\sclause\slogic.\s(CVS\s4716)
|
||||
D 2008-01-17T02:36:28
|
||||
F Makefile.arm-wince-mingw32ce-gcc ac5f7b2cef0cd850d6f755ba6ee4ab961b1fadf7
|
||||
F Makefile.in 30789bf70614bad659351660d76b8e533f3340e9
|
||||
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
|
||||
@ -79,24 +79,24 @@ F sqlite3.1 6be1ad09113570e1fc8dcaff84c9b0b337db5ffc
|
||||
F sqlite3.def a96c1d0d39362b763d2ddba220a32da41a15c4b4
|
||||
F sqlite3.pc.in abed4664817e1cd500f2276142c71958087c16bc
|
||||
F src/alter.c 5a54f58d9481ac14c4e58b702f3f8758dee84d04
|
||||
F src/analyze.c 5aa93f191b365ea308795f62ca6f2e8caa9de3e1
|
||||
F src/analyze.c ac17da1f9c804aabf709a1afff12ed35fc215104
|
||||
F src/attach.c 71f5c886004a9740fc6e6033d4e1ce0517ab6574
|
||||
F src/auth.c c8b2ab5c8bad4bd90ed7c294694f48269162c627
|
||||
F src/btmutex.c 5d39da37c9d1282f3c6f9967afae6a34ee36b7ff
|
||||
F src/btree.c 5164b32950cfd41f2c5c31e8ff82c4a499918aef
|
||||
F src/btree.h 19dcf5ad23c17b98855da548e9a8e3eb4429d5eb
|
||||
F src/btreeInt.h 1c5a9da165718ef7de81e35ce9ab5d9ba9283f76
|
||||
F src/build.c c0f9dba7028d415fb8d282e34a8ebcf69614befd
|
||||
F src/build.c ea291f091434aa9cd9700ea1611f2601c3c6a118
|
||||
F src/callback.c 77b302b0d41468dcda78c70e706e5b84577f0fa0
|
||||
F src/complete.c 4cf68fd75d60257524cbe74f87351b9848399131
|
||||
F src/date.c 49c5a6d2de6c12000905b4d36868b07d3011bbf6
|
||||
F src/delete.c 00e536847b8eedc5d35f89f7f38a8a7c1d2a22f9
|
||||
F src/delete.c ca07deed95f6f79c64338147147f698811628dc9
|
||||
F src/experimental.c 1b2d1a6cd62ecc39610e97670332ca073c50792b
|
||||
F src/expr.c be1018f2911bd93e6fc34f216ed263ce733569b6
|
||||
F src/expr.c 00ee6555e323cd772f85e48b353109865d1eb539
|
||||
F src/func.c 996071cf0af9d967e58b69fce1909555059ebc7d
|
||||
F src/hash.c 45a7005aac044b6c86bd7e49c44bc15d30006d6c
|
||||
F src/hash.h 031cd9f915aff27e12262cb9eb570ac1b8326b53
|
||||
F src/insert.c a19d9f51b611943386fcff714e3a0ffb137e463b
|
||||
F src/insert.c 8a90ba2d934bef98562cee12b778a17446730594
|
||||
F src/journal.c 807bed7a158979ac8d63953e1774e8d85bff65e2
|
||||
F src/legacy.c 4ac53191fad2e3c4d59bde1228879b2dc5a96d66
|
||||
F src/limits.h 71ab25f17e35e0a9f3f6f234b8ed49cc56731d35
|
||||
@ -127,16 +127,16 @@ F src/os_win.h 41a946bea10f61c158ce8645e7646b29d44f122b
|
||||
F src/pager.c 0cb6ccea4b9615627d61d7c4417cedc45776d429
|
||||
F src/pager.h f504f7ae84060fee0416a853e368d3d113c3d6fa
|
||||
F src/parse.y 2ae06e8d3190faace49c5b82e7cea1fc60d084a1
|
||||
F src/pragma.c b4e77e057990bb2c295c63327406d9bcbf6c9c08
|
||||
F src/pragma.c 0768de04ea4e97c8c79748110147c5bc6986c440
|
||||
F src/prepare.c c31a879d6795f4765fd0b113675c6debbc96b7fd
|
||||
F src/printf.c eb27822ba2eec669161409ca31279a24c26ac910
|
||||
F src/random.c 02ef38b469237482f1ea14a78b2087cfbaec48bd
|
||||
F src/select.c 578f7b01047b20349ead5a36d7e64274a61bea80
|
||||
F src/select.c 841eba5f83fb81f267bb2633bbf1b0cb7cfda96f
|
||||
F src/server.c 087b92a39d883e3fa113cae259d64e4c7438bc96
|
||||
F src/shell.c 0691a3d52dc37cf6ac2f74838e5ff8ae1055ac9b
|
||||
F src/sqlite.h.in 2a7e3776534bbe6ff2cdc058f3abebe91e7e429f
|
||||
F src/sqlite3ext.h a93f59cdee3638dc0c9c086f80df743a4e68c3cb
|
||||
F src/sqliteInt.h c3f43826e48b0d2928b9e6fa3aca887317285392
|
||||
F src/sqliteInt.h 89dc8eb7784948ef80966addc645721e20f9b772
|
||||
F src/sqliteLimit.h ee4430f88f69bf63527967bb35ca52af7b0ccb1e
|
||||
F src/table.c 1aeb9eab57b4235db86fe15a35dec76fb445a9c4
|
||||
F src/tclsqlite.c 9923abeffc9b3d7dad58e92b319661521f60debf
|
||||
@ -163,21 +163,21 @@ F src/test_server.c a6ece6c835e7eae835054124e09e947e422b1ac5
|
||||
F src/test_tclvar.c b2d1115e4d489179d3f029e765211b2ad527ba59
|
||||
F src/test_thread.c e297dd41db0b249646e69f97d36ec13e56e8b730
|
||||
F src/tokenize.c a4e04438c11fed2c67ec47fe3edbef9cca2d1b48
|
||||
F src/trigger.c 3a863b9952164ab5de58406c26daf06144bbddc4
|
||||
F src/update.c aad823f97a930e6982264299863837d4c6107d3b
|
||||
F src/trigger.c 5e869352a2f35890dc4711161bfe958fcec8f4d7
|
||||
F src/update.c a4da9976e06bf1cc676dc270e0e0dba8ae39729c
|
||||
F src/utf.c ef4b7d83bae533b76c3e1bf635b113fdad86a736
|
||||
F src/util.c 05f31144bbd3f1a24f4139ae029c42545cb72624
|
||||
F src/vacuum.c 3f34f278809bf3eb0b62ec46ff779e9c385b28f0
|
||||
F src/vdbe.c 1c58599437d048a2d14c5ce04e4576d2e3e78dfc
|
||||
F src/vdbe.c 9de1ce4ddf2906a63cef6bd11156d299edf31cd0
|
||||
F src/vdbe.h a9166e1601f5b74c20516a74182773a20baee43e
|
||||
F src/vdbeInt.h 31bd686595356284d5484592e2dc6e58025aa346
|
||||
F src/vdbeapi.c cb8c427a3ab646490c83204a98e94eff03ee2e89
|
||||
F src/vdbeaux.c 1bf7dbab24af0be35855abd5e4d9c6290e38f4ce
|
||||
F src/vdbeaux.c e5b401253f66f099c5d790dcbee43d614681eae5
|
||||
F src/vdbeblob.c e386d49d8354aa5a58f0a7f2794303442c149120
|
||||
F src/vdbefifo.c 334c838c8f42d61a94813d136019ee566b5dc2f6
|
||||
F src/vdbemem.c a86119b5ccc41ab8653e4746f83d591ff0ae892e
|
||||
F src/vtab.c 7f206d148f6e76f427f008f589610c72a4b9336c
|
||||
F src/where.c 27e40d32b7b47e70db9ac61b91a3a46c8dc6b47d
|
||||
F src/where.c 75908cb6dbcc7f2f21e42d65b68b1a24e6b5f679
|
||||
F tclinstaller.tcl 4356d9d94d2b5ed5e68f9f0c80c4df3048dd7617
|
||||
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
|
||||
F test/all.test ee350b9ab15b175fc0a8fb51bf2141ed3a3b9cba
|
||||
@ -445,7 +445,7 @@ F test/table.test 13b1c2e2fb4727b35ee1fb7641fc469214fd2455
|
||||
F test/tableapi.test 92651a95c23cf955e92407928e640536402fa3cc
|
||||
F test/tclsqlite.test 3fac87cb1059c46b8fa8a60b553f4f1adb0fb6d9
|
||||
F test/temptable.test 19b851b9e3e64d91e9867619b2a3f5fffee6e125
|
||||
F test/tester.tcl f851528e033e40b2c708eebf09c6ab4cb27c47d4
|
||||
F test/tester.tcl 493be4c2f8f4ea561d91c448b37da2d30fedb3f9
|
||||
F test/thread001.test 8fbd9559da0bbdc273e00318c7fd66c162020af7
|
||||
F test/thread002.test 2c4ad2c386f60f6fe268cd91c769ee35b3c1fd0b
|
||||
F test/thread1.test 776c9e459b75ba905193b351926ac4019b049f35
|
||||
@ -504,8 +504,8 @@ F test/unique.test 0253c4227a5dc533e312202ce21ecfad18058d18
|
||||
F test/update.test 24c1dcc025f7ef352759afe3f4a20e6fdfd43a97
|
||||
F test/utf16.test 20e2d9ba0d57e952a18b1ac8deab9ad49e082893
|
||||
F test/utf16align.test 7360e84472095518c56746f76b1f9d4dce99fb4d
|
||||
F test/vacuum.test 7493b09398d576b69a8b2f55bac92d50a9b8e796
|
||||
F test/vacuum2.test 970acadc2b4c3342fa2584410d96eae2c2b37c25
|
||||
F test/vacuum.test f67853a15caa120af591f819670f01a11fcc2bfc
|
||||
F test/vacuum2.test d3b9691541fe6ed5c711f547a1c7d70e9760ac6f
|
||||
F test/varint.test ab7b110089a08b9926ed7390e7e97bdefeb74102
|
||||
F test/view.test 7e15fa1ba3267ddaa9ae96b6daf519f23f95b43e
|
||||
F test/vtab1.test bd905d1d43637a700308da6ffcc4e014c27e2f0a
|
||||
@ -606,7 +606,7 @@ F www/tclsqlite.tcl 8be95ee6dba05eabcd27a9d91331c803f2ce2130
|
||||
F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
|
||||
F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
|
||||
F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5
|
||||
P 5807921f5a6e2e08f2c9e79aa91d8c587d64de74
|
||||
R 871f72c6ea2165bc803ac14747ee932f
|
||||
U danielk1977
|
||||
Z b5d54334b931393ae4ef6244d18f48c7
|
||||
P 3a289b6d28bcf399845586b15f100d7c3a78b550
|
||||
R 9b81ffae960f644182cd49ff81018f5f
|
||||
U drh
|
||||
Z ae8f3f9d0f33bb8446db7603cd67f9f8
|
||||
|
@ -1 +1 @@
|
||||
3a289b6d28bcf399845586b15f100d7c3a78b550
|
||||
b3a141b2b0c09bf3c7704deeade290d71b7c9b77
|
@ -11,7 +11,7 @@
|
||||
*************************************************************************
|
||||
** This file contains code associated with the ANALYZE command.
|
||||
**
|
||||
** @(#) $Id: analyze.c,v 1.38 2008/01/12 12:48:08 drh Exp $
|
||||
** @(#) $Id: analyze.c,v 1.39 2008/01/17 02:36:28 drh Exp $
|
||||
*/
|
||||
#ifndef SQLITE_OMIT_ANALYZE
|
||||
#include "sqliteInt.h"
|
||||
@ -216,7 +216,7 @@ static void analyzeOneTable(
|
||||
sqlite3VdbeAddOp1(v, OP_ToInt, regTemp);
|
||||
sqlite3VdbeAddOp3(v, OP_Concat, regTemp, regF2, regF2);
|
||||
}
|
||||
sqlite3VdbeAddOp4(v, OP_RegMakeRec, regFields, 3, regRec, "aaa", 0);
|
||||
sqlite3VdbeAddOp4(v, OP_MakeRecord, regFields, 3, regRec, "aaa", 0);
|
||||
sqlite3VdbeAddOp2(v, OP_NewRowid, iStatCur, regRowid);
|
||||
sqlite3VdbeAddOp3(v, OP_Insert, iStatCur, regRec, regRowid);
|
||||
sqlite3VdbeChangeP5(v, OPFLAG_APPEND);
|
||||
|
22
src/build.c
22
src/build.c
@ -22,7 +22,7 @@
|
||||
** COMMIT
|
||||
** ROLLBACK
|
||||
**
|
||||
** $Id: build.c,v 1.465 2008/01/12 21:35:57 drh Exp $
|
||||
** $Id: build.c,v 1.466 2008/01/17 02:36:28 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include <ctype.h>
|
||||
@ -2215,7 +2215,7 @@ void sqlite3DeferForeignKey(Parse *pParse, int isDeferred){
|
||||
** content of an index in response to a REINDEX command.
|
||||
**
|
||||
** if memRootPage is not negative, it means that the index is newly
|
||||
** created. The memory cell specified by memRootPage contains the
|
||||
** created. The register specified by memRootPage contains the
|
||||
** root page number of the index. If memRootPage is negative, then
|
||||
** the index already exists and must be cleared before being refilled and
|
||||
** the root page number of the index is taken from pIndex->tnum.
|
||||
@ -2246,8 +2246,7 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
|
||||
v = sqlite3GetVdbe(pParse);
|
||||
if( v==0 ) return;
|
||||
if( memRootPage>=0 ){
|
||||
sqlite3VdbeAddOp1(v, OP_SCopy, memRootPage);
|
||||
tnum = 0;
|
||||
tnum = memRootPage;
|
||||
}else{
|
||||
tnum = pIndex->tnum;
|
||||
sqlite3VdbeAddOp2(v, OP_Clear, tnum, iDb);
|
||||
@ -2736,12 +2735,17 @@ void sqlite3MinimumFileFormat(Parse *pParse, int iDb, int minFormat){
|
||||
Vdbe *v;
|
||||
v = sqlite3GetVdbe(pParse);
|
||||
if( v ){
|
||||
sqlite3VdbeAddOp3(v, OP_ReadCookie, iDb, 0, 1);
|
||||
int r1 = sqlite3GetTempReg(pParse);
|
||||
int r2 = sqlite3GetTempReg(pParse);
|
||||
int j1;
|
||||
sqlite3VdbeAddOp3(v, OP_ReadCookie, iDb, r1, 1);
|
||||
sqlite3VdbeUsesBtree(v, iDb);
|
||||
sqlite3VdbeAddOp1(v, OP_Integer, minFormat);
|
||||
sqlite3VdbeAddOp2(v, OP_Ge, 0, sqlite3VdbeCurrentAddr(v)+3);
|
||||
sqlite3VdbeAddOp1(v, OP_Integer, minFormat);
|
||||
sqlite3VdbeAddOp2(v, OP_SetCookie, iDb, 1);
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, minFormat, r2);
|
||||
j1 = sqlite3VdbeAddOp3(v, OP_Ge, r2, 0, r1);
|
||||
sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, 1, r2);
|
||||
sqlite3VdbeJumpHere(v, j1);
|
||||
sqlite3ReleaseTempReg(pParse, r1);
|
||||
sqlite3ReleaseTempReg(pParse, r2);
|
||||
}
|
||||
}
|
||||
|
||||
|
22
src/delete.c
22
src/delete.c
@ -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.157 2008/01/12 12:48:08 drh Exp $
|
||||
** $Id: delete.c,v 1.158 2008/01/17 02:36:28 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
|
||||
@ -60,24 +60,6 @@ int sqlite3IsReadOnly(Parse *pParse, Table *pTab, int viewOk){
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Allocate nVal contiguous memory cells and return the index of the
|
||||
** first. Also pop nVal elements from the stack and store them in the
|
||||
** registers. The element on the top of the stack is stored in the
|
||||
** register with the largest index.
|
||||
*/
|
||||
int sqlite3StackToReg(Parse *p, int nVal){
|
||||
int i;
|
||||
int iRet = p->nMem+1;
|
||||
Vdbe *v = sqlite3GetVdbe(p);
|
||||
assert(v);
|
||||
p->nMem += nVal;
|
||||
for(i=nVal-1; i>=0; i--){
|
||||
sqlite3VdbeAddOp2(v, OP_Move, 0, iRet+i);
|
||||
}
|
||||
return iRet;
|
||||
}
|
||||
|
||||
/*
|
||||
** Generate code that will open a table for reading.
|
||||
*/
|
||||
@ -519,7 +501,7 @@ int sqlite3GenerateIndexKey(
|
||||
sqlite3ColumnDefault(v, pTab, idx);
|
||||
}
|
||||
}
|
||||
sqlite3VdbeAddOp3(v, OP_RegMakeRec, regBase, nCol+1, regOut);
|
||||
sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol+1, regOut);
|
||||
sqlite3IndexAffinityStr(v, pIdx);
|
||||
sqlite3ReleaseTempRange(pParse, regBase, nCol+1);
|
||||
return regBase;
|
||||
|
@ -12,7 +12,7 @@
|
||||
** This file contains routines used for analyzing expressions and
|
||||
** for generating VDBE code that evaluates expressions in SQLite.
|
||||
**
|
||||
** $Id: expr.c,v 1.345 2008/01/13 19:02:11 drh Exp $
|
||||
** $Id: expr.c,v 1.346 2008/01/17 02:36:28 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include <ctype.h>
|
||||
@ -1786,7 +1786,7 @@ void sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){
|
||||
|
||||
/* Evaluate the expression and insert it into the temp table */
|
||||
sqlite3ExprCode(pParse, pE2, r1);
|
||||
sqlite3VdbeAddOp4(v, OP_RegMakeRec, r1, 1, r2, &affinity, 1);
|
||||
sqlite3VdbeAddOp4(v, OP_MakeRecord, r1, 1, r2, &affinity, 1);
|
||||
sqlite3VdbeAddOp2(v, OP_IdxInsert, pExpr->iTable, r2);
|
||||
}
|
||||
sqlite3ReleaseTempReg(pParse, r1);
|
||||
@ -2246,7 +2246,7 @@ static int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
|
||||
sqlite3VdbeJumpHere(v, j4);
|
||||
}else{
|
||||
r2 = regFree2 = sqlite3GetTempReg(pParse);
|
||||
sqlite3VdbeAddOp4(v, OP_RegMakeRec, r1, 1, r2, &affinity, 1);
|
||||
sqlite3VdbeAddOp4(v, OP_MakeRecord, r1, 1, r2, &affinity, 1);
|
||||
j5 = sqlite3VdbeAddOp3(v, OP_Found, pExpr->iTable, 0, r2);
|
||||
}
|
||||
sqlite3VdbeAddOp2(v, OP_AddImm, target, -1);
|
||||
|
31
src/insert.c
31
src/insert.c
@ -12,7 +12,7 @@
|
||||
** This file contains C code routines that are called by the parser
|
||||
** to handle INSERT statements in SQLite.
|
||||
**
|
||||
** $Id: insert.c,v 1.223 2008/01/12 12:48:08 drh Exp $
|
||||
** $Id: insert.c,v 1.224 2008/01/17 02:36:28 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
|
||||
@ -174,15 +174,15 @@ static int autoIncBegin(
|
||||
pParse->nMem++;
|
||||
sqlite3OpenTable(pParse, iCur, iDb, pDb->pSchema->pSeqTab, OP_OpenRead);
|
||||
addr = sqlite3VdbeCurrentAddr(v);
|
||||
sqlite3VdbeAddOp4(v, OP_String8, 0, memId-1, 0, pTab->zName, 0);
|
||||
sqlite3VdbeAddOp2(v, OP_Rewind, iCur, addr+8);
|
||||
sqlite3VdbeAddOp2(v, OP_Column, iCur, 0);
|
||||
sqlite3VdbeAddOp4(v, OP_String8, 0, 0, 0, pTab->zName, 0);
|
||||
sqlite3VdbeAddOp2(v, OP_Ne, 0, addr+7);
|
||||
sqlite3VdbeAddOp3(v, OP_Column, iCur, 0, memId);
|
||||
sqlite3VdbeAddOp3(v, OP_Ne, memId-1, addr+7, memId);
|
||||
sqlite3VdbeChangeP5(v, SQLITE_JUMPIFNULL);
|
||||
sqlite3VdbeAddOp2(v, OP_Rowid, iCur, memId+1);
|
||||
sqlite3VdbeAddOp3(v, OP_Column, iCur, 1, memId);
|
||||
sqlite3VdbeAddOp2(v, OP_Goto, 0, addr+8);
|
||||
sqlite3VdbeAddOp2(v, OP_Next, iCur, addr+1);
|
||||
sqlite3VdbeAddOp2(v, OP_Next, iCur, addr+2);
|
||||
sqlite3VdbeAddOp2(v, OP_Close, iCur, 0);
|
||||
}
|
||||
return memId;
|
||||
@ -224,8 +224,7 @@ static void autoIncEnd(
|
||||
j1 = sqlite3VdbeAddOp1(v, OP_NotNull, memId+1);
|
||||
sqlite3VdbeAddOp2(v, OP_NewRowid, iCur, memId+1);
|
||||
sqlite3VdbeJumpHere(v, j1);
|
||||
sqlite3VdbeAddOp4(v, OP_String8, 0, memId-1, 0, pTab->zName, 0);
|
||||
sqlite3VdbeAddOp3(v, OP_RegMakeRec, memId-1, 2, memId-1);
|
||||
sqlite3VdbeAddOp3(v, OP_MakeRecord, memId-1, 2, memId-1);
|
||||
sqlite3VdbeAddOp3(v, OP_Insert, iCur, memId-1, memId+1);
|
||||
sqlite3VdbeChangeP5(v, OPFLAG_APPEND);
|
||||
sqlite3VdbeAddOp1(v, OP_Close, iCur);
|
||||
@ -525,7 +524,7 @@ void sqlite3Insert(
|
||||
regRec = sqlite3GetTempReg(pParse);
|
||||
regRowid = sqlite3GetTempReg(pParse);
|
||||
sqlite3VdbeResolveLabel(v, iInsertBlock);
|
||||
sqlite3VdbeAddOp3(v, OP_RegMakeRec, regFromSelect, nColumn, regRec);
|
||||
sqlite3VdbeAddOp3(v, OP_MakeRecord, regFromSelect, nColumn, regRec);
|
||||
sqlite3VdbeAddOp2(v, OP_NewRowid, srcTab, regRowid);
|
||||
sqlite3VdbeAddOp3(v, OP_Insert, srcTab, regRec, regRowid);
|
||||
sqlite3VdbeAddOp2(v, OP_Return, 0, 0);
|
||||
@ -738,7 +737,7 @@ void sqlite3Insert(
|
||||
}
|
||||
}
|
||||
regRec = sqlite3GetTempReg(pParse);
|
||||
sqlite3VdbeAddOp3(v, OP_RegMakeRec, regCols, pTab->nCol, regRec);
|
||||
sqlite3VdbeAddOp3(v, OP_MakeRecord, regCols, pTab->nCol, regRec);
|
||||
|
||||
/* If this is an INSERT on a view with an INSTEAD OF INSERT trigger,
|
||||
** do not attempt any conversions before assembling the record.
|
||||
@ -777,7 +776,7 @@ void sqlite3Insert(
|
||||
sqlite3VdbeAddOp2(v, OP_SCopy, regFromSelect+keyColumn, regRowid);
|
||||
}else{
|
||||
VdbeOp *pOp;
|
||||
sqlite3ExprCode(pParse, pList->a[keyColumn].pExpr, 0);
|
||||
sqlite3ExprCode(pParse, pList->a[keyColumn].pExpr, regRowid);
|
||||
pOp = sqlite3VdbeGetOp(v, sqlite3VdbeCurrentAddr(v) - 1);
|
||||
if( pOp && pOp->opcode==OP_Null ){
|
||||
appendFlag = 1;
|
||||
@ -785,18 +784,16 @@ void sqlite3Insert(
|
||||
pOp->p1 = baseCur;
|
||||
pOp->p2 = regRowid;
|
||||
pOp->p3 = regAutoinc;
|
||||
}else{
|
||||
/* TODO: Avoid this use of the stack. */
|
||||
sqlite3VdbeAddOp2(v, OP_Move, 0, regRowid);
|
||||
}
|
||||
}
|
||||
/* If the PRIMARY KEY expression is NULL, then use OP_NewRowid
|
||||
** to generate a unique primary key value.
|
||||
*/
|
||||
if( !appendFlag ){
|
||||
sqlite3VdbeAddOp2(v, OP_IsNull, regRowid, sqlite3VdbeCurrentAddr(v)+2);
|
||||
sqlite3VdbeAddOp2(v, OP_Goto, -1, sqlite3VdbeCurrentAddr(v)+2);
|
||||
int j1;
|
||||
j1 = sqlite3VdbeAddOp1(v, OP_NotNull, regRowid);
|
||||
sqlite3VdbeAddOp3(v, OP_NewRowid, baseCur, regRowid, regAutoinc);
|
||||
sqlite3VdbeJumpHere(v, j1);
|
||||
sqlite3VdbeAddOp1(v, OP_MustBeInt, regRowid);
|
||||
}
|
||||
}else if( IsVirtual(pTab) ){
|
||||
@ -1178,7 +1175,7 @@ void sqlite3GenerateConstraintChecks(
|
||||
}
|
||||
}
|
||||
sqlite3VdbeAddOp2(v, OP_SCopy, regRowid, regIdx+i);
|
||||
sqlite3VdbeAddOp3(v, OP_RegMakeRec, regIdx, pIdx->nColumn+1, aRegIdx[iCur]);
|
||||
sqlite3VdbeAddOp3(v, OP_MakeRecord, regIdx, pIdx->nColumn+1, aRegIdx[iCur]);
|
||||
sqlite3IndexAffinityStr(v, pIdx);
|
||||
sqlite3ReleaseTempRange(pParse, regIdx, pIdx->nColumn+1);
|
||||
|
||||
@ -1294,7 +1291,7 @@ void sqlite3CompleteInsertion(
|
||||
}
|
||||
regData = regRowid + 1;
|
||||
regRec = sqlite3GetTempReg(pParse);
|
||||
sqlite3VdbeAddOp3(v, OP_RegMakeRec, regData, pTab->nCol, regRec);
|
||||
sqlite3VdbeAddOp3(v, OP_MakeRecord, regData, pTab->nCol, regRec);
|
||||
sqlite3TableAffinityStr(v, pTab);
|
||||
#ifndef SQLITE_OMIT_TRIGGER
|
||||
if( newIdx>=0 ){
|
||||
|
10
src/pragma.c
10
src/pragma.c
@ -11,7 +11,7 @@
|
||||
*************************************************************************
|
||||
** This file contains code used to implement the PRAGMA command.
|
||||
**
|
||||
** $Id: pragma.c,v 1.166 2008/01/12 21:35:57 drh Exp $
|
||||
** $Id: pragma.c,v 1.167 2008/01/17 02:36:28 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include <ctype.h>
|
||||
@ -459,11 +459,11 @@ void sqlite3Pragma(
|
||||
*/
|
||||
static const VdbeOpList setMeta6[] = {
|
||||
{ OP_Transaction, 0, 1, 0}, /* 0 */
|
||||
{ OP_ReadCookie, 0, 0, 3}, /* 1 */
|
||||
{ OP_If, 0, 0, 0}, /* 2 */
|
||||
{ OP_ReadCookie, 0, 1, 3}, /* 1 */
|
||||
{ OP_If, 1, 0, 0}, /* 2 */
|
||||
{ OP_Halt, SQLITE_OK, OE_Abort, 0}, /* 3 */
|
||||
{ OP_Integer, 0, 0, 0}, /* 4 */
|
||||
{ OP_SetCookie, 0, 6, 0}, /* 5 */
|
||||
{ OP_Integer, 0, 1, 0}, /* 4 */
|
||||
{ OP_SetCookie, 0, 6, 1}, /* 5 */
|
||||
};
|
||||
int iAddr;
|
||||
iAddr = sqlite3VdbeAddOpList(v, ArraySize(setMeta6), setMeta6);
|
||||
|
20
src/select.c
20
src/select.c
@ -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.402 2008/01/15 02:22:24 drh Exp $
|
||||
** $Id: select.c,v 1.403 2008/01/17 02:36:28 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
|
||||
@ -404,7 +404,7 @@ static void pushOntoSorter(
|
||||
sqlite3ExprCodeExprList(pParse, pOrderBy, regBase);
|
||||
sqlite3VdbeAddOp2(v, OP_Sequence, pOrderBy->iECursor, regBase+nExpr);
|
||||
sqlite3VdbeAddOp2(v, OP_Move, regData, regBase+nExpr+1);
|
||||
sqlite3VdbeAddOp3(v, OP_RegMakeRec, regBase, nExpr + 2, regRecord);
|
||||
sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nExpr + 2, regRecord);
|
||||
sqlite3VdbeAddOp2(v, OP_IdxInsert, pOrderBy->iECursor, regRecord);
|
||||
sqlite3ReleaseTempReg(pParse, regRecord);
|
||||
sqlite3ReleaseTempRange(pParse, regBase, nExpr+2);
|
||||
@ -466,7 +466,7 @@ static void codeDistinct(
|
||||
|
||||
v = pParse->pVdbe;
|
||||
r1 = sqlite3GetTempReg(pParse);
|
||||
sqlite3VdbeAddOp3(v, OP_RegMakeRec, iMem, N, r1);
|
||||
sqlite3VdbeAddOp3(v, OP_MakeRecord, iMem, N, r1);
|
||||
sqlite3VdbeAddOp3(v, OP_Found, iTab, addrRepeat, r1);
|
||||
sqlite3VdbeAddOp2(v, OP_IdxInsert, iTab, r1);
|
||||
sqlite3ReleaseTempReg(pParse, r1);
|
||||
@ -583,7 +583,7 @@ static int selectInnerLoop(
|
||||
*/
|
||||
#ifndef SQLITE_OMIT_COMPOUND_SELECT
|
||||
case SRT_Union: {
|
||||
sqlite3VdbeAddOp2(v, OP_RegMakeRec, iMem, nColumn);
|
||||
sqlite3VdbeAddOp2(v, OP_MakeRecord, iMem, nColumn);
|
||||
if( aff ){
|
||||
sqlite3VdbeChangeP4(v, -1, aff, P4_STATIC);
|
||||
}
|
||||
@ -597,7 +597,7 @@ static int selectInnerLoop(
|
||||
*/
|
||||
case SRT_Except: {
|
||||
int addr;
|
||||
addr = sqlite3VdbeAddOp2(v, OP_RegMakeRec, iMem, nColumn);
|
||||
addr = sqlite3VdbeAddOp2(v, OP_MakeRecord, iMem, nColumn);
|
||||
sqlite3VdbeChangeP4(v, -1, aff, P4_STATIC);
|
||||
sqlite3VdbeAddOp2(v, OP_NotFound, iParm, addr+3);
|
||||
sqlite3VdbeAddOp2(v, OP_Delete, iParm, 0);
|
||||
@ -610,7 +610,7 @@ static int selectInnerLoop(
|
||||
case SRT_Table:
|
||||
case SRT_EphemTab: {
|
||||
int r1 = sqlite3GetTempReg(pParse);
|
||||
sqlite3VdbeAddOp3(v, OP_RegMakeRec, iMem, nColumn, r1);
|
||||
sqlite3VdbeAddOp3(v, OP_MakeRecord, iMem, nColumn, r1);
|
||||
if( pOrderBy ){
|
||||
pushOntoSorter(pParse, pOrderBy, p, r1);
|
||||
}else{
|
||||
@ -643,7 +643,7 @@ static int selectInnerLoop(
|
||||
pushOntoSorter(pParse, pOrderBy, p, iMem);
|
||||
}else{
|
||||
int r1 = sqlite3GetTempReg(pParse);
|
||||
sqlite3VdbeAddOp4(v, OP_RegMakeRec, iMem, 1, r1, &p->affinity, 1);
|
||||
sqlite3VdbeAddOp4(v, OP_MakeRecord, iMem, 1, r1, &p->affinity, 1);
|
||||
sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, r1);
|
||||
sqlite3ReleaseTempReg(pParse, r1);
|
||||
}
|
||||
@ -683,7 +683,7 @@ static int selectInnerLoop(
|
||||
case SRT_Callback: {
|
||||
if( pOrderBy ){
|
||||
int r1 = sqlite3GetTempReg(pParse);
|
||||
sqlite3VdbeAddOp3(v, OP_RegMakeRec, iMem, nColumn, r1);
|
||||
sqlite3VdbeAddOp3(v, OP_MakeRecord, iMem, nColumn, r1);
|
||||
pushOntoSorter(pParse, pOrderBy, p, r1);
|
||||
sqlite3ReleaseTempReg(pParse, r1);
|
||||
}else if( eDest==SRT_Subroutine ){
|
||||
@ -808,7 +808,7 @@ static void generateSortTail(
|
||||
int j1;
|
||||
assert( nColumn==1 );
|
||||
j1 = sqlite3VdbeAddOp1(v, OP_IsNull, regRow);
|
||||
sqlite3VdbeAddOp4(v, OP_RegMakeRec, regRow, 1, regRow, &p->affinity, 1);
|
||||
sqlite3VdbeAddOp4(v, OP_MakeRecord, regRow, 1, regRow, &p->affinity, 1);
|
||||
sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, regRow);
|
||||
sqlite3VdbeJumpHere(v, j1);
|
||||
break;
|
||||
@ -3430,7 +3430,7 @@ int sqlite3Select(
|
||||
}
|
||||
}
|
||||
regRecord = sqlite3GetTempReg(pParse);
|
||||
sqlite3VdbeAddOp3(v, OP_RegMakeRec, regBase, nCol, regRecord);
|
||||
sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol, regRecord);
|
||||
sqlite3VdbeAddOp2(v, OP_IdxInsert, sAggInfo.sortingIdx, regRecord);
|
||||
sqlite3ReleaseTempReg(pParse, regRecord);
|
||||
sqlite3ReleaseTempRange(pParse, regBase, nCol);
|
||||
|
@ -11,7 +11,7 @@
|
||||
*************************************************************************
|
||||
** Internal interface definitions for SQLite.
|
||||
**
|
||||
** @(#) $Id: sqliteInt.h,v 1.649 2008/01/12 19:03:49 drh Exp $
|
||||
** @(#) $Id: sqliteInt.h,v 1.650 2008/01/17 02:36:28 drh Exp $
|
||||
*/
|
||||
#ifndef _SQLITEINT_H_
|
||||
#define _SQLITEINT_H_
|
||||
@ -1949,7 +1949,6 @@ int sqlite3OpenTempDatabase(Parse *);
|
||||
void sqlite3StrAccumAppend(StrAccum*,const char*,int);
|
||||
char *sqlite3StrAccumFinish(StrAccum*);
|
||||
void sqlite3StrAccumReset(StrAccum*);
|
||||
int sqlite3StackToReg(Parse *, int);
|
||||
void sqlite3SelectDestInit(SelectDest*,int,int);
|
||||
|
||||
/*
|
||||
|
@ -523,12 +523,12 @@ void sqlite3DropTriggerPtr(Parse *pParse, Trigger *pTrigger){
|
||||
int base;
|
||||
static const VdbeOpList dropTrigger[] = {
|
||||
{ OP_Rewind, 0, ADDR(9), 0},
|
||||
{ OP_String8, 0, 0, 0}, /* 1 */
|
||||
{ OP_Column, 0, 1, 0},
|
||||
{ OP_Ne, 0, ADDR(8), 0},
|
||||
{ OP_String8, 0, 0, 0}, /* 4: "trigger" */
|
||||
{ OP_Column, 0, 0, 0},
|
||||
{ OP_Ne, 0, ADDR(8), 0},
|
||||
{ OP_String8, 0, 1, 0}, /* 1 */
|
||||
{ OP_Column, 0, 1, 2},
|
||||
{ OP_Ne, 2, ADDR(8), 1},
|
||||
{ OP_String8, 0, 1, 0}, /* 4: "trigger" */
|
||||
{ OP_Column, 0, 0, 2},
|
||||
{ OP_Ne, 2, ADDR(8), 1},
|
||||
{ OP_Delete, 0, 0, 0},
|
||||
{ OP_Next, 0, ADDR(1), 0}, /* 8 */
|
||||
};
|
||||
|
@ -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.167 2008/01/10 23:50:11 drh Exp $
|
||||
** $Id: update.c,v 1.168 2008/01/17 02:36:28 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
|
||||
@ -449,7 +449,7 @@ void sqlite3Update(
|
||||
sqlite3VdbeAddOp2(v, OP_Null, 0, regCols+i);
|
||||
}
|
||||
}
|
||||
sqlite3VdbeAddOp3(v, OP_RegMakeRec, regCols, pTab->nCol, regRow);
|
||||
sqlite3VdbeAddOp3(v, OP_MakeRecord, regCols, pTab->nCol, regRow);
|
||||
if( !isView ){
|
||||
sqlite3TableAffinityStr(v, pTab);
|
||||
}
|
||||
|
93
src/vdbe.c
93
src/vdbe.c
@ -43,7 +43,7 @@
|
||||
** in this file for details. If in doubt, do not deviate from existing
|
||||
** commenting and indentation practices when changing or adding code.
|
||||
**
|
||||
** $Id: vdbe.c,v 1.696 2008/01/16 17:46:38 drh Exp $
|
||||
** $Id: vdbe.c,v 1.697 2008/01/17 02:36:28 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include <ctype.h>
|
||||
@ -1984,27 +1984,6 @@ case OP_IfNot: { /* no-push, jump, in1 */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Opcode: StackIsNull P1 P2 *
|
||||
**
|
||||
** Check the top of the stack and jump to P2 if the top of the stack
|
||||
** is NULL. If P1 is positive, then pop P1 elements from the stack
|
||||
** regardless of whether or not the jump is taken. If P1 is negative,
|
||||
** pop -P1 elements from the stack only if the jump is taken and leave
|
||||
** the stack unchanged if the jump is not taken.
|
||||
*/
|
||||
case OP_StackIsNull: { /* no-push, jump */
|
||||
if( pTos->flags & MEM_Null ){
|
||||
pc = pOp->p2-1;
|
||||
if( pOp->p1<0 ){
|
||||
popStack(&pTos, -pOp->p1);
|
||||
}
|
||||
}
|
||||
if( pOp->p1>0 ){
|
||||
popStack(&pTos, pOp->p1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* Opcode: IsNull P1 P2 P3 * *
|
||||
**
|
||||
** Jump to P2 if the value in register P1 is NULL. If P3 is greater
|
||||
@ -2319,9 +2298,9 @@ op_column_out:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Opcode: MakeRecord P1 P2 P4
|
||||
/* Opcode: MakeRecord P1 P2 P3 P4 *
|
||||
**
|
||||
** Convert the top abs(P1) entries of the stack into a single entry
|
||||
** Convert P2 registers beginning with P1 into a single entry
|
||||
** suitable for use as a data record in a database table or as a key
|
||||
** in an index. The details of the format are irrelavant as long as
|
||||
** the OP_Column opcode can decode the record later and as long as the
|
||||
@ -2329,13 +2308,6 @@ op_column_out:
|
||||
** records. Refer to source code comments for the details of the record
|
||||
** format.
|
||||
**
|
||||
** The original stack entries are popped from the stack if P1>0 but
|
||||
** remain on the stack if P1<0.
|
||||
**
|
||||
** If P2 is not zero and one or more of the entries are NULL, then jump
|
||||
** to the address given by P2. This feature can be used to skip a
|
||||
** uniqueness test on indices.
|
||||
**
|
||||
** P4 may be a string that is P1 characters long. The nth character of the
|
||||
** string indicates the column affinity that should be used for the nth
|
||||
** field of the index key (i.e. the first character of P4 corresponds to the
|
||||
@ -2346,17 +2318,7 @@ op_column_out:
|
||||
**
|
||||
** If P4 is NULL then all index fields have the affinity NONE.
|
||||
*/
|
||||
/*
|
||||
** Opcode: RegMakeRec P1 P2 P3 P4 *
|
||||
**
|
||||
** Builds a record like OP_MakeRecord. But the data is taken from
|
||||
** P2 registers beginning with P1: P1, P1+1, P1+2, ..., P1+P2-1.
|
||||
** The result is written into P3 or pushed onto the stack if P3 is zero.
|
||||
** There is no jump on NULL - that can be done with a separate
|
||||
** OP_AnyNull opcode.
|
||||
*/
|
||||
case OP_RegMakeRec:
|
||||
case OP_MakeRecord: { /* jump */
|
||||
case OP_MakeRecord: {
|
||||
/* Assuming the record contains N fields, the record format looks
|
||||
** like this:
|
||||
**
|
||||
@ -2380,41 +2342,20 @@ case OP_MakeRecord: { /* jump */
|
||||
int nZero = 0; /* Number of zero bytes at the end of the record */
|
||||
int nVarint; /* Number of bytes in a varint */
|
||||
u32 serial_type; /* Type field */
|
||||
int containsNull = 0; /* True if any of the data fields are NULL */
|
||||
Mem *pData0; /* Bottom of the stack */
|
||||
Mem *pLast; /* Top of the stack */
|
||||
int leaveOnStack; /* If true, leave the entries on the stack */
|
||||
Mem *pData0; /* First field to be combined into the record */
|
||||
Mem *pLast; /* Last field of the record */
|
||||
int nField; /* Number of fields in the record */
|
||||
int jumpIfNull; /* Jump here if non-zero and any entries are NULL. */
|
||||
char *zAffinity; /* The affinity string for the record */
|
||||
int file_format; /* File format to use for encoding */
|
||||
int i; /* Space used in zNewRecord[] */
|
||||
char zTemp[NBFS]; /* Space to hold small records */
|
||||
|
||||
if( pOp->p1<0 ){
|
||||
assert( pOp->opcode==OP_MakeRecord );
|
||||
leaveOnStack = 1;
|
||||
nField = -pOp->p1;
|
||||
}else{
|
||||
leaveOnStack = 0;
|
||||
nField = pOp->p1;
|
||||
}
|
||||
nField = pOp->p1;
|
||||
zAffinity = pOp->p4.z;
|
||||
|
||||
if( pOp->opcode==OP_RegMakeRec ){
|
||||
assert( nField>0 && pOp->p2>0 && pOp->p2+nField<=p->nMem );
|
||||
pData0 = &p->aMem[nField];
|
||||
nField = pOp->p2;
|
||||
leaveOnStack = 1;
|
||||
jumpIfNull = 0;
|
||||
pLast = &pData0[nField-1];
|
||||
}else{
|
||||
jumpIfNull = pOp->p2;
|
||||
pData0 = &pTos[1-nField];
|
||||
pLast = pTos;
|
||||
assert( pData0>=p->aStack );
|
||||
}
|
||||
containsNull = 0;
|
||||
assert( nField>0 && pOp->p2>0 && pOp->p2+nField<=p->nMem );
|
||||
pData0 = &p->aMem[nField];
|
||||
nField = pOp->p2;
|
||||
pLast = &pData0[nField-1];
|
||||
file_format = p->minWriteFileFormat;
|
||||
|
||||
/* Loop through the elements that will make up the record to figure
|
||||
@ -2425,9 +2366,6 @@ case OP_MakeRecord: { /* jump */
|
||||
if( zAffinity ){
|
||||
applyAffinity(pRec, zAffinity[pRec-pData0], encoding);
|
||||
}
|
||||
if( pRec->flags&MEM_Null ){
|
||||
containsNull = 1;
|
||||
}
|
||||
if( pRec->flags&MEM_Zero && pRec->n>0 ){
|
||||
ExpandBlob(pRec);
|
||||
}
|
||||
@ -2475,10 +2413,6 @@ case OP_MakeRecord: { /* jump */
|
||||
}
|
||||
assert( i==nByte );
|
||||
|
||||
/* Pop entries off the stack if required. Push the new record on. */
|
||||
if( !leaveOnStack ){
|
||||
popStack(&pTos, nField);
|
||||
}
|
||||
if( pOp->p3==0 ){
|
||||
pOut = ++pTos;
|
||||
}else{
|
||||
@ -2504,11 +2438,6 @@ case OP_MakeRecord: { /* jump */
|
||||
pOut->enc = SQLITE_UTF8; /* In case the blob is ever converted to text */
|
||||
REGISTER_TRACE(pOp->p3, pOut);
|
||||
UPDATE_MAX_BLOBSIZE(pOut);
|
||||
|
||||
/* If a NULL was encountered and jumpIfNull is non-zero, take the jump. */
|
||||
if( jumpIfNull && containsNull ){
|
||||
pc = jumpIfNull - 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -717,11 +717,17 @@ void sqlite3VdbeUsesBtree(Vdbe *p, int i){
|
||||
void sqlite3VdbePrintOp(FILE *pOut, int pc, Op *pOp){
|
||||
char *zP4;
|
||||
char zPtr[50];
|
||||
static const char *zFormat1 = "%4d %-13s %4d %4d %4d %-4s %.2X\n";
|
||||
static const char *zFormat1 = "%4d %-13s %4d %4d %4d %-4s %.2X %s\n";
|
||||
if( pOut==0 ) pOut = stdout;
|
||||
zP4 = displayP4(pOp, zPtr, sizeof(zPtr));
|
||||
fprintf(pOut, zFormat1, pc,
|
||||
sqlite3OpcodeName(pOp->opcode), pOp->p1, pOp->p2, pOp->p3, zP4, pOp->p5);
|
||||
sqlite3OpcodeName(pOp->opcode), pOp->p1, pOp->p2, pOp->p3, zP4, pOp->p5,
|
||||
#ifdef SQLITE_DEBUG
|
||||
pOp->zComment ? pOp->zComment : ""
|
||||
#else
|
||||
""
|
||||
#endif
|
||||
);
|
||||
fflush(pOut);
|
||||
}
|
||||
#endif
|
||||
|
203
src/where.c
203
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.281 2008/01/12 19:03:49 drh Exp $
|
||||
** $Id: where.c,v 1.282 2008/01/17 02:36:28 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
|
||||
@ -1705,9 +1705,13 @@ static void disableTerm(WhereLevel *pLevel, WhereTerm *pTerm){
|
||||
static void buildIndexProbe(
|
||||
Vdbe *v, /* Generate code into this VM */
|
||||
int nColumn, /* The number of columns to check for NULL */
|
||||
Index *pIdx /* Index that we will be searching */
|
||||
Index *pIdx, /* Index that we will be searching */
|
||||
int regSrc, /* Take values from this register */
|
||||
int regDest /* Write the result into this register */
|
||||
){
|
||||
sqlite3VdbeAddOp2(v, OP_MakeRecord, nColumn, 0);
|
||||
assert( regSrc>0 );
|
||||
assert( regDest>0 );
|
||||
sqlite3VdbeAddOp3(v, OP_MakeRecord, regSrc, nColumn, regDest);
|
||||
sqlite3IndexAffinityStr(v, pIdx);
|
||||
}
|
||||
|
||||
@ -1717,7 +1721,7 @@ static void buildIndexProbe(
|
||||
** term can be either X=expr or X IN (...). pTerm is the term to be
|
||||
** coded.
|
||||
**
|
||||
** The current value for the constraint is left on the top of the stack.
|
||||
** The current value for the constraint is left in register iReg.
|
||||
**
|
||||
** For a constraint of the form X=expr, the expression is evaluated and its
|
||||
** result is left on the stack. For constraints of the form X IN (...)
|
||||
@ -1726,14 +1730,17 @@ static void buildIndexProbe(
|
||||
static void codeEqualityTerm(
|
||||
Parse *pParse, /* The parsing context */
|
||||
WhereTerm *pTerm, /* The term of the WHERE clause to be coded */
|
||||
WhereLevel *pLevel /* When level of the FROM clause we are working on */
|
||||
WhereLevel *pLevel, /* When level of the FROM clause we are working on */
|
||||
int iReg /* Leave results in this register */
|
||||
){
|
||||
Expr *pX = pTerm->pExpr;
|
||||
Vdbe *v = pParse->pVdbe;
|
||||
|
||||
assert( iReg>0 && iReg<=pParse->nMem );
|
||||
if( pX->op==TK_EQ ){
|
||||
sqlite3ExprCode(pParse, pX->pRight, 0);
|
||||
sqlite3ExprCode(pParse, pX->pRight, iReg);
|
||||
}else if( pX->op==TK_ISNULL ){
|
||||
sqlite3VdbeAddOp2(v, OP_Null, 0, 0);
|
||||
sqlite3VdbeAddOp2(v, OP_Null, 0, iReg);
|
||||
#ifndef SQLITE_OMIT_SUBQUERY
|
||||
}else{
|
||||
int eType;
|
||||
@ -1753,11 +1760,14 @@ static void codeEqualityTerm(
|
||||
sizeof(pLevel->aInLoop[0])*pLevel->nIn);
|
||||
pIn = pLevel->aInLoop;
|
||||
if( pIn ){
|
||||
int op = ((eType==IN_INDEX_ROWID)?OP_Rowid:OP_Column);
|
||||
pIn += pLevel->nIn - 1;
|
||||
pIn->iCur = iTab;
|
||||
pIn->topAddr = sqlite3VdbeAddOp2(v, op, iTab, 0);
|
||||
sqlite3VdbeAddOp2(v, OP_StackIsNull, -1, 0);
|
||||
if( eType==IN_INDEX_ROWID ){
|
||||
pIn->topAddr = sqlite3VdbeAddOp2(v, OP_Rowid, iTab, iReg);
|
||||
}else{
|
||||
pIn->topAddr = sqlite3VdbeAddOp3(v, OP_Column, iTab, 0, iReg);
|
||||
}
|
||||
sqlite3VdbeAddOp1(v, OP_IsNull, iReg);
|
||||
}else{
|
||||
pLevel->nIn = 0;
|
||||
}
|
||||
@ -1789,30 +1799,29 @@ static void codeEqualityTerm(
|
||||
** this routine allocates an additional nEq memory cells for internal
|
||||
** use.
|
||||
*/
|
||||
static void codeAllEqualityTerms(
|
||||
static int codeAllEqualityTerms(
|
||||
Parse *pParse, /* Parsing context */
|
||||
WhereLevel *pLevel, /* Which nested loop of the FROM we are coding */
|
||||
WhereClause *pWC, /* The WHERE clause */
|
||||
Bitmask notReady /* Which parts of FROM have not yet been coded */
|
||||
Bitmask notReady, /* Which parts of FROM have not yet been coded */
|
||||
int nExtraReg /* Number of extra registers to allocate */
|
||||
){
|
||||
int nEq = pLevel->nEq; /* The number of == or IN constraints to code */
|
||||
int termsInMem = 0; /* If true, store value in mem[] cells */
|
||||
Vdbe *v = pParse->pVdbe; /* The virtual machine under construction */
|
||||
Index *pIdx = pLevel->pIdx; /* The index being used for this loop */
|
||||
int iCur = pLevel->iTabCur; /* The cursor of the table */
|
||||
WhereTerm *pTerm; /* A single constraint term */
|
||||
int j; /* Loop counter */
|
||||
int regBase; /* Base register */
|
||||
|
||||
/* Figure out how many memory cells we will need then allocate them.
|
||||
** We always need at least one used to store the loop terminator
|
||||
** value. If there are IN operators we'll need one for each == or
|
||||
** IN constraint.
|
||||
*/
|
||||
pLevel->iMem = ++pParse->nMem;
|
||||
if( pLevel->flags & WHERE_COLUMN_IN ){
|
||||
pParse->nMem += pLevel->nEq;
|
||||
termsInMem = 1;
|
||||
}
|
||||
pLevel->iMem = pParse->nMem + 1;
|
||||
regBase = pParse->nMem + 2;
|
||||
pParse->nMem += pLevel->nEq + 2 + nExtraReg;
|
||||
|
||||
/* Evaluate the equality constraints
|
||||
*/
|
||||
@ -1822,22 +1831,12 @@ static void codeAllEqualityTerms(
|
||||
pTerm = findTerm(pWC, iCur, k, notReady, pLevel->flags, pIdx);
|
||||
if( pTerm==0 ) break;
|
||||
assert( (pTerm->flags & TERM_CODED)==0 );
|
||||
codeEqualityTerm(pParse, pTerm, pLevel);
|
||||
codeEqualityTerm(pParse, pTerm, pLevel, regBase+j);
|
||||
if( (pTerm->eOperator & (WO_ISNULL|WO_IN))==0 ){
|
||||
sqlite3VdbeAddOp2(v, OP_StackIsNull, termsInMem ? -1 : -(j+1), pLevel->brk);
|
||||
}
|
||||
if( termsInMem ){
|
||||
sqlite3VdbeAddOp2(v, OP_Move, 0, pLevel->iMem+j+1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Make sure all the constraint values are on the top of the stack
|
||||
*/
|
||||
if( termsInMem ){
|
||||
for(j=0; j<nEq; j++){
|
||||
sqlite3VdbeAddOp2(v, OP_SCopy, pLevel->iMem+j+1, 0);
|
||||
sqlite3VdbeAddOp2(v, OP_IsNull, regBase+j, pLevel->brk);
|
||||
}
|
||||
}
|
||||
return regBase;
|
||||
}
|
||||
|
||||
#if defined(SQLITE_TEST)
|
||||
@ -2285,24 +2284,23 @@ WhereInfo *sqlite3WhereBegin(
|
||||
const struct sqlite3_index_constraint *aConstraint =
|
||||
pBestIdx->aConstraint;
|
||||
|
||||
iReg = sqlite3GetTempRange(pParse, nConstraint+2);
|
||||
for(j=1; j<=nConstraint; j++){
|
||||
int k;
|
||||
for(k=0; k<nConstraint; k++){
|
||||
if( aUsage[k].argvIndex==j ){
|
||||
int iTerm = aConstraint[k].iTermOffset;
|
||||
sqlite3ExprCode(pParse, wc.a[iTerm].pExpr->pRight, 0);
|
||||
sqlite3ExprCode(pParse, wc.a[iTerm].pExpr->pRight, iReg+j+1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( k==nConstraint ) break;
|
||||
}
|
||||
iReg = ++pParse->nMem;
|
||||
pParse->nMem++;
|
||||
sqlite3StackToReg(pParse, j-1);
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, pBestIdx->idxNum, iReg);
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, j-1, iReg+1);
|
||||
sqlite3VdbeAddOp4(v, OP_VFilter, iCur, brk, iReg, pBestIdx->idxStr,
|
||||
pBestIdx->needToFreeIdxStr ? P4_MPRINTF : P4_STATIC);
|
||||
sqlite3ReleaseTempRange(pParse, iReg, nConstraint+2);
|
||||
pBestIdx->needToFreeIdxStr = 0;
|
||||
for(j=0; j<pBestIdx->nConstraint; j++){
|
||||
if( aUsage[j].omit ){
|
||||
@ -2322,16 +2320,19 @@ WhereInfo *sqlite3WhereBegin(
|
||||
** we reference multiple rows using a "rowid IN (...)"
|
||||
** construct.
|
||||
*/
|
||||
int r1;
|
||||
pTerm = findTerm(&wc, iCur, -1, notReady, WO_EQ|WO_IN, 0);
|
||||
assert( pTerm!=0 );
|
||||
assert( pTerm->pExpr!=0 );
|
||||
assert( pTerm->leftCursor==iCur );
|
||||
assert( omitTable==0 );
|
||||
codeEqualityTerm(pParse, pTerm, pLevel);
|
||||
r1 = sqlite3GetTempReg(pParse);
|
||||
codeEqualityTerm(pParse, pTerm, pLevel, r1);
|
||||
nxt = pLevel->nxt;
|
||||
sqlite3VdbeAddOp3(v, OP_MustBeInt, 0, nxt, 1);
|
||||
sqlite3VdbeAddOp2(v, OP_NotExists, iCur, nxt);
|
||||
sqlite3VdbeAddOp3(v, OP_MustBeInt, r1, nxt, 1);
|
||||
sqlite3VdbeAddOp3(v, OP_NotExists, iCur, nxt, r1);
|
||||
VdbeComment((v, "pk"));
|
||||
sqlite3ReleaseTempReg(pParse, r1);
|
||||
pLevel->op = OP_Noop;
|
||||
}else if( pLevel->flags & WHERE_ROWID_RANGE ){
|
||||
/* Case 2: We have an inequality comparison against the ROWID field.
|
||||
@ -2350,14 +2351,16 @@ WhereInfo *sqlite3WhereBegin(
|
||||
}
|
||||
if( pStart ){
|
||||
Expr *pX;
|
||||
int r1, regFree1;
|
||||
pX = pStart->pExpr;
|
||||
assert( pX!=0 );
|
||||
assert( pStart->leftCursor==iCur );
|
||||
sqlite3ExprCode(pParse, pX->pRight, 0);
|
||||
sqlite3VdbeAddOp3(v, OP_ForceInt, 0, brk,
|
||||
r1 = sqlite3ExprCodeTemp(pParse, pX->pRight, ®Free1);
|
||||
sqlite3VdbeAddOp3(v, OP_ForceInt, r1, brk,
|
||||
pX->op==TK_LE || pX->op==TK_GT);
|
||||
sqlite3VdbeAddOp2(v, bRev ? OP_MoveLt : OP_MoveGe, iCur, brk);
|
||||
sqlite3VdbeAddOp3(v, bRev ? OP_MoveLt : OP_MoveGe, iCur, brk, r1);
|
||||
VdbeComment((v, "pk"));
|
||||
sqlite3ReleaseTempReg(pParse, regFree1);
|
||||
disableTerm(pLevel, pStart);
|
||||
}else{
|
||||
sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iCur, brk);
|
||||
@ -2367,9 +2370,8 @@ WhereInfo *sqlite3WhereBegin(
|
||||
pX = pEnd->pExpr;
|
||||
assert( pX!=0 );
|
||||
assert( pEnd->leftCursor==iCur );
|
||||
sqlite3ExprCode(pParse, pX->pRight, 0);
|
||||
pLevel->iMem = ++pParse->nMem;
|
||||
sqlite3VdbeAddOp2(v, OP_Move, 0, pLevel->iMem);
|
||||
sqlite3ExprCode(pParse, pX->pRight, pLevel->iMem);
|
||||
if( pX->op==TK_LT || pX->op==TK_GT ){
|
||||
testOp = bRev ? OP_Le : OP_Ge;
|
||||
}else{
|
||||
@ -2382,10 +2384,12 @@ WhereInfo *sqlite3WhereBegin(
|
||||
pLevel->p1 = iCur;
|
||||
pLevel->p2 = start;
|
||||
if( testOp!=OP_Noop ){
|
||||
sqlite3VdbeAddOp2(v, OP_Rowid, iCur, 0);
|
||||
sqlite3VdbeAddOp2(v, OP_SCopy, pLevel->iMem, 0);
|
||||
sqlite3VdbeAddOp2(v, testOp, 0, brk);
|
||||
int r1 = sqlite3GetTempReg(pParse);
|
||||
sqlite3VdbeAddOp2(v, OP_Rowid, iCur, r1);
|
||||
/* sqlite3VdbeAddOp2(v, OP_SCopy, pLevel->iMem, 0); */
|
||||
sqlite3VdbeAddOp3(v, testOp, pLevel->iMem, brk, r1);
|
||||
sqlite3VdbeChangeP5(v, SQLITE_AFF_NUMERIC | SQLITE_JUMPIFNULL);
|
||||
sqlite3ReleaseTempReg(pParse, r1);
|
||||
}
|
||||
}else if( pLevel->flags & WHERE_COLUMN_RANGE ){
|
||||
/* Case 3: The WHERE clause term that refers to the right-most
|
||||
@ -2408,19 +2412,13 @@ WhereInfo *sqlite3WhereBegin(
|
||||
int topLimit = (pLevel->flags & WHERE_TOP_LIMIT)!=0;
|
||||
int btmLimit = (pLevel->flags & WHERE_BTM_LIMIT)!=0;
|
||||
int isMinQuery = 0; /* If this is an optimized SELECT min(x) ... */
|
||||
int regBase; /* Base register holding constraint values */
|
||||
int r1; /* Temp register */
|
||||
|
||||
/* Generate code to evaluate all constraint terms using == or IN
|
||||
** and level the values of those terms on the stack.
|
||||
*/
|
||||
codeAllEqualityTerms(pParse, pLevel, &wc, notReady);
|
||||
|
||||
/* Duplicate the equality term values because they will all be
|
||||
** used twice: once to make the termination key and once to make the
|
||||
** start key.
|
||||
*/
|
||||
for(j=0; j<nEq; j++){
|
||||
sqlite3VdbeAddOp1(v, OP_Copy, 1-nEq);
|
||||
}
|
||||
regBase = codeAllEqualityTerms(pParse, pLevel, &wc, notReady, 2);
|
||||
|
||||
/* Figure out what comparison operators to use for top and bottom
|
||||
** search bounds. For an ascending index, the bottom bound is a > or >=
|
||||
@ -2462,13 +2460,13 @@ WhereInfo *sqlite3WhereBegin(
|
||||
nxt = pLevel->nxt;
|
||||
if( topLimit ){
|
||||
Expr *pX;
|
||||
int k = pIdx->aiColumn[j];
|
||||
int k = pIdx->aiColumn[nEq];
|
||||
pTerm = findTerm(&wc, iCur, k, notReady, topOp, pIdx);
|
||||
assert( pTerm!=0 );
|
||||
pX = pTerm->pExpr;
|
||||
assert( (pTerm->flags & TERM_CODED)==0 );
|
||||
sqlite3ExprCode(pParse, pX->pRight, 0);
|
||||
sqlite3VdbeAddOp2(v, OP_StackIsNull, -(nEq*2+1), nxt);
|
||||
sqlite3ExprCode(pParse, pX->pRight, regBase+nEq);
|
||||
sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, nxt);
|
||||
topEq = pTerm->eOperator & (WO_LE|WO_GE);
|
||||
disableTerm(pLevel, pTerm);
|
||||
testOp = OP_IdxGE;
|
||||
@ -2478,18 +2476,15 @@ WhereInfo *sqlite3WhereBegin(
|
||||
}
|
||||
if( testOp!=OP_Noop || (isMinQuery&&bRev) ){
|
||||
int nCol = nEq + topLimit;
|
||||
pLevel->iMem = ++pParse->nMem;
|
||||
if( isMinQuery && !topLimit ){
|
||||
sqlite3VdbeAddOp2(v, OP_Null, 0, regBase+nCol);
|
||||
nCol++;
|
||||
sqlite3VdbeAddOp2(v, OP_Null, 0, 0);
|
||||
topEq = 0;
|
||||
}
|
||||
buildIndexProbe(v, nCol, pIdx);
|
||||
buildIndexProbe(v, nCol, pIdx, regBase, pLevel->iMem);
|
||||
if( bRev ){
|
||||
int op = topEq ? OP_MoveLe : OP_MoveLt;
|
||||
sqlite3VdbeAddOp2(v, op, iIdxCur, nxt);
|
||||
}else{
|
||||
sqlite3VdbeAddOp2(v, OP_Move, 0, pLevel->iMem);
|
||||
sqlite3VdbeAddOp3(v, op, iIdxCur, nxt, pLevel->iMem);
|
||||
}
|
||||
}else if( bRev ){
|
||||
sqlite3VdbeAddOp2(v, OP_Last, iIdxCur, brk);
|
||||
@ -2506,13 +2501,13 @@ WhereInfo *sqlite3WhereBegin(
|
||||
*/
|
||||
if( btmLimit ){
|
||||
Expr *pX;
|
||||
int k = pIdx->aiColumn[j];
|
||||
int k = pIdx->aiColumn[nEq];
|
||||
pTerm = findTerm(&wc, iCur, k, notReady, btmOp, pIdx);
|
||||
assert( pTerm!=0 );
|
||||
pX = pTerm->pExpr;
|
||||
assert( (pTerm->flags & TERM_CODED)==0 );
|
||||
sqlite3ExprCode(pParse, pX->pRight, 0);
|
||||
sqlite3VdbeAddOp2(v, OP_StackIsNull, -(nEq+1), nxt);
|
||||
sqlite3ExprCode(pParse, pX->pRight, regBase+nEq);
|
||||
sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, nxt);
|
||||
btmEq = pTerm->eOperator & (WO_LE|WO_GE);
|
||||
disableTerm(pLevel, pTerm);
|
||||
}else{
|
||||
@ -2521,18 +2516,21 @@ WhereInfo *sqlite3WhereBegin(
|
||||
if( nEq>0 || btmLimit || (isMinQuery&&!bRev) ){
|
||||
int nCol = nEq + btmLimit;
|
||||
if( isMinQuery && !btmLimit ){
|
||||
sqlite3VdbeAddOp2(v, OP_Null, 0, regBase+nCol);
|
||||
nCol++;
|
||||
sqlite3VdbeAddOp2(v, OP_Null, 0, 0);
|
||||
btmEq = 0;
|
||||
}
|
||||
buildIndexProbe(v, nCol, pIdx);
|
||||
if( bRev ){
|
||||
pLevel->iMem = ++pParse->nMem;
|
||||
sqlite3VdbeAddOp2(v, OP_Move, 0, pLevel->iMem);
|
||||
r1 = pLevel->iMem;
|
||||
testOp = OP_IdxLT;
|
||||
}else{
|
||||
r1 = sqlite3GetTempReg(pParse);
|
||||
}
|
||||
buildIndexProbe(v, nCol, pIdx, regBase, r1);
|
||||
if( !bRev ){
|
||||
int op = btmEq ? OP_MoveGe : OP_MoveGt;
|
||||
sqlite3VdbeAddOp2(v, op, iIdxCur, nxt);
|
||||
sqlite3VdbeAddOp3(v, op, iIdxCur, nxt, r1);
|
||||
sqlite3ReleaseTempReg(pParse, r1);
|
||||
}
|
||||
}else if( bRev ){
|
||||
testOp = OP_Noop;
|
||||
@ -2546,20 +2544,21 @@ WhereInfo *sqlite3WhereBegin(
|
||||
*/
|
||||
start = sqlite3VdbeCurrentAddr(v);
|
||||
if( testOp!=OP_Noop ){
|
||||
sqlite3VdbeAddOp2(v, OP_SCopy, pLevel->iMem, 0);
|
||||
sqlite3VdbeAddOp2(v, testOp, iIdxCur, nxt);
|
||||
sqlite3VdbeAddOp3(v, testOp, iIdxCur, nxt, pLevel->iMem);
|
||||
if( (topEq && !bRev) || (!btmEq && bRev) ){
|
||||
sqlite3VdbeChangeP5(v, 1);
|
||||
}
|
||||
}
|
||||
r1 = sqlite3GetTempReg(pParse);
|
||||
if( topLimit | btmLimit ){
|
||||
sqlite3VdbeAddOp2(v, OP_Column, iIdxCur, nEq);
|
||||
sqlite3VdbeAddOp2(v, OP_StackIsNull, 1, cont);
|
||||
sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, nEq, r1);
|
||||
sqlite3VdbeAddOp2(v, OP_IsNull, r1, cont);
|
||||
}
|
||||
if( !omitTable ){
|
||||
sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, 0);
|
||||
sqlite3VdbeAddOp2(v, OP_MoveGe, iCur, 0);
|
||||
sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, r1);
|
||||
sqlite3VdbeAddOp3(v, OP_MoveGe, iCur, 0, r1);
|
||||
}
|
||||
sqlite3ReleaseTempReg(pParse, r1);
|
||||
|
||||
/* Record the instruction used to terminate the loop.
|
||||
*/
|
||||
@ -2573,11 +2572,13 @@ WhereInfo *sqlite3WhereBegin(
|
||||
int start;
|
||||
int nEq = pLevel->nEq;
|
||||
int isMinQuery = 0; /* If this is an optimized SELECT min(x) ... */
|
||||
int regBase; /* Base register of array holding constraints */
|
||||
int r1;
|
||||
|
||||
/* Generate code to evaluate all constraint terms using == or IN
|
||||
** and leave the values of those terms on the stack.
|
||||
*/
|
||||
codeAllEqualityTerms(pParse, pLevel, &wc, notReady);
|
||||
regBase = codeAllEqualityTerms(pParse, pLevel, &wc, notReady, 1);
|
||||
nxt = pLevel->nxt;
|
||||
|
||||
if( (obflag==ORDERBY_MIN)
|
||||
@ -2585,21 +2586,17 @@ WhereInfo *sqlite3WhereBegin(
|
||||
&& (pIdx->nColumn>nEq)
|
||||
&& (pOrderBy->a[0].pExpr->iColumn==pIdx->aiColumn[nEq])
|
||||
){
|
||||
int h;
|
||||
isMinQuery = 1;
|
||||
for(h=0; h<nEq; h++){
|
||||
sqlite3VdbeAddOp1(v, OP_Copy, 1-nEq);
|
||||
}
|
||||
buildIndexProbe(v, nEq, pIdx);
|
||||
sqlite3VdbeAddOp2(v, OP_Move, 0, pLevel->iMem);
|
||||
sqlite3VdbeAddOp2(v, OP_Null, 0, 0);
|
||||
buildIndexProbe(v, nEq+1, pIdx);
|
||||
buildIndexProbe(v, nEq, pIdx, regBase, pLevel->iMem);
|
||||
sqlite3VdbeAddOp2(v, OP_Null, 0, regBase+nEq);
|
||||
r1 = ++pParse->nMem;
|
||||
buildIndexProbe(v, nEq+1, pIdx, regBase, r1);
|
||||
}else{
|
||||
/* Generate a single key that will be used to both start and
|
||||
** terminate the search
|
||||
*/
|
||||
buildIndexProbe(v, nEq, pIdx);
|
||||
sqlite3VdbeAddOp2(v, OP_Copy, 0, pLevel->iMem);
|
||||
r1 = pLevel->iMem;
|
||||
buildIndexProbe(v, nEq, pIdx, regBase, r1);
|
||||
}
|
||||
|
||||
/* Generate code (1) to move to the first matching element of the table.
|
||||
@ -2609,21 +2606,33 @@ WhereInfo *sqlite3WhereBegin(
|
||||
** iteration of the scan to see if the scan has finished. */
|
||||
if( bRev ){
|
||||
/* Scan in reverse order */
|
||||
sqlite3VdbeAddOp2(v, (isMinQuery?OP_MoveLt:OP_MoveLe), iIdxCur, nxt);
|
||||
start = sqlite3VdbeAddOp2(v, OP_SCopy, pLevel->iMem, 0);
|
||||
sqlite3VdbeAddOp2(v, OP_IdxLT, iIdxCur, nxt);
|
||||
int op;
|
||||
if( isMinQuery ){
|
||||
op = OP_MoveLt;
|
||||
}else{
|
||||
op = OP_MoveLe;
|
||||
}
|
||||
sqlite3VdbeAddOp3(v, op, iIdxCur, nxt, r1);
|
||||
start = sqlite3VdbeAddOp3(v, OP_IdxLT, iIdxCur, nxt, pLevel->iMem);
|
||||
pLevel->op = OP_Prev;
|
||||
}else{
|
||||
/* Scan in the forward order */
|
||||
sqlite3VdbeAddOp2(v, (isMinQuery?OP_MoveGt:OP_MoveGe), iIdxCur, nxt);
|
||||
start = sqlite3VdbeAddOp2(v, OP_SCopy, pLevel->iMem, 0);
|
||||
sqlite3VdbeAddOp2(v, OP_IdxGE, iIdxCur, nxt);
|
||||
int op;
|
||||
if( isMinQuery ){
|
||||
op = OP_MoveGt;
|
||||
}else{
|
||||
op = OP_MoveGe;
|
||||
}
|
||||
sqlite3VdbeAddOp3(v, op, iIdxCur, nxt, r1);
|
||||
start = sqlite3VdbeAddOp3(v, OP_IdxGE, iIdxCur, nxt, pLevel->iMem);
|
||||
sqlite3VdbeChangeP5(v, 1);
|
||||
pLevel->op = OP_Next;
|
||||
}
|
||||
if( !omitTable ){
|
||||
sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, 0);
|
||||
sqlite3VdbeAddOp2(v, OP_MoveGe, iCur, 0);
|
||||
r1 = sqlite3GetTempReg(pParse);
|
||||
sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, r1);
|
||||
sqlite3VdbeAddOp3(v, OP_MoveGe, iCur, 0, r1);
|
||||
sqlite3ReleaseTempReg(pParse, r1);
|
||||
}
|
||||
pLevel->p1 = iIdxCur;
|
||||
pLevel->p2 = start;
|
||||
|
@ -11,7 +11,7 @@
|
||||
# This file implements some common TCL routines used for regression
|
||||
# testing the SQLite library
|
||||
#
|
||||
# $Id: tester.tcl,v 1.100 2008/01/16 17:46:38 drh Exp $
|
||||
# $Id: tester.tcl,v 1.101 2008/01/17 02:36:28 drh Exp $
|
||||
|
||||
|
||||
set tcl_precision 15
|
||||
@ -603,7 +603,7 @@ proc cksum {{db db}} {
|
||||
# database $db. If the checksum of two databases is the same, and the
|
||||
# integrity-check passes for both, the two databases are identical.
|
||||
#
|
||||
proc allcksum {db} {
|
||||
proc allcksum {{db db}} {
|
||||
set ret [list]
|
||||
ifcapable tempdb {
|
||||
set sql {
|
||||
|
@ -11,7 +11,7 @@
|
||||
# This file implements regression tests for SQLite library. The
|
||||
# focus of this file is testing the VACUUM statement.
|
||||
#
|
||||
# $Id: vacuum.test,v 1.39 2008/01/16 17:46:38 drh Exp $
|
||||
# $Id: vacuum.test,v 1.40 2008/01/17 02:36:28 drh Exp $
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
@ -49,14 +49,14 @@ do_test vacuum-1.1 {
|
||||
DROP TABLE t2;
|
||||
}
|
||||
set ::size1 [file size test.db]
|
||||
set ::cksum [allcksum]
|
||||
set ::cksum [cksum]
|
||||
expr {$::cksum!=""}
|
||||
} {1}
|
||||
do_test vacuum-1.2 {
|
||||
execsql {
|
||||
VACUUM;
|
||||
}
|
||||
allcksum
|
||||
cksum
|
||||
} $cksum
|
||||
ifcapable vacuum {
|
||||
do_test vacuum-1.3 {
|
||||
@ -84,14 +84,14 @@ do_test vacuum-1.4 {
|
||||
}
|
||||
execsql $sql_script
|
||||
set ::size1 [file size test.db]
|
||||
set ::cksum [allcksum]
|
||||
set ::cksum [cksum]
|
||||
expr {$::cksum!=""}
|
||||
} {1}
|
||||
do_test vacuum-1.5 {
|
||||
execsql {
|
||||
VACUUM;
|
||||
}
|
||||
allcksum
|
||||
cksum
|
||||
} $cksum
|
||||
|
||||
ifcapable vacuum {
|
||||
@ -119,17 +119,17 @@ do_test vacuum-2.2 {
|
||||
DROP TABLE t4;
|
||||
DROP TABLE t5;
|
||||
} db2
|
||||
set ::cksum [allcksum db2]
|
||||
set ::cksum [cksum db2]
|
||||
catchsql {
|
||||
VACUUM
|
||||
}
|
||||
} {0 {}}
|
||||
do_test vacuum-2.3 {
|
||||
allcksum
|
||||
cksum
|
||||
} $cksum
|
||||
do_test vacuum-2.4 {
|
||||
catch {db2 eval {SELECT count(*) FROM sqlite_master}}
|
||||
allcksum db2
|
||||
cksum db2
|
||||
} $cksum
|
||||
|
||||
# Make sure the schema cookie is incremented by vacuum.
|
||||
@ -308,28 +308,28 @@ ifcapable {autoinc} {
|
||||
INSERT INTO autoinc(b) VALUES('there');
|
||||
DELETE FROM autoinc;
|
||||
}
|
||||
set ::cksum [allcksum]
|
||||
set ::cksum [cksum]
|
||||
expr {$::cksum!=""}
|
||||
} {1}
|
||||
do_test vacuum-9.2 {
|
||||
execsql {
|
||||
VACUUM;
|
||||
}
|
||||
allcksum
|
||||
cksum
|
||||
} $::cksum
|
||||
do_test vacuum-9.3 {
|
||||
execsql {
|
||||
INSERT INTO autoinc(b) VALUES('one');
|
||||
INSERT INTO autoinc(b) VALUES('two');
|
||||
}
|
||||
set ::cksum [allcksum]
|
||||
set ::cksum [cksum]
|
||||
expr {$::cksum!=""}
|
||||
} {1}
|
||||
do_test vacuum-9.4 {
|
||||
execsql {
|
||||
VACUUM;
|
||||
}
|
||||
allcksum
|
||||
cksum
|
||||
} $::cksum
|
||||
}
|
||||
|
||||
|
@ -11,7 +11,7 @@
|
||||
# This file implements regression tests for SQLite library. The
|
||||
# focus of this file is testing the VACUUM statement.
|
||||
#
|
||||
# $Id: vacuum2.test,v 1.6 2008/01/16 17:46:38 drh Exp $
|
||||
# $Id: vacuum2.test,v 1.7 2008/01/17 02:36:28 drh Exp $
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
@ -76,9 +76,9 @@ do_test vacuum2-3.1 {
|
||||
}
|
||||
expr {[file size test.db]/$pageSize}
|
||||
} {3}
|
||||
set cksum [allcksum]
|
||||
set cksum [cksum]
|
||||
do_test vacuum2-3.2 {
|
||||
allcksum db2
|
||||
cksum db2
|
||||
} $cksum
|
||||
|
||||
# Convert the database to an autovacuumed database.
|
||||
@ -90,10 +90,10 @@ do_test vacuum2-3.3 {
|
||||
expr {[file size test.db]/$pageSize}
|
||||
} {4}
|
||||
do_test vacuum2-3.4 {
|
||||
allcksum db2
|
||||
cksum db2
|
||||
} $cksum
|
||||
do_test vacuum2-3.5 {
|
||||
allcksum
|
||||
cksum
|
||||
} $cksum
|
||||
do_test vacuum2-3.6 {
|
||||
execsql {PRAGMA integrity_check} db2
|
||||
@ -111,10 +111,10 @@ do_test vacuum2-3.13 {
|
||||
expr {[file size test.db]/$pageSize}
|
||||
} {3}
|
||||
do_test vacuum2-3.14 {
|
||||
allcksum db2
|
||||
cksum db2
|
||||
} $cksum
|
||||
do_test vacuum2-3.15 {
|
||||
allcksum
|
||||
cksum
|
||||
} $cksum
|
||||
do_test vacuum2-3.16 {
|
||||
execsql {PRAGMA integrity_check} db2
|
||||
|
Reference in New Issue
Block a user