mirror of
				https://github.com/glebarez/go-sqlite.git
				synced 2025-10-31 19:13:06 +08:00 
			
		
		
		
	
		
			
				
	
	
		
			623 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			623 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| # 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.
 | |
| #
 | |
| # $Id: insert4.test,v 1.10 2008/01/21 16:22:46 drh Exp $
 | |
| 
 | |
| 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}
 | |
| 
 | |
| #-------------------------------------------------------------------------
 | |
| # 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
 | 
