| OLD | NEW | 
 | (Empty) | 
|    1 # 2007 January 24 |  | 
|    2 # |  | 
|    3 # The author disclaims copyright to this source code.  In place of |  | 
|    4 # a legal notice, here is a blessing: |  | 
|    5 # |  | 
|    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. |  | 
|    9 # |  | 
|   10 #*********************************************************************** |  | 
|   11 # This file implements regression tests for SQLite library.  The |  | 
|   12 # focus of this file is testing the INSERT transfer optimization. |  | 
|   13 # |  | 
|   14 # $Id: insert4.test,v 1.10 2008/01/21 16:22:46 drh Exp $ |  | 
|   15  |  | 
|   16 set testdir [file dirname $argv0] |  | 
|   17 source $testdir/tester.tcl |  | 
|   18  |  | 
|   19 ifcapable !view||!subquery { |  | 
|   20   finish_test |  | 
|   21   return |  | 
|   22 } |  | 
|   23  |  | 
|   24 # The sqlite3_xferopt_count variable is incremented whenever the  |  | 
|   25 # insert transfer optimization applies. |  | 
|   26 # |  | 
|   27 # This procedure runs a test to see if the sqlite3_xferopt_count is |  | 
|   28 # set to N. |  | 
|   29 # |  | 
|   30 proc xferopt_test {testname N} { |  | 
|   31   do_test $testname {set ::sqlite3_xferopt_count} $N |  | 
|   32 } |  | 
|   33  |  | 
|   34 # Create tables used for testing. |  | 
|   35 # |  | 
|   36 execsql { |  | 
|   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); |  | 
|   42 } |  | 
|   43  |  | 
|   44 # Ticket #2252.  Make sure the an INSERT from identical tables |  | 
|   45 # does not violate constraints. |  | 
|   46 # |  | 
|   47 do_test insert4-1.1 { |  | 
|   48   set sqlite3_xferopt_count 0 |  | 
|   49   execsql { |  | 
|   50     DELETE FROM t1; |  | 
|   51     DELETE FROM t2; |  | 
|   52     INSERT INTO t2 VALUES(9,1); |  | 
|   53   } |  | 
|   54   catchsql { |  | 
|   55     INSERT INTO t1 SELECT * FROM t2; |  | 
|   56   } |  | 
|   57 } {1 {constraint failed}} |  | 
|   58 xferopt_test insert4-1.2 0 |  | 
|   59 do_test insert4-1.3 { |  | 
|   60   execsql { |  | 
|   61     SELECT * FROM t1; |  | 
|   62   } |  | 
|   63 } {} |  | 
|   64  |  | 
|   65 # Tests to make sure that the transfer optimization is not occurring |  | 
|   66 # when it is not a valid optimization. |  | 
|   67 # |  | 
|   68 # The SELECT must be against a real table. |  | 
|   69 do_test insert4-2.1.1 { |  | 
|   70   execsql { |  | 
|   71     DELETE FROM t1; |  | 
|   72     INSERT INTO t1 SELECT 4, 8; |  | 
|   73     SELECT * FROM t1; |  | 
|   74   } |  | 
|   75 } {4 8} |  | 
|   76 xferopt_test insert4-2.1.2  0 |  | 
|   77 do_test insert4-2.2.1 { |  | 
|   78   catchsql { |  | 
|   79     DELETE FROM t1; |  | 
|   80     INSERT INTO t1 SELECT * FROM v2; |  | 
|   81     SELECT * FROM t1; |  | 
|   82   } |  | 
|   83 } {0 {1 9}} |  | 
|   84 xferopt_test insert4-2.2.2 0 |  | 
|   85  |  | 
|   86 # Do not run the transfer optimization if there is a LIMIT clause |  | 
|   87 # |  | 
|   88 do_test insert4-2.3.1 { |  | 
|   89   execsql { |  | 
|   90     DELETE FROM t2; |  | 
|   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; |  | 
|   94     SELECT * FROM t3; |  | 
|   95   } |  | 
|   96 } {9 1} |  | 
|   97 xferopt_test insert4-2.3.2  0 |  | 
|   98 do_test insert4-2.3.3 { |  | 
|   99   catchsql { |  | 
|  100     DELETE FROM t1; |  | 
|  101     INSERT INTO t1 SELECT * FROM t2 LIMIT 1; |  | 
|  102     SELECT * FROM t1; |  | 
|  103   } |  | 
|  104 } {1 {constraint failed}} |  | 
|  105 xferopt_test insert4-2.3.4 0 |  | 
|  106  |  | 
|  107 # Do not run the transfer optimization if there is a DISTINCT |  | 
|  108 # |  | 
|  109 do_test insert4-2.4.1 { |  | 
|  110   execsql { |  | 
|  111     DELETE FROM t3; |  | 
|  112     INSERT INTO t3 SELECT DISTINCT * FROM t2; |  | 
|  113     SELECT * FROM t3; |  | 
|  114   } |  | 
|  115 } {1 9 9 1} |  | 
|  116 xferopt_test insert4-2.4.2 0 |  | 
|  117 do_test insert4-2.4.3 { |  | 
|  118   catchsql { |  | 
|  119     DELETE FROM t1; |  | 
|  120     INSERT INTO t1 SELECT DISTINCT * FROM t2; |  | 
|  121   } |  | 
|  122 } {1 {constraint failed}} |  | 
|  123 xferopt_test insert4-2.4.4 0 |  | 
|  124  |  | 
|  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. |  | 
|  129 # |  | 
|  130 #     xfer_check TESTID  XFER-USED   INIT-DATA   DEST-SCHEMA   SRC-SCHEMA  |  | 
|  131 # |  | 
|  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. |  | 
|  137 # |  | 
|  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 |  | 
|  143   do_test $testid.1 { |  | 
|  144     execsql { |  | 
|  145       INSERT INTO dest SELECT * FROM src; |  | 
|  146       SELECT * FROM dest; |  | 
|  147     } |  | 
|  148   } $initdata |  | 
|  149   do_test $testid.2 { |  | 
|  150     set ::sqlite3_xferopt_count |  | 
|  151   } $xferused |  | 
|  152   execsql { |  | 
|  153     DROP TABLE dest; |  | 
|  154     DROP TABLE src; |  | 
|  155   } |  | 
|  156 } |  | 
|  157  |  | 
|  158  |  | 
|  159 # Do run the transfer optimization if tables have identical |  | 
|  160 # CHECK constraints. |  | 
|  161 # |  | 
|  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} |  | 
|  168  |  | 
|  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. |  | 
|  172 # |  | 
|  173 xfer_check insert4-3.3 1 {1 9} \ |  | 
|  174     {a int, b int} \ |  | 
|  175     {x int, y int CHECK(y>x)} |  | 
|  176  |  | 
|  177 # Do run the transfer optimization if the destination table omits |  | 
|  178 # NOT NULL constraints that the source table has. |  | 
|  179 # |  | 
|  180 xfer_check insert4-3.4 0 {1 9} \ |  | 
|  181     {a int, b int CHECK(b>a)} \ |  | 
|  182     {x int, y int} |  | 
|  183  |  | 
|  184 # Do not run the optimization if the destination has NOT NULL |  | 
|  185 # constraints that the source table lacks. |  | 
|  186 # |  | 
|  187 xfer_check insert4-3.5 0 {1 9} \ |  | 
|  188     {a int, b int NOT NULL} \ |  | 
|  189     {x int, y int} |  | 
|  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} \ |  | 
|  198     {x int, y int} |  | 
|  199  |  | 
|  200  |  | 
|  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. |  | 
|  204 # |  | 
|  205 xfer_check insert4-3.9 1 {1 9} \ |  | 
|  206     {a int, b int} \ |  | 
|  207     {x int NOT NULL, y int} |  | 
|  208 xfer_check insert4-3.10 1 {1 9} \ |  | 
|  209     {a int, b int} \ |  | 
|  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} |  | 
|  217  |  | 
|  218 # Do not run the optimization if any corresponding table |  | 
|  219 # columns have different affinities. |  | 
|  220 # |  | 
|  221 xfer_check insert4-3.20 0 {1 9} \ |  | 
|  222     {a text, b int} \ |  | 
|  223     {x int, b int} |  | 
|  224 xfer_check insert4-3.21 0 {1 9} \ |  | 
|  225     {a int, b int} \ |  | 
|  226     {x text, b int} |  | 
|  227  |  | 
|  228 # "int" and "integer" are equivalent so the optimization should |  | 
|  229 # run here. |  | 
|  230 # |  | 
|  231 xfer_check insert4-3.22 1 {1 9} \ |  | 
|  232     {a int, b int} \ |  | 
|  233     {x integer, b int} |  | 
|  234  |  | 
|  235 # Ticket #2291. |  | 
|  236 # |  | 
|  237  |  | 
|  238 do_test insert4-4.1a { |  | 
|  239   execsql {CREATE TABLE t4(a, b, UNIQUE(a,b))} |  | 
|  240 } {} |  | 
|  241 ifcapable vacuum { |  | 
|  242   do_test insert4-4.1b { |  | 
|  243     execsql { |  | 
|  244       INSERT INTO t4 VALUES(NULL,0); |  | 
|  245       INSERT INTO t4 VALUES(NULL,1); |  | 
|  246       INSERT INTO t4 VALUES(NULL,1); |  | 
|  247       VACUUM;    |  | 
|  248     } |  | 
|  249   } {} |  | 
|  250 } |  | 
|  251  |  | 
|  252 # Check some error conditions: |  | 
|  253 # |  | 
|  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. |  | 
|  260   catchsql {  |  | 
|  261     CREATE TABLE t5(a, b, c); |  | 
|  262     INSERT INTO t4 SELECT * FROM t5; |  | 
|  263   } |  | 
|  264 } {1 {table t4 has 2 columns but 3 values were supplied}} |  | 
|  265  |  | 
|  266 do_test insert4-6.1 { |  | 
|  267   set ::sqlite3_xferopt_count 0 |  | 
|  268   execsql { |  | 
|  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; |  | 
|  273   } |  | 
|  274   set ::sqlite3_xferopt_count |  | 
|  275 } {0} |  | 
|  276 do_test insert4-6.2 { |  | 
|  277   set ::sqlite3_xferopt_count 0 |  | 
|  278   execsql { |  | 
|  279     DROP INDEX t2_i2; |  | 
|  280     INSERT INTO t2 SELECT * FROM t3; |  | 
|  281   } |  | 
|  282   set ::sqlite3_xferopt_count |  | 
|  283 } {0} |  | 
|  284 do_test insert4-6.3 { |  | 
|  285   set ::sqlite3_xferopt_count 0 |  | 
|  286   execsql { |  | 
|  287     DROP INDEX t2_i1; |  | 
|  288     CREATE INDEX t2_i1 ON t2(x ASC, y ASC); |  | 
|  289     INSERT INTO t2 SELECT * FROM t3; |  | 
|  290   } |  | 
|  291   set ::sqlite3_xferopt_count |  | 
|  292 } {1} |  | 
|  293 do_test insert4-6.4 { |  | 
|  294   set ::sqlite3_xferopt_count 0 |  | 
|  295   execsql { |  | 
|  296     DROP INDEX t2_i1; |  | 
|  297     CREATE INDEX t2_i1 ON t2(x ASC, y COLLATE RTRIM); |  | 
|  298     INSERT INTO t2 SELECT * FROM t3; |  | 
|  299   } |  | 
|  300   set ::sqlite3_xferopt_count |  | 
|  301 } {0} |  | 
|  302  |  | 
|  303  |  | 
|  304  |  | 
|  305  |  | 
|  306 finish_test |  | 
| OLD | NEW |