insert4.test 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564
  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. set testdir [file dirname $argv0]
  16. source $testdir/tester.tcl
  17. ifcapable !view||!subquery {
  18. finish_test
  19. return
  20. }
  21. # The sqlite3_xferopt_count variable is incremented whenever the
  22. # insert transfer optimization applies.
  23. #
  24. # This procedure runs a test to see if the sqlite3_xferopt_count is
  25. # set to N.
  26. #
  27. proc xferopt_test {testname N} {
  28. do_test $testname {set ::sqlite3_xferopt_count} $N
  29. }
  30. # Create tables used for testing.
  31. #
  32. execsql {
  33. PRAGMA legacy_file_format = 0;
  34. CREATE TABLE t1(a int, b int, check(b>a));
  35. CREATE TABLE t2(x int, y int);
  36. CREATE VIEW v2 AS SELECT y, x FROM t2;
  37. CREATE TABLE t3(a int, b int);
  38. }
  39. # Ticket #2252. Make sure the an INSERT from identical tables
  40. # does not violate constraints.
  41. #
  42. do_test insert4-1.1 {
  43. set sqlite3_xferopt_count 0
  44. execsql {
  45. DELETE FROM t1;
  46. DELETE FROM t2;
  47. INSERT INTO t2 VALUES(9,1);
  48. }
  49. catchsql {
  50. INSERT INTO t1 SELECT * FROM t2;
  51. }
  52. } {1 {constraint failed}}
  53. xferopt_test insert4-1.2 0
  54. do_test insert4-1.3 {
  55. execsql {
  56. SELECT * FROM t1;
  57. }
  58. } {}
  59. # Tests to make sure that the transfer optimization is not occurring
  60. # when it is not a valid optimization.
  61. #
  62. # The SELECT must be against a real table.
  63. do_test insert4-2.1.1 {
  64. execsql {
  65. DELETE FROM t1;
  66. INSERT INTO t1 SELECT 4, 8;
  67. SELECT * FROM t1;
  68. }
  69. } {4 8}
  70. xferopt_test insert4-2.1.2 0
  71. do_test insert4-2.2.1 {
  72. catchsql {
  73. DELETE FROM t1;
  74. INSERT INTO t1 SELECT * FROM v2;
  75. SELECT * FROM t1;
  76. }
  77. } {0 {1 9}}
  78. xferopt_test insert4-2.2.2 0
  79. # Do not run the transfer optimization if there is a LIMIT clause
  80. #
  81. do_test insert4-2.3.1 {
  82. execsql {
  83. DELETE FROM t2;
  84. INSERT INTO t2 VALUES(9,1);
  85. INSERT INTO t2 SELECT y, x FROM t2;
  86. INSERT INTO t3 SELECT * FROM t2 LIMIT 1;
  87. SELECT * FROM t3;
  88. }
  89. } {9 1}
  90. xferopt_test insert4-2.3.2 0
  91. do_test insert4-2.3.3 {
  92. catchsql {
  93. DELETE FROM t1;
  94. INSERT INTO t1 SELECT * FROM t2 LIMIT 1;
  95. SELECT * FROM t1;
  96. }
  97. } {1 {constraint failed}}
  98. xferopt_test insert4-2.3.4 0
  99. # Do not run the transfer optimization if there is a DISTINCT
  100. #
  101. do_test insert4-2.4.1 {
  102. execsql {
  103. DELETE FROM t3;
  104. INSERT INTO t3 SELECT DISTINCT * FROM t2;
  105. SELECT * FROM t3;
  106. }
  107. } {9 1 1 9}
  108. xferopt_test insert4-2.4.2 0
  109. do_test insert4-2.4.3 {
  110. catchsql {
  111. DELETE FROM t1;
  112. INSERT INTO t1 SELECT DISTINCT * FROM t2;
  113. }
  114. } {1 {constraint failed}}
  115. xferopt_test insert4-2.4.4 0
  116. # The following procedure constructs two tables then tries to transfer
  117. # data from one table to the other. Checks are made to make sure the
  118. # transfer is successful and that the transfer optimization was used or
  119. # not, as appropriate.
  120. #
  121. # xfer_check TESTID XFER-USED INIT-DATA DEST-SCHEMA SRC-SCHEMA
  122. #
  123. # The TESTID argument is the symbolic name for this test. The XFER-USED
  124. # argument is true if the transfer optimization should be employed and
  125. # false if not. INIT-DATA is a single row of data that is to be
  126. # transfered. DEST-SCHEMA and SRC-SCHEMA are table declarations for
  127. # the destination and source tables.
  128. #
  129. proc xfer_check {testid xferused initdata destschema srcschema} {
  130. execsql "CREATE TABLE dest($destschema)"
  131. execsql "CREATE TABLE src($srcschema)"
  132. execsql "INSERT INTO src VALUES([join $initdata ,])"
  133. set ::sqlite3_xferopt_count 0
  134. do_test $testid.1 {
  135. execsql {
  136. INSERT INTO dest SELECT * FROM src;
  137. SELECT * FROM dest;
  138. }
  139. } $initdata
  140. do_test $testid.2 {
  141. set ::sqlite3_xferopt_count
  142. } $xferused
  143. execsql {
  144. DROP TABLE dest;
  145. DROP TABLE src;
  146. }
  147. }
  148. # Do run the transfer optimization if tables have identical
  149. # CHECK constraints.
  150. #
  151. xfer_check insert4-3.1 1 {1 9} \
  152. {a int, b int CHECK(b>a)} \
  153. {x int, y int CHECK(y>x)}
  154. xfer_check insert4-3.2 1 {1 9} \
  155. {a int, b int CHECK(b>a)} \
  156. {x int CHECK(y>x), y int}
  157. # Do run the transfer optimization if the destination table lacks
  158. # any CHECK constraints regardless of whether or not there are CHECK
  159. # constraints on the source table.
  160. #
  161. xfer_check insert4-3.3 1 {1 9} \
  162. {a int, b int} \
  163. {x int, y int CHECK(y>x)}
  164. # Do run the transfer optimization if the destination table omits
  165. # NOT NULL constraints that the source table has.
  166. #
  167. xfer_check insert4-3.4 0 {1 9} \
  168. {a int, b int CHECK(b>a)} \
  169. {x int, y int}
  170. # Do not run the optimization if the destination has NOT NULL
  171. # constraints that the source table lacks.
  172. #
  173. xfer_check insert4-3.5 0 {1 9} \
  174. {a int, b int NOT NULL} \
  175. {x int, y int}
  176. xfer_check insert4-3.6 0 {1 9} \
  177. {a int, b int NOT NULL} \
  178. {x int NOT NULL, y int}
  179. xfer_check insert4-3.7 0 {1 9} \
  180. {a int NOT NULL, b int NOT NULL} \
  181. {x int NOT NULL, y int}
  182. xfer_check insert4-3.8 0 {1 9} \
  183. {a int NOT NULL, b int} \
  184. {x int, y int}
  185. # Do run the transfer optimization if the destination table and
  186. # source table have the same NOT NULL constraints or if the
  187. # source table has extra NOT NULL constraints.
  188. #
  189. xfer_check insert4-3.9 1 {1 9} \
  190. {a int, b int} \
  191. {x int NOT NULL, y int}
  192. xfer_check insert4-3.10 1 {1 9} \
  193. {a int, b int} \
  194. {x int NOT NULL, y int NOT NULL}
  195. xfer_check insert4-3.11 1 {1 9} \
  196. {a int NOT NULL, b int} \
  197. {x int NOT NULL, y int NOT NULL}
  198. xfer_check insert4-3.12 1 {1 9} \
  199. {a int, b int NOT NULL} \
  200. {x int NOT NULL, y int NOT NULL}
  201. # Do not run the optimization if any corresponding table
  202. # columns have different affinities.
  203. #
  204. xfer_check insert4-3.20 0 {1 9} \
  205. {a text, b int} \
  206. {x int, b int}
  207. xfer_check insert4-3.21 0 {1 9} \
  208. {a int, b int} \
  209. {x text, b int}
  210. # "int" and "integer" are equivalent so the optimization should
  211. # run here.
  212. #
  213. xfer_check insert4-3.22 1 {1 9} \
  214. {a int, b int} \
  215. {x integer, b int}
  216. # Ticket #2291.
  217. #
  218. do_test insert4-4.1a {
  219. execsql {CREATE TABLE t4(a, b, UNIQUE(a,b))}
  220. } {}
  221. ifcapable vacuum {
  222. do_test insert4-4.1b {
  223. execsql {
  224. INSERT INTO t4 VALUES(NULL,0);
  225. INSERT INTO t4 VALUES(NULL,1);
  226. INSERT INTO t4 VALUES(NULL,1);
  227. VACUUM;
  228. }
  229. } {}
  230. }
  231. # Check some error conditions:
  232. #
  233. do_test insert4-5.1 {
  234. # Table does not exist.
  235. catchsql { INSERT INTO t2 SELECT * FROM nosuchtable }
  236. } {1 {no such table: nosuchtable}}
  237. do_test insert4-5.2 {
  238. # Number of columns does not match.
  239. catchsql {
  240. CREATE TABLE t5(a, b, c);
  241. INSERT INTO t4 SELECT * FROM t5;
  242. }
  243. } {1 {table t4 has 2 columns but 3 values were supplied}}
  244. do_test insert4-6.1 {
  245. set ::sqlite3_xferopt_count 0
  246. execsql {
  247. CREATE INDEX t2_i2 ON t2(x, y COLLATE nocase);
  248. CREATE INDEX t2_i1 ON t2(x ASC, y DESC);
  249. CREATE INDEX t3_i1 ON t3(a, b);
  250. INSERT INTO t2 SELECT * FROM t3;
  251. }
  252. set ::sqlite3_xferopt_count
  253. } {0}
  254. do_test insert4-6.2 {
  255. set ::sqlite3_xferopt_count 0
  256. execsql {
  257. DROP INDEX t2_i2;
  258. INSERT INTO t2 SELECT * FROM t3;
  259. }
  260. set ::sqlite3_xferopt_count
  261. } {0}
  262. do_test insert4-6.3 {
  263. set ::sqlite3_xferopt_count 0
  264. execsql {
  265. DROP INDEX t2_i1;
  266. CREATE INDEX t2_i1 ON t2(x ASC, y ASC);
  267. INSERT INTO t2 SELECT * FROM t3;
  268. }
  269. set ::sqlite3_xferopt_count
  270. } {1}
  271. do_test insert4-6.4 {
  272. set ::sqlite3_xferopt_count 0
  273. execsql {
  274. DROP INDEX t2_i1;
  275. CREATE INDEX t2_i1 ON t2(x ASC, y COLLATE RTRIM);
  276. INSERT INTO t2 SELECT * FROM t3;
  277. }
  278. set ::sqlite3_xferopt_count
  279. } {0}
  280. do_test insert4-6.5 {
  281. execsql {
  282. CREATE TABLE t6a(x CHECK( x<>'abc' ));
  283. INSERT INTO t6a VALUES('ABC');
  284. SELECT * FROM t6a;
  285. }
  286. } {ABC}
  287. do_test insert4-6.6 {
  288. execsql {
  289. CREATE TABLE t6b(x CHECK( x<>'abc' COLLATE nocase ));
  290. }
  291. catchsql {
  292. INSERT INTO t6b SELECT * FROM t6a;
  293. }
  294. } {1 {constraint failed}}
  295. do_test insert4-6.7 {
  296. execsql {
  297. DROP TABLE t6b;
  298. CREATE TABLE t6b(x CHECK( x COLLATE nocase <>'abc' ));
  299. }
  300. catchsql {
  301. INSERT INTO t6b SELECT * FROM t6a;
  302. }
  303. } {1 {constraint failed}}
  304. # Ticket [6284df89debdfa61db8073e062908af0c9b6118e]
  305. # Disable the xfer optimization if the destination table contains
  306. # a foreign key constraint
  307. #
  308. ifcapable foreignkey {
  309. do_test insert4-7.1 {
  310. set ::sqlite3_xferopt_count 0
  311. execsql {
  312. CREATE TABLE t7a(x INTEGER PRIMARY KEY); INSERT INTO t7a VALUES(123);
  313. CREATE TABLE t7b(y INTEGER REFERENCES t7a);
  314. CREATE TABLE t7c(z INT); INSERT INTO t7c VALUES(234);
  315. INSERT INTO t7b SELECT * FROM t7c;
  316. SELECT * FROM t7b;
  317. }
  318. } {234}
  319. do_test insert4-7.2 {
  320. set ::sqlite3_xferopt_count
  321. } {1}
  322. do_test insert4-7.3 {
  323. set ::sqlite3_xferopt_count 0
  324. execsql {
  325. DELETE FROM t7b;
  326. PRAGMA foreign_keys=ON;
  327. }
  328. catchsql {
  329. INSERT INTO t7b SELECT * FROM t7c;
  330. }
  331. } {1 {foreign key constraint failed}}
  332. do_test insert4-7.4 {
  333. execsql {SELECT * FROM t7b}
  334. } {}
  335. do_test insert4-7.5 {
  336. set ::sqlite3_xferopt_count
  337. } {0}
  338. do_test insert4-7.6 {
  339. set ::sqlite3_xferopt_count 0
  340. execsql {
  341. DELETE FROM t7b; DELETE FROM t7c;
  342. INSERT INTO t7c VALUES(123);
  343. INSERT INTO t7b SELECT * FROM t7c;
  344. SELECT * FROM t7b;
  345. }
  346. } {123}
  347. do_test insert4-7.7 {
  348. set ::sqlite3_xferopt_count
  349. } {0}
  350. do_test insert4-7.7 {
  351. set ::sqlite3_xferopt_count 0
  352. execsql {
  353. PRAGMA foreign_keys=OFF;
  354. DELETE FROM t7b;
  355. INSERT INTO t7b SELECT * FROM t7c;
  356. SELECT * FROM t7b;
  357. }
  358. } {123}
  359. do_test insert4-7.8 {
  360. set ::sqlite3_xferopt_count
  361. } {1}
  362. }
  363. # Ticket [676bc02b87176125635cb174d110b431581912bb]
  364. # Make sure INTEGER PRIMARY KEY ON CONFLICT ... works with the xfer
  365. # optimization.
  366. #
  367. do_test insert4-8.1 {
  368. execsql {
  369. DROP TABLE IF EXISTS t1;
  370. DROP TABLE IF EXISTS t2;
  371. CREATE TABLE t1(a INTEGER PRIMARY KEY ON CONFLICT REPLACE, b);
  372. CREATE TABLE t2(x INTEGER PRIMARY KEY ON CONFLICT REPLACE, y);
  373. INSERT INTO t1 VALUES(1,2);
  374. INSERT INTO t2 VALUES(1,3);
  375. INSERT INTO t1 SELECT * FROM t2;
  376. SELECT * FROM t1;
  377. }
  378. } {1 3}
  379. do_test insert4-8.2 {
  380. execsql {
  381. DROP TABLE IF EXISTS t1;
  382. DROP TABLE IF EXISTS t2;
  383. CREATE TABLE t1(a INTEGER PRIMARY KEY ON CONFLICT REPLACE, b);
  384. CREATE TABLE t2(x, y);
  385. INSERT INTO t1 VALUES(1,2);
  386. INSERT INTO t2 VALUES(1,3);
  387. INSERT INTO t1 SELECT * FROM t2;
  388. SELECT * FROM t1;
  389. }
  390. } {1 3}
  391. do_test insert4-8.3 {
  392. execsql {
  393. DROP TABLE IF EXISTS t1;
  394. DROP TABLE IF EXISTS t2;
  395. CREATE TABLE t1(a INTEGER PRIMARY KEY ON CONFLICT IGNORE, b);
  396. CREATE TABLE t2(x INTEGER PRIMARY KEY ON CONFLICT IGNORE, y);
  397. INSERT INTO t1 VALUES(1,2);
  398. INSERT INTO t2 VALUES(1,3);
  399. INSERT INTO t1 SELECT * FROM t2;
  400. SELECT * FROM t1;
  401. }
  402. } {1 2}
  403. do_test insert4-8.4 {
  404. execsql {
  405. DROP TABLE IF EXISTS t1;
  406. DROP TABLE IF EXISTS t2;
  407. CREATE TABLE t1(a INTEGER PRIMARY KEY ON CONFLICT IGNORE, b);
  408. CREATE TABLE t2(x, y);
  409. INSERT INTO t1 VALUES(1,2);
  410. INSERT INTO t2 VALUES(1,3);
  411. INSERT INTO t1 SELECT * FROM t2;
  412. SELECT * FROM t1;
  413. }
  414. } {1 2}
  415. do_test insert4-8.5 {
  416. execsql {
  417. DROP TABLE IF EXISTS t1;
  418. DROP TABLE IF EXISTS t2;
  419. CREATE TABLE t1(a INTEGER PRIMARY KEY ON CONFLICT FAIL, b);
  420. CREATE TABLE t2(x INTEGER PRIMARY KEY ON CONFLICT FAIL, y);
  421. INSERT INTO t1 VALUES(1,2);
  422. INSERT INTO t2 VALUES(-99,100);
  423. INSERT INTO t2 VALUES(1,3);
  424. SELECT * FROM t1;
  425. }
  426. catchsql {
  427. INSERT INTO t1 SELECT * FROM t2;
  428. }
  429. } {1 {PRIMARY KEY must be unique}}
  430. do_test insert4-8.6 {
  431. execsql {
  432. SELECT * FROM t1;
  433. }
  434. } {-99 100 1 2}
  435. do_test insert4-8.7 {
  436. execsql {
  437. DROP TABLE IF EXISTS t1;
  438. DROP TABLE IF EXISTS t2;
  439. CREATE TABLE t1(a INTEGER PRIMARY KEY ON CONFLICT ABORT, b);
  440. CREATE TABLE t2(x INTEGER PRIMARY KEY ON CONFLICT ABORT, y);
  441. INSERT INTO t1 VALUES(1,2);
  442. INSERT INTO t2 VALUES(-99,100);
  443. INSERT INTO t2 VALUES(1,3);
  444. SELECT * FROM t1;
  445. }
  446. catchsql {
  447. INSERT INTO t1 SELECT * FROM t2;
  448. }
  449. } {1 {PRIMARY KEY must be unique}}
  450. do_test insert4-8.8 {
  451. execsql {
  452. SELECT * FROM t1;
  453. }
  454. } {1 2}
  455. do_test insert4-8.9 {
  456. execsql {
  457. DROP TABLE IF EXISTS t1;
  458. DROP TABLE IF EXISTS t2;
  459. CREATE TABLE t1(a INTEGER PRIMARY KEY ON CONFLICT ROLLBACK, b);
  460. CREATE TABLE t2(x INTEGER PRIMARY KEY ON CONFLICT ROLLBACK, y);
  461. INSERT INTO t1 VALUES(1,2);
  462. INSERT INTO t2 VALUES(-99,100);
  463. INSERT INTO t2 VALUES(1,3);
  464. SELECT * FROM t1;
  465. }
  466. catchsql {
  467. BEGIN;
  468. INSERT INTO t1 VALUES(2,3);
  469. INSERT INTO t1 SELECT * FROM t2;
  470. }
  471. } {1 {PRIMARY KEY must be unique}}
  472. do_test insert4-8.10 {
  473. catchsql {COMMIT}
  474. } {1 {cannot commit - no transaction is active}}
  475. do_test insert4-8.11 {
  476. execsql {
  477. SELECT * FROM t1;
  478. }
  479. } {1 2}
  480. do_test insert4-8.21 {
  481. execsql {
  482. DROP TABLE IF EXISTS t1;
  483. DROP TABLE IF EXISTS t2;
  484. CREATE TABLE t1(a INTEGER PRIMARY KEY ON CONFLICT REPLACE, b);
  485. CREATE TABLE t2(x INTEGER PRIMARY KEY ON CONFLICT REPLACE, y);
  486. INSERT INTO t2 VALUES(1,3);
  487. INSERT INTO t1 SELECT * FROM t2;
  488. SELECT * FROM t1;
  489. }
  490. } {1 3}
  491. do_test insert4-8.22 {
  492. execsql {
  493. DROP TABLE IF EXISTS t1;
  494. DROP TABLE IF EXISTS t2;
  495. CREATE TABLE t1(a INTEGER PRIMARY KEY ON CONFLICT IGNORE, b);
  496. CREATE TABLE t2(x INTEGER PRIMARY KEY ON CONFLICT IGNORE, y);
  497. INSERT INTO t2 VALUES(1,3);
  498. INSERT INTO t1 SELECT * FROM t2;
  499. SELECT * FROM t1;
  500. }
  501. } {1 3}
  502. do_test insert4-8.23 {
  503. execsql {
  504. DROP TABLE IF EXISTS t1;
  505. DROP TABLE IF EXISTS t2;
  506. CREATE TABLE t1(a INTEGER PRIMARY KEY ON CONFLICT ABORT, b);
  507. CREATE TABLE t2(x INTEGER PRIMARY KEY ON CONFLICT ABORT, y);
  508. INSERT INTO t2 VALUES(1,3);
  509. INSERT INTO t1 SELECT * FROM t2;
  510. SELECT * FROM t1;
  511. }
  512. } {1 3}
  513. do_test insert4-8.24 {
  514. execsql {
  515. DROP TABLE IF EXISTS t1;
  516. DROP TABLE IF EXISTS t2;
  517. CREATE TABLE t1(a INTEGER PRIMARY KEY ON CONFLICT FAIL, b);
  518. CREATE TABLE t2(x INTEGER PRIMARY KEY ON CONFLICT FAIL, y);
  519. INSERT INTO t2 VALUES(1,3);
  520. INSERT INTO t1 SELECT * FROM t2;
  521. SELECT * FROM t1;
  522. }
  523. } {1 3}
  524. do_test insert4-8.25 {
  525. execsql {
  526. DROP TABLE IF EXISTS t1;
  527. DROP TABLE IF EXISTS t2;
  528. CREATE TABLE t1(a INTEGER PRIMARY KEY ON CONFLICT ROLLBACK, b);
  529. CREATE TABLE t2(x INTEGER PRIMARY KEY ON CONFLICT ROLLBACK, y);
  530. INSERT INTO t2 VALUES(1,3);
  531. INSERT INTO t1 SELECT * FROM t2;
  532. SELECT * FROM t1;
  533. }
  534. } {1 3}
  535. finish_test