Annotation of embedaddon/sqlite3/test/insert4.test, revision 1.1
1.1 ! misho 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: } {9 1 1 9}
! 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: # Ticket [6284df89debdfa61db8073e062908af0c9b6118e]
! 330: # Disable the xfer optimization if the destination table contains
! 331: # a foreign key constraint
! 332: #
! 333: ifcapable foreignkey {
! 334: do_test insert4-7.1 {
! 335: set ::sqlite3_xferopt_count 0
! 336: execsql {
! 337: CREATE TABLE t7a(x INTEGER PRIMARY KEY); INSERT INTO t7a VALUES(123);
! 338: CREATE TABLE t7b(y INTEGER REFERENCES t7a);
! 339: CREATE TABLE t7c(z INT); INSERT INTO t7c VALUES(234);
! 340: INSERT INTO t7b SELECT * FROM t7c;
! 341: SELECT * FROM t7b;
! 342: }
! 343: } {234}
! 344: do_test insert4-7.2 {
! 345: set ::sqlite3_xferopt_count
! 346: } {1}
! 347: do_test insert4-7.3 {
! 348: set ::sqlite3_xferopt_count 0
! 349: execsql {
! 350: DELETE FROM t7b;
! 351: PRAGMA foreign_keys=ON;
! 352: }
! 353: catchsql {
! 354: INSERT INTO t7b SELECT * FROM t7c;
! 355: }
! 356: } {1 {foreign key constraint failed}}
! 357: do_test insert4-7.4 {
! 358: execsql {SELECT * FROM t7b}
! 359: } {}
! 360: do_test insert4-7.5 {
! 361: set ::sqlite3_xferopt_count
! 362: } {0}
! 363: do_test insert4-7.6 {
! 364: set ::sqlite3_xferopt_count 0
! 365: execsql {
! 366: DELETE FROM t7b; DELETE FROM t7c;
! 367: INSERT INTO t7c VALUES(123);
! 368: INSERT INTO t7b SELECT * FROM t7c;
! 369: SELECT * FROM t7b;
! 370: }
! 371: } {123}
! 372: do_test insert4-7.7 {
! 373: set ::sqlite3_xferopt_count
! 374: } {0}
! 375: do_test insert4-7.7 {
! 376: set ::sqlite3_xferopt_count 0
! 377: execsql {
! 378: PRAGMA foreign_keys=OFF;
! 379: DELETE FROM t7b;
! 380: INSERT INTO t7b SELECT * FROM t7c;
! 381: SELECT * FROM t7b;
! 382: }
! 383: } {123}
! 384: do_test insert4-7.8 {
! 385: set ::sqlite3_xferopt_count
! 386: } {1}
! 387: }
! 388:
! 389: # Ticket [676bc02b87176125635cb174d110b431581912bb]
! 390: # Make sure INTEGER PRIMARY KEY ON CONFLICT ... works with the xfer
! 391: # optimization.
! 392: #
! 393: do_test insert4-8.1 {
! 394: execsql {
! 395: DROP TABLE IF EXISTS t1;
! 396: DROP TABLE IF EXISTS t2;
! 397: CREATE TABLE t1(a INTEGER PRIMARY KEY ON CONFLICT REPLACE, b);
! 398: CREATE TABLE t2(x INTEGER PRIMARY KEY ON CONFLICT REPLACE, y);
! 399: INSERT INTO t1 VALUES(1,2);
! 400: INSERT INTO t2 VALUES(1,3);
! 401: INSERT INTO t1 SELECT * FROM t2;
! 402: SELECT * FROM t1;
! 403: }
! 404: } {1 3}
! 405: do_test insert4-8.2 {
! 406: execsql {
! 407: DROP TABLE IF EXISTS t1;
! 408: DROP TABLE IF EXISTS t2;
! 409: CREATE TABLE t1(a INTEGER PRIMARY KEY ON CONFLICT REPLACE, b);
! 410: CREATE TABLE t2(x, y);
! 411: INSERT INTO t1 VALUES(1,2);
! 412: INSERT INTO t2 VALUES(1,3);
! 413: INSERT INTO t1 SELECT * FROM t2;
! 414: SELECT * FROM t1;
! 415: }
! 416: } {1 3}
! 417: do_test insert4-8.3 {
! 418: execsql {
! 419: DROP TABLE IF EXISTS t1;
! 420: DROP TABLE IF EXISTS t2;
! 421: CREATE TABLE t1(a INTEGER PRIMARY KEY ON CONFLICT IGNORE, b);
! 422: CREATE TABLE t2(x INTEGER PRIMARY KEY ON CONFLICT IGNORE, y);
! 423: INSERT INTO t1 VALUES(1,2);
! 424: INSERT INTO t2 VALUES(1,3);
! 425: INSERT INTO t1 SELECT * FROM t2;
! 426: SELECT * FROM t1;
! 427: }
! 428: } {1 2}
! 429: do_test insert4-8.4 {
! 430: execsql {
! 431: DROP TABLE IF EXISTS t1;
! 432: DROP TABLE IF EXISTS t2;
! 433: CREATE TABLE t1(a INTEGER PRIMARY KEY ON CONFLICT IGNORE, b);
! 434: CREATE TABLE t2(x, y);
! 435: INSERT INTO t1 VALUES(1,2);
! 436: INSERT INTO t2 VALUES(1,3);
! 437: INSERT INTO t1 SELECT * FROM t2;
! 438: SELECT * FROM t1;
! 439: }
! 440: } {1 2}
! 441: do_test insert4-8.5 {
! 442: execsql {
! 443: DROP TABLE IF EXISTS t1;
! 444: DROP TABLE IF EXISTS t2;
! 445: CREATE TABLE t1(a INTEGER PRIMARY KEY ON CONFLICT FAIL, b);
! 446: CREATE TABLE t2(x INTEGER PRIMARY KEY ON CONFLICT FAIL, y);
! 447: INSERT INTO t1 VALUES(1,2);
! 448: INSERT INTO t2 VALUES(-99,100);
! 449: INSERT INTO t2 VALUES(1,3);
! 450: SELECT * FROM t1;
! 451: }
! 452: catchsql {
! 453: INSERT INTO t1 SELECT * FROM t2;
! 454: }
! 455: } {1 {PRIMARY KEY must be unique}}
! 456: do_test insert4-8.6 {
! 457: execsql {
! 458: SELECT * FROM t1;
! 459: }
! 460: } {-99 100 1 2}
! 461: do_test insert4-8.7 {
! 462: execsql {
! 463: DROP TABLE IF EXISTS t1;
! 464: DROP TABLE IF EXISTS t2;
! 465: CREATE TABLE t1(a INTEGER PRIMARY KEY ON CONFLICT ABORT, b);
! 466: CREATE TABLE t2(x INTEGER PRIMARY KEY ON CONFLICT ABORT, y);
! 467: INSERT INTO t1 VALUES(1,2);
! 468: INSERT INTO t2 VALUES(-99,100);
! 469: INSERT INTO t2 VALUES(1,3);
! 470: SELECT * FROM t1;
! 471: }
! 472: catchsql {
! 473: INSERT INTO t1 SELECT * FROM t2;
! 474: }
! 475: } {1 {PRIMARY KEY must be unique}}
! 476: do_test insert4-8.8 {
! 477: execsql {
! 478: SELECT * FROM t1;
! 479: }
! 480: } {1 2}
! 481: do_test insert4-8.9 {
! 482: execsql {
! 483: DROP TABLE IF EXISTS t1;
! 484: DROP TABLE IF EXISTS t2;
! 485: CREATE TABLE t1(a INTEGER PRIMARY KEY ON CONFLICT ROLLBACK, b);
! 486: CREATE TABLE t2(x INTEGER PRIMARY KEY ON CONFLICT ROLLBACK, y);
! 487: INSERT INTO t1 VALUES(1,2);
! 488: INSERT INTO t2 VALUES(-99,100);
! 489: INSERT INTO t2 VALUES(1,3);
! 490: SELECT * FROM t1;
! 491: }
! 492: catchsql {
! 493: BEGIN;
! 494: INSERT INTO t1 VALUES(2,3);
! 495: INSERT INTO t1 SELECT * FROM t2;
! 496: }
! 497: } {1 {PRIMARY KEY must be unique}}
! 498: do_test insert4-8.10 {
! 499: catchsql {COMMIT}
! 500: } {1 {cannot commit - no transaction is active}}
! 501: do_test insert4-8.11 {
! 502: execsql {
! 503: SELECT * FROM t1;
! 504: }
! 505: } {1 2}
! 506:
! 507: do_test insert4-8.21 {
! 508: execsql {
! 509: DROP TABLE IF EXISTS t1;
! 510: DROP TABLE IF EXISTS t2;
! 511: CREATE TABLE t1(a INTEGER PRIMARY KEY ON CONFLICT REPLACE, b);
! 512: CREATE TABLE t2(x INTEGER PRIMARY KEY ON CONFLICT REPLACE, y);
! 513: INSERT INTO t2 VALUES(1,3);
! 514: INSERT INTO t1 SELECT * FROM t2;
! 515: SELECT * FROM t1;
! 516: }
! 517: } {1 3}
! 518: do_test insert4-8.22 {
! 519: execsql {
! 520: DROP TABLE IF EXISTS t1;
! 521: DROP TABLE IF EXISTS t2;
! 522: CREATE TABLE t1(a INTEGER PRIMARY KEY ON CONFLICT IGNORE, b);
! 523: CREATE TABLE t2(x INTEGER PRIMARY KEY ON CONFLICT IGNORE, y);
! 524: INSERT INTO t2 VALUES(1,3);
! 525: INSERT INTO t1 SELECT * FROM t2;
! 526: SELECT * FROM t1;
! 527: }
! 528: } {1 3}
! 529: do_test insert4-8.23 {
! 530: execsql {
! 531: DROP TABLE IF EXISTS t1;
! 532: DROP TABLE IF EXISTS t2;
! 533: CREATE TABLE t1(a INTEGER PRIMARY KEY ON CONFLICT ABORT, b);
! 534: CREATE TABLE t2(x INTEGER PRIMARY KEY ON CONFLICT ABORT, y);
! 535: INSERT INTO t2 VALUES(1,3);
! 536: INSERT INTO t1 SELECT * FROM t2;
! 537: SELECT * FROM t1;
! 538: }
! 539: } {1 3}
! 540: do_test insert4-8.24 {
! 541: execsql {
! 542: DROP TABLE IF EXISTS t1;
! 543: DROP TABLE IF EXISTS t2;
! 544: CREATE TABLE t1(a INTEGER PRIMARY KEY ON CONFLICT FAIL, b);
! 545: CREATE TABLE t2(x INTEGER PRIMARY KEY ON CONFLICT FAIL, y);
! 546: INSERT INTO t2 VALUES(1,3);
! 547: INSERT INTO t1 SELECT * FROM t2;
! 548: SELECT * FROM t1;
! 549: }
! 550: } {1 3}
! 551: do_test insert4-8.25 {
! 552: execsql {
! 553: DROP TABLE IF EXISTS t1;
! 554: DROP TABLE IF EXISTS t2;
! 555: CREATE TABLE t1(a INTEGER PRIMARY KEY ON CONFLICT ROLLBACK, b);
! 556: CREATE TABLE t2(x INTEGER PRIMARY KEY ON CONFLICT ROLLBACK, y);
! 557: INSERT INTO t2 VALUES(1,3);
! 558: INSERT INTO t1 SELECT * FROM t2;
! 559: SELECT * FROM t1;
! 560: }
! 561: } {1 3}
! 562:
! 563:
! 564: finish_test
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>