Fix a buggy interaction between "INSERT ... SELECT" processing and optimization (2170). (CVS 2319)
FossilOrigin-Name: c54ad2123693be8777d80343979e3261c4892105
This commit is contained in:
parent
a58fdfb162
commit
4d88778b26
14
manifest
14
manifest
@ -1,5 +1,5 @@
|
||||
C Fix\sfor\scorrelated\ssubqueries\swhere\sthe\sparent\sis\san\saggregate.\sTicket\s#1105.\s(CVS\s2318)
|
||||
D 2005-02-08T07:50:41
|
||||
C Fix\sa\sbuggy\sinteraction\sbetween\s"INSERT\s...\sSELECT"\sprocessing\sand\soptimization\s(2170).\s(CVS\s2319)
|
||||
D 2005-02-08T08:42:28
|
||||
F Makefile.in d928187101fa3d78426cf48ca30e39d0fb714e57
|
||||
F Makefile.linux-gcc a9e5a0d309fa7c38e7c14d3ecf7690879d3a5457
|
||||
F README a01693e454a00cc117967e3f9fdab2d4d52e9bc1
|
||||
@ -39,7 +39,7 @@ F src/expr.c b9ffd249cef8cd0f2d3681da8daf9a4292dcd005
|
||||
F src/func.c f096b6771cc0aaa11790aca95773a50a8f74ba73
|
||||
F src/hash.c 2b1b13f7400e179631c83a1be0c664608c8f021f
|
||||
F src/hash.h 1b0c445e1c89ff2aaad9b4605ba61375af001e84
|
||||
F src/insert.c 6ab596846d52bd63d6227f9128a29e4f5b2cf524
|
||||
F src/insert.c 0456649d4d48396f918e7ea1fecbf3d66ed90816
|
||||
F src/legacy.c d58ea507bce885298a2c8c3cbb0f4bff5d47830b
|
||||
F src/main.c 981099f5f73a71e54b0858b01e03d29b83168f7b
|
||||
F src/md5.c 7ae1c39044b95de2f62e066f47bb1deb880a1070
|
||||
@ -132,7 +132,7 @@ F test/in.test ed134f8d477a6280297ced1646de83cccf8f196d
|
||||
F test/index.test 51e01a0928b4b61228917ddd8c6c0e2466547f6f
|
||||
F test/index2.test 9ad98243fd7fe833795a9cc662f371f0eed4ff4f
|
||||
F test/insert.test f39cb2306199c6f9d8959b843c9199d799217055
|
||||
F test/insert2.test 420cb5c23912732219aad87420abdd7b994b1cad
|
||||
F test/insert2.test 065f179a21b42f9746b97571b8ad10b092e90913
|
||||
F test/insert3.test c67f0240b1c17e71fa2ed8bb6de064928f549f95
|
||||
F test/interrupt.test 5b4d8389e6cf2d01b94f87cfd02d9df1073bfb2d
|
||||
F test/intpkey.test b57cf5236fde1bd8cbc1388fa0c91908f6fd9194
|
||||
@ -270,7 +270,7 @@ F www/tclsqlite.tcl e73f8f8e5f20e8277619433f7970060ab01088fc
|
||||
F www/vdbe.tcl 095f106d93875c94b47367384ebc870517431618
|
||||
F www/version3.tcl 092a01f5ef430d2c4acc0ae558d74c4bb89638a0
|
||||
F www/whentouse.tcl 3e522a06ad41992023c80ca29a048ae2331ca5bd
|
||||
P 2155448d2128119f74241da0ea07d6713b71765c
|
||||
R 606c27806bb193ef40535820164d7cb2
|
||||
P f0d3ca10c5bccf8fca7143028ebb3e604c0e3f20
|
||||
R 93ae7881c0534be4b69c417087656125
|
||||
U danielk1977
|
||||
Z ab8a5b2917edd9042037cd2b7cc41ebd
|
||||
Z 4617442cd0669e690e2b0abf1defb4ca
|
||||
|
@ -1 +1 @@
|
||||
f0d3ca10c5bccf8fca7143028ebb3e604c0e3f20
|
||||
c54ad2123693be8777d80343979e3261c4892105
|
39
src/insert.c
39
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.135 2005/01/29 08:32:45 danielk1977 Exp $
|
||||
** $Id: insert.c,v 1.136 2005/02/08 08:42:28 danielk1977 Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
|
||||
@ -94,6 +94,27 @@ void sqlite3TableAffinityStr(Vdbe *v, Table *pTab){
|
||||
sqlite3VdbeChangeP3(v, -1, pTab->zColAff, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
** Return non-zero if SELECT statement p opens the table with rootpage
|
||||
** iTab in database iDb. This is used to see if a statement of the form
|
||||
** "INSERT INTO <iDb, iTab> SELECT ..." can run without using temporary
|
||||
** table for the results of the SELECT.
|
||||
**
|
||||
** No checking is done for sub-selects that are part of expressions.
|
||||
*/
|
||||
static int selectReadsTable(Select *p, int iDb, int iTab){
|
||||
int i;
|
||||
struct SrcList_item *pItem;
|
||||
if( p->pSrc==0 ) return 0;
|
||||
for(i=0, pItem=p->pSrc->a; i<p->pSrc->nSrc; i++, pItem++){
|
||||
if( pItem->pSelect ){
|
||||
if( selectReadsTable(p, iDb, iTab) ) return 1;
|
||||
}else{
|
||||
if( pItem->pTab->iDb==iDb && pItem->pTab->tnum==iTab ) return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** This routine is call to handle SQL of the following forms:
|
||||
@ -182,7 +203,7 @@ void sqlite3Insert(
|
||||
sqlite3 *db; /* The main database structure */
|
||||
int keyColumn = -1; /* Column that is the INTEGER PRIMARY KEY */
|
||||
int endOfLoop; /* Label for the end of the insertion loop */
|
||||
int useTempTable; /* Store SELECT results in intermediate table */
|
||||
int useTempTable = 0; /* Store SELECT results in intermediate table */
|
||||
int srcTab = 0; /* Data comes from this temporary cursor if >=0 */
|
||||
int iSelectLoop = 0; /* Address of code that implements the SELECT */
|
||||
int iCleanup = 0; /* Address of the cleanup code */
|
||||
@ -330,20 +351,8 @@ void sqlite3Insert(
|
||||
** of the tables being read by the SELECT statement. Also use a
|
||||
** temp table in the case of row triggers.
|
||||
*/
|
||||
if( triggers_exist ){
|
||||
if( triggers_exist || selectReadsTable(pSelect, pTab->iDb, pTab->tnum) ){
|
||||
useTempTable = 1;
|
||||
}else{
|
||||
int addr = 0;
|
||||
useTempTable = 0;
|
||||
while( useTempTable==0 ){
|
||||
VdbeOp *pOp;
|
||||
addr = sqlite3VdbeFindOp(v, addr, OP_OpenRead, pTab->tnum);
|
||||
if( addr==0 ) break;
|
||||
pOp = sqlite3VdbeGetOp(v, addr-2);
|
||||
if( pOp->opcode==OP_Integer && pOp->p1==pTab->iDb ){
|
||||
useTempTable = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( useTempTable ){
|
||||
|
@ -12,7 +12,7 @@
|
||||
# focus of this file is testing the INSERT statement that takes is
|
||||
# result from a SELECT.
|
||||
#
|
||||
# $Id: insert2.test,v 1.14 2005/01/21 03:12:16 danielk1977 Exp $
|
||||
# $Id: insert2.test,v 1.15 2005/02/08 08:42:29 danielk1977 Exp $
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
@ -244,4 +244,25 @@ do_test insert2-4.1 {
|
||||
};
|
||||
} {}
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# Test that the INSERT works when the SELECT statement (a) references
|
||||
# the table being inserted into and (b) is optimized to use an index
|
||||
# only.
|
||||
do_test insert2-5.1 {
|
||||
execsql {
|
||||
CREATE TABLE t2(a, b);
|
||||
INSERT INTO t2 VALUES(1, 2);
|
||||
CREATE INDEX t2i1 ON t2(a);
|
||||
INSERT INTO t2 SELECT a, 3 FROM t2 WHERE a = 1;
|
||||
SELECT * FROM t2;
|
||||
}
|
||||
} {1 2 1 3}
|
||||
do_test insert2-5.2 {
|
||||
execsql {
|
||||
INSERT INTO t2 SELECT (SELECT a FROM t2), 4;
|
||||
SELECT * FROM t2;
|
||||
}
|
||||
} {1 2 1 3 1 4}
|
||||
|
||||
finish_test
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user