index.test 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384
  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. The
  12. # focus of this file is testing the CREATE INDEX statement.
  13. #
  14. # $Id: index.test,v 1.17 2001/11/24 00:31:47 drh Exp $
  15. set testdir [file dirname $argv0]
  16. source $testdir/tester.tcl
  17. # Create a basic index and verify it is added to sqlite_master
  18. #
  19. do_test index-1.1 {
  20. execsql {CREATE TABLE test1(f1 int, f2 int, f3 int)}
  21. execsql {CREATE INDEX index1 ON test1(f1)}
  22. execsql {SELECT name FROM sqlite_master WHERE type!='meta' ORDER BY name}
  23. } {index1 test1}
  24. do_test index-1.1b {
  25. execsql {SELECT name, sql, tbl_name, type FROM sqlite_master
  26. WHERE name='index1'}
  27. } {index1 {CREATE INDEX index1 ON test1(f1)} test1 index}
  28. do_test index-1.1c {
  29. db close
  30. sqlite db test.db
  31. execsql {SELECT name, sql, tbl_name, type FROM sqlite_master
  32. WHERE name='index1'}
  33. } {index1 {CREATE INDEX index1 ON test1(f1)} test1 index}
  34. do_test index-1.1d {
  35. db close
  36. sqlite db test.db
  37. execsql {SELECT name FROM sqlite_master WHERE type!='meta' ORDER BY name}
  38. } {index1 test1}
  39. # Verify that the index dies with the table
  40. #
  41. do_test index-1.2 {
  42. execsql {DROP TABLE test1}
  43. execsql {SELECT name FROM sqlite_master WHERE type!='meta' ORDER BY name}
  44. } {}
  45. # Try adding an index to a table that does not exist
  46. #
  47. do_test index-2.1 {
  48. set v [catch {execsql {CREATE INDEX index1 ON test1(f1)}} msg]
  49. lappend v $msg
  50. } {1 {no such table: test1}}
  51. # Try adding an index on a column of a table where the table
  52. # exists but the column does not.
  53. #
  54. do_test index-2.1 {
  55. execsql {CREATE TABLE test1(f1 int, f2 int, f3 int)}
  56. set v [catch {execsql {CREATE INDEX index1 ON test1(f4)}} msg]
  57. lappend v $msg
  58. } {1 {table test1 has no column named f4}}
  59. # Try an index with some columns that match and others that do now.
  60. #
  61. do_test index-2.2 {
  62. set v [catch {execsql {CREATE INDEX index1 ON test1(f1, f2, f4, f3)}} msg]
  63. execsql {DROP TABLE test1}
  64. lappend v $msg
  65. } {1 {table test1 has no column named f4}}
  66. # Try creating a bunch of indices on the same table
  67. #
  68. set r {}
  69. for {set i 1} {$i<100} {incr i} {
  70. lappend r index$i
  71. }
  72. do_test index-3.1 {
  73. execsql {CREATE TABLE test1(f1 int, f2 int, f3 int, f4 int, f5 int)}
  74. for {set i 1} {$i<100} {incr i} {
  75. set sql "CREATE INDEX index$i ON test1(f[expr {($i%5)+1}])"
  76. execsql $sql
  77. }
  78. execsql {SELECT name FROM sqlite_master
  79. WHERE type='index' AND tbl_name='test1'
  80. ORDER BY name}
  81. } $r
  82. # Verify that all the indices go away when we drop the table.
  83. #
  84. do_test index-3.3 {
  85. execsql {DROP TABLE test1}
  86. execsql {SELECT name FROM sqlite_master
  87. WHERE type='index' AND tbl_name='test1'
  88. ORDER BY name}
  89. } {}
  90. # Create a table and insert values into that table. Then create
  91. # an index on that table. Verify that we can select values
  92. # from the table correctly using the index.
  93. #
  94. # Note that the index names "index9" and "indext" are chosen because
  95. # they both have the same hash.
  96. #
  97. do_test index-4.1 {
  98. execsql {CREATE TABLE test1(cnt int, power int)}
  99. for {set i 1} {$i<20} {incr i} {
  100. execsql "INSERT INTO test1 VALUES($i,[expr {int(pow(2,$i))}])"
  101. }
  102. execsql {CREATE INDEX index9 ON test1(cnt)}
  103. execsql {CREATE INDEX indext ON test1(power)}
  104. execsql {SELECT name FROM sqlite_master WHERE type!='meta' ORDER BY name}
  105. } {index9 indext test1}
  106. do_test index-4.2 {
  107. execsql {SELECT cnt FROM test1 WHERE power=4}
  108. } {2}
  109. do_test index-4.3 {
  110. execsql {SELECT cnt FROM test1 WHERE power=1024}
  111. } {10}
  112. do_test index-4.4 {
  113. execsql {SELECT power FROM test1 WHERE cnt=6}
  114. } {64}
  115. do_test index-4.5 {
  116. execsql {DROP INDEX indext}
  117. execsql {SELECT power FROM test1 WHERE cnt=6}
  118. } {64}
  119. do_test index-4.6 {
  120. execsql {SELECT cnt FROM test1 WHERE power=1024}
  121. } {10}
  122. do_test index-4.7 {
  123. execsql {CREATE INDEX indext ON test1(cnt)}
  124. execsql {SELECT power FROM test1 WHERE cnt=6}
  125. } {64}
  126. do_test index-4.8 {
  127. execsql {SELECT cnt FROM test1 WHERE power=1024}
  128. } {10}
  129. do_test index-4.9 {
  130. execsql {DROP INDEX index9}
  131. execsql {SELECT power FROM test1 WHERE cnt=6}
  132. } {64}
  133. do_test index-4.10 {
  134. execsql {SELECT cnt FROM test1 WHERE power=1024}
  135. } {10}
  136. do_test index-4.11 {
  137. execsql {DROP INDEX indext}
  138. execsql {SELECT power FROM test1 WHERE cnt=6}
  139. } {64}
  140. do_test index-4.12 {
  141. execsql {SELECT cnt FROM test1 WHERE power=1024}
  142. } {10}
  143. do_test index-4.13 {
  144. execsql {DROP TABLE test1}
  145. execsql {SELECT name FROM sqlite_master WHERE type!='meta' ORDER BY name}
  146. } {}
  147. # Do not allow indices to be added to sqlite_master
  148. #
  149. do_test index-5.1 {
  150. set v [catch {execsql {CREATE INDEX index1 ON sqlite_master(name)}} msg]
  151. lappend v $msg
  152. } {1 {table sqlite_master may not have new indices added}}
  153. do_test index-5.2 {
  154. execsql {SELECT name FROM sqlite_master WHERE type!='meta'}
  155. } {}
  156. # Do not allow indices with duplicate names to be added
  157. #
  158. do_test index-6.1 {
  159. execsql {CREATE TABLE test1(f1 int, f2 int)}
  160. execsql {CREATE TABLE test2(g1 real, g2 real)}
  161. execsql {CREATE INDEX index1 ON test1(f1)}
  162. set v [catch {execsql {CREATE INDEX index1 ON test2(g1)}} msg]
  163. lappend v $msg
  164. } {1 {index index1 already exists}}
  165. do_test index-6.1b {
  166. execsql {SELECT name FROM sqlite_master WHERE type!='meta' ORDER BY name}
  167. } {index1 test1 test2}
  168. do_test index-6.2 {
  169. set v [catch {execsql {CREATE INDEX test1 ON test2(g1)}} msg]
  170. lappend v $msg
  171. } {1 {there is already a table named test1}}
  172. do_test index-6.2b {
  173. execsql {SELECT name FROM sqlite_master WHERE type!='meta' ORDER BY name}
  174. } {index1 test1 test2}
  175. do_test index-6.3 {
  176. execsql {DROP TABLE test1}
  177. execsql {DROP TABLE test2}
  178. execsql {SELECT name FROM sqlite_master WHERE type!='meta' ORDER BY name}
  179. } {}
  180. do_test index-6.4 {
  181. execsql {
  182. CREATE TABLE test1(a,b);
  183. CREATE INDEX index1 ON test1(a);
  184. CREATE INDEX index2 ON test1(b);
  185. CREATE INDEX index3 ON test1(a,b);
  186. DROP TABLE test1;
  187. SELECT name FROM sqlite_master WHERE type!='meta' ORDER BY name;
  188. }
  189. } {}
  190. # Create a primary key
  191. #
  192. do_test index-7.1 {
  193. execsql {CREATE TABLE test1(f1 int, f2 int primary key)}
  194. for {set i 1} {$i<20} {incr i} {
  195. execsql "INSERT INTO test1 VALUES($i,[expr {int(pow(2,$i))}])"
  196. }
  197. execsql {SELECT count(*) FROM test1}
  198. } {19}
  199. do_test index-7.2 {
  200. execsql {SELECT f1 FROM test1 WHERE f2=65536}
  201. } {16}
  202. do_test index-7.3 {
  203. execsql {
  204. SELECT name FROM sqlite_master
  205. WHERE type='index' AND tbl_name='test1'
  206. }
  207. } {{(test1 autoindex 1)}}
  208. do_test index-7.4 {
  209. execsql {DROP table test1}
  210. execsql {SELECT name FROM sqlite_master WHERE type!='meta'}
  211. } {}
  212. # Make sure we cannot drop a non-existant index.
  213. #
  214. do_test index-8.1 {
  215. set v [catch {execsql {DROP INDEX index1}} msg]
  216. lappend v $msg
  217. } {1 {no such index: index1}}
  218. # Make sure we don't actually create an index when the EXPLAIN keyword
  219. # is used.
  220. #
  221. do_test index-9.1 {
  222. execsql {CREATE TABLE tab1(a int)}
  223. execsql {EXPLAIN CREATE INDEX idx1 ON tab1(a)}
  224. execsql {SELECT name FROM sqlite_master WHERE tbl_name='tab1'}
  225. } {tab1}
  226. do_test index-9.2 {
  227. execsql {CREATE INDEX idx1 ON tab1(a)}
  228. execsql {SELECT name FROM sqlite_master WHERE tbl_name='tab1' ORDER BY name}
  229. } {idx1 tab1}
  230. # Allow more than one entry with the same key.
  231. #
  232. do_test index-10.0 {
  233. execsql {
  234. CREATE TABLE t1(a int, b int);
  235. CREATE INDEX i1 ON t1(a);
  236. INSERT INTO t1 VALUES(1,2);
  237. INSERT INTO t1 VALUES(2,4);
  238. INSERT INTO t1 VALUES(3,8);
  239. INSERT INTO t1 VALUES(1,12);
  240. SELECT b FROM t1 WHERE a=1 ORDER BY b;
  241. }
  242. } {2 12}
  243. do_test index-10.1 {
  244. execsql {
  245. SELECT b FROM t1 WHERE a=2 ORDER BY b;
  246. }
  247. } {4}
  248. do_test index-10.2 {
  249. execsql {
  250. DELETE FROM t1 WHERE b=12;
  251. SELECT b FROM t1 WHERE a=1 ORDER BY b;
  252. }
  253. } {2}
  254. do_test index-10.3 {
  255. execsql {
  256. DELETE FROM t1 WHERE b=2;
  257. SELECT b FROM t1 WHERE a=1 ORDER BY b;
  258. }
  259. } {}
  260. do_test index-10.4 {
  261. execsql {
  262. DELETE FROM t1;
  263. INSERT INTO t1 VALUES (1,1);
  264. INSERT INTO t1 VALUES (1,2);
  265. INSERT INTO t1 VALUES (1,3);
  266. INSERT INTO t1 VALUES (1,4);
  267. INSERT INTO t1 VALUES (1,5);
  268. INSERT INTO t1 VALUES (1,6);
  269. INSERT INTO t1 VALUES (1,7);
  270. INSERT INTO t1 VALUES (1,8);
  271. INSERT INTO t1 VALUES (1,9);
  272. INSERT INTO t1 VALUES (2,0);
  273. SELECT b FROM t1 WHERE a=1 ORDER BY b;
  274. }
  275. } {1 2 3 4 5 6 7 8 9}
  276. do_test index-10.5 {
  277. execsql {
  278. DELETE FROM t1 WHERE b IN (2, 4, 6, 8);
  279. SELECT b FROM t1 WHERE a=1 ORDER BY b;
  280. }
  281. } {1 3 5 7 9}
  282. do_test index-10.6 {
  283. execsql {
  284. DELETE FROM t1 WHERE b>2;
  285. SELECT b FROM t1 WHERE a=1 ORDER BY b;
  286. }
  287. } {1}
  288. do_test index-10.7 {
  289. execsql {
  290. DELETE FROM t1 WHERE b=1;
  291. SELECT b FROM t1 WHERE a=1 ORDER BY b;
  292. }
  293. } {}
  294. do_test index-10.8 {
  295. execsql {
  296. SELECT b FROM t1 ORDER BY b;
  297. }
  298. } {0}
  299. # Automatically create an index when we specify a primary key.
  300. #
  301. do_test index-11.1 {
  302. execsql {
  303. CREATE TABLE t3(
  304. a text,
  305. b int,
  306. c float,
  307. PRIMARY KEY(b)
  308. );
  309. }
  310. for {set i 1} {$i<=50} {incr i} {
  311. execsql "INSERT INTO t3 VALUES('x${i}x',$i,0.$i)"
  312. }
  313. set sqlite_search_count 0
  314. concat [execsql {SELECT c FROM t3 WHERE b==10}] $sqlite_search_count
  315. } {0.10 3}
  316. # Numeric strings should compare as if they were numbers. So even if the
  317. # strings are not character-by-character the same, if they represent the
  318. # same number they should compare equal to one another. Verify that this
  319. # is true in indices.
  320. #
  321. do_test index-12.1 {
  322. execsql {
  323. CREATE TABLE t4(a,b);
  324. INSERT INTO t4 VALUES('0.0',1);
  325. INSERT INTO t4 VALUES('0.00',2);
  326. INSERT INTO t4 VALUES('abc',3);
  327. INSERT INTO t4 VALUES('-1.0',4);
  328. INSERT INTO t4 VALUES('+1.0',5);
  329. INSERT INTO t4 VALUES('0',6);
  330. INSERT INTO t4 VALUES('00000',7);
  331. SELECT a FROM t4 ORDER BY b;
  332. }
  333. } {0.0 0.00 abc -1.0 +1.0 0 00000}
  334. do_test index-12.2 {
  335. execsql {
  336. SELECT a FROM t4 WHERE a==0 ORDER BY b
  337. }
  338. } {0.0 0.00 0 00000}
  339. do_test index-12.3 {
  340. execsql {
  341. SELECT a FROM t4 WHERE a<0.5 ORDER BY b
  342. }
  343. } {0.0 0.00 -1.0 0 00000}
  344. do_test index-12.4 {
  345. execsql {
  346. SELECT a FROM t4 WHERE a>-0.5 ORDER BY b
  347. }
  348. } {0.0 0.00 abc +1.0 0 00000}
  349. do_test index-12.5 {
  350. execsql {
  351. CREATE INDEX t4i1 ON t4(a);
  352. SELECT a FROM t4 WHERE a==0 ORDER BY b
  353. }
  354. } {0.0 0.00 0 00000}
  355. do_test index-12.6 {
  356. execsql {
  357. SELECT a FROM t4 WHERE a<0.5 ORDER BY b
  358. }
  359. } {0.0 0.00 -1.0 0 00000}
  360. do_test index-12.7 {
  361. execsql {
  362. SELECT a FROM t4 WHERE a>-0.5 ORDER BY b
  363. }
  364. } {0.0 0.00 abc +1.0 0 00000}
  365. finish_test