1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-08-08 14:02:16 +03:00

Continuing work toward converting the VM into a register machine. (CVS 4707)

FossilOrigin-Name: a6dddebcc5ccbbf3009c9d06163a8b59036331de
This commit is contained in:
drh
2008-01-12 12:48:07 +00:00
parent d8c303fe0a
commit b765411161
13 changed files with 299 additions and 216 deletions

View File

@@ -1,5 +1,5 @@
C Do\sexplicit\srange\stests\sbefore\sattempting\sto\sconvert\sa\s64-bit\sfloat\ninto\sa\s64-bit\sinteger.\s\sSome\ssystems\s(windows)\sseem\sto\sthrow\sexceptions\nif\sthe\sconversion\sis\sout\sof\srange.\s\sTicket\s#2880.\s(CVS\s4706) C Continuing\swork\stoward\sconverting\sthe\sVM\sinto\sa\sregister\smachine.\s(CVS\s4707)
D 2008-01-11T15:27:03 D 2008-01-12T12:48:08
F Makefile.arm-wince-mingw32ce-gcc ac5f7b2cef0cd850d6f755ba6ee4ab961b1fadf7 F Makefile.arm-wince-mingw32ce-gcc ac5f7b2cef0cd850d6f755ba6ee4ab961b1fadf7
F Makefile.in 30789bf70614bad659351660d76b8e533f3340e9 F Makefile.in 30789bf70614bad659351660d76b8e533f3340e9
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
@@ -79,24 +79,24 @@ F sqlite3.1 6be1ad09113570e1fc8dcaff84c9b0b337db5ffc
F sqlite3.def a96c1d0d39362b763d2ddba220a32da41a15c4b4 F sqlite3.def a96c1d0d39362b763d2ddba220a32da41a15c4b4
F sqlite3.pc.in abed4664817e1cd500f2276142c71958087c16bc F sqlite3.pc.in abed4664817e1cd500f2276142c71958087c16bc
F src/alter.c 5a54f58d9481ac14c4e58b702f3f8758dee84d04 F src/alter.c 5a54f58d9481ac14c4e58b702f3f8758dee84d04
F src/analyze.c 52cbc3577c962975445d3e1341cba046f228d21e F src/analyze.c 5aa93f191b365ea308795f62ca6f2e8caa9de3e1
F src/attach.c 61f0cae7b1a0e7c3b5f5286be5dc1a7c4d7112d2 F src/attach.c 61f0cae7b1a0e7c3b5f5286be5dc1a7c4d7112d2
F src/auth.c c8b2ab5c8bad4bd90ed7c294694f48269162c627 F src/auth.c c8b2ab5c8bad4bd90ed7c294694f48269162c627
F src/btmutex.c 5d39da37c9d1282f3c6f9967afae6a34ee36b7ff F src/btmutex.c 5d39da37c9d1282f3c6f9967afae6a34ee36b7ff
F src/btree.c 5164b32950cfd41f2c5c31e8ff82c4a499918aef F src/btree.c 5164b32950cfd41f2c5c31e8ff82c4a499918aef
F src/btree.h 19dcf5ad23c17b98855da548e9a8e3eb4429d5eb F src/btree.h 19dcf5ad23c17b98855da548e9a8e3eb4429d5eb
F src/btreeInt.h 1c5a9da165718ef7de81e35ce9ab5d9ba9283f76 F src/btreeInt.h 1c5a9da165718ef7de81e35ce9ab5d9ba9283f76
F src/build.c e5bb1ddf630d4fbd042bf6a09168fe2feb4f7549 F src/build.c 353cce0f4e773b0889d94663dca6dc99598d6b3d
F src/callback.c 77b302b0d41468dcda78c70e706e5b84577f0fa0 F src/callback.c 77b302b0d41468dcda78c70e706e5b84577f0fa0
F src/complete.c 4cf68fd75d60257524cbe74f87351b9848399131 F src/complete.c 4cf68fd75d60257524cbe74f87351b9848399131
F src/date.c 49c5a6d2de6c12000905b4d36868b07d3011bbf6 F src/date.c 49c5a6d2de6c12000905b4d36868b07d3011bbf6
F src/delete.c 44eac0a8a1bad1e62ee64e59e07a5a97a838bd0f F src/delete.c 00e536847b8eedc5d35f89f7f38a8a7c1d2a22f9
F src/experimental.c 1b2d1a6cd62ecc39610e97670332ca073c50792b F src/experimental.c 1b2d1a6cd62ecc39610e97670332ca073c50792b
F src/expr.c 560fbd4aff7c65e716e0310f85f044141abd9523 F src/expr.c 68bcc07517c763cc7601be45d60084bc11ee0212
F src/func.c 996071cf0af9d967e58b69fce1909555059ebc7d F src/func.c 996071cf0af9d967e58b69fce1909555059ebc7d
F src/hash.c 45a7005aac044b6c86bd7e49c44bc15d30006d6c F src/hash.c 45a7005aac044b6c86bd7e49c44bc15d30006d6c
F src/hash.h 031cd9f915aff27e12262cb9eb570ac1b8326b53 F src/hash.h 031cd9f915aff27e12262cb9eb570ac1b8326b53
F src/insert.c 405cf0550252cdd3ba5b14ce1545571c82e35250 F src/insert.c a19d9f51b611943386fcff714e3a0ffb137e463b
F src/journal.c 807bed7a158979ac8d63953e1774e8d85bff65e2 F src/journal.c 807bed7a158979ac8d63953e1774e8d85bff65e2
F src/legacy.c 4ac53191fad2e3c4d59bde1228879b2dc5a96d66 F src/legacy.c 4ac53191fad2e3c4d59bde1228879b2dc5a96d66
F src/limits.h 71ab25f17e35e0a9f3f6f234b8ed49cc56731d35 F src/limits.h 71ab25f17e35e0a9f3f6f234b8ed49cc56731d35
@@ -131,12 +131,12 @@ F src/pragma.c 1d3d9deefcf325e14a99b94f9f506f1a90a9232b
F src/prepare.c c31a879d6795f4765fd0b113675c6debbc96b7fd F src/prepare.c c31a879d6795f4765fd0b113675c6debbc96b7fd
F src/printf.c eb27822ba2eec669161409ca31279a24c26ac910 F src/printf.c eb27822ba2eec669161409ca31279a24c26ac910
F src/random.c 4a22746501bf36b0a088c66e38dde5daba6a35da F src/random.c 4a22746501bf36b0a088c66e38dde5daba6a35da
F src/select.c ff00897172bad962c7f775f0a1daa19e2a3ed80a F src/select.c 9e3c65ca3d2508b585b6786dbcbe6cd65560b013
F src/server.c 087b92a39d883e3fa113cae259d64e4c7438bc96 F src/server.c 087b92a39d883e3fa113cae259d64e4c7438bc96
F src/shell.c 5391e889384d2062249f668110d64ed16f601c4b F src/shell.c 5391e889384d2062249f668110d64ed16f601c4b
F src/sqlite.h.in 2a7e3776534bbe6ff2cdc058f3abebe91e7e429f F src/sqlite.h.in 2a7e3776534bbe6ff2cdc058f3abebe91e7e429f
F src/sqlite3ext.h a93f59cdee3638dc0c9c086f80df743a4e68c3cb F src/sqlite3ext.h a93f59cdee3638dc0c9c086f80df743a4e68c3cb
F src/sqliteInt.h ba917f5ed26ab1b47d3814d624e36a73dfe4c5bd F src/sqliteInt.h b143c53760aeb4feeb4eaf8cb10eb26ad5b6c89e
F src/sqliteLimit.h ee4430f88f69bf63527967bb35ca52af7b0ccb1e F src/sqliteLimit.h ee4430f88f69bf63527967bb35ca52af7b0ccb1e
F src/table.c 1aeb9eab57b4235db86fe15a35dec76fb445a9c4 F src/table.c 1aeb9eab57b4235db86fe15a35dec76fb445a9c4
F src/tclsqlite.c 9923abeffc9b3d7dad58e92b319661521f60debf F src/tclsqlite.c 9923abeffc9b3d7dad58e92b319661521f60debf
@@ -168,7 +168,7 @@ F src/update.c aad823f97a930e6982264299863837d4c6107d3b
F src/utf.c ef4b7d83bae533b76c3e1bf635b113fdad86a736 F src/utf.c ef4b7d83bae533b76c3e1bf635b113fdad86a736
F src/util.c 05f31144bbd3f1a24f4139ae029c42545cb72624 F src/util.c 05f31144bbd3f1a24f4139ae029c42545cb72624
F src/vacuum.c 3f34f278809bf3eb0b62ec46ff779e9c385b28f0 F src/vacuum.c 3f34f278809bf3eb0b62ec46ff779e9c385b28f0
F src/vdbe.c 2a62b69e8344f28438ba0a007582be93b33b53ca F src/vdbe.c 20bd088657280d75b630d299c59cdb3c6a5c9b9e
F src/vdbe.h a9166e1601f5b74c20516a74182773a20baee43e F src/vdbe.h a9166e1601f5b74c20516a74182773a20baee43e
F src/vdbeInt.h 31bd686595356284d5484592e2dc6e58025aa346 F src/vdbeInt.h 31bd686595356284d5484592e2dc6e58025aa346
F src/vdbeapi.c f14174843bf4be2c9afdf2ef48b61e7c3ac62d7c F src/vdbeapi.c f14174843bf4be2c9afdf2ef48b61e7c3ac62d7c
@@ -176,7 +176,7 @@ F src/vdbeaux.c db33a4c2477546da05e772352be43896d24d51d5
F src/vdbeblob.c e386d49d8354aa5a58f0a7f2794303442c149120 F src/vdbeblob.c e386d49d8354aa5a58f0a7f2794303442c149120
F src/vdbefifo.c 334c838c8f42d61a94813d136019ee566b5dc2f6 F src/vdbefifo.c 334c838c8f42d61a94813d136019ee566b5dc2f6
F src/vdbemem.c a86119b5ccc41ab8653e4746f83d591ff0ae892e F src/vdbemem.c a86119b5ccc41ab8653e4746f83d591ff0ae892e
F src/vtab.c 03014b2bfa8096ecac5fcdc80d34cd76e06af52a F src/vtab.c 7f206d148f6e76f427f008f589610c72a4b9336c
F src/where.c 9705df3c2b78ea8e02a768be8ac5d3f7a2902f1e F src/where.c 9705df3c2b78ea8e02a768be8ac5d3f7a2902f1e
F tclinstaller.tcl 4356d9d94d2b5ed5e68f9f0c80c4df3048dd7617 F tclinstaller.tcl 4356d9d94d2b5ed5e68f9f0c80c4df3048dd7617
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
@@ -417,10 +417,11 @@ F test/schema2.test 35e1c9696443d6694c8980c411497c2b5190d32e
F test/select1.test 871df931cbbc0e78170605628e8b5fc60765e265 F test/select1.test 871df931cbbc0e78170605628e8b5fc60765e265
F test/select2.test f3c2678c3a9f3cf08ec4988a3845bda64be6d9e3 F test/select2.test f3c2678c3a9f3cf08ec4988a3845bda64be6d9e3
F test/select3.test 7f99c0d4067064e0865479a56faa7aaa29b9041a F test/select3.test 7f99c0d4067064e0865479a56faa7aaa29b9041a
F test/select4.test 69015a6c02c3d8efed01f15e5d025fb4e5256183 F test/select4.test 491193f50799e7fdb375ef04a1a8f40393dd7cfe
F test/select5.test 0b47058d3e916c1fc9fe81f44b438e02bade21ce F test/select5.test 0b47058d3e916c1fc9fe81f44b438e02bade21ce
F test/select6.test 399f14b9ba37b768afe5d2cd8c12e4f340a69db8 F test/select6.test 399f14b9ba37b768afe5d2cd8c12e4f340a69db8
F test/select7.test 7906735805cfbee4dddc0bed4c14e68d7f5f9c5f F test/select7.test 7906735805cfbee4dddc0bed4c14e68d7f5f9c5f
F test/select8.test 391de11bdd52339c30580dabbbbe97e3e9a3c79d
F test/server1.test f5b790d4c0498179151ca8a7715a65a7802c859c F test/server1.test f5b790d4c0498179151ca8a7715a65a7802c859c
F test/shared.test 9a1e81629efaebaad2247e9e81aa33570fba8f13 F test/shared.test 9a1e81629efaebaad2247e9e81aa33570fba8f13
F test/shared2.test 0ee9de8964d70e451936a48c41cb161d9134ccf4 F test/shared2.test 0ee9de8964d70e451936a48c41cb161d9134ccf4
@@ -605,7 +606,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 6de0ee49073c7a47d5e10495b569b33df76d1448 P 4744257d3cd2dd96485fde6d9f60542714383421
R 72b005345d91bd390788cc14572cdea6 R 9fded3f0e818ece501c0ececcbd26a94
U drh U drh
Z f60ae65829aa8eb88bba7196814bec78 Z fe475f28d0df336b5a859493e9293538

View File

@@ -1 +1 @@
4744257d3cd2dd96485fde6d9f60542714383421 a6dddebcc5ccbbf3009c9d06163a8b59036331de

View File

@@ -11,7 +11,7 @@
************************************************************************* *************************************************************************
** This file contains code associated with the ANALYZE command. ** This file contains code associated with the ANALYZE command.
** **
** @(#) $Id: analyze.c,v 1.37 2008/01/10 23:50:11 drh Exp $ ** @(#) $Id: analyze.c,v 1.38 2008/01/12 12:48:08 drh Exp $
*/ */
#ifndef SQLITE_OMIT_ANALYZE #ifndef SQLITE_OMIT_ANALYZE
#include "sqliteInt.h" #include "sqliteInt.h"
@@ -33,6 +33,7 @@ static void openStatTable(
sqlite3 *db = pParse->db; sqlite3 *db = pParse->db;
Db *pDb; Db *pDb;
int iRootPage; int iRootPage;
int createStat1 = 0;
Table *pStat; Table *pStat;
Vdbe *v = sqlite3GetVdbe(pParse); Vdbe *v = sqlite3GetVdbe(pParse);
@@ -43,13 +44,14 @@ static void openStatTable(
if( (pStat = sqlite3FindTable(db, "sqlite_stat1", pDb->zName))==0 ){ if( (pStat = sqlite3FindTable(db, "sqlite_stat1", pDb->zName))==0 ){
/* The sqlite_stat1 tables does not exist. Create it. /* The sqlite_stat1 tables does not exist. Create it.
** Note that a side-effect of the CREATE TABLE statement is to leave ** Note that a side-effect of the CREATE TABLE statement is to leave
** the rootpage of the new table on the top of the stack. This is ** the rootpage of the new table in register pParse->regRoot. This is
** important because the OpenWrite opcode below will be needing it. */ ** important because the OpenWrite opcode below will be needing it. */
sqlite3NestedParse(pParse, sqlite3NestedParse(pParse,
"CREATE TABLE %Q.sqlite_stat1(tbl,idx,stat)", "CREATE TABLE %Q.sqlite_stat1(tbl,idx,stat)",
pDb->zName pDb->zName
); );
iRootPage = 0; /* Cause rootpage to be taken from top of stack */ iRootPage = pParse->regRoot;
createStat1 = 1; /* Cause rootpage to be taken from top of stack */
}else if( zWhere ){ }else if( zWhere ){
/* The sqlite_stat1 table exists. Delete all entries associated with /* The sqlite_stat1 table exists. Delete all entries associated with
** the table zWhere. */ ** the table zWhere. */
@@ -69,13 +71,11 @@ static void openStatTable(
** If this vdbe did create the sqlite_stat1 table, then it must have ** If this vdbe did create the sqlite_stat1 table, then it must have
** already obtained a schema-lock, making the write-lock redundant. ** already obtained a schema-lock, making the write-lock redundant.
*/ */
if( iRootPage>0 ){ if( !createStat1 ){
sqlite3TableLock(pParse, iDb, iRootPage, 1, "sqlite_stat1"); sqlite3TableLock(pParse, iDb, iRootPage, 1, "sqlite_stat1");
} }
sqlite3VdbeAddOp3(v, OP_OpenWrite, iStatCur, iRootPage, iDb); sqlite3VdbeAddOp3(v, OP_OpenWrite, iStatCur, iRootPage, iDb);
if( iRootPage==0 ){ sqlite3VdbeChangeP5(v, createStat1);
sqlite3VdbeChangeP5(v, 1);
}
sqlite3VdbeAddOp2(v, OP_SetNumColumns, iStatCur, 3); sqlite3VdbeAddOp2(v, OP_SetNumColumns, iStatCur, 3);
} }

View File

@@ -22,7 +22,7 @@
** COMMIT ** COMMIT
** ROLLBACK ** ROLLBACK
** **
** $Id: build.c,v 1.463 2008/01/10 23:50:11 drh Exp $ ** $Id: build.c,v 1.464 2008/01/12 12:48:08 drh Exp $
*/ */
#include "sqliteInt.h" #include "sqliteInt.h"
#include <ctype.h> #include <ctype.h>
@@ -838,8 +838,9 @@ void sqlite3StartTable(
** now. ** now.
*/ */
if( !db->init.busy && (v = sqlite3GetVdbe(pParse))!=0 ){ if( !db->init.busy && (v = sqlite3GetVdbe(pParse))!=0 ){
int lbl; int j1;
int fileFormat; int fileFormat;
int reg1, reg2, reg3;
sqlite3BeginWriteOperation(pParse, 0, iDb); sqlite3BeginWriteOperation(pParse, 0, iDb);
#ifndef SQLITE_OMIT_VIRTUALTABLE #ifndef SQLITE_OMIT_VIRTUALTABLE
@@ -851,17 +852,19 @@ void sqlite3StartTable(
/* If the file format and encoding in the database have not been set, /* If the file format and encoding in the database have not been set,
** set them now. ** set them now.
*/ */
sqlite3VdbeAddOp3(v, OP_ReadCookie, iDb, 0, 1); /* file_format */ reg1 = pParse->regRowid = ++pParse->nMem;
reg2 = pParse->regRoot = ++pParse->nMem;
reg3 = ++pParse->nMem;
sqlite3VdbeAddOp3(v, OP_ReadCookie, iDb, reg3, 1); /* file_format */
sqlite3VdbeUsesBtree(v, iDb); sqlite3VdbeUsesBtree(v, iDb);
lbl = sqlite3VdbeMakeLabel(v); j1 = sqlite3VdbeAddOp1(v, OP_If, reg3);
sqlite3VdbeAddOp2(v, OP_If, 0, lbl);
fileFormat = (db->flags & SQLITE_LegacyFileFmt)!=0 ? fileFormat = (db->flags & SQLITE_LegacyFileFmt)!=0 ?
1 : SQLITE_MAX_FILE_FORMAT; 1 : SQLITE_MAX_FILE_FORMAT;
sqlite3VdbeAddOp1(v, OP_Integer, fileFormat); sqlite3VdbeAddOp2(v, OP_Integer, fileFormat, reg3);
sqlite3VdbeAddOp2(v, OP_SetCookie, iDb, 1); sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, 1, reg3);
sqlite3VdbeAddOp1(v, OP_Integer, ENC(db)); sqlite3VdbeAddOp2(v, OP_Integer, ENC(db), reg3);
sqlite3VdbeAddOp2(v, OP_SetCookie, iDb, 4); sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, 4, reg3);
sqlite3VdbeResolveLabel(v, lbl); sqlite3VdbeJumpHere(v, j1);
/* This just creates a place-holder record in the sqlite_master table. /* This just creates a place-holder record in the sqlite_master table.
** The record created does not contain anything yet. It will be replaced ** The record created does not contain anything yet. It will be replaced
@@ -873,19 +876,18 @@ void sqlite3StartTable(
*/ */
#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE) #if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE)
if( isView || isVirtual ){ if( isView || isVirtual ){
sqlite3VdbeAddOp0(v, OP_Integer); sqlite3VdbeAddOp2(v, OP_Integer, 0, reg2);
}else }else
#endif #endif
{ {
sqlite3VdbeAddOp1(v, OP_CreateTable, iDb); sqlite3VdbeAddOp2(v, OP_CreateTable, iDb, reg2);
} }
sqlite3OpenMasterTable(pParse, iDb); sqlite3OpenMasterTable(pParse, iDb);
sqlite3VdbeAddOp0(v, OP_NewRowid); sqlite3VdbeAddOp2(v, OP_NewRowid, 0, reg1);
sqlite3VdbeAddOp0(v, OP_Copy); sqlite3VdbeAddOp2(v, OP_Null, 0, reg3);
sqlite3VdbeAddOp0(v, OP_Null); sqlite3VdbeAddOp3(v, OP_Insert, 0, reg3, reg1);
sqlite3CodeInsert(pParse, 0, OPFLAG_APPEND); sqlite3VdbeChangeP5(v, OPFLAG_APPEND);
sqlite3VdbeAddOp0(v, OP_Close); sqlite3VdbeAddOp0(v, OP_Close);
sqlite3VdbeAddOp1(v, OP_Pull, 1);
} }
/* Normal (non-error) return. */ /* Normal (non-error) return. */
@@ -1494,8 +1496,7 @@ void sqlite3EndTable(
SelectDest dest; SelectDest dest;
Table *pSelTab; Table *pSelTab;
sqlite3VdbeAddOp0(v, OP_Copy); sqlite3VdbeAddOp3(v, OP_OpenWrite, 1, pParse->regRoot, iDb);
sqlite3VdbeAddOp3(v, OP_OpenWrite, 1, 0, iDb);
sqlite3VdbeChangeP5(v, 1); sqlite3VdbeChangeP5(v, 1);
pParse->nTab = 2; pParse->nTab = 2;
sqlite3SelectDestInit(&dest, SRT_Table, 1); sqlite3SelectDestInit(&dest, SRT_Table, 1);
@@ -1531,13 +1532,15 @@ void sqlite3EndTable(
*/ */
sqlite3NestedParse(pParse, sqlite3NestedParse(pParse,
"UPDATE %Q.%s " "UPDATE %Q.%s "
"SET type='%s', name=%Q, tbl_name=%Q, rootpage=#0, sql=%Q " "SET type='%s', name=%Q, tbl_name=%Q, rootpage=#%d, sql=%Q "
"WHERE rowid=#1", "WHERE rowid=#%d",
db->aDb[iDb].zName, SCHEMA_TABLE(iDb), db->aDb[iDb].zName, SCHEMA_TABLE(iDb),
zType, zType,
p->zName, p->zName,
p->zName, p->zName,
zStmt pParse->regRoot,
zStmt,
pParse->regRowid
); );
sqlite3_free(zStmt); sqlite3_free(zStmt);
sqlite3ChangeCookie(db, v, iDb); sqlite3ChangeCookie(db, v, iDb);
@@ -1835,20 +1838,22 @@ void sqlite3RootPageMoved(Db *pDb, int iFrom, int iTo){
*/ */
static void destroyRootPage(Parse *pParse, int iTable, int iDb){ static void destroyRootPage(Parse *pParse, int iTable, int iDb){
Vdbe *v = sqlite3GetVdbe(pParse); Vdbe *v = sqlite3GetVdbe(pParse);
sqlite3VdbeAddOp3(v, OP_Destroy, iTable, 0, iDb); int r1 = sqlite3GetTempReg(pParse);
sqlite3VdbeAddOp3(v, OP_Destroy, iTable, r1, iDb);
#ifndef SQLITE_OMIT_AUTOVACUUM #ifndef SQLITE_OMIT_AUTOVACUUM
/* OP_Destroy pushes an integer onto the stack. If this integer /* OP_Destroy stores an in integer r1. If this integer
** is non-zero, then it is the root page number of a table moved to ** is non-zero, then it is the root page number of a table moved to
** location iTable. The following code modifies the sqlite_master table to ** location iTable. The following code modifies the sqlite_master table to
** reflect this. ** reflect this.
** **
** The "#0" in the SQL is a special constant that means whatever value ** The "#%d" in the SQL is a special constant that means whatever value
** is on the top of the stack. See sqlite3RegisterExpr(). ** is on the top of the stack. See sqlite3RegisterExpr().
*/ */
sqlite3NestedParse(pParse, sqlite3NestedParse(pParse,
"UPDATE %Q.%s SET rootpage=%d WHERE #0 AND rootpage=#0", "UPDATE %Q.%s SET rootpage=%d WHERE #%d AND rootpage=#%d",
pParse->db->aDb[iDb].zName, SCHEMA_TABLE(iDb), iTable); pParse->db->aDb[iDb].zName, SCHEMA_TABLE(iDb), iTable, r1, r1);
#endif #endif
sqlite3ReleaseTempReg(pParse, r1);
} }
/* /*
@@ -2649,8 +2654,7 @@ void sqlite3CreateIndex(
/* Create the rootpage for the index /* Create the rootpage for the index
*/ */
sqlite3BeginWriteOperation(pParse, 1, iDb); sqlite3BeginWriteOperation(pParse, 1, iDb);
sqlite3VdbeAddOp1(v, OP_CreateIndex, iDb); sqlite3VdbeAddOp2(v, OP_CreateIndex, iDb, iMem);
sqlite3VdbeAddOp2(v, OP_Copy, 0, iMem);
/* Gather the complete text of the CREATE INDEX statement into /* Gather the complete text of the CREATE INDEX statement into
** the zStmt variable ** the zStmt variable
@@ -2670,13 +2674,13 @@ void sqlite3CreateIndex(
/* Add an entry in sqlite_master for this index /* Add an entry in sqlite_master for this index
*/ */
sqlite3NestedParse(pParse, sqlite3NestedParse(pParse,
"INSERT INTO %Q.%s VALUES('index',%Q,%Q,#0,%Q);", "INSERT INTO %Q.%s VALUES('index',%Q,%Q,#%d,%Q);",
db->aDb[iDb].zName, SCHEMA_TABLE(iDb), db->aDb[iDb].zName, SCHEMA_TABLE(iDb),
pIndex->zName, pIndex->zName,
pTab->zName, pTab->zName,
iMem,
zStmt zStmt
); );
sqlite3VdbeAddOp1(v, OP_Pop, 1);
sqlite3_free(zStmt); sqlite3_free(zStmt);
/* Fill the index with data and reparse the schema. Code an OP_Expire /* Fill the index with data and reparse the schema. Code an OP_Expire

View File

@@ -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
** in order to generate code for DELETE FROM statements. ** in order to generate code for DELETE FROM statements.
** **
** $Id: delete.c,v 1.156 2008/01/10 23:50:11 drh Exp $ ** $Id: delete.c,v 1.157 2008/01/12 12:48:08 drh Exp $
*/ */
#include "sqliteInt.h" #include "sqliteInt.h"
@@ -60,20 +60,6 @@ int sqlite3IsReadOnly(Parse *pParse, Table *pTab, int viewOk){
return 0; return 0;
} }
/*
** This function is a temporary measure required because OP_Insert now
** reads the key and data to insert from memory cells.
*/
void sqlite3CodeInsert(Parse *p, int iCur, u8 flags){
int iData = ++p->nMem;
int iKey = ++p->nMem;
Vdbe *v = sqlite3GetVdbe(p);
sqlite3VdbeAddOp2(v, OP_Move, 0, iData);
sqlite3VdbeAddOp2(v, OP_Move, 0, iKey);
sqlite3VdbeAddOp3(v, OP_Insert, iCur, iData, iKey);
sqlite3VdbeChangeP5(v, flags);
}
/* /*
** Allocate nVal contiguous memory cells and return the index of the ** Allocate nVal contiguous memory cells and return the index of the
** first. Also pop nVal elements from the stack and store them in the ** first. Also pop nVal elements from the stack and store them in the
@@ -91,14 +77,6 @@ int sqlite3StackToReg(Parse *p, int nVal){
} }
return iRet; return iRet;
} }
void sqlite3RegToStack(Parse *p, int iReg, int nVal){
int i;
Vdbe *v = sqlite3GetVdbe(p);
assert(v);
for(i=0; i<nVal; i++){
sqlite3VdbeAddOp2(v, OP_SCopy, iReg+i, 0);
}
}
/* /*
** Generate code that will open a table for reading. ** Generate code that will open a table for reading.

View File

@@ -12,7 +12,7 @@
** This file contains routines used for analyzing expressions and ** This file contains routines used for analyzing expressions and
** for generating VDBE code that evaluates expressions in SQLite. ** for generating VDBE code that evaluates expressions in SQLite.
** **
** $Id: expr.c,v 1.342 2008/01/10 23:50:11 drh Exp $ ** $Id: expr.c,v 1.343 2008/01/12 12:48:08 drh Exp $
*/ */
#include "sqliteInt.h" #include "sqliteInt.h"
#include <ctype.h> #include <ctype.h>
@@ -289,9 +289,8 @@ Expr *sqlite3PExpr(
/* /*
** When doing a nested parse, you can include terms in an expression ** When doing a nested parse, you can include terms in an expression
** that look like this: #0 #1 #2 ... These terms refer to elements ** that look like this: #1 #2 ... These terms refer to registers
** on the stack. "#0" means the top of the stack. ** in the virtual machine. #N is the N-th register.
** "#1" means the next down on the stack. And so forth.
** **
** This routine is called by the parser to deal with on of those terms. ** This routine is called by the parser to deal with on of those terms.
** It immediately generates code to store the value in a memory location. ** It immediately generates code to store the value in a memory location.
@@ -301,7 +300,6 @@ Expr *sqlite3PExpr(
Expr *sqlite3RegisterExpr(Parse *pParse, Token *pToken){ Expr *sqlite3RegisterExpr(Parse *pParse, Token *pToken){
Vdbe *v = pParse->pVdbe; Vdbe *v = pParse->pVdbe;
Expr *p; Expr *p;
int depth;
if( pParse->nested==0 ){ if( pParse->nested==0 ){
sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", pToken); sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", pToken);
return sqlite3PExpr(pParse, TK_NULL, 0, 0, 0); return sqlite3PExpr(pParse, TK_NULL, 0, 0, 0);
@@ -311,9 +309,7 @@ Expr *sqlite3RegisterExpr(Parse *pParse, Token *pToken){
if( p==0 ){ if( p==0 ){
return 0; /* Malloc failed */ return 0; /* Malloc failed */
} }
depth = atoi((char*)&pToken->z[1]); p->iTable = atoi((char*)&pToken->z[1]);
p->iTable = ++pParse->nMem;
sqlite3VdbeAddOp2(v, OP_Copy, -depth, p->iTable);
return p; return p;
} }

View File

@@ -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 INSERT statements in SQLite. ** to handle INSERT statements in SQLite.
** **
** $Id: insert.c,v 1.222 2008/01/10 23:50:11 drh Exp $ ** $Id: insert.c,v 1.223 2008/01/12 12:48:08 drh Exp $
*/ */
#include "sqliteInt.h" #include "sqliteInt.h"
@@ -519,13 +519,18 @@ void sqlite3Insert(
/* Generate the subroutine that SELECT calls to process each row of /* Generate the subroutine that SELECT calls to process each row of
** the result. Store the result in a temporary table ** the result. Store the result in a temporary table
*/ */
int regRec, regRowid;
srcTab = pParse->nTab++; srcTab = pParse->nTab++;
regRec = sqlite3GetTempReg(pParse);
regRowid = sqlite3GetTempReg(pParse);
sqlite3VdbeResolveLabel(v, iInsertBlock); sqlite3VdbeResolveLabel(v, iInsertBlock);
sqlite3VdbeAddOp2(v, OP_RegMakeRec, regFromSelect, nColumn); sqlite3VdbeAddOp3(v, OP_RegMakeRec, regFromSelect, nColumn, regRec);
sqlite3VdbeAddOp1(v, OP_NewRowid, srcTab); sqlite3VdbeAddOp2(v, OP_NewRowid, srcTab, regRowid);
sqlite3VdbeAddOp2(v, OP_Pull, 1, 0); sqlite3VdbeAddOp3(v, OP_Insert, srcTab, regRec, regRowid);
sqlite3CodeInsert(pParse, srcTab, OPFLAG_APPEND);
sqlite3VdbeAddOp2(v, OP_Return, 0, 0); sqlite3VdbeAddOp2(v, OP_Return, 0, 0);
sqlite3ReleaseTempReg(pParse, regRec);
sqlite3ReleaseTempReg(pParse, regRowid);
/* The following code runs first because the GOTO at the very top /* The following code runs first because the GOTO at the very top
** of the program jumps to it. Create the temporary table, then jump ** of the program jumps to it. Create the temporary table, then jump
@@ -663,7 +668,6 @@ void sqlite3Insert(
}else if( pSelect ){ }else if( pSelect ){
sqlite3VdbeAddOp2(v, OP_Goto, 0, iSelectLoop); sqlite3VdbeAddOp2(v, OP_Goto, 0, iSelectLoop);
sqlite3VdbeResolveLabel(v, iInsertBlock); sqlite3VdbeResolveLabel(v, iInsertBlock);
sqlite3RegToStack(pParse, regFromSelect, nColumn);
sqlite3VdbeAddOp2(v, OP_StackDepth, -1, 0); sqlite3VdbeAddOp2(v, OP_StackDepth, -1, 0);
} }
@@ -770,7 +774,7 @@ void sqlite3Insert(
if( useTempTable ){ if( useTempTable ){
sqlite3VdbeAddOp3(v, OP_Column, srcTab, keyColumn, regRowid); sqlite3VdbeAddOp3(v, OP_Column, srcTab, keyColumn, regRowid);
}else if( pSelect ){ }else if( pSelect ){
sqlite3VdbeAddOp2(v, OP_SCopy, -(nColumn - keyColumn - 1), regRowid); sqlite3VdbeAddOp2(v, OP_SCopy, regFromSelect+keyColumn, regRowid);
}else{ }else{
VdbeOp *pOp; VdbeOp *pOp;
sqlite3ExprCode(pParse, pList->a[keyColumn].pExpr, 0); sqlite3ExprCode(pParse, pList->a[keyColumn].pExpr, 0);
@@ -835,7 +839,7 @@ void sqlite3Insert(
}else if( useTempTable ){ }else if( useTempTable ){
sqlite3VdbeAddOp3(v, OP_Column, srcTab, j, iRegStore); sqlite3VdbeAddOp3(v, OP_Column, srcTab, j, iRegStore);
}else if( pSelect ){ }else if( pSelect ){
sqlite3VdbeAddOp2(v, OP_SCopy, -(nColumn-j-1), iRegStore); sqlite3VdbeAddOp2(v, OP_SCopy, regFromSelect+j, iRegStore);
}else{ }else{
sqlite3ExprCode(pParse, pList->a[j].pExpr, iRegStore); sqlite3ExprCode(pParse, pList->a[j].pExpr, iRegStore);
} }
@@ -899,7 +903,6 @@ void sqlite3Insert(
sqlite3VdbeResolveLabel(v, iBreak); sqlite3VdbeResolveLabel(v, iBreak);
sqlite3VdbeAddOp2(v, OP_Close, srcTab, 0); sqlite3VdbeAddOp2(v, OP_Close, srcTab, 0);
}else if( pSelect ){ }else if( pSelect ){
sqlite3VdbeAddOp2(v, OP_Pop, nColumn, 0);
sqlite3VdbeAddOp2(v, OP_Return, 0, 0); sqlite3VdbeAddOp2(v, OP_Return, 0, 0);
sqlite3VdbeResolveLabel(v, iCleanup); sqlite3VdbeResolveLabel(v, iCleanup);
} }
@@ -1279,6 +1282,7 @@ void sqlite3CompleteInsertion(
Index *pIdx; Index *pIdx;
int pik_flags; int pik_flags;
int regData; int regData;
int regRec;
v = sqlite3GetVdbe(pParse); v = sqlite3GetVdbe(pParse);
assert( v!=0 ); assert( v!=0 );
@@ -1289,14 +1293,12 @@ void sqlite3CompleteInsertion(
sqlite3VdbeAddOp2(v, OP_IdxInsert, baseCur+i+1, aRegIdx[i]); sqlite3VdbeAddOp2(v, OP_IdxInsert, baseCur+i+1, aRegIdx[i]);
} }
regData = regRowid + 1; regData = regRowid + 1;
sqlite3VdbeAddOp1(v, OP_SCopy, regRowid); regRec = sqlite3GetTempReg(pParse);
sqlite3VdbeAddOp2(v, OP_RegMakeRec, regData, pTab->nCol); sqlite3VdbeAddOp3(v, OP_RegMakeRec, regData, pTab->nCol, regRec);
sqlite3TableAffinityStr(v, pTab); sqlite3TableAffinityStr(v, pTab);
#ifndef SQLITE_OMIT_TRIGGER #ifndef SQLITE_OMIT_TRIGGER
if( newIdx>=0 ){ if( newIdx>=0 ){
sqlite3VdbeAddOp1(v, OP_SCopy, regRowid); sqlite3VdbeAddOp3(v, OP_Insert, newIdx, regRec, regRowid);
sqlite3VdbeAddOp1(v, OP_SCopy, -1);
sqlite3CodeInsert(pParse, newIdx, 0);
} }
#endif #endif
if( pParse->nested ){ if( pParse->nested ){
@@ -1308,10 +1310,11 @@ void sqlite3CompleteInsertion(
if( appendBias ){ if( appendBias ){
pik_flags |= OPFLAG_APPEND; pik_flags |= OPFLAG_APPEND;
} }
sqlite3CodeInsert(pParse, baseCur, pik_flags); sqlite3VdbeAddOp3(v, OP_Insert, baseCur, regRec, regRowid);
if( !pParse->nested ){ if( !pParse->nested ){
sqlite3VdbeChangeP4(v, -1, pTab->zName, P4_STATIC); sqlite3VdbeChangeP4(v, -1, pTab->zName, P4_STATIC);
} }
sqlite3VdbeChangeP5(v, pik_flags);
} }
/* /*
@@ -1465,6 +1468,7 @@ static int xferOptimization(
KeyInfo *pKey; /* Key information for an index */ KeyInfo *pKey; /* Key information for an index */
int regAutoinc; /* Memory register used by AUTOINC */ int regAutoinc; /* Memory register used by AUTOINC */
int destHasUniqueIdx = 0; /* True if pDest has a UNIQUE index */ int destHasUniqueIdx = 0; /* True if pDest has a UNIQUE index */
int regData, regRowid; /* Registers holding data and rowid */
if( pSelect==0 ){ if( pSelect==0 ){
return 0; /* Must be of the form INSERT INTO ... SELECT ... */ return 0; /* Must be of the form INSERT INTO ... SELECT ... */
@@ -1612,22 +1616,24 @@ static int xferOptimization(
} }
sqlite3OpenTable(pParse, iSrc, iDbSrc, pSrc, OP_OpenRead); sqlite3OpenTable(pParse, iSrc, iDbSrc, pSrc, OP_OpenRead);
emptySrcTest = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0); emptySrcTest = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0);
regData = sqlite3GetTempReg(pParse);
regRowid = sqlite3GetTempReg(pParse);
if( pDest->iPKey>=0 ){ if( pDest->iPKey>=0 ){
addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, 0); addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, regRowid);
sqlite3VdbeAddOp0(v, OP_Copy); addr2 = sqlite3VdbeAddOp3(v, OP_NotExists, iDest, 0, regRowid);
addr2 = sqlite3VdbeAddOp2(v, OP_NotExists, iDest, 0);
sqlite3VdbeAddOp4(v, OP_Halt, SQLITE_CONSTRAINT, onError, 0, sqlite3VdbeAddOp4(v, OP_Halt, SQLITE_CONSTRAINT, onError, 0,
"PRIMARY KEY must be unique", P4_STATIC); "PRIMARY KEY must be unique", P4_STATIC);
sqlite3VdbeJumpHere(v, addr2); sqlite3VdbeJumpHere(v, addr2);
autoIncStep(pParse, regAutoinc, 0); autoIncStep(pParse, regAutoinc, regRowid);
}else if( pDest->pIndex==0 ){ }else if( pDest->pIndex==0 ){
addr1 = sqlite3VdbeAddOp1(v, OP_NewRowid, iDest); addr1 = sqlite3VdbeAddOp2(v, OP_NewRowid, iDest, regRowid);
}else{ }else{
addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, 0); addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, regRowid);
assert( pDest->autoInc==0 ); assert( pDest->autoInc==0 );
} }
sqlite3VdbeAddOp1(v, OP_RowData, iSrc); sqlite3VdbeAddOp2(v, OP_RowData, iSrc, regData);
sqlite3CodeInsert(pParse,iDest,OPFLAG_NCHANGE|OPFLAG_LASTROWID|OPFLAG_APPEND); sqlite3VdbeAddOp3(v, OP_Insert, iDest, regData, regRowid);
sqlite3VdbeChangeP5(v, OPFLAG_NCHANGE|OPFLAG_LASTROWID|OPFLAG_APPEND);
sqlite3VdbeChangeP4(v, -1, pDest->zName, 0); sqlite3VdbeChangeP4(v, -1, pDest->zName, 0);
sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1); sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1);
autoIncEnd(pParse, iDbDest, pDest, regAutoinc); autoIncEnd(pParse, iDbDest, pDest, regAutoinc);
@@ -1647,12 +1653,14 @@ static int xferOptimization(
(char*)pKey, P4_KEYINFO_HANDOFF); (char*)pKey, P4_KEYINFO_HANDOFF);
VdbeComment((v, "%s", pDestIdx->zName)); VdbeComment((v, "%s", pDestIdx->zName));
addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0); addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0);
sqlite3VdbeAddOp1(v, OP_RowKey, iSrc); sqlite3VdbeAddOp2(v, OP_RowKey, iSrc, regData);
sqlite3VdbeAddOp3(v, OP_IdxInsert, iDest, 0, 1); sqlite3VdbeAddOp3(v, OP_IdxInsert, iDest, regData, 1);
sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1+1); sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1+1);
sqlite3VdbeJumpHere(v, addr1); sqlite3VdbeJumpHere(v, addr1);
} }
sqlite3VdbeJumpHere(v, emptySrcTest); sqlite3VdbeJumpHere(v, emptySrcTest);
sqlite3ReleaseTempReg(pParse, regRowid);
sqlite3ReleaseTempReg(pParse, regData);
sqlite3VdbeAddOp2(v, OP_Close, iSrc, 0); sqlite3VdbeAddOp2(v, OP_Close, iSrc, 0);
sqlite3VdbeAddOp2(v, OP_Close, iDest, 0); sqlite3VdbeAddOp2(v, OP_Close, iDest, 0);
if( emptyDestTest ){ if( emptyDestTest ){

View File

@@ -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.397 2008/01/10 23:50:11 drh Exp $ ** $Id: select.c,v 1.398 2008/01/12 12:48:08 drh Exp $
*/ */
#include "sqliteInt.h" #include "sqliteInt.h"
@@ -394,7 +394,8 @@ static int sqliteProcessJoin(Parse *pParse, Select *p){
static void pushOntoSorter( static void pushOntoSorter(
Parse *pParse, /* Parser context */ Parse *pParse, /* Parser context */
ExprList *pOrderBy, /* The ORDER BY clause */ ExprList *pOrderBy, /* The ORDER BY clause */
Select *pSelect /* The whole SELECT statement */ Select *pSelect, /* The whole SELECT statement */
int regData /* Register holding data to be sorted */
){ ){
Vdbe *v = pParse->pVdbe; Vdbe *v = pParse->pVdbe;
int nExpr = pOrderBy->nExpr; int nExpr = pOrderBy->nExpr;
@@ -402,15 +403,21 @@ static void pushOntoSorter(
int regRecord = sqlite3GetTempReg(pParse); int regRecord = sqlite3GetTempReg(pParse);
sqlite3ExprCodeExprList(pParse, pOrderBy, regBase); sqlite3ExprCodeExprList(pParse, pOrderBy, regBase);
sqlite3VdbeAddOp2(v, OP_Sequence, pOrderBy->iECursor, regBase+nExpr); sqlite3VdbeAddOp2(v, OP_Sequence, pOrderBy->iECursor, regBase+nExpr);
sqlite3VdbeAddOp2(v, OP_Move, 0, regBase+nExpr+1); sqlite3VdbeAddOp2(v, OP_Move, regData, regBase+nExpr+1);
sqlite3VdbeAddOp3(v, OP_RegMakeRec, regBase, nExpr + 2, regRecord); sqlite3VdbeAddOp3(v, OP_RegMakeRec, regBase, nExpr + 2, regRecord);
sqlite3VdbeAddOp2(v, OP_IdxInsert, pOrderBy->iECursor, regRecord); sqlite3VdbeAddOp2(v, OP_IdxInsert, pOrderBy->iECursor, regRecord);
sqlite3ReleaseTempReg(pParse, regRecord); sqlite3ReleaseTempReg(pParse, regRecord);
sqlite3ReleaseTempRange(pParse, regBase, nExpr+2); sqlite3ReleaseTempRange(pParse, regBase, nExpr+2);
if( pSelect->iLimit>=0 ){ if( pSelect->iLimit>=0 ){
int addr1, addr2; int addr1, addr2;
addr1 = sqlite3VdbeAddOp1(v, OP_IfZero, pSelect->iLimit+1); int iLimit;
sqlite3VdbeAddOp2(v, OP_AddImm, pSelect->iLimit+1, -1); if( pSelect->pOffset ){
iLimit = pSelect->iOffset+1;
}else{
iLimit = pSelect->iLimit;
}
addr1 = sqlite3VdbeAddOp1(v, OP_IfZero, iLimit);
sqlite3VdbeAddOp2(v, OP_AddImm, iLimit, -1);
addr2 = sqlite3VdbeAddOp0(v, OP_Goto); addr2 = sqlite3VdbeAddOp0(v, OP_Goto);
sqlite3VdbeJumpHere(v, addr1); sqlite3VdbeJumpHere(v, addr1);
sqlite3VdbeAddOp1(v, OP_Last, pOrderBy->iECursor); sqlite3VdbeAddOp1(v, OP_Last, pOrderBy->iECursor);
@@ -426,16 +433,12 @@ static void pushOntoSorter(
static void codeOffset( static void codeOffset(
Vdbe *v, /* Generate code into this VM */ Vdbe *v, /* Generate code into this VM */
Select *p, /* The SELECT statement being coded */ Select *p, /* The SELECT statement being coded */
int iContinue, /* Jump here to skip the current record */ int iContinue /* Jump here to skip the current record */
int nPop /* Number of times to pop stack when jumping */
){ ){
if( p->iOffset>=0 && iContinue!=0 ){ if( p->iOffset>=0 && iContinue!=0 ){
int addr; int addr;
sqlite3VdbeAddOp2(v, OP_AddImm, p->iOffset, -1); sqlite3VdbeAddOp2(v, OP_AddImm, p->iOffset, -1);
addr = sqlite3VdbeAddOp1(v, OP_IfNeg, p->iOffset); addr = sqlite3VdbeAddOp1(v, OP_IfNeg, p->iOffset);
if( nPop>0 ){
sqlite3VdbeAddOp1(v, OP_Pop, nPop);
}
sqlite3VdbeAddOp2(v, OP_Goto, 0, iContinue); sqlite3VdbeAddOp2(v, OP_Goto, 0, iContinue);
VdbeComment((v, "skip OFFSET records")); VdbeComment((v, "skip OFFSET records"));
sqlite3VdbeJumpHere(v, addr); sqlite3VdbeJumpHere(v, addr);
@@ -524,7 +527,7 @@ static int selectInnerLoop(
*/ */
hasDistinct = distinct>=0 && pEList->nExpr>0; hasDistinct = distinct>=0 && pEList->nExpr>0;
if( pOrderBy==0 && !hasDistinct ){ if( pOrderBy==0 && !hasDistinct ){
codeOffset(v, p, iContinue, 0); codeOffset(v, p, iContinue);
} }
/* Pull the requested columns. /* Pull the requested columns.
@@ -563,7 +566,7 @@ static int selectInnerLoop(
assert( pEList->nExpr==nColumn ); assert( pEList->nExpr==nColumn );
codeDistinct(v, distinct, iContinue, nColumn, iMem); codeDistinct(v, distinct, iContinue, nColumn, iMem);
if( pOrderBy==0 ){ if( pOrderBy==0 ){
codeOffset(v, p, iContinue, nColumn); codeOffset(v, p, iContinue);
} }
} }
@@ -603,14 +606,18 @@ static int selectInnerLoop(
*/ */
case SRT_Table: case SRT_Table:
case SRT_EphemTab: { case SRT_EphemTab: {
sqlite3VdbeAddOp2(v, OP_RegMakeRec, iMem, nColumn); int r1 = sqlite3GetTempReg(pParse);
sqlite3VdbeAddOp3(v, OP_RegMakeRec, iMem, nColumn, r1);
if( pOrderBy ){ if( pOrderBy ){
pushOntoSorter(pParse, pOrderBy, p); pushOntoSorter(pParse, pOrderBy, p, r1);
}else{ }else{
sqlite3VdbeAddOp1(v, OP_NewRowid, iParm); int r2 = sqlite3GetTempReg(pParse);
sqlite3VdbeAddOp2(v, OP_Pull, 1, 0); sqlite3VdbeAddOp2(v, OP_NewRowid, iParm, r2);
sqlite3CodeInsert(pParse, iParm, OPFLAG_APPEND); sqlite3VdbeAddOp3(v, OP_Insert, iParm, r1, r2);
sqlite3VdbeChangeP5(v, OPFLAG_APPEND);
sqlite3ReleaseTempReg(pParse, r2);
} }
sqlite3ReleaseTempReg(pParse, r1);
break; break;
} }
@@ -630,11 +637,12 @@ static int selectInnerLoop(
** ORDER BY in this case since the order of entries in the set ** ORDER BY in this case since the order of entries in the set
** does not matter. But there might be a LIMIT clause, in which ** does not matter. But there might be a LIMIT clause, in which
** case the order does matter */ ** case the order does matter */
sqlite3VdbeAddOp2(v, OP_SCopy, iMem, 0); pushOntoSorter(pParse, pOrderBy, p, iMem);
pushOntoSorter(pParse, pOrderBy, p);
}else{ }else{
sqlite3VdbeAddOp4(v, OP_RegMakeRec, iMem, 1, 0, &p->affinity, 1); int r1 = sqlite3GetTempReg(pParse);
sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, 0); sqlite3VdbeAddOp4(v, OP_RegMakeRec, iMem, 1, r1, &p->affinity, 1);
sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, r1);
sqlite3ReleaseTempReg(pParse, r1);
} }
sqlite3VdbeJumpHere(v, addr2); sqlite3VdbeJumpHere(v, addr2);
break; break;
@@ -654,11 +662,10 @@ static int selectInnerLoop(
*/ */
case SRT_Mem: { case SRT_Mem: {
assert( nColumn==1 ); assert( nColumn==1 );
sqlite3VdbeAddOp2(v, OP_SCopy, iMem, 0);
if( pOrderBy ){ if( pOrderBy ){
pushOntoSorter(pParse, pOrderBy, p); pushOntoSorter(pParse, pOrderBy, p, iMem);
}else{ }else{
sqlite3VdbeAddOp2(v, OP_Move, 0, iParm); sqlite3VdbeAddOp2(v, OP_Move, iMem, iParm);
/* The LIMIT clause will jump out of the loop for us */ /* The LIMIT clause will jump out of the loop for us */
} }
break; break;
@@ -672,8 +679,10 @@ static int selectInnerLoop(
case SRT_Subroutine: case SRT_Subroutine:
case SRT_Callback: { case SRT_Callback: {
if( pOrderBy ){ if( pOrderBy ){
sqlite3VdbeAddOp2(v, OP_RegMakeRec, iMem, nColumn); int r1 = sqlite3GetTempReg(pParse);
pushOntoSorter(pParse, pOrderBy, p); sqlite3VdbeAddOp3(v, OP_RegMakeRec, iMem, nColumn, r1);
pushOntoSorter(pParse, pOrderBy, p, r1);
sqlite3ReleaseTempReg(pParse, r1);
}else if( eDest==SRT_Subroutine ){ }else if( eDest==SRT_Subroutine ){
sqlite3VdbeAddOp2(v, OP_Gosub, 0, iParm); sqlite3VdbeAddOp2(v, OP_Gosub, 0, iParm);
}else{ }else{
@@ -779,7 +788,7 @@ static void generateSortTail(
sqlite3VdbeAddOp2(v, OP_SetNumColumns, pseudoTab, nColumn); sqlite3VdbeAddOp2(v, OP_SetNumColumns, pseudoTab, nColumn);
} }
addr = 1 + sqlite3VdbeAddOp2(v, OP_Sort, iTab, brk); addr = 1 + sqlite3VdbeAddOp2(v, OP_Sort, iTab, brk);
codeOffset(v, p, cont, 0); codeOffset(v, p, cont);
regRow = sqlite3GetTempReg(pParse); regRow = sqlite3GetTempReg(pParse);
regRowid = sqlite3GetTempReg(pParse); regRowid = sqlite3GetTempReg(pParse);
sqlite3VdbeAddOp3(v, OP_Column, iTab, pOrderBy->nExpr + 1, regRow); sqlite3VdbeAddOp3(v, OP_Column, iTab, pOrderBy->nExpr + 1, regRow);
@@ -1737,7 +1746,7 @@ static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){
Vdbe *v = 0; Vdbe *v = 0;
int iLimit = 0; int iLimit = 0;
int iOffset; int iOffset;
int addr1, addr2; int addr1;
/* /*
** "LIMIT -1" always shows all rows. There is some ** "LIMIT -1" always shows all rows. There is some
@@ -1747,42 +1756,34 @@ static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){
*/ */
if( p->pLimit ){ if( p->pLimit ){
p->iLimit = iLimit = ++pParse->nMem; p->iLimit = iLimit = ++pParse->nMem;
pParse->nMem++;
v = sqlite3GetVdbe(pParse); v = sqlite3GetVdbe(pParse);
if( v==0 ) return; if( v==0 ) return;
sqlite3ExprCode(pParse, p->pLimit, 0); sqlite3ExprCode(pParse, p->pLimit, iLimit);
sqlite3VdbeAddOp0(v, OP_MustBeInt); sqlite3VdbeAddOp1(v, OP_MustBeInt, iLimit);
sqlite3VdbeAddOp2(v, OP_Move, 0, iLimit);
VdbeComment((v, "LIMIT counter")); VdbeComment((v, "LIMIT counter"));
sqlite3VdbeAddOp2(v, OP_IfZero, iLimit, iBreak); sqlite3VdbeAddOp2(v, OP_IfZero, iLimit, iBreak);
sqlite3VdbeAddOp2(v, OP_SCopy, iLimit, 0);
} }
if( p->pOffset ){ if( p->pOffset ){
p->iOffset = iOffset = ++pParse->nMem; p->iOffset = iOffset = ++pParse->nMem;
if( p->pLimit ){
pParse->nMem++; /* Allocate an extra register for limit+offset */
}
v = sqlite3GetVdbe(pParse); v = sqlite3GetVdbe(pParse);
if( v==0 ) return; if( v==0 ) return;
sqlite3ExprCode(pParse, p->pOffset, 0); sqlite3ExprCode(pParse, p->pOffset, iOffset);
sqlite3VdbeAddOp0(v, OP_MustBeInt); sqlite3VdbeAddOp1(v, OP_MustBeInt, iOffset);
sqlite3VdbeAddOp2(v, p->pLimit==0 ? OP_Move : OP_Copy, 0, iOffset);
VdbeComment((v, "OFFSET counter")); VdbeComment((v, "OFFSET counter"));
addr1 = sqlite3VdbeAddOp1(v, OP_IfPos, iOffset); addr1 = sqlite3VdbeAddOp1(v, OP_IfPos, iOffset);
sqlite3VdbeAddOp2(v, OP_Pop, 1, 0); sqlite3VdbeAddOp2(v, OP_Integer, 0, iOffset);
sqlite3VdbeAddOp2(v, OP_Integer, 0, 0);
sqlite3VdbeJumpHere(v, addr1); sqlite3VdbeJumpHere(v, addr1);
if( p->pLimit ){ if( p->pLimit ){
sqlite3VdbeAddOp2(v, OP_Add, 0, 0); sqlite3VdbeAddOp3(v, OP_Add, iLimit, iOffset, iOffset+1);
VdbeComment((v, "LIMIT+OFFSET"));
addr1 = sqlite3VdbeAddOp1(v, OP_IfPos, iLimit);
sqlite3VdbeAddOp2(v, OP_Integer, -1, iOffset+1);
sqlite3VdbeJumpHere(v, addr1);
} }
} }
if( p->pLimit ){
addr1 = sqlite3VdbeAddOp1(v, OP_IfPos, iLimit);
sqlite3VdbeAddOp1(v, OP_Pop, 1);
sqlite3VdbeAddOp2(v, OP_Integer, -1, iLimit+1);
addr2 = sqlite3VdbeAddOp0(v, OP_Goto);
sqlite3VdbeJumpHere(v, addr1);
sqlite3VdbeAddOp2(v, OP_Move, 0, iLimit+1);
VdbeComment((v, "LIMIT+OFFSET"));
sqlite3VdbeJumpHere(v, addr2);
}
} }
/* /*

View File

@@ -11,7 +11,7 @@
************************************************************************* *************************************************************************
** Internal interface definitions for SQLite. ** Internal interface definitions for SQLite.
** **
** @(#) $Id: sqliteInt.h,v 1.647 2008/01/10 23:50:11 drh Exp $ ** @(#) $Id: sqliteInt.h,v 1.648 2008/01/12 12:48:08 drh Exp $
*/ */
#ifndef _SQLITEINT_H_ #ifndef _SQLITEINT_H_
#define _SQLITEINT_H_ #define _SQLITEINT_H_
@@ -1420,6 +1420,8 @@ struct Parse {
/* Above is constant between recursions. Below is reset before and after /* Above is constant between recursions. Below is reset before and after
** each recursion */ ** each recursion */
int regRowid; /* Register holding rowid of CREATE TABLE entry */
int regRoot; /* Register holding root page number for new objects */
int nVar; /* Number of '?' variables seen in the SQL so far */ int nVar; /* Number of '?' variables seen in the SQL so far */
int nVarExpr; /* Number of used slots in apVarExpr[] */ int nVarExpr; /* Number of used slots in apVarExpr[] */
int nVarExprAlloc; /* Number of allocated slots in apVarExpr[] */ int nVarExprAlloc; /* Number of allocated slots in apVarExpr[] */
@@ -1945,9 +1947,7 @@ int sqlite3OpenTempDatabase(Parse *);
void sqlite3StrAccumAppend(StrAccum*,const char*,int); void sqlite3StrAccumAppend(StrAccum*,const char*,int);
char *sqlite3StrAccumFinish(StrAccum*); char *sqlite3StrAccumFinish(StrAccum*);
void sqlite3StrAccumReset(StrAccum*); void sqlite3StrAccumReset(StrAccum*);
void sqlite3CodeInsert(Parse *, int, u8);
int sqlite3StackToReg(Parse *, int); int sqlite3StackToReg(Parse *, int);
void sqlite3RegToStack(Parse *, int, int);
void sqlite3SelectDestInit(SelectDest*,int,int); void sqlite3SelectDestInit(SelectDest*,int,int);
/* /*

View File

@@ -43,7 +43,7 @@
** in this file for details. If in doubt, do not deviate from existing ** in this file for details. If in doubt, do not deviate from existing
** commenting and indentation practices when changing or adding code. ** commenting and indentation practices when changing or adding code.
** **
** $Id: vdbe.c,v 1.692 2008/01/10 23:50:11 drh Exp $ ** $Id: vdbe.c,v 1.693 2008/01/12 12:48:08 drh Exp $
*/ */
#include "sqliteInt.h" #include "sqliteInt.h"
#include <ctype.h> #include <ctype.h>
@@ -94,6 +94,18 @@ int sqlite3_sort_count = 0;
int sqlite3_max_blobsize = 0; int sqlite3_max_blobsize = 0;
#endif #endif
/*
** Test a register to see if it exceeds the current maximum blob size.
** If it does, record the new maximum blob size.
*/
#ifdef SQLITE_TEST
# define UPDATE_MAX_BLOBSIZE(P) if( ((P)->flags&(MEM_Str|MEM_Blob))!=0 \
&& (P)->n>sqlite3_max_blobsize ) \
{sqlite3_max_blobsize = (P)->n;}
#else
# define UPDATE_MAX_BLOBSIZE(P)
#endif
/* /*
** Release the memory associated with the given stack level. This ** Release the memory associated with the given stack level. This
** leaves the Mem.flags field in an inconsistent state. ** leaves the Mem.flags field in an inconsistent state.
@@ -939,6 +951,7 @@ case OP_String8: { /* same as TK_STRING, out2-prerelease */
if( pOp->p1>SQLITE_MAX_LENGTH ){ if( pOp->p1>SQLITE_MAX_LENGTH ){
goto too_big; goto too_big;
} }
UPDATE_MAX_BLOBSIZE(pOut);
break; break;
} }
#endif #endif
@@ -959,6 +972,7 @@ case OP_String: { /* out2-prerelease */
pOut->z = pOp->p4.z; pOut->z = pOp->p4.z;
pOut->n = pOp->p1; pOut->n = pOp->p1;
pOut->enc = encoding; pOut->enc = encoding;
UPDATE_MAX_BLOBSIZE(pOut);
break; break;
} }
@@ -1019,6 +1033,7 @@ case OP_Blob: { /* out2-prerelease */
assert( pOp->p1 <= SQLITE_MAX_LENGTH ); assert( pOp->p1 <= SQLITE_MAX_LENGTH );
sqlite3VdbeMemSetStr(pOut, pOp->p4.z, pOp->p1, 0, 0); sqlite3VdbeMemSetStr(pOut, pOp->p4.z, pOp->p1, 0, 0);
pOut->enc = encoding; pOut->enc = encoding;
UPDATE_MAX_BLOBSIZE(pOut);
break; break;
} }
#endif /* SQLITE_OMIT_BLOB_LITERAL */ #endif /* SQLITE_OMIT_BLOB_LITERAL */
@@ -1043,6 +1058,7 @@ case OP_Variable: { /* out2-prerelease */
goto too_big; goto too_big;
} }
sqlite3VdbeMemShallowCopy(pOut, &p->aVar[j], MEM_Static); sqlite3VdbeMemShallowCopy(pOut, &p->aVar[j], MEM_Static);
UPDATE_MAX_BLOBSIZE(pOut);
break; break;
} }
@@ -1136,40 +1152,6 @@ case OP_SCopy: {
break; break;
} }
/* Opcode: Pull P1 * *
**
** The P1-th element is removed from its current location on
** the stack and pushed back on top of the stack. The
** top of the stack is element 0, so "Pull 0 0 0" is
** a no-op. "Pull 1 0 0" swaps the top two elements of
** the stack.
*/
case OP_Pull: { /* no-push */
Mem *pFrom = &pTos[-pOp->p1];
int i;
Mem ts;
ts = *pFrom;
Deephemeralize(pTos);
for(i=0; i<pOp->p1; i++, pFrom++){
Deephemeralize(&pFrom[1]);
assert( (pFrom[1].flags & MEM_Ephem)==0 );
*pFrom = pFrom[1];
if( pFrom->flags & MEM_Short ){
assert( pFrom->flags & (MEM_Str|MEM_Blob) );
assert( pFrom->z==pFrom[1].zShort );
pFrom->z = pFrom->zShort;
}
}
*pTos = ts;
if( pTos->flags & MEM_Short ){
assert( pTos->flags & (MEM_Str|MEM_Blob) );
assert( pTos->z==pTos[-pOp->p1].zShort );
pTos->z = pTos->zShort;
}
break;
}
/* Opcode: ResultRow P1 P2 * /* Opcode: ResultRow P1 P2 *
** **
** The registers P1 throught P1+P2-1 contain a single row of ** The registers P1 throught P1+P2-1 contain a single row of
@@ -1257,6 +1239,7 @@ case OP_Concat: { /* same as TK_CONCAT, in1, in2, out3 */
pOut->xDel = 0; pOut->xDel = 0;
pOut->enc = encoding; pOut->enc = encoding;
pOut->z = zNew; pOut->z = zNew;
UPDATE_MAX_BLOBSIZE(pOut);
break; break;
} }
@@ -1489,6 +1472,7 @@ case OP_Function: {
if( sqlite3VdbeMemTooBig(pOut) ){ if( sqlite3VdbeMemTooBig(pOut) ){
goto too_big; goto too_big;
} }
UPDATE_MAX_BLOBSIZE(pOut);
break; break;
} }
@@ -1658,6 +1642,7 @@ case OP_ToText: { /* same as TK_TO_TEXT, no-push, in1 */
rc = ExpandBlob(pIn1); rc = ExpandBlob(pIn1);
assert( pIn1->flags & MEM_Str ); assert( pIn1->flags & MEM_Str );
pIn1->flags &= ~(MEM_Int|MEM_Real|MEM_Blob); pIn1->flags &= ~(MEM_Int|MEM_Real|MEM_Blob);
UPDATE_MAX_BLOBSIZE(pIn1);
break; break;
} }
@@ -1679,6 +1664,7 @@ case OP_ToBlob: { /* same as TK_TO_BLOB, no-push, in1 */
pIn1->flags |= MEM_Blob; pIn1->flags |= MEM_Blob;
} }
pIn1->flags &= ~(MEM_Int|MEM_Real|MEM_Str); pIn1->flags &= ~(MEM_Int|MEM_Real|MEM_Str);
UPDATE_MAX_BLOBSIZE(pIn1);
break; break;
} }
@@ -2337,6 +2323,7 @@ case OP_Column: {
rc = sqlite3VdbeMemMakeWriteable(pDest); rc = sqlite3VdbeMemMakeWriteable(pDest);
op_column_out: op_column_out:
UPDATE_MAX_BLOBSIZE(pDest);
REGISTER_TRACE(pOp->p3, pDest); REGISTER_TRACE(pOp->p3, pDest);
break; break;
} }
@@ -2525,6 +2512,7 @@ case OP_MakeRecord: { /* jump */
} }
pOut->enc = SQLITE_UTF8; /* In case the blob is ever converted to text */ pOut->enc = SQLITE_UTF8; /* In case the blob is ever converted to text */
REGISTER_TRACE(pOp->p3, pOut); REGISTER_TRACE(pOp->p3, pOut);
UPDATE_MAX_BLOBSIZE(pOut);
/* If a NULL was encountered and jumpIfNull is non-zero, take the jump. */ /* If a NULL was encountered and jumpIfNull is non-zero, take the jump. */
if( jumpIfNull && containsNull ){ if( jumpIfNull && containsNull ){
@@ -2683,7 +2671,7 @@ case OP_ReadCookie: { /* out2-prerelease */
int iDb = pOp->p1; int iDb = pOp->p1;
int iCookie = pOp->p3; int iCookie = pOp->p3;
assert( pOp->p2<SQLITE_N_BTREE_META ); assert( pOp->p3<SQLITE_N_BTREE_META );
if( iDb<0 ){ if( iDb<0 ){
iDb = (-1*(iDb+1)); iDb = (-1*(iDb+1));
iCookie *= -1; iCookie *= -1;
@@ -3819,6 +3807,7 @@ case OP_RowData: { /* out2-prerelease */
pOut->flags = MEM_Null; pOut->flags = MEM_Null;
} }
pOut->enc = SQLITE_UTF8; /* In case the blob is ever cast to text */ pOut->enc = SQLITE_UTF8; /* In case the blob is ever cast to text */
UPDATE_MAX_BLOBSIZE(pOut);
break; break;
} }
@@ -4440,6 +4429,7 @@ case OP_IntegrityCk: {
pIn1->xDel = 0; pIn1->xDel = 0;
} }
pIn1->enc = SQLITE_UTF8; pIn1->enc = SQLITE_UTF8;
UPDATE_MAX_BLOBSIZE(pIn1);
sqlite3VdbeChangeEncoding(pIn1, encoding); sqlite3VdbeChangeEncoding(pIn1, encoding);
sqlite3_free(aRoot); sqlite3_free(aRoot);
break; break;
@@ -4656,6 +4646,7 @@ case OP_AggFinal: { /* no-push */
if( rc==SQLITE_ERROR ){ if( rc==SQLITE_ERROR ){
sqlite3SetString(&p->zErrMsg, sqlite3_value_text(pMem), (char*)0); sqlite3SetString(&p->zErrMsg, sqlite3_value_text(pMem), (char*)0);
} }
UPDATE_MAX_BLOBSIZE(pMem);
if( sqlite3VdbeMemTooBig(pMem) ){ if( sqlite3VdbeMemTooBig(pMem) ){
goto too_big; goto too_big;
} }
@@ -4961,6 +4952,7 @@ case OP_VColumn: {
pDest->flags = 0; pDest->flags = 0;
} }
sqlite3VdbeMemMove(pDest, &sContext.s); sqlite3VdbeMemMove(pDest, &sContext.s);
UPDATE_MAX_BLOBSIZE(pDest);
if( sqlite3SafetyOn(db) ){ if( sqlite3SafetyOn(db) ){
goto abort_due_to_misuse; goto abort_due_to_misuse;
@@ -5134,16 +5126,6 @@ default: {
} }
#endif #endif
#ifdef SQLITE_TEST
/* Keep track of the size of the largest BLOB or STR that has appeared
** on the top of the VDBE stack.
*/
if( pTos>=p->aStack && (pTos->flags & (MEM_Blob|MEM_Str))!=0
&& pTos->n>sqlite3_max_blobsize ){
sqlite3_max_blobsize = pTos->n;
}
#endif
/* The following code adds nothing to the actual functionality /* The following code adds nothing to the actual functionality
** of the program. It is only here for testing and debugging. ** of the program. It is only here for testing and debugging.
** On the other hand, it does burn CPU cycles every time through ** On the other hand, it does burn CPU cycles every time through

View File

@@ -11,7 +11,7 @@
************************************************************************* *************************************************************************
** This file contains code used to help implement virtual tables. ** This file contains code used to help implement virtual tables.
** **
** $Id: vtab.c,v 1.60 2008/01/03 00:01:25 drh Exp $ ** $Id: vtab.c,v 1.61 2008/01/12 12:48:08 drh Exp $
*/ */
#ifndef SQLITE_OMIT_VIRTUALTABLE #ifndef SQLITE_OMIT_VIRTUALTABLE
#include "sqliteInt.h" #include "sqliteInt.h"
@@ -259,20 +259,20 @@ void sqlite3VtabFinishParse(Parse *pParse, Token *pEnd){
** SQLITE_MASTER table. We just need to update that slot with all ** SQLITE_MASTER table. We just need to update that slot with all
** the information we've collected. ** the information we've collected.
** **
** The top of the stack is the rootpage allocated by sqlite3StartTable(). ** The VM register number pParse->regRowid holds the rowid of an
** This value is always 0 and is ignored, a virtual table does not have a ** entry in the sqlite_master table tht was created for this vtab
** rootpage. The next entry on the stack is the rowid of the record ** by sqlite3StartTable().
** in the sqlite_master table.
*/ */
iDb = sqlite3SchemaToIndex(db, pTab->pSchema); iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
sqlite3NestedParse(pParse, sqlite3NestedParse(pParse,
"UPDATE %Q.%s " "UPDATE %Q.%s "
"SET type='table', name=%Q, tbl_name=%Q, rootpage=0, sql=%Q " "SET type='table', name=%Q, tbl_name=%Q, rootpage=0, sql=%Q "
"WHERE rowid=#1", "WHERE rowid=#%d",
db->aDb[iDb].zName, SCHEMA_TABLE(iDb), db->aDb[iDb].zName, SCHEMA_TABLE(iDb),
pTab->zName, pTab->zName,
pTab->zName, pTab->zName,
zStmt zStmt,
pParse->regRowid
); );
sqlite3_free(zStmt); sqlite3_free(zStmt);
v = sqlite3GetVdbe(pParse); v = sqlite3GetVdbe(pParse);

View File

@@ -12,7 +12,7 @@
# focus of this file is testing UNION, INTERSECT and EXCEPT operators # focus of this file is testing UNION, INTERSECT and EXCEPT operators
# in SELECT statements. # in SELECT statements.
# #
# $Id: select4.test,v 1.24 2007/12/13 07:58:51 danielk1977 Exp $ # $Id: select4.test,v 1.25 2008/01/12 12:48:09 drh Exp $
set testdir [file dirname $argv0] set testdir [file dirname $argv0]
source $testdir/tester.tcl source $testdir/tester.tcl
@@ -618,4 +618,55 @@ do_test select4-9.12 {
} ;# ifcapable compound } ;# ifcapable compound
# Try combining DISTINCT, LIMIT, and OFFSET. Make sure they all work
# together.
#
do_test select4-10.1 {
execsql {
SELECT DISTINCT log FROM t1 ORDER BY log
}
} {0 1 2 3 4 5}
do_test select4-10.2 {
execsql {
SELECT DISTINCT log FROM t1 ORDER BY log LIMIT 4
}
} {0 1 2 3}
do_test select4-10.3 {
execsql {
SELECT DISTINCT log FROM t1 ORDER BY log LIMIT 0
}
} {}
do_test select4-10.4 {
execsql {
SELECT DISTINCT log FROM t1 ORDER BY log LIMIT -1
}
} {0 1 2 3 4 5}
do_test select4-10.5 {
execsql {
SELECT DISTINCT log FROM t1 ORDER BY log LIMIT -1 OFFSET 2
}
} {2 3 4 5}
do_test select4-10.6 {
execsql {
SELECT DISTINCT log FROM t1 ORDER BY log LIMIT 3 OFFSET 2
}
} {2 3 4}
do_test select4-10.7 {
execsql {
SELECT DISTINCT log FROM t1 ORDER BY +log LIMIT 3 OFFSET 20
}
} {}
do_test select4-10.8 {
execsql {
SELECT DISTINCT log FROM t1 ORDER BY log LIMIT 0 OFFSET 3
}
} {}
do_test select4-10.9 {
breakpoint
execsql {
SELECT DISTINCT max(n), log FROM t1 ORDER BY +log; -- LIMIT 2 OFFSET 1
}
} {31 5}
finish_test finish_test

62
test/select8.test Normal file
View File

@@ -0,0 +1,62 @@
# 2001 September 15
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.
#
# The focus of this file is testing that LIMIT and OFFSET work for
# unusual combinations SELECT statements.
#
# $Id: select8.test,v 1.1 2008/01/12 12:48:09 drh Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
execsql {
CREATE TABLE songs(songid, artist, timesplayed);
INSERT INTO songs VALUES(1,'one',1);
INSERT INTO songs VALUES(2,'one',2);
INSERT INTO songs VALUES(3,'two',3);
INSERT INTO songs VALUES(4,'three',5);
INSERT INTO songs VALUES(5,'one',7);
INSERT INTO songs VALUES(6,'two',11);
}
set result [execsql {
SELECT DISTINCT artist,sum(timesplayed) AS total
FROM songs
GROUP BY LOWER(artist)
}]
puts result=$result
do_test select8-1.1 {
execsql {
SELECT DISTINCT artist,sum(timesplayed) AS total
FROM songs
GROUP BY LOWER(artist)
LIMIT 1 OFFSET 1
}
} [lrange $result 2 3]
do_test select8-1.2 {
execsql {
SELECT DISTINCT artist,sum(timesplayed) AS total
FROM songs
GROUP BY LOWER(artist)
LIMIT 2 OFFSET 1
}
} [lrange $result 2 5]
do_test select8-1.3 {
execsql {
SELECT DISTINCT artist,sum(timesplayed) AS total
FROM songs
GROUP BY LOWER(artist)
LIMIT -1 OFFSET 2
}
} [lrange $result 4 end]
finish_test