intpkey.test 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459
  1. # 2001 September 15
  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.
  12. #
  13. # This file implements tests for the special processing associated
  14. # with INTEGER PRIMARY KEY columns.
  15. #
  16. # $Id: intpkey.test,v 1.9 2002/03/31 18:29:03 drh Exp $
  17. set testdir [file dirname $argv0]
  18. source $testdir/tester.tcl
  19. # Create a table with a primary key and a datatype other than
  20. # integer
  21. #
  22. do_test intpkey-1.0 {
  23. execsql {
  24. CREATE TABLE t1(a TEXT PRIMARY KEY, b, c);
  25. }
  26. } {}
  27. # There should be an index associated with the primary key
  28. #
  29. do_test intpkey-1.1 {
  30. execsql {
  31. SELECT name FROM sqlite_master
  32. WHERE type='index' AND tbl_name='t1';
  33. }
  34. } {{(t1 autoindex 1)}}
  35. # Now create a table with an integer primary key and verify that
  36. # there is no associated index.
  37. #
  38. do_test intpkey-1.2 {
  39. execsql {
  40. DROP TABLE t1;
  41. CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
  42. SELECT name FROM sqlite_master
  43. WHERE type='index' AND tbl_name='t1';
  44. }
  45. } {}
  46. # Insert some records into the new table. Specify the primary key
  47. # and verify that the key is used as the record number.
  48. #
  49. do_test intpkey-1.3 {
  50. execsql {
  51. INSERT INTO t1 VALUES(5,'hello','world');
  52. }
  53. db last_insert_rowid
  54. } {5}
  55. do_test intpkey-1.4 {
  56. execsql {
  57. SELECT * FROM t1;
  58. }
  59. } {5 hello world}
  60. do_test intpkey-1.5 {
  61. execsql {
  62. SELECT rowid, * FROM t1;
  63. }
  64. } {5 5 hello world}
  65. # Attempting to insert a duplicate primary key should give a constraint
  66. # failure.
  67. #
  68. do_test intpkey-1.6 {
  69. set r [catch {execsql {
  70. INSERT INTO t1 VALUES(5,'second','entry');
  71. }} msg]
  72. lappend r $msg
  73. } {1 {constraint failed}}
  74. do_test intpkey-1.7 {
  75. execsql {
  76. SELECT rowid, * FROM t1;
  77. }
  78. } {5 5 hello world}
  79. do_test intpkey-1.8 {
  80. set r [catch {execsql {
  81. INSERT INTO t1 VALUES(6,'second','entry');
  82. }} msg]
  83. lappend r $msg
  84. } {0 {}}
  85. do_test intpkey-1.8.1 {
  86. db last_insert_rowid
  87. } {6}
  88. do_test intpkey-1.9 {
  89. execsql {
  90. SELECT rowid, * FROM t1;
  91. }
  92. } {5 5 hello world 6 6 second entry}
  93. # A ROWID is automatically generated for new records that do not specify
  94. # the integer primary key.
  95. #
  96. do_test intpkey-1.10 {
  97. execsql {
  98. INSERT INTO t1(b,c) VALUES('one','two');
  99. SELECT b FROM t1 ORDER BY b;
  100. }
  101. } {hello one second}
  102. # Try to change the ROWID for the new entry.
  103. #
  104. do_test intpkey-1.11 {
  105. execsql {
  106. UPDATE t1 SET a=4 WHERE b='one';
  107. SELECT * FROM t1;
  108. }
  109. } {4 one two 5 hello world 6 second entry}
  110. # Make sure SELECT statements are able to use the primary key column
  111. # as an index.
  112. #
  113. do_test intpkey-1.12 {
  114. execsql {
  115. SELECT * FROM t1 WHERE a==4;
  116. }
  117. } {4 one two}
  118. # Try to insert a non-integer value into the primary key field. This
  119. # should result in a data type mismatch.
  120. #
  121. do_test intpkey-1.13 {
  122. set r [catch {execsql {
  123. INSERT INTO t1 VALUES('x','y','z');
  124. }} msg]
  125. lappend r $msg
  126. } {1 {datatype mismatch}}
  127. do_test intpkey-1.14 {
  128. set r [catch {execsql {
  129. INSERT INTO t1 VALUES(3.4,'y','z');
  130. }} msg]
  131. lappend r $msg
  132. } {1 {datatype mismatch}}
  133. do_test intpkey-1.15 {
  134. set r [catch {execsql {
  135. INSERT INTO t1 VALUES(-3,'y','z');
  136. }} msg]
  137. lappend r $msg
  138. } {0 {}}
  139. do_test intpkey-1.16 {
  140. execsql {SELECT * FROM t1}
  141. } {-3 y z 4 one two 5 hello world 6 second entry}
  142. #### INDICES
  143. # Check to make sure indices work correctly with integer primary keys
  144. #
  145. do_test intpkey-2.1 {
  146. execsql {
  147. CREATE INDEX i1 ON t1(b);
  148. SELECT * FROM t1 WHERE b=='y'
  149. }
  150. } {-3 y z}
  151. do_test intpkey-2.1.1 {
  152. execsql {
  153. SELECT * FROM t1 WHERE b=='y' AND rowid<0
  154. }
  155. } {-3 y z}
  156. do_test intpkey-2.1.2 {
  157. execsql {
  158. SELECT * FROM t1 WHERE b=='y' AND rowid<0 AND rowid>=-20
  159. }
  160. } {-3 y z}
  161. do_test intpkey-2.1.3 {
  162. execsql {
  163. SELECT * FROM t1 WHERE b>='y'
  164. }
  165. } {-3 y z}
  166. do_test intpkey-2.1.4 {
  167. execsql {
  168. SELECT * FROM t1 WHERE b>='y' AND rowid<10
  169. }
  170. } {-3 y z}
  171. do_test intpkey-2.2 {
  172. execsql {
  173. UPDATE t1 SET a=8 WHERE b=='y';
  174. SELECT * FROM t1 WHERE b=='y';
  175. }
  176. } {8 y z}
  177. do_test intpkey-2.3 {
  178. execsql {
  179. SELECT rowid, * FROM t1;
  180. }
  181. } {4 4 one two 5 5 hello world 6 6 second entry 8 8 y z}
  182. do_test intpkey-2.4 {
  183. execsql {
  184. SELECT rowid, * FROM t1 WHERE b<'second'
  185. }
  186. } {5 5 hello world 4 4 one two}
  187. do_test intpkey-2.4.1 {
  188. execsql {
  189. SELECT rowid, * FROM t1 WHERE 'second'>b
  190. }
  191. } {5 5 hello world 4 4 one two}
  192. do_test intpkey-2.4.2 {
  193. execsql {
  194. SELECT rowid, * FROM t1 WHERE 8>rowid AND 'second'>b
  195. }
  196. } {4 4 one two 5 5 hello world}
  197. do_test intpkey-2.4.3 {
  198. execsql {
  199. SELECT rowid, * FROM t1 WHERE 8>rowid AND 'second'>b AND 0<rowid
  200. }
  201. } {4 4 one two 5 5 hello world}
  202. do_test intpkey-2.5 {
  203. execsql {
  204. SELECT rowid, * FROM t1 WHERE b>'a'
  205. }
  206. } {5 5 hello world 4 4 one two 6 6 second entry 8 8 y z}
  207. do_test intpkey-2.6 {
  208. execsql {
  209. DELETE FROM t1 WHERE rowid=4;
  210. SELECT * FROM t1 WHERE b>'a';
  211. }
  212. } {5 hello world 6 second entry 8 y z}
  213. do_test intpkey-2.7 {
  214. execsql {
  215. UPDATE t1 SET a=-4 WHERE rowid=8;
  216. SELECT * FROM t1 WHERE b>'a';
  217. }
  218. } {5 hello world 6 second entry -4 y z}
  219. do_test intpkey-2.7 {
  220. execsql {
  221. SELECT * FROM t1
  222. }
  223. } {-4 y z 5 hello world 6 second entry}
  224. # Do an SQL statement. Append the search count to the end of the result.
  225. #
  226. proc count sql {
  227. set ::sqlite_search_count 0
  228. return [concat [execsql $sql] $::sqlite_search_count]
  229. }
  230. # Create indices that include the integer primary key as one of their
  231. # columns.
  232. #
  233. do_test intpkey-3.1 {
  234. execsql {
  235. CREATE INDEX i2 ON t1(a);
  236. }
  237. } {}
  238. do_test intpkey-3.2 {
  239. count {
  240. SELECT * FROM t1 WHERE a=5;
  241. }
  242. } {5 hello world 0}
  243. do_test intpkey-3.3 {
  244. count {
  245. SELECT * FROM t1 WHERE a>4 AND a<6;
  246. }
  247. } {5 hello world 2}
  248. do_test intpkey-3.4 {
  249. count {
  250. SELECT * FROM t1 WHERE b>='hello' AND b<'hello2';
  251. }
  252. } {5 hello world 3}
  253. do_test intpkey-3.5 {
  254. execsql {
  255. CREATE INDEX i3 ON t1(c,a);
  256. }
  257. } {}
  258. do_test intpkey-3.6 {
  259. count {
  260. SELECT * FROM t1 WHERE c=='world';
  261. }
  262. } {5 hello world 3}
  263. do_test intpkey-3.7 {
  264. execsql {INSERT INTO t1 VALUES(11,'hello','world')}
  265. count {
  266. SELECT * FROM t1 WHERE c=='world';
  267. }
  268. } {5 hello world 11 hello world 5}
  269. do_test intpkey-3.8 {
  270. count {
  271. SELECT * FROM t1 WHERE c=='world' AND a>7;
  272. }
  273. } {11 hello world 5}
  274. do_test intpkey-3.9 {
  275. count {
  276. SELECT * FROM t1 WHERE 7<a;
  277. }
  278. } {11 hello world 1}
  279. # Test inequality constraints on integer primary keys and rowids
  280. #
  281. do_test intpkey-4.1 {
  282. count {
  283. SELECT * FROM t1 WHERE 11=rowid
  284. }
  285. } {11 hello world 0}
  286. do_test intpkey-4.2 {
  287. count {
  288. SELECT * FROM t1 WHERE 11=rowid AND b=='hello'
  289. }
  290. } {11 hello world 0}
  291. do_test intpkey-4.3 {
  292. count {
  293. SELECT * FROM t1 WHERE 11=rowid AND b=='hello' AND c IS NOT NULL;
  294. }
  295. } {11 hello world 0}
  296. do_test intpkey-4.4 {
  297. count {
  298. SELECT * FROM t1 WHERE rowid==11
  299. }
  300. } {11 hello world 0}
  301. do_test intpkey-4.5 {
  302. count {
  303. SELECT * FROM t1 WHERE oid==11 AND b=='hello'
  304. }
  305. } {11 hello world 0}
  306. do_test intpkey-4.6 {
  307. count {
  308. SELECT * FROM t1 WHERE a==11 AND b=='hello' AND c IS NOT NULL;
  309. }
  310. } {11 hello world 0}
  311. do_test intpkey-4.7 {
  312. count {
  313. SELECT * FROM t1 WHERE 8<rowid;
  314. }
  315. } {11 hello world 1}
  316. do_test intpkey-4.8 {
  317. count {
  318. SELECT * FROM t1 WHERE 8<rowid AND 11>=oid;
  319. }
  320. } {11 hello world 1}
  321. do_test intpkey-4.9 {
  322. count {
  323. SELECT * FROM t1 WHERE 11<=_rowid_ AND 12>=a;
  324. }
  325. } {11 hello world 1}
  326. do_test intpkey-4.10 {
  327. count {
  328. SELECT * FROM t1 WHERE 0>=_rowid_;
  329. }
  330. } {-4 y z 1}
  331. do_test intpkey-4.11 {
  332. count {
  333. SELECT * FROM t1 WHERE a<0;
  334. }
  335. } {-4 y z 1}
  336. do_test intpkey-4.12 {
  337. count {
  338. SELECT * FROM t1 WHERE a<0 AND a>10;
  339. }
  340. } {1}
  341. # Make sure it is OK to insert a rowid of 0
  342. #
  343. do_test intpkey-5.1 {
  344. execsql {
  345. INSERT INTO t1 VALUES(0,'zero','entry');
  346. }
  347. count {
  348. SELECT * FROM t1 WHERE a=0;
  349. }
  350. } {0 zero entry 0}
  351. do_test intpkey=5.2 {
  352. execsql {
  353. SELECT rowid, a FROM t1
  354. }
  355. } {-4 -4 0 0 5 5 6 6 11 11}
  356. # Test the ability of the COPY command to put data into a
  357. # table that contains an integer primary key.
  358. #
  359. do_test intpkey-6.1 {
  360. set f [open ./data1.txt w]
  361. puts $f "20\tb-20\tc-20"
  362. puts $f "21\tb-21\tc-21"
  363. puts $f "22\tb-22\tc-22"
  364. close $f
  365. execsql {
  366. COPY t1 FROM 'data1.txt';
  367. SELECT * FROM t1 WHERE a>=20;
  368. }
  369. } {20 b-20 c-20 21 b-21 c-21 22 b-22 c-22}
  370. do_test intpkey-6.2 {
  371. execsql {
  372. SELECT * FROM t1 WHERE b=='hello'
  373. }
  374. } {5 hello world 11 hello world}
  375. do_test intpkey-6.3 {
  376. execsql {
  377. DELETE FROM t1 WHERE b='b-21';
  378. SELECT * FROM t1 WHERE b=='b-21';
  379. }
  380. } {}
  381. do_test intpkey-6.4 {
  382. execsql {
  383. SELECT * FROM t1 WHERE a>=20
  384. }
  385. } {20 b-20 c-20 22 b-22 c-22}
  386. # Do an insert of values with the columns specified out of order.
  387. #
  388. do_test intpkey-7.1 {
  389. execsql {
  390. INSERT INTO t1(c,b,a) VALUES('row','new',30);
  391. SELECT * FROM t1 WHERE rowid>=30;
  392. }
  393. } {30 new row}
  394. do_test intpkey-7.2 {
  395. execsql {
  396. SELECT * FROM t1 WHERE rowid>20;
  397. }
  398. } {22 b-22 c-22 30 new row}
  399. # Do an insert from a select statement.
  400. #
  401. do_test intpkey-8.1 {
  402. execsql {
  403. CREATE TABLE t2(x INTEGER PRIMARY KEY, y, z);
  404. INSERT INTO t2 SELECT * FROM t1;
  405. SELECT rowid FROM t2;
  406. }
  407. } {-4 0 5 6 11 20 22 30}
  408. do_test intpkey-8.2 {
  409. execsql {
  410. SELECT x FROM t2;
  411. }
  412. } {-4 0 5 6 11 20 22 30}
  413. do_test intpkey-9.1 {
  414. execsql {
  415. UPDATE t1 SET c='www' WHERE c='world';
  416. SELECT rowid, a, c FROM t1 WHERE c=='www';
  417. }
  418. } {5 5 www 11 11 www}
  419. # Check insert of NULL for primary key
  420. #
  421. do_test intpkey-10.1 {
  422. execsql {
  423. DROP TABLE t2;
  424. CREATE TABLE t2(x INTEGER PRIMARY KEY, y, z);
  425. INSERT INTO t2 VALUES(NULL, 1, 2);
  426. SELECT * from t2;
  427. }
  428. } {1 1 2}
  429. do_test intpkey-10.2 {
  430. execsql {
  431. INSERT INTO t2 VALUES(NULL, 2, 3);
  432. SELECT * from t2 WHERE x=2;
  433. }
  434. } {2 2 3}
  435. finish_test