-C Add\sinfrastructure\sto\ssuport\smultiple\sbtree\simplementations\s(CVS\s894)
-D 2003-04-01T21:16:42
+C Use\sa\sintermediate\stable\swhen\sinserting\sa\sTEMP\stable\sfrom\sa\sSELECT\sthat\nreads\sfrom\sthat\ssame\sTEMP\stable.\s\sTicket\s#275.\s(CVS\s895)
+D 2003-04-03T01:50:44
F Makefile.in 3c4ba24253e61c954d67adbbb4245e7117c5357e
F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906
F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
F src/func.c 882c3ed5a02be18cd904715c7ec62947a34a3605
F src/hash.c 4fc39feb7b7711f6495ee9f2159559bedb043e1f
F src/hash.h cd0433998bc1a3759d244e1637fe5a3c13b53bf8
-F src/insert.c dad4d914dc729a94e48de171802c23587a62c34f
+F src/insert.c e2f5e7feecb507d904a7da48874595f440b715aa
F src/main.c 6d9a38491fdc40c041df64a7399244c364481a09
F src/md5.c fe4f9c9c6f71dfc26af8da63e4d04489b1430565
F src/os.c dfed46091f69cd2d1e601f8a214d41344f2b00b6
F src/trigger.c bd5a5b234b47f28f9f21a46243dcaf1c5b2383a3
F src/update.c b368369f1fbe6d7f56a53e5ffad3b75dae9e3e1a
F src/util.c 8953c612a036e30f24c1c1f5a1498176173daa37
-F src/vdbe.c 7171dbe873760f403b2501e96fd3d1bd852b3ce8
-F src/vdbe.h ed43771f1dc2b994d5c484fdf2eab357c6ef0ee3
+F src/vdbe.c b3b840b555b5238926b7ebb01cd47526a29bb853
+F src/vdbe.h 985c24f312d10f9ef8f9a8b8ea62fcdf68e82f21
F src/where.c e5733f7d5e9cc4ed3590dc3401f779e7b7bb8127
F test/all.test 569a92a8ee88f5300c057cc4a8f50fbbc69a3242
F test/auth.test 33e8b9680eb0ce521c54096fff1c9ab506c7dfb8
F test/func.test 000515779001ac6899eec4b54e65c6e2501279d4
F test/in.test 3171a2b3170a8223665c1a4f26be5f3eda36cc4b
F test/index.test faeb1bcf776e3ff9ba1b4be1eadd1fece708aa7b
-F test/insert.test a122afb86911e77c181d912348866a5b1a61eeab
+F test/insert.test 5697ba098e4d8a6f0151f281b7e39dec9c439e05
F test/insert2.test c288375a64dad3295044714f0dfed4a193cf067f
F test/intpkey.test 39f49fd993350f7f3ab255e5cfbf9a09d8f8800e
F test/ioerr.test 45c8feebe608d7f456fea27ff27a0aaaf0b9c636
F www/sqlite.tcl ae3dcfb077e53833b59d4fcc94d8a12c50a44098
F www/tclsqlite.tcl 1db15abeb446aad0caf0b95b8b9579720e4ea331
F www/vdbe.tcl 2013852c27a02a091d39a766bc87cff329f21218
-P 11378c5bf988412f8564cdc0314fc241793b292e
-R cc8e4c3807eb9ac6929fb512790ca871
-U paul
-Z 048b3196e99f227ca8551c2b49ca1411
+P 79b3aed2a74a67cbad631c4e2e4a43469d80c162
+R 6e7a48442426732645524eccf6cea407
+U drh
+Z b83fa935d7c88982a4c85635851f4582
-79b3aed2a74a67cbad631c4e2e4a43469d80c162
\ No newline at end of file
+087d1e83af12b3a9aedd4945f02774a1043b1eb4
\ No newline at end of file
** This file contains C code routines that are called by the parser
** to handle INSERT statements in SQLite.
**
-** $Id: insert.c,v 1.77 2003/03/31 02:12:47 drh Exp $
+** $Id: insert.c,v 1.78 2003/04/03 01:50:44 drh Exp $
*/
#include "sqliteInt.h"
/* Data is coming from a SELECT. Generate code to implement that SELECT
*/
int rc, iInitCode;
- int opCode;
iInitCode = sqliteVdbeAddOp(v, OP_Goto, 0, 0);
iSelectLoop = sqliteVdbeCurrentAddr(v);
iInsertBlock = sqliteVdbeMakeLabel(v);
/* Set useTempTable to TRUE if the result of the SELECT statement
** should be written into a temporary table. Set to FALSE if each
** row of the SELECT can be written directly into the result table.
+ **
+ ** A temp table must be used if the table being updated is also one
+ ** of the tables being read by the SELECT statement. Also use a
+ ** temp table in the case of row triggers.
*/
- opCode = pTab->iDb==1 ? OP_OpenTemp : OP_OpenRead;
- useTempTable = row_triggers_exist || sqliteVdbeFindOp(v,opCode,pTab->tnum);
+ if( row_triggers_exist ){
+ useTempTable = 1;
+ }else{
+ int addr = sqliteVdbeFindOp(v, OP_OpenRead, pTab->tnum);
+ useTempTable = 0;
+ if( addr>0 ){
+ VdbeOp *pOp = sqliteVdbeGetOp(v, addr-2);
+ if( pOp->opcode==OP_Integer && pOp->p1==pTab->iDb ){
+ useTempTable = 1;
+ }
+ }
+ }
if( useTempTable ){
/* Generate the subroutine that SELECT calls to process each row of
** 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.209 2003/03/20 01:16:59 drh Exp $
+** $Id: vdbe.c,v 1.210 2003/04/03 01:50:45 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
/*
** Search for the current program for the given opcode and P2
-** value. Return 1 if found and 0 if not found.
+** value. Return the address plus 1 if found and 0 if not found.
*/
int sqliteVdbeFindOp(Vdbe *p, int op, int p2){
int i;
assert( p->magic==VDBE_MAGIC_INIT );
for(i=0; i<p->nOp; i++){
- if( p->aOp[i].opcode==op && p->aOp[i].p2==p2 ) return 1;
+ if( p->aOp[i].opcode==op && p->aOp[i].p2==p2 ) return i+1;
}
return 0;
}
+/*
+** Return the opcode for a given address.
+*/
+VdbeOp *sqliteVdbeGetOp(Vdbe *p, int addr){
+ assert( p->magic==VDBE_MAGIC_INIT );
+ assert( addr>=0 && addr<p->nOp );
+ return &p->aOp[addr];
+}
+
/*
** The following group or routines are employed by installable functions
** to return their results.
** or VDBE. The VDBE implements an abstract machine that runs a
** simple program to access and modify the underlying database.
**
-** $Id: vdbe.h,v 1.64 2003/01/29 18:46:53 drh Exp $
+** $Id: vdbe.h,v 1.65 2003/04/03 01:50:47 drh Exp $
*/
#ifndef _SQLITE_VDBE_H_
#define _SQLITE_VDBE_H_
void sqliteVdbeChangeP3(Vdbe*, int addr, const char *zP1, int N);
void sqliteVdbeDequoteP3(Vdbe*, int addr);
int sqliteVdbeFindOp(Vdbe*, int, int);
+VdbeOp *sqliteVdbeGetOp(Vdbe*, int);
int sqliteVdbeMakeLabel(Vdbe*);
void sqliteVdbeDelete(Vdbe*);
void sqliteVdbeMakeReady(Vdbe*,sqlite_callback,void*,int);
# This file implements regression tests for SQLite library. The
# focus of this file is testing the INSERT statement.
#
-# $Id: insert.test,v 1.11 2002/06/25 13:16:04 drh Exp $
+# $Id: insert.test,v 1.12 2003/04/03 01:50:48 drh Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
}
} {1 3 99}
-# Test
+# Test the ability to insert from a temporary table into itself.
+# Ticket #275.
+#
+do_test insert-5.1 {
+ execsql {
+ CREATE TEMP TABLE t4(x);
+ INSERT INTO t4 VALUES(1);
+ SELECT * FROM t4;
+ }
+} {1}
+do_test insert-5.2 {
+ execsql {
+ INSERT INTO t4 SELECT x+1 FROM t4;
+ SELECT * FROM t4;
+ }
+} {1 2}
+do_test insert-5.3 {
+ # verify that a temporary table is used to copy t4 to t4
+ set x [execsql {
+ EXPLAIN INSERT INTO t4 SELECT x+2 FROM t4;
+ }]
+ expr {[lsearch $x OpenTemp]>0}
+} {1}
+do_test insert-5.4 {
+ # Verify that table "test1" begins on page 3. This should be the same
+ # page number used by "t4" above.
+ execsql {
+ SELECT rootpage FROM sqlite_master WHERE name='test1';
+ }
+} {3}
+do_test insert-5.5 {
+ # Verify that "t4" begins on page 3.
+ execsql {
+ SELECT rootpage FROM sqlite_temp_master WHERE name='t4';
+ }
+} {3}
+do_test insert-5.6 {
+ # This should not use an intermediate temporary table.
+ execsql {
+ INSERT INTO t4 SELECT one FROM test1 WHERE three=7;
+ SELECT * FROM t4
+ }
+} {1 2 8}
+do_test insert-5.7 {
+ # verify that no temporary table is used to copy test1 to t4
+ set x [execsql {
+ EXPLAIN INSERT INTO t4 SELECT one FROM test1;
+ }]
+ expr {[lsearch $x OpenTemp]>0}
+} {0}
+
finish_test