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

Use a intermediate table when inserting a TEMP table from a SELECT that

reads from that same TEMP table.  Ticket #275. (CVS 895)

FossilOrigin-Name: 087d1e83af12b3a9aedd4945f02774a1043b1eb4
This commit is contained in:
drh
2003-04-03 01:50:44 +00:00
parent b95a8864c9
commit 048c530c01
6 changed files with 94 additions and 21 deletions

View File

@@ -1,5 +1,5 @@
C Add\sinfrastructure\sto\ssuport\smultiple\sbtree\simplementations\s(CVS\s894) 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-01T21:16:42 D 2003-04-03T01:50:44
F Makefile.in 3c4ba24253e61c954d67adbbb4245e7117c5357e F Makefile.in 3c4ba24253e61c954d67adbbb4245e7117c5357e
F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906 F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906
F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
@@ -29,7 +29,7 @@ F src/expr.c b8daee83f837b24a22d889200bdd74973ca2d8db
F src/func.c 882c3ed5a02be18cd904715c7ec62947a34a3605 F src/func.c 882c3ed5a02be18cd904715c7ec62947a34a3605
F src/hash.c 4fc39feb7b7711f6495ee9f2159559bedb043e1f F src/hash.c 4fc39feb7b7711f6495ee9f2159559bedb043e1f
F src/hash.h cd0433998bc1a3759d244e1637fe5a3c13b53bf8 F src/hash.h cd0433998bc1a3759d244e1637fe5a3c13b53bf8
F src/insert.c dad4d914dc729a94e48de171802c23587a62c34f F src/insert.c e2f5e7feecb507d904a7da48874595f440b715aa
F src/main.c 6d9a38491fdc40c041df64a7399244c364481a09 F src/main.c 6d9a38491fdc40c041df64a7399244c364481a09
F src/md5.c fe4f9c9c6f71dfc26af8da63e4d04489b1430565 F src/md5.c fe4f9c9c6f71dfc26af8da63e4d04489b1430565
F src/os.c dfed46091f69cd2d1e601f8a214d41344f2b00b6 F src/os.c dfed46091f69cd2d1e601f8a214d41344f2b00b6
@@ -54,8 +54,8 @@ F src/tokenize.c 675b4718d17c69fe7609dc8e85e426ef002be811
F src/trigger.c bd5a5b234b47f28f9f21a46243dcaf1c5b2383a3 F src/trigger.c bd5a5b234b47f28f9f21a46243dcaf1c5b2383a3
F src/update.c b368369f1fbe6d7f56a53e5ffad3b75dae9e3e1a F src/update.c b368369f1fbe6d7f56a53e5ffad3b75dae9e3e1a
F src/util.c 8953c612a036e30f24c1c1f5a1498176173daa37 F src/util.c 8953c612a036e30f24c1c1f5a1498176173daa37
F src/vdbe.c 7171dbe873760f403b2501e96fd3d1bd852b3ce8 F src/vdbe.c b3b840b555b5238926b7ebb01cd47526a29bb853
F src/vdbe.h ed43771f1dc2b994d5c484fdf2eab357c6ef0ee3 F src/vdbe.h 985c24f312d10f9ef8f9a8b8ea62fcdf68e82f21
F src/where.c e5733f7d5e9cc4ed3590dc3401f779e7b7bb8127 F src/where.c e5733f7d5e9cc4ed3590dc3401f779e7b7bb8127
F test/all.test 569a92a8ee88f5300c057cc4a8f50fbbc69a3242 F test/all.test 569a92a8ee88f5300c057cc4a8f50fbbc69a3242
F test/auth.test 33e8b9680eb0ce521c54096fff1c9ab506c7dfb8 F test/auth.test 33e8b9680eb0ce521c54096fff1c9ab506c7dfb8
@@ -75,7 +75,7 @@ F test/format3.test 64ab6c4db132b28a645996d413530f7b2a462cc2
F test/func.test 000515779001ac6899eec4b54e65c6e2501279d4 F test/func.test 000515779001ac6899eec4b54e65c6e2501279d4
F test/in.test 3171a2b3170a8223665c1a4f26be5f3eda36cc4b F test/in.test 3171a2b3170a8223665c1a4f26be5f3eda36cc4b
F test/index.test faeb1bcf776e3ff9ba1b4be1eadd1fece708aa7b F test/index.test faeb1bcf776e3ff9ba1b4be1eadd1fece708aa7b
F test/insert.test a122afb86911e77c181d912348866a5b1a61eeab F test/insert.test 5697ba098e4d8a6f0151f281b7e39dec9c439e05
F test/insert2.test c288375a64dad3295044714f0dfed4a193cf067f F test/insert2.test c288375a64dad3295044714f0dfed4a193cf067f
F test/intpkey.test 39f49fd993350f7f3ab255e5cfbf9a09d8f8800e F test/intpkey.test 39f49fd993350f7f3ab255e5cfbf9a09d8f8800e
F test/ioerr.test 45c8feebe608d7f456fea27ff27a0aaaf0b9c636 F test/ioerr.test 45c8feebe608d7f456fea27ff27a0aaaf0b9c636
@@ -155,7 +155,7 @@ F www/speed.tcl cb4c10a722614aea76d2c51f32ee43400d5951be
F www/sqlite.tcl ae3dcfb077e53833b59d4fcc94d8a12c50a44098 F www/sqlite.tcl ae3dcfb077e53833b59d4fcc94d8a12c50a44098
F www/tclsqlite.tcl 1db15abeb446aad0caf0b95b8b9579720e4ea331 F www/tclsqlite.tcl 1db15abeb446aad0caf0b95b8b9579720e4ea331
F www/vdbe.tcl 2013852c27a02a091d39a766bc87cff329f21218 F www/vdbe.tcl 2013852c27a02a091d39a766bc87cff329f21218
P 11378c5bf988412f8564cdc0314fc241793b292e P 79b3aed2a74a67cbad631c4e2e4a43469d80c162
R cc8e4c3807eb9ac6929fb512790ca871 R 6e7a48442426732645524eccf6cea407
U paul U drh
Z 048b3196e99f227ca8551c2b49ca1411 Z b83fa935d7c88982a4c85635851f4582

View File

@@ -1 +1 @@
79b3aed2a74a67cbad631c4e2e4a43469d80c162 087d1e83af12b3a9aedd4945f02774a1043b1eb4

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.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" #include "sqliteInt.h"
@@ -177,7 +177,6 @@ void sqliteInsert(
/* Data is coming from a SELECT. Generate code to implement that SELECT /* Data is coming from a SELECT. Generate code to implement that SELECT
*/ */
int rc, iInitCode; int rc, iInitCode;
int opCode;
iInitCode = sqliteVdbeAddOp(v, OP_Goto, 0, 0); iInitCode = sqliteVdbeAddOp(v, OP_Goto, 0, 0);
iSelectLoop = sqliteVdbeCurrentAddr(v); iSelectLoop = sqliteVdbeCurrentAddr(v);
iInsertBlock = sqliteVdbeMakeLabel(v); iInsertBlock = sqliteVdbeMakeLabel(v);
@@ -191,9 +190,23 @@ void sqliteInsert(
/* Set useTempTable to TRUE if the result of the SELECT statement /* Set useTempTable to TRUE if the result of the SELECT statement
** should be written into a temporary table. Set to FALSE if each ** should be written into a temporary table. Set to FALSE if each
** row of the SELECT can be written directly into the result table. ** 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; if( row_triggers_exist ){
useTempTable = row_triggers_exist || sqliteVdbeFindOp(v,opCode,pTab->tnum); 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 ){ if( useTempTable ){
/* Generate the subroutine that SELECT calls to process each row of /* Generate the subroutine that SELECT calls to process each row of

View File

@@ -36,7 +36,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.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 "sqliteInt.h"
#include <ctype.h> #include <ctype.h>
@@ -603,17 +603,26 @@ void sqliteVdbeCompressSpace(Vdbe *p, int addr){
/* /*
** Search for the current program for the given opcode and P2 ** 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 sqliteVdbeFindOp(Vdbe *p, int op, int p2){
int i; int i;
assert( p->magic==VDBE_MAGIC_INIT ); assert( p->magic==VDBE_MAGIC_INIT );
for(i=0; i<p->nOp; i++){ 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 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 ** The following group or routines are employed by installable functions
** to return their results. ** to return their results.

View File

@@ -15,7 +15,7 @@
** or VDBE. The VDBE implements an abstract machine that runs a ** or VDBE. The VDBE implements an abstract machine that runs a
** simple program to access and modify the underlying database. ** 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_ #ifndef _SQLITE_VDBE_H_
#define _SQLITE_VDBE_H_ #define _SQLITE_VDBE_H_
@@ -81,6 +81,7 @@ void sqliteVdbeChangeP2(Vdbe*, int addr, int P2);
void sqliteVdbeChangeP3(Vdbe*, int addr, const char *zP1, int N); void sqliteVdbeChangeP3(Vdbe*, int addr, const char *zP1, int N);
void sqliteVdbeDequoteP3(Vdbe*, int addr); void sqliteVdbeDequoteP3(Vdbe*, int addr);
int sqliteVdbeFindOp(Vdbe*, int, int); int sqliteVdbeFindOp(Vdbe*, int, int);
VdbeOp *sqliteVdbeGetOp(Vdbe*, int);
int sqliteVdbeMakeLabel(Vdbe*); int sqliteVdbeMakeLabel(Vdbe*);
void sqliteVdbeDelete(Vdbe*); void sqliteVdbeDelete(Vdbe*);
void sqliteVdbeMakeReady(Vdbe*,sqlite_callback,void*,int); void sqliteVdbeMakeReady(Vdbe*,sqlite_callback,void*,int);

View File

@@ -11,7 +11,7 @@
# This file implements regression tests for SQLite library. The # This file implements regression tests for SQLite library. The
# focus of this file is testing the INSERT statement. # 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] set testdir [file dirname $argv0]
source $testdir/tester.tcl source $testdir/tester.tcl
@@ -202,6 +202,56 @@ do_test insert-4.7 {
} }
} {1 3 99} } {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 finish_test