persistentstorage/sqlite3api/TEST/TclScript/insert4.test
changeset 0 08ec8eefde2f
equal deleted inserted replaced
-1:000000000000 0:08ec8eefde2f
       
     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