Home | History | Annotate | Download | only in test
      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 do_test insert4-6.5 {
    305   execsql {
    306     CREATE TABLE t6a(x CHECK( x<>'abc' ));
    307     INSERT INTO t6a VALUES('ABC');
    308     SELECT * FROM t6a;
    309   }
    310 } {ABC}
    311 do_test insert4-6.6 {
    312   execsql {
    313     CREATE TABLE t6b(x CHECK( x<>'abc' COLLATE nocase ));
    314   }
    315   catchsql {
    316     INSERT INTO t6b SELECT * FROM t6a;
    317   }
    318 } {1 {constraint failed}}
    319 do_test insert4-6.7 {
    320   execsql {
    321     DROP TABLE t6b;
    322     CREATE TABLE t6b(x CHECK( x COLLATE nocase <>'abc' ));
    323   }
    324   catchsql {
    325     INSERT INTO t6b SELECT * FROM t6a;
    326   }
    327 } {1 {constraint failed}}
    328 
    329 finish_test
    330