mirror of
https://github.com/aljazceru/turso.git
synced 2026-02-14 12:34:20 +01:00
testing/sqlite3: Import INSERT statement TCL tests
This commit is contained in:
@@ -19,3 +19,9 @@ source $testdir/selectE.test
|
||||
source $testdir/selectF.test
|
||||
source $testdir/selectG.test
|
||||
source $testdir/selectH.test
|
||||
|
||||
source $testdir/insert.test
|
||||
source $testdir/insert2.test
|
||||
source $testdir/insert3.test
|
||||
source $testdir/insert4.test
|
||||
source $testdir/insert5.test
|
||||
603
testing/sqlite3/insert.test
Normal file
603
testing/sqlite3/insert.test
Normal file
@@ -0,0 +1,603 @@
|
||||
# 2001-09-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 the INSERT statement.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
|
||||
# Try to insert into a non-existant table.
|
||||
#
|
||||
do_test insert-1.1 {
|
||||
set v [catch {execsql {INSERT INTO test1 VALUES(1,2,3)}} msg]
|
||||
lappend v $msg
|
||||
} {1 {no such table: test1}}
|
||||
|
||||
# Try to insert into sqlite_master
|
||||
#
|
||||
do_test insert-1.2 {
|
||||
set v [catch {execsql {INSERT INTO sqlite_master VALUES(1,2,3,4)}} msg]
|
||||
lappend v $msg
|
||||
} {1 {table sqlite_master may not be modified}}
|
||||
|
||||
# Try to insert the wrong number of entries.
|
||||
#
|
||||
do_test insert-1.3 {
|
||||
execsql {CREATE TABLE test1(one int, two int, three int)}
|
||||
set v [catch {execsql {INSERT INTO test1 VALUES(1,2)}} msg]
|
||||
lappend v $msg
|
||||
} {1 {table test1 has 3 columns but 2 values were supplied}}
|
||||
do_test insert-1.3b {
|
||||
set v [catch {execsql {INSERT INTO test1 VALUES(1,2,3,4)}} msg]
|
||||
lappend v $msg
|
||||
} {1 {table test1 has 3 columns but 4 values were supplied}}
|
||||
do_test insert-1.3c {
|
||||
set v [catch {execsql {INSERT INTO test1(one,two) VALUES(1,2,3,4)}} msg]
|
||||
lappend v $msg
|
||||
} {1 {4 values for 2 columns}}
|
||||
do_test insert-1.3d {
|
||||
set v [catch {execsql {INSERT INTO test1(one,two) VALUES(1)}} msg]
|
||||
lappend v $msg
|
||||
} {1 {1 values for 2 columns}}
|
||||
|
||||
# Try to insert into a non-existant column of a table.
|
||||
#
|
||||
do_test insert-1.4 {
|
||||
set v [catch {execsql {INSERT INTO test1(one,four) VALUES(1,2)}} msg]
|
||||
lappend v $msg
|
||||
} {1 {table test1 has no column named four}}
|
||||
|
||||
# Make sure the inserts actually happen
|
||||
#
|
||||
do_test insert-1.5 {
|
||||
execsql {INSERT INTO test1 VALUES(1,2,3)}
|
||||
execsql {SELECT * FROM test1}
|
||||
} {1 2 3}
|
||||
do_test insert-1.5b {
|
||||
execsql {INSERT INTO test1 VALUES(4,5,6)}
|
||||
execsql {SELECT * FROM test1 ORDER BY one}
|
||||
} {1 2 3 4 5 6}
|
||||
do_test insert-1.5c {
|
||||
execsql {INSERT INTO test1 VALUES(7,8,9)}
|
||||
execsql {SELECT * FROM test1 ORDER BY one}
|
||||
} {1 2 3 4 5 6 7 8 9}
|
||||
|
||||
do_test insert-1.6 {
|
||||
execsql {DELETE FROM test1}
|
||||
execsql {INSERT INTO test1(one,two) VALUES(1,2)}
|
||||
execsql {SELECT * FROM test1 ORDER BY one}
|
||||
} {1 2 {}}
|
||||
do_test insert-1.6b {
|
||||
execsql {INSERT INTO test1(two,three) VALUES(5,6)}
|
||||
execsql {SELECT * FROM test1 ORDER BY one}
|
||||
} {{} 5 6 1 2 {}}
|
||||
do_test insert-1.6c {
|
||||
execsql {INSERT INTO test1(three,one) VALUES(7,8)}
|
||||
execsql {SELECT * FROM test1 ORDER BY one}
|
||||
} {{} 5 6 1 2 {} 8 {} 7}
|
||||
|
||||
# A table to use for testing default values
|
||||
#
|
||||
do_test insert-2.1 {
|
||||
execsql {
|
||||
CREATE TABLE test2(
|
||||
f1 int default -111,
|
||||
f2 real default +4.32,
|
||||
f3 int default +222,
|
||||
f4 int default 7.89
|
||||
)
|
||||
}
|
||||
execsql {SELECT * from test2}
|
||||
} {}
|
||||
do_test insert-2.2 {
|
||||
execsql {INSERT INTO test2(f1,f3) VALUES(+10,-10)}
|
||||
execsql {SELECT * FROM test2}
|
||||
} {10 4.32 -10 7.89}
|
||||
do_test insert-2.3 {
|
||||
execsql {INSERT INTO test2(f2,f4) VALUES(1.23,-3.45)}
|
||||
execsql {SELECT * FROM test2 WHERE f1==-111}
|
||||
} {-111 1.23 222 -3.45}
|
||||
do_test insert-2.4 {
|
||||
execsql {INSERT INTO test2(f1,f2,f4) VALUES(77,+1.23,3.45)}
|
||||
execsql {SELECT * FROM test2 WHERE f1==77}
|
||||
} {77 1.23 222 3.45}
|
||||
do_test insert-2.10 {
|
||||
execsql {
|
||||
DROP TABLE test2;
|
||||
CREATE TABLE test2(
|
||||
f1 int default 111,
|
||||
f2 real default -4.32,
|
||||
f3 text default hi,
|
||||
f4 text default 'abc-123',
|
||||
f5 varchar(10)
|
||||
)
|
||||
}
|
||||
execsql {SELECT * from test2}
|
||||
} {}
|
||||
do_test insert-2.11 {
|
||||
execsql {INSERT INTO test2(f2,f4) VALUES(-2.22,'hi!')}
|
||||
execsql {SELECT * FROM test2}
|
||||
} {111 -2.22 hi hi! {}}
|
||||
do_test insert-2.12 {
|
||||
execsql {INSERT INTO test2(f1,f5) VALUES(1,'xyzzy')}
|
||||
execsql {SELECT * FROM test2 ORDER BY f1}
|
||||
} {1 -4.32 hi abc-123 xyzzy 111 -2.22 hi hi! {}}
|
||||
|
||||
# Do additional inserts with default values, but this time
|
||||
# on a table that has indices. In particular we want to verify
|
||||
# that the correct default values are inserted into the indices.
|
||||
#
|
||||
do_test insert-3.1 {
|
||||
execsql {
|
||||
DELETE FROM test2;
|
||||
CREATE INDEX index9 ON test2(f1,f2);
|
||||
CREATE INDEX indext ON test2(f4,f5);
|
||||
SELECT * from test2;
|
||||
}
|
||||
} {}
|
||||
|
||||
# Update for sqlite3 v3:
|
||||
# Change the 111 to '111' in the following two test cases, because
|
||||
# the default value is being inserted as a string. TODO: It shouldn't be.
|
||||
do_test insert-3.2 {
|
||||
execsql {INSERT INTO test2(f2,f4) VALUES(-3.33,'hum')}
|
||||
execsql {SELECT * FROM test2 WHERE f1='111' AND f2=-3.33}
|
||||
} {111 -3.33 hi hum {}}
|
||||
do_test insert-3.3 {
|
||||
execsql {INSERT INTO test2(f1,f2,f5) VALUES(22,-4.44,'wham')}
|
||||
execsql {SELECT * FROM test2 WHERE f1='111' AND f2=-3.33}
|
||||
} {111 -3.33 hi hum {}}
|
||||
do_test insert-3.4 {
|
||||
execsql {SELECT * FROM test2 WHERE f1=22 AND f2=-4.44}
|
||||
} {22 -4.44 hi abc-123 wham}
|
||||
ifcapable {reindex} {
|
||||
do_test insert-3.5 {
|
||||
execsql REINDEX
|
||||
} {}
|
||||
}
|
||||
integrity_check insert-3.5
|
||||
|
||||
# Test of expressions in the VALUES clause
|
||||
#
|
||||
do_test insert-4.1 {
|
||||
execsql {
|
||||
CREATE TABLE t3(a,b,c);
|
||||
INSERT INTO t3 VALUES(1+2+3,4,5);
|
||||
SELECT * FROM t3;
|
||||
}
|
||||
} {6 4 5}
|
||||
do_test insert-4.2 {
|
||||
ifcapable subquery {
|
||||
execsql {INSERT INTO t3 VALUES((SELECT max(a) FROM t3)+1,5,6);}
|
||||
} else {
|
||||
set maxa [execsql {SELECT max(a) FROM t3}]
|
||||
execsql "INSERT INTO t3 VALUES($maxa+1,5,6);"
|
||||
}
|
||||
execsql {
|
||||
SELECT * FROM t3 ORDER BY a;
|
||||
}
|
||||
} {6 4 5 7 5 6}
|
||||
ifcapable subquery {
|
||||
do_test insert-4.3 {
|
||||
catchsql {
|
||||
INSERT INTO t3 VALUES((SELECT max(a) FROM t3)+1,t3.a,6);
|
||||
SELECT * FROM t3 ORDER BY a;
|
||||
}
|
||||
} {1 {no such column: t3.a}}
|
||||
}
|
||||
do_test insert-4.4 {
|
||||
ifcapable subquery {
|
||||
execsql {INSERT INTO t3 VALUES((SELECT b FROM t3 WHERE a=0),6,7);}
|
||||
} else {
|
||||
set b [execsql {SELECT b FROM t3 WHERE a = 0}]
|
||||
if {$b==""} {set b NULL}
|
||||
execsql "INSERT INTO t3 VALUES($b,6,7);"
|
||||
}
|
||||
execsql {
|
||||
SELECT * FROM t3 ORDER BY a;
|
||||
}
|
||||
} {{} 6 7 6 4 5 7 5 6}
|
||||
do_test insert-4.5 {
|
||||
execsql {
|
||||
SELECT b,c FROM t3 WHERE a IS NULL;
|
||||
}
|
||||
} {6 7}
|
||||
do_test insert-4.6 {
|
||||
catchsql {
|
||||
INSERT INTO t3 VALUES(notafunc(2,3),2,3);
|
||||
}
|
||||
} {1 {no such function: notafunc}}
|
||||
do_test insert-4.7 {
|
||||
execsql {
|
||||
INSERT INTO t3 VALUES(min(1,2,3),max(1,2,3),99);
|
||||
SELECT * FROM t3 WHERE c=99;
|
||||
}
|
||||
} {1 3 99}
|
||||
|
||||
# Test the ability to insert from a temporary table into itself.
|
||||
# Ticket #275.
|
||||
#
|
||||
ifcapable tempdb {
|
||||
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}
|
||||
ifcapable {explain} {
|
||||
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 OpenEphemeral]>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.
|
||||
#
|
||||
# Update for v3 - the first table now begins on page 2 of each file, not 3.
|
||||
execsql {
|
||||
SELECT rootpage FROM sqlite_master WHERE name='test1';
|
||||
}
|
||||
} [expr $AUTOVACUUM?3:2]
|
||||
do_test insert-5.5 {
|
||||
# Verify that "t4" begins on page 3.
|
||||
#
|
||||
# Update for v3 - the first table now begins on page 2 of each file, not 3.
|
||||
execsql {
|
||||
SELECT rootpage FROM sqlite_temp_master WHERE name='t4';
|
||||
}
|
||||
} {2}
|
||||
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}
|
||||
ifcapable {explain} {
|
||||
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}
|
||||
}
|
||||
}
|
||||
|
||||
# Ticket #334: REPLACE statement corrupting indices.
|
||||
#
|
||||
ifcapable conflict {
|
||||
# The REPLACE command is not available if SQLITE_OMIT_CONFLICT is
|
||||
# defined at compilation time.
|
||||
do_test insert-6.1 {
|
||||
execsql {
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY, b UNIQUE);
|
||||
INSERT INTO t1 VALUES(1,2);
|
||||
INSERT INTO t1 VALUES(2,3);
|
||||
SELECT b FROM t1 WHERE b=2;
|
||||
}
|
||||
} {2}
|
||||
do_test insert-6.2 {
|
||||
execsql {
|
||||
REPLACE INTO t1 VALUES(1,4);
|
||||
SELECT b FROM t1 WHERE b=2;
|
||||
}
|
||||
} {}
|
||||
do_test insert-6.3 {
|
||||
execsql {
|
||||
UPDATE OR REPLACE t1 SET a=2 WHERE b=4;
|
||||
SELECT * FROM t1 WHERE b=4;
|
||||
}
|
||||
} {2 4}
|
||||
do_test insert-6.4 {
|
||||
execsql {
|
||||
SELECT * FROM t1 WHERE b=3;
|
||||
}
|
||||
} {}
|
||||
ifcapable {reindex} {
|
||||
do_test insert-6.5 {
|
||||
execsql REINDEX
|
||||
} {}
|
||||
}
|
||||
do_test insert-6.6 {
|
||||
execsql {
|
||||
DROP TABLE t1;
|
||||
}
|
||||
} {}
|
||||
}
|
||||
|
||||
# Test that the special optimization for queries of the form
|
||||
# "SELECT max(x) FROM tbl" where there is an index on tbl(x) works with
|
||||
# INSERT statments.
|
||||
do_test insert-7.1 {
|
||||
execsql {
|
||||
CREATE TABLE t1(a);
|
||||
INSERT INTO t1 VALUES(1);
|
||||
INSERT INTO t1 VALUES(2);
|
||||
CREATE INDEX i1 ON t1(a);
|
||||
}
|
||||
} {}
|
||||
do_test insert-7.2 {
|
||||
execsql {
|
||||
INSERT INTO t1 SELECT max(a) FROM t1;
|
||||
}
|
||||
} {}
|
||||
do_test insert-7.3 {
|
||||
execsql {
|
||||
SELECT a FROM t1;
|
||||
}
|
||||
} {1 2 2}
|
||||
|
||||
# Ticket #1140: Check for an infinite loop in the algorithm that tests
|
||||
# to see if the right-hand side of an INSERT...SELECT references the left-hand
|
||||
# side.
|
||||
#
|
||||
ifcapable subquery&&compound {
|
||||
do_test insert-8.1 {
|
||||
execsql {
|
||||
INSERT INTO t3 SELECT * FROM (SELECT * FROM t3 UNION ALL SELECT 1,2,3)
|
||||
}
|
||||
} {}
|
||||
}
|
||||
|
||||
# Make sure the rowid cache in the VDBE is reset correctly when
|
||||
# an explicit rowid is given.
|
||||
#
|
||||
do_test insert-9.1 {
|
||||
execsql {
|
||||
CREATE TABLE t5(x);
|
||||
INSERT INTO t5 VALUES(1);
|
||||
INSERT INTO t5 VALUES(2);
|
||||
INSERT INTO t5 VALUES(3);
|
||||
INSERT INTO t5(rowid, x) SELECT nullif(x*2+10,14), x+100 FROM t5;
|
||||
SELECT rowid, x FROM t5;
|
||||
}
|
||||
} {1 1 2 2 3 3 12 101 13 102 16 103}
|
||||
do_test insert-9.2 {
|
||||
execsql {
|
||||
CREATE TABLE t6(x INTEGER PRIMARY KEY, y);
|
||||
INSERT INTO t6 VALUES(1,1);
|
||||
INSERT INTO t6 VALUES(2,2);
|
||||
INSERT INTO t6 VALUES(3,3);
|
||||
INSERT INTO t6 SELECT nullif(y*2+10,14), y+100 FROM t6;
|
||||
SELECT x, y FROM t6;
|
||||
}
|
||||
} {1 1 2 2 3 3 12 101 13 102 16 103}
|
||||
|
||||
# Multiple VALUES clauses
|
||||
#
|
||||
ifcapable compound {
|
||||
do_test insert-10.1 {
|
||||
execsql {
|
||||
CREATE TABLE t10(a,b,c);
|
||||
INSERT INTO t10 VALUES(1,2,3), (4,5,6), (7,8,9);
|
||||
SELECT * FROM t10;
|
||||
}
|
||||
} {1 2 3 4 5 6 7 8 9}
|
||||
do_test insert-10.2 {
|
||||
catchsql {
|
||||
INSERT INTO t10 VALUES(11,12,13), (14,15), (16,17,28);
|
||||
}
|
||||
} {1 {all VALUES must have the same number of terms}}
|
||||
}
|
||||
|
||||
# Need for the OP_SoftNull opcode
|
||||
#
|
||||
do_execsql_test insert-11.1 {
|
||||
CREATE TABLE t11a AS SELECT '123456789' AS x;
|
||||
CREATE TABLE t11b (a INTEGER PRIMARY KEY, b, c);
|
||||
INSERT INTO t11b SELECT x, x, x FROM t11a;
|
||||
SELECT quote(a), quote(b), quote(c) FROM t11b;
|
||||
} {123456789 '123456789' '123456789'}
|
||||
|
||||
|
||||
# More columns of input than there are columns in the table.
|
||||
# Ticket http://sqlite.org/src/info/e9654505cfda9361
|
||||
#
|
||||
do_execsql_test insert-12.1 {
|
||||
CREATE TABLE t12a(a,b,c,d,e,f,g);
|
||||
INSERT INTO t12a VALUES(101,102,103,104,105,106,107);
|
||||
CREATE TABLE t12b(x);
|
||||
INSERT INTO t12b(x,rowid,x,x,x,x,x) SELECT * FROM t12a;
|
||||
SELECT rowid, x FROM t12b;
|
||||
} {102 101}
|
||||
do_execsql_test insert-12.2 {
|
||||
CREATE TABLE tab1( value INTEGER);
|
||||
INSERT INTO tab1 (value, _rowid_) values( 11, 1);
|
||||
INSERT INTO tab1 (value, _rowid_) SELECT 22,999;
|
||||
SELECT * FROM tab1;
|
||||
} {11 22}
|
||||
do_execsql_test insert-12.3 {
|
||||
CREATE TABLE t12c(a, b DEFAULT 'xyzzy', c);
|
||||
INSERT INTO t12c(a, rowid, c) SELECT 'one', 999, 'two';
|
||||
SELECT * FROM t12c;
|
||||
} {one xyzzy two}
|
||||
|
||||
# 2018-06-11. From OSSFuzz. A column cache malfunction in
|
||||
# the constraint checking on an index of expressions causes
|
||||
# an assertion fault in a REPLACE. Ticket
|
||||
# https://sqlite.org/src/info/c2432ef9089ee73b
|
||||
#
|
||||
do_execsql_test insert-13.1 {
|
||||
DROP TABLE IF EXISTS t13;
|
||||
CREATE TABLE t13(a INTEGER PRIMARY KEY,b UNIQUE);
|
||||
CREATE INDEX t13x1 ON t13(-b=b);
|
||||
INSERT INTO t13 VALUES(1,5),(6,2);
|
||||
REPLACE INTO t13 SELECT b,0 FROM t13;
|
||||
SELECT * FROM t13 ORDER BY +b;
|
||||
} {2 0 6 2 1 5}
|
||||
|
||||
# 2019-01-17. From the chromium fuzzer.
|
||||
#
|
||||
do_execsql_test insert-14.1 {
|
||||
DROP TABLE IF EXISTS t14;
|
||||
CREATE TABLE t14(x INTEGER PRIMARY KEY);
|
||||
INSERT INTO t14 VALUES(CASE WHEN 1 THEN null END);
|
||||
SELECT x FROM t14;
|
||||
} {1}
|
||||
|
||||
integrity_check insert-14.2
|
||||
|
||||
# 2019-08-12.
|
||||
#
|
||||
do_execsql_test insert-15.1 {
|
||||
DROP TABLE IF EXISTS t1;
|
||||
DROP TABLE IF EXISTS t2;
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY, b TEXT);
|
||||
CREATE INDEX i1 ON t1(b);
|
||||
CREATE TABLE t2(a, b);
|
||||
INSERT INTO t2 VALUES(4, randomblob(31000));
|
||||
INSERT INTO t2 VALUES(4, randomblob(32000));
|
||||
INSERT INTO t2 VALUES(4, randomblob(33000));
|
||||
REPLACE INTO t1 SELECT a, b FROM t2;
|
||||
SELECT a, length(b) FROM t1;
|
||||
} {4 33000}
|
||||
|
||||
# 2019-10-16
|
||||
# ticket https://sqlite.org/src/info/a8a4847a2d96f5de
|
||||
# On a REPLACE INTO, if an AFTER trigger adds back the conflicting
|
||||
# row, you can end up with the wrong number of rows in an index.
|
||||
#
|
||||
db close
|
||||
sqlite3 db :memory:
|
||||
do_catchsql_test insert-16.1 {
|
||||
PRAGMA recursive_triggers = true;
|
||||
CREATE TABLE t0(c0,c1);
|
||||
CREATE UNIQUE INDEX i0 ON t0(c0);
|
||||
INSERT INTO t0(c0,c1) VALUES(123,1);
|
||||
CREATE TRIGGER tr0 AFTER DELETE ON t0
|
||||
BEGIN
|
||||
INSERT INTO t0 VALUES(123,2);
|
||||
END;
|
||||
REPLACE INTO t0(c0,c1) VALUES(123,3);
|
||||
} {1 {UNIQUE constraint failed: t0.c0}}
|
||||
do_execsql_test insert-16.2 {
|
||||
SELECT * FROM t0;
|
||||
} {123 1}
|
||||
integrity_check insert-16.3
|
||||
do_catchsql_test insert-16.4 {
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
|
||||
CREATE INDEX t1b ON t1(b);
|
||||
INSERT INTO t1 VALUES(1, 'one');
|
||||
CREATE TRIGGER tr3 AFTER DELETE ON t1 BEGIN
|
||||
INSERT INTO t1 VALUES(1, 'three');
|
||||
END;
|
||||
REPLACE INTO t1 VALUES(1, 'two');
|
||||
} {1 {UNIQUE constraint failed: t1.a}}
|
||||
integrity_check insert-16.5
|
||||
do_catchsql_test insert-16.6 {
|
||||
PRAGMA foreign_keys = 1;
|
||||
CREATE TABLE p1(a, b UNIQUE);
|
||||
CREATE TABLE c1(c, d REFERENCES p1(b) ON DELETE CASCADE);
|
||||
CREATE TRIGGER tr6 AFTER DELETE ON c1 BEGIN
|
||||
INSERT INTO p1 VALUES(4, 1);
|
||||
END;
|
||||
INSERT INTO p1 VALUES(1, 1);
|
||||
INSERT INTO c1 VALUES(2, 1);
|
||||
REPLACE INTO p1 VALUES(3, 1);2
|
||||
} {1 {UNIQUE constraint failed: p1.b}}
|
||||
integrity_check insert-16.7
|
||||
|
||||
# 2019-10-25 ticket c1e19e12046d23fe
|
||||
do_catchsql_test insert-17.1 {
|
||||
PRAGMA temp.recursive_triggers = true;
|
||||
DROP TABLE IF EXISTS t0;
|
||||
CREATE TABLE t0(aa, bb);
|
||||
CREATE UNIQUE INDEX t0bb ON t0(bb);
|
||||
CREATE TRIGGER "r17.1" BEFORE DELETE ON t0
|
||||
BEGIN INSERT INTO t0(aa,bb) VALUES(99,1);
|
||||
END;
|
||||
INSERT INTO t0(aa,bb) VALUES(10,20);
|
||||
REPLACE INTO t0(aa,bb) VALUES(30,20);
|
||||
} {1 {UNIQUE constraint failed: t0.rowid}}
|
||||
integrity_check insert-17.2
|
||||
do_catchsql_test insert-17.3 {
|
||||
DROP TABLE IF EXISTS t1;
|
||||
CREATE TABLE t1(a, b UNIQUE, c UNIQUE);
|
||||
INSERT INTO t1(a,b,c) VALUES(1,1,1),(2,2,2),(3,3,3),(4,4,4);
|
||||
CREATE TRIGGER "r17.3" AFTER DELETE ON t1 WHEN OLD.c<>3 BEGIN
|
||||
INSERT INTO t1(rowid,a,b,c) VALUES(100,100,100,3);
|
||||
END;
|
||||
REPLACE INTO t1(rowid,a,b,c) VALUES(200,1,2,3);
|
||||
} {1 {UNIQUE constraint failed: t1.c}}
|
||||
integrity_check insert-17.4
|
||||
do_execsql_test insert-17.5 {
|
||||
CREATE TABLE t2(a INTEGER PRIMARY KEY, b);
|
||||
CREATE UNIQUE INDEX t2b ON t2(b);
|
||||
INSERT INTO t2(a,b) VALUES(1,1),(2,2),(3,3),(4,4);
|
||||
CREATE TABLE fire(x);
|
||||
CREATE TRIGGER t2r1 AFTER DELETE ON t2 BEGIN
|
||||
INSERT INTO fire VALUES(old.a);
|
||||
END;
|
||||
UPDATE OR REPLACE t2 SET a=4, b=3 WHERE a=1;
|
||||
SELECT *, 'x' FROM t2 ORDER BY a;
|
||||
} {2 2 x 4 3 x}
|
||||
do_execsql_test insert-17.6 {
|
||||
SELECT x FROM fire ORDER BY x;
|
||||
} {3 4}
|
||||
do_execsql_test insert-17.7 {
|
||||
DELETE FROM t2;
|
||||
DELETE FROM fire;
|
||||
INSERT INTO t2(a,b) VALUES(1,1),(2,2),(3,3),(4,4);
|
||||
UPDATE OR REPLACE t2 SET a=1, b=3 WHERE a=1;
|
||||
SELECT *, 'x' FROM t2 ORDER BY a;
|
||||
} {1 3 x 2 2 x 4 4 x}
|
||||
do_execsql_test insert-17.8 {
|
||||
SELECT x FROM fire ORDER BY x;
|
||||
} {3}
|
||||
do_execsql_test insert-17.10 {
|
||||
CREATE TABLE t3(a INTEGER PRIMARY KEY, b INT, c INT, d INT);
|
||||
CREATE UNIQUE INDEX t3bpi ON t3(b) WHERE c<=d;
|
||||
CREATE UNIQUE INDEX t3d ON t3(d);
|
||||
INSERT INTO t3(a,b,c,d) VALUES(1,1,1,1),(2,1,3,2),(3,4,5,6);
|
||||
CREATE TRIGGER t3r1 AFTER DELETE ON t3 BEGIN
|
||||
SELECT 'hi';
|
||||
END;
|
||||
REPLACE INTO t3(a,b,c,d) VALUES(4,4,8,9);
|
||||
} {}
|
||||
do_execsql_test insert-17.11 {
|
||||
SELECT *, 'x' FROM t3 ORDER BY a;
|
||||
} {1 1 1 1 x 2 1 3 2 x 4 4 8 9 x}
|
||||
do_execsql_test insert-17.12 {
|
||||
REPLACE INTO t3(a,b,c,d) VALUES(5,1,11,2);
|
||||
SELECT *, 'x' FROM t3 ORDER BY a;
|
||||
} {1 1 1 1 x 4 4 8 9 x 5 1 11 2 x}
|
||||
|
||||
do_execsql_test insert-17.13 {
|
||||
DELETE FROM t3;
|
||||
INSERT INTO t3(a,b,c,d) VALUES(1,1,1,1),(2,1,3,2),(3,4,5,6);
|
||||
DROP TRIGGER t3r1;
|
||||
CREATE TRIGGER t3r1 AFTER DELETE ON t3 BEGIN
|
||||
INSERT INTO t3(b,c,d) VALUES(old.b,old.c,old.d);
|
||||
END;
|
||||
} {}
|
||||
do_catchsql_test insert-17.14 {
|
||||
REPLACE INTO t3(a,b,c,d) VALUES(4,4,8,9);
|
||||
} {1 {UNIQUE constraint failed: t3.b}}
|
||||
do_catchsql_test insert-17.15 {
|
||||
REPLACE INTO t3(a,b,c,d) VALUES(5,1,11,2);
|
||||
} {1 {UNIQUE constraint failed: t3.d}}
|
||||
|
||||
|
||||
finish_test
|
||||
298
testing/sqlite3/insert2.test
Normal file
298
testing/sqlite3/insert2.test
Normal file
@@ -0,0 +1,298 @@
|
||||
# 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 the INSERT statement that takes is
|
||||
# result from a SELECT.
|
||||
#
|
||||
# $Id: insert2.test,v 1.19 2008/01/16 18:20:42 danielk1977 Exp $
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix insert2
|
||||
|
||||
# Create some tables with data that we can select against
|
||||
#
|
||||
do_test insert2-1.0 {
|
||||
execsql {CREATE TABLE d1(n int, log int);}
|
||||
for {set i 1} {$i<=20} {incr i} {
|
||||
for {set j 0} {(1<<$j)<$i} {incr j} {}
|
||||
execsql "INSERT INTO d1 VALUES($i,$j)"
|
||||
}
|
||||
execsql {SELECT * FROM d1 ORDER BY n}
|
||||
} {1 0 2 1 3 2 4 2 5 3 6 3 7 3 8 3 9 4 10 4 11 4 12 4 13 4 14 4 15 4 16 4 17 5 18 5 19 5 20 5}
|
||||
|
||||
# Insert into a new table from the old one.
|
||||
#
|
||||
do_test insert2-1.1.1 {
|
||||
execsql {
|
||||
CREATE TABLE t1(log int, cnt int);
|
||||
PRAGMA count_changes=on;
|
||||
}
|
||||
ifcapable explain {
|
||||
execsql {
|
||||
EXPLAIN INSERT INTO t1 SELECT log, count(*) FROM d1 GROUP BY log;
|
||||
}
|
||||
}
|
||||
execsql {
|
||||
INSERT INTO t1 SELECT log, count(*) FROM d1 GROUP BY log;
|
||||
}
|
||||
} {6}
|
||||
do_test insert2-1.1.2 {
|
||||
db changes
|
||||
} {6}
|
||||
do_test insert2-1.1.3 {
|
||||
execsql {SELECT * FROM t1 ORDER BY log}
|
||||
} {0 1 1 1 2 2 3 4 4 8 5 4}
|
||||
|
||||
ifcapable compound {
|
||||
do_test insert2-1.2.1 {
|
||||
catch {execsql {DROP TABLE t1}}
|
||||
execsql {
|
||||
CREATE TABLE t1(log int, cnt int);
|
||||
INSERT INTO t1
|
||||
SELECT log, count(*) FROM d1 GROUP BY log
|
||||
EXCEPT SELECT n-1,log FROM d1;
|
||||
}
|
||||
} {4}
|
||||
do_test insert2-1.2.2 {
|
||||
execsql {
|
||||
SELECT * FROM t1 ORDER BY log;
|
||||
}
|
||||
} {0 1 3 4 4 8 5 4}
|
||||
do_test insert2-1.3.1 {
|
||||
catch {execsql {DROP TABLE t1}}
|
||||
execsql {
|
||||
CREATE TABLE t1(log int, cnt int);
|
||||
PRAGMA count_changes=off;
|
||||
INSERT INTO t1
|
||||
SELECT log, count(*) FROM d1 GROUP BY log
|
||||
INTERSECT SELECT n-1,log FROM d1;
|
||||
}
|
||||
} {}
|
||||
do_test insert2-1.3.2 {
|
||||
execsql {
|
||||
SELECT * FROM t1 ORDER BY log;
|
||||
}
|
||||
} {1 1 2 2}
|
||||
} ;# ifcapable compound
|
||||
execsql {PRAGMA count_changes=off;}
|
||||
|
||||
do_test insert2-1.4 {
|
||||
catch {execsql {DROP TABLE t1}}
|
||||
set r [execsql {
|
||||
CREATE TABLE t1(log int, cnt int);
|
||||
CREATE INDEX i1 ON t1(log);
|
||||
CREATE INDEX i2 ON t1(cnt);
|
||||
INSERT INTO t1 SELECT log, count() FROM d1 GROUP BY log;
|
||||
SELECT * FROM t1 ORDER BY log;
|
||||
}]
|
||||
lappend r [execsql {SELECT cnt FROM t1 WHERE log=3}]
|
||||
lappend r [execsql {SELECT log FROM t1 WHERE cnt=4 ORDER BY log}]
|
||||
} {0 1 1 1 2 2 3 4 4 8 5 4 4 {3 5}}
|
||||
|
||||
do_test insert2-2.0 {
|
||||
execsql {
|
||||
CREATE TABLE t3(a,b,c);
|
||||
CREATE TABLE t4(x,y);
|
||||
INSERT INTO t4 VALUES(1,2);
|
||||
SELECT * FROM t4;
|
||||
}
|
||||
} {1 2}
|
||||
do_test insert2-2.1 {
|
||||
execsql {
|
||||
INSERT INTO t3(a,c) SELECT * FROM t4;
|
||||
SELECT * FROM t3;
|
||||
}
|
||||
} {1 {} 2}
|
||||
do_test insert2-2.2 {
|
||||
execsql {
|
||||
DELETE FROM t3;
|
||||
INSERT INTO t3(c,b) SELECT * FROM t4;
|
||||
SELECT * FROM t3;
|
||||
}
|
||||
} {{} 2 1}
|
||||
do_test insert2-2.3 {
|
||||
execsql {
|
||||
DELETE FROM t3;
|
||||
INSERT INTO t3(c,a,b) SELECT x, 'hi', y FROM t4;
|
||||
SELECT * FROM t3;
|
||||
}
|
||||
} {hi 2 1}
|
||||
|
||||
integrity_check insert2-3.0
|
||||
|
||||
# File table t4 with lots of data
|
||||
#
|
||||
do_test insert2-3.1 {
|
||||
execsql {
|
||||
SELECT * from t4;
|
||||
}
|
||||
} {1 2}
|
||||
do_test insert2-3.2 {
|
||||
set x [db total_changes]
|
||||
execsql {
|
||||
BEGIN;
|
||||
INSERT INTO t4 VALUES(2,4);
|
||||
INSERT INTO t4 VALUES(3,6);
|
||||
INSERT INTO t4 VALUES(4,8);
|
||||
INSERT INTO t4 VALUES(5,10);
|
||||
INSERT INTO t4 VALUES(6,12);
|
||||
INSERT INTO t4 VALUES(7,14);
|
||||
INSERT INTO t4 VALUES(8,16);
|
||||
INSERT INTO t4 VALUES(9,18);
|
||||
INSERT INTO t4 VALUES(10,20);
|
||||
COMMIT;
|
||||
}
|
||||
expr [db total_changes] - $x
|
||||
} {9}
|
||||
do_test insert2-3.2.1 {
|
||||
execsql {
|
||||
SELECT count(*) FROM t4;
|
||||
}
|
||||
} {10}
|
||||
do_test insert2-3.3 {
|
||||
ifcapable subquery {
|
||||
execsql {
|
||||
BEGIN;
|
||||
INSERT INTO t4 SELECT x+(SELECT max(x) FROM t4),y FROM t4;
|
||||
INSERT INTO t4 SELECT x+(SELECT max(x) FROM t4),y FROM t4;
|
||||
INSERT INTO t4 SELECT x+(SELECT max(x) FROM t4),y FROM t4;
|
||||
INSERT INTO t4 SELECT x+(SELECT max(x) FROM t4),y FROM t4;
|
||||
COMMIT;
|
||||
SELECT count(*) FROM t4;
|
||||
}
|
||||
} else {
|
||||
db function max_x_t4 {execsql {SELECT max(x) FROM t4}}
|
||||
execsql {
|
||||
BEGIN;
|
||||
INSERT INTO t4 SELECT x+max_x_t4() ,y FROM t4;
|
||||
INSERT INTO t4 SELECT x+max_x_t4() ,y FROM t4;
|
||||
INSERT INTO t4 SELECT x+max_x_t4() ,y FROM t4;
|
||||
INSERT INTO t4 SELECT x+max_x_t4() ,y FROM t4;
|
||||
COMMIT;
|
||||
SELECT count(*) FROM t4;
|
||||
}
|
||||
}
|
||||
} {160}
|
||||
do_test insert2-3.4 {
|
||||
execsql {
|
||||
BEGIN;
|
||||
UPDATE t4 SET y='lots of data for the row where x=' || x
|
||||
|| ' and y=' || y || ' - even more data to fill space';
|
||||
COMMIT;
|
||||
SELECT count(*) FROM t4;
|
||||
}
|
||||
} {160}
|
||||
do_test insert2-3.5 {
|
||||
ifcapable subquery {
|
||||
execsql {
|
||||
BEGIN;
|
||||
INSERT INTO t4 SELECT x+(SELECT max(x)+1 FROM t4),y FROM t4;
|
||||
SELECT count(*) from t4;
|
||||
ROLLBACK;
|
||||
}
|
||||
} else {
|
||||
execsql {
|
||||
BEGIN;
|
||||
INSERT INTO t4 SELECT x+max_x_t4()+1,y FROM t4;
|
||||
SELECT count(*) from t4;
|
||||
ROLLBACK;
|
||||
}
|
||||
}
|
||||
} {320}
|
||||
do_test insert2-3.6 {
|
||||
execsql {
|
||||
SELECT count(*) FROM t4;
|
||||
}
|
||||
} {160}
|
||||
do_test insert2-3.7 {
|
||||
execsql {
|
||||
BEGIN;
|
||||
DELETE FROM t4 WHERE x!=123;
|
||||
SELECT count(*) FROM t4;
|
||||
ROLLBACK;
|
||||
}
|
||||
} {1}
|
||||
do_test insert2-3.8 {
|
||||
db changes
|
||||
} {159}
|
||||
integrity_check insert2-3.9
|
||||
|
||||
# Ticket #901
|
||||
#
|
||||
ifcapable tempdb {
|
||||
do_test insert2-4.1 {
|
||||
execsql {
|
||||
CREATE TABLE Dependencies(depId integer primary key,
|
||||
class integer, name str, flag str);
|
||||
CREATE TEMPORARY TABLE DepCheck(troveId INT, depNum INT,
|
||||
flagCount INT, isProvides BOOL, class INTEGER, name STRING,
|
||||
flag STRING);
|
||||
INSERT INTO DepCheck
|
||||
VALUES(-1, 0, 1, 0, 2, 'libc.so.6', 'GLIBC_2.0');
|
||||
INSERT INTO Dependencies
|
||||
SELECT DISTINCT
|
||||
NULL,
|
||||
DepCheck.class,
|
||||
DepCheck.name,
|
||||
DepCheck.flag
|
||||
FROM DepCheck LEFT OUTER JOIN Dependencies ON
|
||||
DepCheck.class == Dependencies.class AND
|
||||
DepCheck.name == Dependencies.name AND
|
||||
DepCheck.flag == Dependencies.flag
|
||||
WHERE
|
||||
Dependencies.depId is NULL;
|
||||
};
|
||||
} {}
|
||||
}
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# 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}
|
||||
ifcapable subquery {
|
||||
do_test insert2-5.2 {
|
||||
execsql {
|
||||
INSERT INTO t2 SELECT (SELECT a FROM t2), 4;
|
||||
SELECT * FROM t2;
|
||||
}
|
||||
} {1 2 1 3 1 4}
|
||||
}
|
||||
|
||||
do_execsql_test 6.0 {
|
||||
CREATE TABLE t5(a, b, c DEFAULT 'c', d);
|
||||
}
|
||||
do_execsql_test 6.1 {
|
||||
INSERT INTO t5(a) SELECT 456 UNION ALL SELECT 123 ORDER BY 1;
|
||||
SELECT * FROM t5 ORDER BY rowid;
|
||||
} {123 {} c {} 456 {} c {}}
|
||||
|
||||
ifcapable fts3 {
|
||||
do_execsql_test 6.2 {
|
||||
CREATE VIRTUAL TABLE t0 USING fts4(a);
|
||||
}
|
||||
do_execsql_test 6.3 {
|
||||
INSERT INTO t0 SELECT 0 UNION SELECT 0 AS 'x' ORDER BY x;
|
||||
SELECT * FROM t0;
|
||||
} {0}
|
||||
}
|
||||
|
||||
|
||||
finish_test
|
||||
205
testing/sqlite3/insert3.test
Normal file
205
testing/sqlite3/insert3.test
Normal file
@@ -0,0 +1,205 @@
|
||||
# 2005 January 13
|
||||
#
|
||||
# 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 corner cases of the INSERT statement.
|
||||
#
|
||||
# $Id: insert3.test,v 1.9 2009/04/23 14:58:40 danielk1977 Exp $
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
|
||||
# All the tests in this file require trigger support
|
||||
#
|
||||
ifcapable {trigger} {
|
||||
|
||||
# Create a table and a corresponding insert trigger. Do a self-insert
|
||||
# into the table.
|
||||
#
|
||||
do_test insert3-1.0 {
|
||||
execsql {
|
||||
CREATE TABLE t1(a,b);
|
||||
CREATE TABLE log(x UNIQUE, y);
|
||||
CREATE TRIGGER r1 AFTER INSERT ON t1 BEGIN
|
||||
UPDATE log SET y=y+1 WHERE x=new.a;
|
||||
INSERT OR IGNORE INTO log VALUES(new.a, 1);
|
||||
END;
|
||||
INSERT INTO t1 VALUES('hello','world');
|
||||
INSERT INTO t1 VALUES(5,10);
|
||||
SELECT * FROM log ORDER BY x;
|
||||
}
|
||||
} {5 1 hello 1}
|
||||
do_test insert3-1.1 {
|
||||
execsql {
|
||||
INSERT INTO t1 SELECT a, b+10 FROM t1;
|
||||
SELECT * FROM log ORDER BY x;
|
||||
}
|
||||
} {5 2 hello 2}
|
||||
do_test insert3-1.2 {
|
||||
execsql {
|
||||
CREATE TABLE log2(x PRIMARY KEY,y);
|
||||
CREATE TRIGGER r2 BEFORE INSERT ON t1 BEGIN
|
||||
UPDATE log2 SET y=y+1 WHERE x=new.b;
|
||||
INSERT OR IGNORE INTO log2 VALUES(new.b,1);
|
||||
END;
|
||||
INSERT INTO t1 VALUES(453,'hi');
|
||||
SELECT * FROM log ORDER BY x;
|
||||
}
|
||||
} {5 2 453 1 hello 2}
|
||||
do_test insert3-1.3 {
|
||||
execsql {
|
||||
SELECT * FROM log2 ORDER BY x;
|
||||
}
|
||||
} {hi 1}
|
||||
ifcapable compound {
|
||||
do_test insert3-1.4.1 {
|
||||
execsql {
|
||||
INSERT INTO t1 SELECT * FROM t1;
|
||||
SELECT 'a:', x, y FROM log UNION ALL
|
||||
SELECT 'b:', x, y FROM log2 ORDER BY x;
|
||||
}
|
||||
} {a: 5 4 b: 10 2 b: 20 1 a: 453 2 a: hello 4 b: hi 2 b: world 1}
|
||||
do_test insert3-1.4.2 {
|
||||
execsql {
|
||||
SELECT 'a:', x, y FROM log UNION ALL
|
||||
SELECT 'b:', x, y FROM log2 ORDER BY x, y;
|
||||
}
|
||||
} {a: 5 4 b: 10 2 b: 20 1 a: 453 2 a: hello 4 b: hi 2 b: world 1}
|
||||
do_test insert3-1.5 {
|
||||
execsql {
|
||||
INSERT INTO t1(a) VALUES('xyz');
|
||||
SELECT * FROM log ORDER BY x;
|
||||
}
|
||||
} {5 4 453 2 hello 4 xyz 1}
|
||||
}
|
||||
|
||||
do_test insert3-2.1 {
|
||||
execsql {
|
||||
CREATE TABLE t2(
|
||||
a INTEGER PRIMARY KEY,
|
||||
b DEFAULT 'b',
|
||||
c DEFAULT 'c'
|
||||
);
|
||||
CREATE TABLE t2dup(a,b,c);
|
||||
CREATE TRIGGER t2r1 BEFORE INSERT ON t2 BEGIN
|
||||
INSERT INTO t2dup(a,b,c) VALUES(new.a,new.b,new.c);
|
||||
END;
|
||||
INSERT INTO t2(a) VALUES(123);
|
||||
INSERT INTO t2(b) VALUES(234);
|
||||
INSERT INTO t2(c) VALUES(345);
|
||||
SELECT * FROM t2dup;
|
||||
}
|
||||
} {123 b c -1 234 c -1 b 345}
|
||||
do_test insert3-2.2 {
|
||||
execsql {
|
||||
DELETE FROM t2dup;
|
||||
INSERT INTO t2(a) SELECT 1 FROM t1 LIMIT 1;
|
||||
INSERT INTO t2(b) SELECT 987 FROM t1 LIMIT 1;
|
||||
INSERT INTO t2(c) SELECT 876 FROM t1 LIMIT 1;
|
||||
SELECT * FROM t2dup;
|
||||
}
|
||||
} {1 b c -1 987 c -1 b 876}
|
||||
|
||||
# Test for proper detection of malformed WHEN clauses on INSERT triggers.
|
||||
#
|
||||
do_test insert3-3.1 {
|
||||
execsql {
|
||||
CREATE TABLE t3(a,b,c);
|
||||
CREATE TRIGGER t3r1 BEFORE INSERT on t3 WHEN nosuchcol BEGIN
|
||||
SELECT 'illegal WHEN clause';
|
||||
END;
|
||||
}
|
||||
} {}
|
||||
do_test insert3-3.2 {
|
||||
catchsql {
|
||||
INSERT INTO t3 VALUES(1,2,3)
|
||||
}
|
||||
} {1 {no such column: nosuchcol}}
|
||||
do_test insert3-3.3 {
|
||||
execsql {
|
||||
CREATE TABLE t4(a,b,c);
|
||||
CREATE TRIGGER t4r1 AFTER INSERT on t4 WHEN nosuchcol BEGIN
|
||||
SELECT 'illegal WHEN clause';
|
||||
END;
|
||||
}
|
||||
} {}
|
||||
do_test insert3-3.4 {
|
||||
catchsql {
|
||||
INSERT INTO t4 VALUES(1,2,3)
|
||||
}
|
||||
} {1 {no such column: nosuchcol}}
|
||||
|
||||
} ;# ifcapable {trigger}
|
||||
|
||||
# Tests for the INSERT INTO ... DEFAULT VALUES construct
|
||||
#
|
||||
do_test insert3-3.5 {
|
||||
execsql {
|
||||
CREATE TABLE t5(
|
||||
a INTEGER PRIMARY KEY,
|
||||
b DEFAULT 'xyz'
|
||||
);
|
||||
INSERT INTO t5 DEFAULT VALUES;
|
||||
SELECT * FROM t5;
|
||||
}
|
||||
} {1 xyz}
|
||||
do_test insert3-3.6 {
|
||||
execsql {
|
||||
INSERT INTO t5 DEFAULT VALUES;
|
||||
SELECT * FROM t5;
|
||||
}
|
||||
} {1 xyz 2 xyz}
|
||||
|
||||
ifcapable bloblit {
|
||||
do_test insert3-3.7 {
|
||||
execsql {
|
||||
CREATE TABLE t6(x,y DEFAULT 4.3, z DEFAULT x'6869');
|
||||
INSERT INTO t6 DEFAULT VALUES;
|
||||
SELECT * FROM t6;
|
||||
}
|
||||
} {{} 4.3 hi}
|
||||
}
|
||||
|
||||
foreach tab [db eval {SELECT name FROM sqlite_master WHERE type = 'table'}] {
|
||||
db eval "DROP TABLE $tab"
|
||||
}
|
||||
db close
|
||||
sqlite3 db test.db
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# While developing tests for a different feature (savepoint) the following
|
||||
# sequence was found to cause an assert() in btree.c to fail. These
|
||||
# tests are included to ensure that that bug is fixed.
|
||||
#
|
||||
do_test insert3-4.1 {
|
||||
execsql {
|
||||
CREATE TABLE t1(a, b, c);
|
||||
CREATE INDEX i1 ON t1(a, b);
|
||||
BEGIN;
|
||||
INSERT INTO t1 VALUES(randstr(10,400),randstr(10,400),randstr(10,400));
|
||||
}
|
||||
set r "randstr(10,400)"
|
||||
for {set ii 0} {$ii < 10} {incr ii} {
|
||||
execsql "INSERT INTO t1 SELECT $r, $r, $r FROM t1"
|
||||
}
|
||||
execsql { COMMIT }
|
||||
} {}
|
||||
do_test insert3-4.2 {
|
||||
execsql {
|
||||
PRAGMA cache_size = 10;
|
||||
BEGIN;
|
||||
UPDATE t1 SET a = randstr(10,10) WHERE (rowid%4)==0;
|
||||
DELETE FROM t1 WHERE rowid%2;
|
||||
INSERT INTO t1 SELECT randstr(10,400), randstr(10,400), c FROM t1;
|
||||
COMMIT;
|
||||
}
|
||||
} {}
|
||||
|
||||
finish_test
|
||||
628
testing/sqlite3/insert4.test
Normal file
628
testing/sqlite3/insert4.test
Normal file
@@ -0,0 +1,628 @@
|
||||
# 2007 January 24
|
||||
#
|
||||
# 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 the INSERT transfer optimization.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix insert4
|
||||
|
||||
ifcapable !view||!subquery {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
# The sqlite3_xferopt_count variable is incremented whenever the
|
||||
# insert transfer optimization applies.
|
||||
#
|
||||
# This procedure runs a test to see if the sqlite3_xferopt_count is
|
||||
# set to N.
|
||||
#
|
||||
proc xferopt_test {testname N} {
|
||||
do_test $testname {set ::sqlite3_xferopt_count} $N
|
||||
}
|
||||
|
||||
# Create tables used for testing.
|
||||
#
|
||||
sqlite3_db_config db LEGACY_FILE_FORMAT 0
|
||||
execsql {
|
||||
CREATE TABLE t1(a int, b int, check(b>a));
|
||||
CREATE TABLE t2(x int, y int);
|
||||
CREATE VIEW v2 AS SELECT y, x FROM t2;
|
||||
CREATE TABLE t3(a int, b int);
|
||||
}
|
||||
|
||||
# Ticket #2252. Make sure the an INSERT from identical tables
|
||||
# does not violate constraints.
|
||||
#
|
||||
do_test insert4-1.1 {
|
||||
set sqlite3_xferopt_count 0
|
||||
execsql {
|
||||
DELETE FROM t1;
|
||||
DELETE FROM t2;
|
||||
INSERT INTO t2 VALUES(9,1);
|
||||
}
|
||||
catchsql {
|
||||
INSERT INTO t1 SELECT * FROM t2;
|
||||
}
|
||||
} {1 {CHECK constraint failed: b>a}}
|
||||
xferopt_test insert4-1.2 0
|
||||
do_test insert4-1.3 {
|
||||
execsql {
|
||||
SELECT * FROM t1;
|
||||
}
|
||||
} {}
|
||||
|
||||
# Tests to make sure that the transfer optimization is not occurring
|
||||
# when it is not a valid optimization.
|
||||
#
|
||||
# The SELECT must be against a real table.
|
||||
do_test insert4-2.1.1 {
|
||||
execsql {
|
||||
DELETE FROM t1;
|
||||
INSERT INTO t1 SELECT 4, 8;
|
||||
SELECT * FROM t1;
|
||||
}
|
||||
} {4 8}
|
||||
xferopt_test insert4-2.1.2 0
|
||||
do_test insert4-2.2.1 {
|
||||
catchsql {
|
||||
DELETE FROM t1;
|
||||
INSERT INTO t1 SELECT * FROM v2;
|
||||
SELECT * FROM t1;
|
||||
}
|
||||
} {0 {1 9}}
|
||||
xferopt_test insert4-2.2.2 0
|
||||
|
||||
# Do not run the transfer optimization if there is a LIMIT clause
|
||||
#
|
||||
do_test insert4-2.3.1 {
|
||||
execsql {
|
||||
DELETE FROM t2;
|
||||
INSERT INTO t2 VALUES(9,1);
|
||||
INSERT INTO t2 SELECT y, x FROM t2;
|
||||
INSERT INTO t3 SELECT * FROM t2 LIMIT 1;
|
||||
SELECT * FROM t3;
|
||||
}
|
||||
} {9 1}
|
||||
xferopt_test insert4-2.3.2 0
|
||||
do_test insert4-2.3.3 {
|
||||
catchsql {
|
||||
DELETE FROM t1;
|
||||
INSERT INTO t1 SELECT * FROM t2 LIMIT 1;
|
||||
SELECT * FROM t1;
|
||||
}
|
||||
} {1 {CHECK constraint failed: b>a}}
|
||||
xferopt_test insert4-2.3.4 0
|
||||
|
||||
# Do not run the transfer optimization if there is a DISTINCT
|
||||
#
|
||||
do_test insert4-2.4.1 {
|
||||
execsql {
|
||||
DELETE FROM t3;
|
||||
INSERT INTO t3 SELECT DISTINCT * FROM t2;
|
||||
SELECT * FROM t3;
|
||||
}
|
||||
} {9 1 1 9}
|
||||
xferopt_test insert4-2.4.2 0
|
||||
do_test insert4-2.4.3 {
|
||||
catchsql {
|
||||
DELETE FROM t1;
|
||||
INSERT INTO t1 SELECT DISTINCT * FROM t2;
|
||||
}
|
||||
} {1 {CHECK constraint failed: b>a}}
|
||||
xferopt_test insert4-2.4.4 0
|
||||
|
||||
# The following procedure constructs two tables then tries to transfer
|
||||
# data from one table to the other. Checks are made to make sure the
|
||||
# transfer is successful and that the transfer optimization was used or
|
||||
# not, as appropriate.
|
||||
#
|
||||
# xfer_check TESTID XFER-USED INIT-DATA DEST-SCHEMA SRC-SCHEMA
|
||||
#
|
||||
# The TESTID argument is the symbolic name for this test. The XFER-USED
|
||||
# argument is true if the transfer optimization should be employed and
|
||||
# false if not. INIT-DATA is a single row of data that is to be
|
||||
# transfered. DEST-SCHEMA and SRC-SCHEMA are table declarations for
|
||||
# the destination and source tables.
|
||||
#
|
||||
proc xfer_check {testid xferused initdata destschema srcschema} {
|
||||
execsql "CREATE TABLE dest($destschema)"
|
||||
execsql "CREATE TABLE src($srcschema)"
|
||||
execsql "INSERT INTO src VALUES([join $initdata ,])"
|
||||
set ::sqlite3_xferopt_count 0
|
||||
do_test $testid.1 {
|
||||
execsql {
|
||||
INSERT INTO dest SELECT * FROM src;
|
||||
SELECT * FROM dest;
|
||||
}
|
||||
} $initdata
|
||||
do_test $testid.2 {
|
||||
set ::sqlite3_xferopt_count
|
||||
} $xferused
|
||||
execsql {
|
||||
DROP TABLE dest;
|
||||
DROP TABLE src;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# Do run the transfer optimization if tables have identical
|
||||
# CHECK constraints.
|
||||
#
|
||||
xfer_check insert4-3.1 1 {1 9} \
|
||||
{a int, b int CHECK(b>a)} \
|
||||
{x int, y int CHECK(y>x)}
|
||||
xfer_check insert4-3.2 1 {1 9} \
|
||||
{a int, b int CHECK(b>a)} \
|
||||
{x int CHECK(y>x), y int}
|
||||
|
||||
# Do run the transfer optimization if the destination table lacks
|
||||
# any CHECK constraints regardless of whether or not there are CHECK
|
||||
# constraints on the source table.
|
||||
#
|
||||
xfer_check insert4-3.3 1 {1 9} \
|
||||
{a int, b int} \
|
||||
{x int, y int CHECK(y>x)}
|
||||
|
||||
# Do run the transfer optimization if the destination table omits
|
||||
# NOT NULL constraints that the source table has.
|
||||
#
|
||||
xfer_check insert4-3.4 0 {1 9} \
|
||||
{a int, b int CHECK(b>a)} \
|
||||
{x int, y int}
|
||||
|
||||
# Do not run the optimization if the destination has NOT NULL
|
||||
# constraints that the source table lacks.
|
||||
#
|
||||
xfer_check insert4-3.5 0 {1 9} \
|
||||
{a int, b int NOT NULL} \
|
||||
{x int, y int}
|
||||
xfer_check insert4-3.6 0 {1 9} \
|
||||
{a int, b int NOT NULL} \
|
||||
{x int NOT NULL, y int}
|
||||
xfer_check insert4-3.7 0 {1 9} \
|
||||
{a int NOT NULL, b int NOT NULL} \
|
||||
{x int NOT NULL, y int}
|
||||
xfer_check insert4-3.8 0 {1 9} \
|
||||
{a int NOT NULL, b int} \
|
||||
{x int, y int}
|
||||
|
||||
|
||||
# Do run the transfer optimization if the destination table and
|
||||
# source table have the same NOT NULL constraints or if the
|
||||
# source table has extra NOT NULL constraints.
|
||||
#
|
||||
xfer_check insert4-3.9 1 {1 9} \
|
||||
{a int, b int} \
|
||||
{x int NOT NULL, y int}
|
||||
xfer_check insert4-3.10 1 {1 9} \
|
||||
{a int, b int} \
|
||||
{x int NOT NULL, y int NOT NULL}
|
||||
xfer_check insert4-3.11 1 {1 9} \
|
||||
{a int NOT NULL, b int} \
|
||||
{x int NOT NULL, y int NOT NULL}
|
||||
xfer_check insert4-3.12 1 {1 9} \
|
||||
{a int, b int NOT NULL} \
|
||||
{x int NOT NULL, y int NOT NULL}
|
||||
|
||||
# Do not run the optimization if any corresponding table
|
||||
# columns have different affinities.
|
||||
#
|
||||
xfer_check insert4-3.20 0 {1 9} \
|
||||
{a text, b int} \
|
||||
{x int, b int}
|
||||
xfer_check insert4-3.21 0 {1 9} \
|
||||
{a int, b int} \
|
||||
{x text, b int}
|
||||
|
||||
# "int" and "integer" are equivalent so the optimization should
|
||||
# run here.
|
||||
#
|
||||
xfer_check insert4-3.22 1 {1 9} \
|
||||
{a int, b int} \
|
||||
{x integer, b int}
|
||||
|
||||
# Ticket #2291.
|
||||
#
|
||||
|
||||
do_test insert4-4.1a {
|
||||
execsql {CREATE TABLE t4(a, b, UNIQUE(a,b))}
|
||||
} {}
|
||||
ifcapable vacuum {
|
||||
do_test insert4-4.1b {
|
||||
execsql {
|
||||
INSERT INTO t4 VALUES(NULL,0);
|
||||
INSERT INTO t4 VALUES(NULL,1);
|
||||
INSERT INTO t4 VALUES(NULL,1);
|
||||
VACUUM;
|
||||
}
|
||||
} {}
|
||||
}
|
||||
|
||||
# Check some error conditions:
|
||||
#
|
||||
do_test insert4-5.1 {
|
||||
# Table does not exist.
|
||||
catchsql { INSERT INTO t2 SELECT a, b FROM nosuchtable }
|
||||
} {1 {no such table: nosuchtable}}
|
||||
do_test insert4-5.2 {
|
||||
# Number of columns does not match.
|
||||
catchsql {
|
||||
CREATE TABLE t5(a, b, c);
|
||||
INSERT INTO t4 SELECT * FROM t5;
|
||||
}
|
||||
} {1 {table t4 has 2 columns but 3 values were supplied}}
|
||||
|
||||
do_test insert4-6.1 {
|
||||
set ::sqlite3_xferopt_count 0
|
||||
execsql {
|
||||
CREATE INDEX t2_i2 ON t2(x, y COLLATE nocase);
|
||||
CREATE INDEX t2_i1 ON t2(x ASC, y DESC);
|
||||
CREATE INDEX t3_i1 ON t3(a, b);
|
||||
INSERT INTO t2 SELECT * FROM t3;
|
||||
}
|
||||
set ::sqlite3_xferopt_count
|
||||
} {0}
|
||||
do_test insert4-6.2 {
|
||||
set ::sqlite3_xferopt_count 0
|
||||
execsql {
|
||||
DROP INDEX t2_i2;
|
||||
INSERT INTO t2 SELECT * FROM t3;
|
||||
}
|
||||
set ::sqlite3_xferopt_count
|
||||
} {0}
|
||||
do_test insert4-6.3 {
|
||||
set ::sqlite3_xferopt_count 0
|
||||
execsql {
|
||||
DROP INDEX t2_i1;
|
||||
CREATE INDEX t2_i1 ON t2(x ASC, y ASC);
|
||||
INSERT INTO t2 SELECT * FROM t3;
|
||||
}
|
||||
set ::sqlite3_xferopt_count
|
||||
} {1}
|
||||
do_test insert4-6.4 {
|
||||
set ::sqlite3_xferopt_count 0
|
||||
execsql {
|
||||
DROP INDEX t2_i1;
|
||||
CREATE INDEX t2_i1 ON t2(x ASC, y COLLATE RTRIM);
|
||||
INSERT INTO t2 SELECT * FROM t3;
|
||||
}
|
||||
set ::sqlite3_xferopt_count
|
||||
} {0}
|
||||
|
||||
|
||||
do_test insert4-6.5 {
|
||||
execsql {
|
||||
CREATE TABLE t6a(x CHECK( x<>'abc' ));
|
||||
INSERT INTO t6a VALUES('ABC');
|
||||
SELECT * FROM t6a;
|
||||
}
|
||||
} {ABC}
|
||||
do_test insert4-6.6 {
|
||||
execsql {
|
||||
CREATE TABLE t6b(x CHECK( x<>'abc' COLLATE nocase ));
|
||||
}
|
||||
catchsql {
|
||||
INSERT INTO t6b SELECT * FROM t6a;
|
||||
}
|
||||
} {1 {CHECK constraint failed: x<>'abc' COLLATE nocase}}
|
||||
do_test insert4-6.7 {
|
||||
execsql {
|
||||
DROP TABLE t6b;
|
||||
CREATE TABLE t6b(x CHECK( x COLLATE nocase <>'abc' ));
|
||||
}
|
||||
catchsql {
|
||||
INSERT INTO t6b SELECT * FROM t6a;
|
||||
}
|
||||
} {1 {CHECK constraint failed: x COLLATE nocase <>'abc'}}
|
||||
|
||||
# Ticket [6284df89debdfa61db8073e062908af0c9b6118e]
|
||||
# Disable the xfer optimization if the destination table contains
|
||||
# a foreign key constraint
|
||||
#
|
||||
ifcapable foreignkey {
|
||||
do_test insert4-7.1 {
|
||||
set ::sqlite3_xferopt_count 0
|
||||
execsql {
|
||||
CREATE TABLE t7a(x INTEGER PRIMARY KEY); INSERT INTO t7a VALUES(123);
|
||||
CREATE TABLE t7b(y INTEGER REFERENCES t7a);
|
||||
CREATE TABLE t7c(z INT); INSERT INTO t7c VALUES(234);
|
||||
INSERT INTO t7b SELECT * FROM t7c;
|
||||
SELECT * FROM t7b;
|
||||
}
|
||||
} {234}
|
||||
do_test insert4-7.2 {
|
||||
set ::sqlite3_xferopt_count
|
||||
} {1}
|
||||
do_test insert4-7.3 {
|
||||
set ::sqlite3_xferopt_count 0
|
||||
execsql {
|
||||
DELETE FROM t7b;
|
||||
PRAGMA foreign_keys=ON;
|
||||
}
|
||||
catchsql {
|
||||
INSERT INTO t7b SELECT * FROM t7c;
|
||||
}
|
||||
} {1 {FOREIGN KEY constraint failed}}
|
||||
do_test insert4-7.4 {
|
||||
execsql {SELECT * FROM t7b}
|
||||
} {}
|
||||
do_test insert4-7.5 {
|
||||
set ::sqlite3_xferopt_count
|
||||
} {0}
|
||||
do_test insert4-7.6 {
|
||||
set ::sqlite3_xferopt_count 0
|
||||
execsql {
|
||||
DELETE FROM t7b; DELETE FROM t7c;
|
||||
INSERT INTO t7c VALUES(123);
|
||||
INSERT INTO t7b SELECT * FROM t7c;
|
||||
SELECT * FROM t7b;
|
||||
}
|
||||
} {123}
|
||||
do_test insert4-7.7 {
|
||||
set ::sqlite3_xferopt_count
|
||||
} {0}
|
||||
do_test insert4-7.7 {
|
||||
set ::sqlite3_xferopt_count 0
|
||||
execsql {
|
||||
PRAGMA foreign_keys=OFF;
|
||||
DELETE FROM t7b;
|
||||
INSERT INTO t7b SELECT * FROM t7c;
|
||||
SELECT * FROM t7b;
|
||||
}
|
||||
} {123}
|
||||
do_test insert4-7.8 {
|
||||
set ::sqlite3_xferopt_count
|
||||
} {1}
|
||||
}
|
||||
|
||||
# Ticket [676bc02b87176125635cb174d110b431581912bb]
|
||||
# Make sure INTEGER PRIMARY KEY ON CONFLICT ... works with the xfer
|
||||
# optimization.
|
||||
#
|
||||
do_test insert4-8.1 {
|
||||
execsql {
|
||||
DROP TABLE IF EXISTS t1;
|
||||
DROP TABLE IF EXISTS t2;
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY ON CONFLICT REPLACE, b);
|
||||
CREATE TABLE t2(x INTEGER PRIMARY KEY ON CONFLICT REPLACE, y);
|
||||
INSERT INTO t1 VALUES(1,2);
|
||||
INSERT INTO t2 VALUES(1,3);
|
||||
INSERT INTO t1 SELECT * FROM t2;
|
||||
SELECT * FROM t1;
|
||||
}
|
||||
} {1 3}
|
||||
do_test insert4-8.2 {
|
||||
execsql {
|
||||
DROP TABLE IF EXISTS t1;
|
||||
DROP TABLE IF EXISTS t2;
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY ON CONFLICT REPLACE, b);
|
||||
CREATE TABLE t2(x, y);
|
||||
INSERT INTO t1 VALUES(1,2);
|
||||
INSERT INTO t2 VALUES(1,3);
|
||||
INSERT INTO t1 SELECT * FROM t2;
|
||||
SELECT * FROM t1;
|
||||
}
|
||||
} {1 3}
|
||||
do_test insert4-8.3 {
|
||||
execsql {
|
||||
DROP TABLE IF EXISTS t1;
|
||||
DROP TABLE IF EXISTS t2;
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY ON CONFLICT IGNORE, b);
|
||||
CREATE TABLE t2(x INTEGER PRIMARY KEY ON CONFLICT IGNORE, y);
|
||||
INSERT INTO t1 VALUES(1,2);
|
||||
INSERT INTO t2 VALUES(1,3);
|
||||
INSERT INTO t1 SELECT * FROM t2;
|
||||
SELECT * FROM t1;
|
||||
}
|
||||
} {1 2}
|
||||
do_test insert4-8.4 {
|
||||
execsql {
|
||||
DROP TABLE IF EXISTS t1;
|
||||
DROP TABLE IF EXISTS t2;
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY ON CONFLICT IGNORE, b);
|
||||
CREATE TABLE t2(x, y);
|
||||
INSERT INTO t1 VALUES(1,2);
|
||||
INSERT INTO t2 VALUES(1,3);
|
||||
INSERT INTO t1 SELECT * FROM t2;
|
||||
SELECT * FROM t1;
|
||||
}
|
||||
} {1 2}
|
||||
do_test insert4-8.5 {
|
||||
execsql {
|
||||
DROP TABLE IF EXISTS t1;
|
||||
DROP TABLE IF EXISTS t2;
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY ON CONFLICT FAIL, b);
|
||||
CREATE TABLE t2(x INTEGER PRIMARY KEY ON CONFLICT FAIL, y);
|
||||
INSERT INTO t1 VALUES(1,2);
|
||||
INSERT INTO t2 VALUES(-99,100);
|
||||
INSERT INTO t2 VALUES(1,3);
|
||||
SELECT * FROM t1;
|
||||
}
|
||||
catchsql {
|
||||
INSERT INTO t1 SELECT * FROM t2;
|
||||
}
|
||||
} {1 {UNIQUE constraint failed: t1.a}}
|
||||
do_test insert4-8.6 {
|
||||
execsql {
|
||||
SELECT * FROM t1;
|
||||
}
|
||||
} {-99 100 1 2}
|
||||
do_test insert4-8.7 {
|
||||
execsql {
|
||||
DROP TABLE IF EXISTS t1;
|
||||
DROP TABLE IF EXISTS t2;
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY ON CONFLICT ABORT, b);
|
||||
CREATE TABLE t2(x INTEGER PRIMARY KEY ON CONFLICT ABORT, y);
|
||||
INSERT INTO t1 VALUES(1,2);
|
||||
INSERT INTO t2 VALUES(-99,100);
|
||||
INSERT INTO t2 VALUES(1,3);
|
||||
SELECT * FROM t1;
|
||||
}
|
||||
catchsql {
|
||||
INSERT INTO t1 SELECT * FROM t2;
|
||||
}
|
||||
} {1 {UNIQUE constraint failed: t1.a}}
|
||||
do_test insert4-8.8 {
|
||||
execsql {
|
||||
SELECT * FROM t1;
|
||||
}
|
||||
} {1 2}
|
||||
do_test insert4-8.9 {
|
||||
execsql {
|
||||
DROP TABLE IF EXISTS t1;
|
||||
DROP TABLE IF EXISTS t2;
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY ON CONFLICT ROLLBACK, b);
|
||||
CREATE TABLE t2(x INTEGER PRIMARY KEY ON CONFLICT ROLLBACK, y);
|
||||
INSERT INTO t1 VALUES(1,2);
|
||||
INSERT INTO t2 VALUES(-99,100);
|
||||
INSERT INTO t2 VALUES(1,3);
|
||||
SELECT * FROM t1;
|
||||
}
|
||||
catchsql {
|
||||
BEGIN;
|
||||
INSERT INTO t1 VALUES(2,3);
|
||||
INSERT INTO t1 SELECT * FROM t2;
|
||||
}
|
||||
} {1 {UNIQUE constraint failed: t1.a}}
|
||||
do_test insert4-8.10 {
|
||||
catchsql {COMMIT}
|
||||
} {1 {cannot commit - no transaction is active}}
|
||||
do_test insert4-8.11 {
|
||||
execsql {
|
||||
SELECT * FROM t1;
|
||||
}
|
||||
} {1 2}
|
||||
|
||||
do_test insert4-8.21 {
|
||||
execsql {
|
||||
DROP TABLE IF EXISTS t1;
|
||||
DROP TABLE IF EXISTS t2;
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY ON CONFLICT REPLACE, b);
|
||||
CREATE TABLE t2(x INTEGER PRIMARY KEY ON CONFLICT REPLACE, y);
|
||||
INSERT INTO t2 VALUES(1,3);
|
||||
INSERT INTO t1 SELECT * FROM t2;
|
||||
SELECT * FROM t1;
|
||||
}
|
||||
} {1 3}
|
||||
do_test insert4-8.22 {
|
||||
execsql {
|
||||
DROP TABLE IF EXISTS t1;
|
||||
DROP TABLE IF EXISTS t2;
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY ON CONFLICT IGNORE, b);
|
||||
CREATE TABLE t2(x INTEGER PRIMARY KEY ON CONFLICT IGNORE, y);
|
||||
INSERT INTO t2 VALUES(1,3);
|
||||
INSERT INTO t1 SELECT * FROM t2;
|
||||
SELECT * FROM t1;
|
||||
}
|
||||
} {1 3}
|
||||
do_test insert4-8.23 {
|
||||
execsql {
|
||||
DROP TABLE IF EXISTS t1;
|
||||
DROP TABLE IF EXISTS t2;
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY ON CONFLICT ABORT, b);
|
||||
CREATE TABLE t2(x INTEGER PRIMARY KEY ON CONFLICT ABORT, y);
|
||||
INSERT INTO t2 VALUES(1,3);
|
||||
INSERT INTO t1 SELECT * FROM t2;
|
||||
SELECT * FROM t1;
|
||||
}
|
||||
} {1 3}
|
||||
do_test insert4-8.24 {
|
||||
execsql {
|
||||
DROP TABLE IF EXISTS t1;
|
||||
DROP TABLE IF EXISTS t2;
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY ON CONFLICT FAIL, b);
|
||||
CREATE TABLE t2(x INTEGER PRIMARY KEY ON CONFLICT FAIL, y);
|
||||
INSERT INTO t2 VALUES(1,3);
|
||||
INSERT INTO t1 SELECT * FROM t2;
|
||||
SELECT * FROM t1;
|
||||
}
|
||||
} {1 3}
|
||||
do_test insert4-8.25 {
|
||||
execsql {
|
||||
DROP TABLE IF EXISTS t1;
|
||||
DROP TABLE IF EXISTS t2;
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY ON CONFLICT ROLLBACK, b);
|
||||
CREATE TABLE t2(x INTEGER PRIMARY KEY ON CONFLICT ROLLBACK, y);
|
||||
INSERT INTO t2 VALUES(1,3);
|
||||
INSERT INTO t1 SELECT * FROM t2;
|
||||
SELECT * FROM t1;
|
||||
}
|
||||
} {1 3}
|
||||
|
||||
do_catchsql_test insert4-9.1 {
|
||||
DROP TABLE IF EXISTS t1;
|
||||
CREATE TABLE t1(x);
|
||||
INSERT INTO t1(x) VALUES(5 COLLATE xyzzy) UNION SELECT 0;
|
||||
} {1 {no such collation sequence: xyzzy}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Check that running an integrity-check does not disable the xfer
|
||||
# optimization for tables with CHECK constraints.
|
||||
#
|
||||
do_execsql_test 10.1 {
|
||||
CREATE TABLE t8(
|
||||
rid INTEGER,
|
||||
pid INTEGER,
|
||||
mid INTEGER,
|
||||
px INTEGER DEFAULT(0) CHECK(px IN(0, 1))
|
||||
);
|
||||
CREATE TEMP TABLE x(
|
||||
rid INTEGER,
|
||||
pid INTEGER,
|
||||
mid INTEGER,
|
||||
px INTEGER DEFAULT(0) CHECK(px IN(0, 1))
|
||||
);
|
||||
}
|
||||
do_test 10.2 {
|
||||
set sqlite3_xferopt_count 0
|
||||
execsql { INSERT INTO x SELECT * FROM t8 }
|
||||
set sqlite3_xferopt_count
|
||||
} {1}
|
||||
|
||||
do_test 10.3 {
|
||||
execsql { PRAGMA integrity_check }
|
||||
set sqlite3_xferopt_count 0
|
||||
execsql { INSERT INTO x SELECT * FROM t8 }
|
||||
set sqlite3_xferopt_count
|
||||
} {1}
|
||||
|
||||
do_test 10.4 {
|
||||
execsql { PRAGMA integrity_check }
|
||||
set sqlite3_xferopt_count 0
|
||||
execsql { INSERT INTO x SELECT * FROM t8 RETURNING * }
|
||||
set sqlite3_xferopt_count
|
||||
} {0}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# xfer transfer between tables where the source has an empty partial index.
|
||||
#
|
||||
do_execsql_test 11.0 {
|
||||
CREATE TABLE t9(a, b, c);
|
||||
CREATE INDEX t9a ON t9(a);
|
||||
CREATE INDEX t9b ON t9(b) WHERE c=0;
|
||||
|
||||
INSERT INTO t9 VALUES(1, 1, 1);
|
||||
INSERT INTO t9 VALUES(2, 2, 2);
|
||||
INSERT INTO t9 VALUES(3, 3, 3);
|
||||
|
||||
CREATE TABLE t10(a, b, c);
|
||||
CREATE INDEX t10a ON t10(a);
|
||||
CREATE INDEX t10b ON t10(b) WHERE c=0;
|
||||
|
||||
INSERT INTO t10 SELECT * FROM t9;
|
||||
SELECT * FROM t10;
|
||||
PRAGMA integrity_check;
|
||||
} {1 1 1 2 2 2 3 3 3 ok}
|
||||
|
||||
finish_test
|
||||
117
testing/sqlite3/insert5.test
Normal file
117
testing/sqlite3/insert5.test
Normal file
@@ -0,0 +1,117 @@
|
||||
# 2007 November 23
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
# The tests in this file ensure that a temporary table is used
|
||||
# when required by an "INSERT INTO ... SELECT ..." statement.
|
||||
#
|
||||
# $Id: insert5.test,v 1.5 2008/08/04 03:51:24 danielk1977 Exp $
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
|
||||
ifcapable !subquery {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
# Return true if the compilation of the sql passed as an argument
|
||||
# includes the opcode OpenEphemeral. An "INSERT INTO ... SELECT"
|
||||
# statement includes such an opcode if a temp-table is used
|
||||
# to store intermediate results.
|
||||
#
|
||||
proc uses_temp_table {sql} {
|
||||
return [expr {[lsearch [execsql "EXPLAIN $sql"] OpenEphemeral]>=0}]
|
||||
}
|
||||
|
||||
# Construct the sample database.
|
||||
#
|
||||
do_test insert5-1.0 {
|
||||
forcedelete test2.db test2.db-journal
|
||||
execsql {
|
||||
CREATE TABLE MAIN(Id INTEGER, Id1 INTEGER);
|
||||
CREATE TABLE B(Id INTEGER, Id1 INTEGER);
|
||||
CREATE VIEW v1 AS SELECT * FROM B;
|
||||
CREATE VIEW v2 AS SELECT * FROM MAIN;
|
||||
INSERT INTO MAIN(Id,Id1) VALUES(2,3);
|
||||
INSERT INTO B(Id,Id1) VALUES(2,3);
|
||||
}
|
||||
} {}
|
||||
|
||||
# Run the query.
|
||||
#
|
||||
ifcapable compound {
|
||||
do_test insert5-1.1 {
|
||||
execsql {
|
||||
INSERT INTO B
|
||||
SELECT * FROM B UNION ALL
|
||||
SELECT * FROM MAIN WHERE exists (select * FROM B WHERE B.Id = MAIN.Id);
|
||||
SELECT * FROM B;
|
||||
}
|
||||
} {2 3 2 3 2 3}
|
||||
} else {
|
||||
do_test insert5-1.1 {
|
||||
execsql {
|
||||
INSERT INTO B SELECT * FROM B;
|
||||
INSERT INTO B
|
||||
SELECT * FROM MAIN WHERE exists (select * FROM B WHERE B.Id = MAIN.Id);
|
||||
SELECT * FROM B;
|
||||
}
|
||||
} {2 3 2 3 2 3}
|
||||
}
|
||||
do_test insert5-2.1 {
|
||||
uses_temp_table { INSERT INTO b SELECT * FROM main }
|
||||
} {0}
|
||||
do_test insert5-2.2 {
|
||||
uses_temp_table { INSERT INTO b SELECT * FROM b }
|
||||
} {1}
|
||||
do_test insert5-2.3 {
|
||||
uses_temp_table { INSERT INTO b SELECT (SELECT id FROM b), id1 FROM main }
|
||||
} {1}
|
||||
do_test insert5-2.4 {
|
||||
uses_temp_table { INSERT INTO b SELECT id1, (SELECT id FROM b) FROM main }
|
||||
} {1}
|
||||
do_test insert5-2.5 {
|
||||
uses_temp_table {
|
||||
INSERT INTO b
|
||||
SELECT * FROM main WHERE id = (SELECT id1 FROM b WHERE main.id = b.id) }
|
||||
} {1}
|
||||
do_test insert5-2.6 {
|
||||
uses_temp_table { INSERT INTO b SELECT * FROM v1 }
|
||||
} {1}
|
||||
do_test insert5-2.7 {
|
||||
uses_temp_table { INSERT INTO b SELECT * FROM v2 }
|
||||
} {0}
|
||||
do_test insert5-2.8 {
|
||||
uses_temp_table {
|
||||
INSERT INTO b
|
||||
SELECT * FROM main WHERE id > 10 AND max(id1, (SELECT id FROM b)) > 10;
|
||||
}
|
||||
} {1}
|
||||
|
||||
# UPDATE: Using a column from the outer query (main.id) in the GROUP BY
|
||||
# or ORDER BY of a sub-query is no longer supported.
|
||||
#
|
||||
# do_test insert5-2.9 {
|
||||
# uses_temp_table {
|
||||
# INSERT INTO b
|
||||
# SELECT * FROM main
|
||||
# WHERE id > 10 AND (SELECT count(*) FROM v2 GROUP BY main.id)
|
||||
# }
|
||||
# } {}
|
||||
do_test insert5-2.9 {
|
||||
catchsql {
|
||||
INSERT INTO b
|
||||
SELECT * FROM main
|
||||
WHERE id > 10 AND (SELECT count(*) FROM v2 GROUP BY main.id)
|
||||
}
|
||||
} {1 {no such column: main.id}}
|
||||
|
||||
finish_test
|
||||
Reference in New Issue
Block a user