3 # The author disclaims copyright to this source code. In place of
4 # a legal notice, here is a blessing:
6 # May you do good and not evil.
7 # May you find forgiveness for yourself and forgive others.
8 # May you share freely, never taking more than you give.
10 #***********************************************************************
11 # This file implements regression tests for SQLite library. The
12 # focus of this file is testing the INSERT transfer optimization.
14 # $Id: insert4.test,v 1.10 2008/01/21 16:22:46 drh Exp $
16 set testdir [file dirname $argv0]
17 source $testdir/tester.tcl
19 ifcapable !view||!subquery {
24 # The sqlite3_xferopt_count variable is incremented whenever the
25 # insert transfer optimization applies.
27 # This procedure runs a test to see if the sqlite3_xferopt_count is
30 proc xferopt_test {testname N} {
31 do_test $testname {set ::sqlite3_xferopt_count} $N
34 # Create tables used for testing.
37 PRAGMA legacy_file_format = 0;
38 CREATE TABLE t1(a int, b int, check(b>a));
39 CREATE TABLE t2(x int, y int);
40 CREATE VIEW v2 AS SELECT y, x FROM t2;
41 CREATE TABLE t3(a int, b int);
44 # Ticket #2252. Make sure the an INSERT from identical tables
45 # does not violate constraints.
48 set sqlite3_xferopt_count 0
52 INSERT INTO t2 VALUES(9,1);
55 INSERT INTO t1 SELECT * FROM t2;
57 } {1 {constraint failed}}
58 xferopt_test insert4-1.2 0
65 # Tests to make sure that the transfer optimization is not occurring
66 # when it is not a valid optimization.
68 # The SELECT must be against a real table.
69 do_test insert4-2.1.1 {
72 INSERT INTO t1 SELECT 4, 8;
76 xferopt_test insert4-2.1.2 0
77 do_test insert4-2.2.1 {
80 INSERT INTO t1 SELECT * FROM v2;
84 xferopt_test insert4-2.2.2 0
86 # Do not run the transfer optimization if there is a LIMIT clause
88 do_test insert4-2.3.1 {
91 INSERT INTO t2 VALUES(9,1);
92 INSERT INTO t2 SELECT y, x FROM t2;
93 INSERT INTO t3 SELECT * FROM t2 LIMIT 1;
97 xferopt_test insert4-2.3.2 0
98 do_test insert4-2.3.3 {
101 INSERT INTO t1 SELECT * FROM t2 LIMIT 1;
104 } {1 {constraint failed}}
105 xferopt_test insert4-2.3.4 0
107 # Do not run the transfer optimization if there is a DISTINCT
109 do_test insert4-2.4.1 {
112 INSERT INTO t3 SELECT DISTINCT * FROM t2;
116 xferopt_test insert4-2.4.2 0
117 do_test insert4-2.4.3 {
120 INSERT INTO t1 SELECT DISTINCT * FROM t2;
122 } {1 {constraint failed}}
123 xferopt_test insert4-2.4.4 0
125 # The following procedure constructs two tables then tries to transfer
126 # data from one table to the other. Checks are made to make sure the
127 # transfer is successful and that the transfer optimization was used or
128 # not, as appropriate.
130 # xfer_check TESTID XFER-USED INIT-DATA DEST-SCHEMA SRC-SCHEMA
132 # The TESTID argument is the symbolic name for this test. The XFER-USED
133 # argument is true if the transfer optimization should be employed and
134 # false if not. INIT-DATA is a single row of data that is to be
135 # transfered. DEST-SCHEMA and SRC-SCHEMA are table declarations for
136 # the destination and source tables.
138 proc xfer_check {testid xferused initdata destschema srcschema} {
139 execsql "CREATE TABLE dest($destschema)"
140 execsql "CREATE TABLE src($srcschema)"
141 execsql "INSERT INTO src VALUES([join $initdata ,])"
142 set ::sqlite3_xferopt_count 0
145 INSERT INTO dest SELECT * FROM src;
150 set ::sqlite3_xferopt_count
159 # Do run the transfer optimization if tables have identical
162 xfer_check insert4-3.1 1 {1 9} \
163 {a int, b int CHECK(b>a)} \
164 {x int, y int CHECK(y>x)}
165 xfer_check insert4-3.2 1 {1 9} \
166 {a int, b int CHECK(b>a)} \
167 {x int CHECK(y>x), y int}
169 # Do run the transfer optimization if the destination table lacks
170 # any CHECK constraints regardless of whether or not there are CHECK
171 # constraints on the source table.
173 xfer_check insert4-3.3 1 {1 9} \
175 {x int, y int CHECK(y>x)}
177 # Do run the transfer optimization if the destination table omits
178 # NOT NULL constraints that the source table has.
180 xfer_check insert4-3.4 0 {1 9} \
181 {a int, b int CHECK(b>a)} \
184 # Do not run the optimization if the destination has NOT NULL
185 # constraints that the source table lacks.
187 xfer_check insert4-3.5 0 {1 9} \
188 {a int, b int NOT NULL} \
190 xfer_check insert4-3.6 0 {1 9} \
191 {a int, b int NOT NULL} \
192 {x int NOT NULL, y int}
193 xfer_check insert4-3.7 0 {1 9} \
194 {a int NOT NULL, b int NOT NULL} \
195 {x int NOT NULL, y int}
196 xfer_check insert4-3.8 0 {1 9} \
197 {a int NOT NULL, b int} \
201 # Do run the transfer optimization if the destination table and
202 # source table have the same NOT NULL constraints or if the
203 # source table has extra NOT NULL constraints.
205 xfer_check insert4-3.9 1 {1 9} \
207 {x int NOT NULL, y int}
208 xfer_check insert4-3.10 1 {1 9} \
210 {x int NOT NULL, y int NOT NULL}
211 xfer_check insert4-3.11 1 {1 9} \
212 {a int NOT NULL, b int} \
213 {x int NOT NULL, y int NOT NULL}
214 xfer_check insert4-3.12 1 {1 9} \
215 {a int, b int NOT NULL} \
216 {x int NOT NULL, y int NOT NULL}
218 # Do not run the optimization if any corresponding table
219 # columns have different affinities.
221 xfer_check insert4-3.20 0 {1 9} \
224 xfer_check insert4-3.21 0 {1 9} \
228 # "int" and "integer" are equivalent so the optimization should
231 xfer_check insert4-3.22 1 {1 9} \
238 do_test insert4-4.1a {
239 execsql {CREATE TABLE t4(a, b, UNIQUE(a,b))}
242 do_test insert4-4.1b {
244 INSERT INTO t4 VALUES(NULL,0);
245 INSERT INTO t4 VALUES(NULL,1);
246 INSERT INTO t4 VALUES(NULL,1);
252 # Check some error conditions:
254 do_test insert4-5.1 {
255 # Table does not exist.
256 catchsql { INSERT INTO t2 SELECT * FROM nosuchtable }
257 } {1 {no such table: nosuchtable}}
258 do_test insert4-5.2 {
259 # Number of columns does not match.
261 CREATE TABLE t5(a, b, c);
262 INSERT INTO t4 SELECT * FROM t5;
264 } {1 {table t4 has 2 columns but 3 values were supplied}}
266 do_test insert4-6.1 {
267 set ::sqlite3_xferopt_count 0
269 CREATE INDEX t2_i2 ON t2(x, y COLLATE nocase);
270 CREATE INDEX t2_i1 ON t2(x ASC, y DESC);
271 CREATE INDEX t3_i1 ON t3(a, b);
272 INSERT INTO t2 SELECT * FROM t3;
274 set ::sqlite3_xferopt_count
276 do_test insert4-6.2 {
277 set ::sqlite3_xferopt_count 0
280 INSERT INTO t2 SELECT * FROM t3;
282 set ::sqlite3_xferopt_count
284 do_test insert4-6.3 {
285 set ::sqlite3_xferopt_count 0
288 CREATE INDEX t2_i1 ON t2(x ASC, y ASC);
289 INSERT INTO t2 SELECT * FROM t3;
291 set ::sqlite3_xferopt_count
293 do_test insert4-6.4 {
294 set ::sqlite3_xferopt_count 0
297 CREATE INDEX t2_i1 ON t2(x ASC, y COLLATE RTRIM);
298 INSERT INTO t2 SELECT * FROM t3;
300 set ::sqlite3_xferopt_count
304 do_test insert4-6.5 {
306 CREATE TABLE t6a(x CHECK( x<>'abc' ));
307 INSERT INTO t6a VALUES('ABC');
311 do_test insert4-6.6 {
313 CREATE TABLE t6b(x CHECK( x<>'abc' COLLATE nocase ));
316 INSERT INTO t6b SELECT * FROM t6a;
318 } {1 {constraint failed}}
319 do_test insert4-6.7 {
322 CREATE TABLE t6b(x CHECK( x COLLATE nocase <>'abc' ));
325 INSERT INTO t6b SELECT * FROM t6a;
327 } {1 {constraint failed}}