blob: f53cc9d3f207fce862400e011a910f6fd9792a09 [file] [log] [blame]
drhb24fcbe2000-05-29 23:30:50 +00001# Copyright (c) 1999, 2000 D. Richard Hipp
2#
3# This program is free software; you can redistribute it and/or
4# modify it under the terms of the GNU General Public
5# License as published by the Free Software Foundation; either
6# version 2 of the License, or (at your option) any later version.
7#
8# This program is distributed in the hope that it will be useful,
9# but WITHOUT ANY WARRANTY; without even the implied warranty of
10# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11# General Public License for more details.
12#
13# You should have received a copy of the GNU General Public
14# License along with this library; if not, write to the
15# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
16# Boston, MA 02111-1307, USA.
17#
18# Author contact information:
19# drh@hwaci.com
20# http://www.hwaci.com/drh/
21#
22#***********************************************************************
23# This file implements regression tests for SQLite library. The
24# focus of this file is testing the CREATE INDEX statement.
25#
drh1b6a71f2000-05-29 23:58:11 +000026# $Id: index.test,v 1.1 2000/05/29 23:58:12 drh Exp $
drhb24fcbe2000-05-29 23:30:50 +000027
28set testdir [file dirname $argv0]
29source $testdir/tester.tcl
30
31# Create a basic index and verify it is added to sqlite_master
32#
drh1b6a71f2000-05-29 23:58:11 +000033do_test index-1.1 {
drhb24fcbe2000-05-29 23:30:50 +000034 execsql {CREATE TABLE test1(f1 int, f2 int, f3 int)}
35 execsql {CREATE INDEX index1 ON test1(f1)}
36 execsql {SELECT name FROM sqlite_master ORDER BY name}
37} {index1 test1}
drh1b6a71f2000-05-29 23:58:11 +000038do_test index-1.1b {
drhb24fcbe2000-05-29 23:30:50 +000039 execsql {SELECT name, sql, tbl_name, type FROM sqlite_master
40 WHERE name='index1'}
41} {index1 {CREATE INDEX index1 ON test1(f1)} test1 index}
drh1b6a71f2000-05-29 23:58:11 +000042do_test index-1.1c {
drhb24fcbe2000-05-29 23:30:50 +000043 db close
44 sqlite db testdb
45 execsql {SELECT name, sql, tbl_name, type FROM sqlite_master
46 WHERE name='index1'}
47} {index1 {CREATE INDEX index1 ON test1(f1)} test1 index}
drh1b6a71f2000-05-29 23:58:11 +000048do_test index-1.1d {
drhb24fcbe2000-05-29 23:30:50 +000049 db close
50 sqlite db testdb
51 execsql {SELECT name FROM sqlite_master ORDER BY name}
52} {index1 test1}
53
54# Verify that the index dies with the table
55#
drh1b6a71f2000-05-29 23:58:11 +000056do_test index-1.2 {
drhb24fcbe2000-05-29 23:30:50 +000057 execsql {DROP TABLE test1}
58 execsql {SELECT name FROM sqlite_master ORDER BY name}
59} {}
60
61# Try adding an index to a table that does not exist
62#
drh1b6a71f2000-05-29 23:58:11 +000063do_test index-2.1 {
drhb24fcbe2000-05-29 23:30:50 +000064 set v [catch {execsql {CREATE INDEX index1 ON test1(f1)}} msg]
65 lappend v $msg
66} {1 {no such table: test1}}
67
68# Try adding an index on a field of a table where the table
69# exists but the field does not.
70#
drh1b6a71f2000-05-29 23:58:11 +000071do_test index-2.1 {
drhb24fcbe2000-05-29 23:30:50 +000072 execsql {CREATE TABLE test1(f1 int, f2 int, f3 int)}
73 set v [catch {execsql {CREATE INDEX index1 ON test1(f4)}} msg]
74 lappend v $msg
75} {1 {table test1 has no field named f4}}
76
77# Try an index with some fields that match and others that do now.
78#
drh1b6a71f2000-05-29 23:58:11 +000079do_test index-2.2 {
drhb24fcbe2000-05-29 23:30:50 +000080 set v [catch {execsql {CREATE INDEX index1 ON test1(f1, f2, f4, f3)}} msg]
81 execsql {DROP TABLE test1}
82 lappend v $msg
83} {1 {table test1 has no field named f4}}
84
85# Try creating a bunch of indices on the same table
86#
87set r {}
88for {set i 1} {$i<100} {incr i} {
89 lappend r index$i
90}
drh1b6a71f2000-05-29 23:58:11 +000091do_test index-3.1 {
drhb24fcbe2000-05-29 23:30:50 +000092 execsql {CREATE TABLE test1(f1 int, f2 int, f3 int, f4 int, f5 int)}
93 for {set i 1} {$i<100} {incr i} {
94 set sql "CREATE INDEX index$i ON test1(f[expr {($i%5)+1}])"
95 execsql $sql
96 }
97 execsql {SELECT name FROM sqlite_master
98 WHERE type='index' AND tbl_name='test1'
99 ORDER BY name}
100} $r
101
102# Add a single entry to the table. Verify that files are created
103# for every index.
104#
105set r {}
106for {set i 1} {$i<100} {incr i} {
107 lappend r testdb/index$i.tbl
108}
drh1b6a71f2000-05-29 23:58:11 +0000109do_test index-3.2 {
drhb24fcbe2000-05-29 23:30:50 +0000110 execsql {INSERT INTO test1 VALUES(1,2,3,4,5)}
111 lsort -dictionary [glob testdb/index*.tbl]
112} $r
113
114# Verify that all the indices go away when we drop the table.
115#
drh1b6a71f2000-05-29 23:58:11 +0000116do_test index-3.3 {
drhb24fcbe2000-05-29 23:30:50 +0000117 execsql {DROP TABLE test1}
118 execsql {SELECT name FROM sqlite_master
119 WHERE type='index' AND tbl_name='test1'
120 ORDER BY name}
121} {}
drh1b6a71f2000-05-29 23:58:11 +0000122do_test index-3.4 {
drhb24fcbe2000-05-29 23:30:50 +0000123 lsort -dictionary [glob -nocomplain testdb/index*.tbl]
124} {}
125
126# Create a table and insert values into that table. Then create
127# an index on that table. Verify that we can select values
128# from the table correctly using the index.
129#
drh1b6a71f2000-05-29 23:58:11 +0000130do_test index-4.1 {
drhb24fcbe2000-05-29 23:30:50 +0000131 execsql {CREATE TABLE test1(cnt int, power int)}
132 for {set i 1} {$i<20} {incr i} {
133 execsql "INSERT INTO test1 VALUES($i,[expr {int(pow(2,$i))}])"
134 }
135 execsql {CREATE INDEX index1 ON test1(cnt)}
136 execsql {CREATE INDEX index2 ON test1(cnt)}
137 execsql {SELECT name FROM sqlite_master ORDER BY name}
138} {index1 index2 test1}
drh1b6a71f2000-05-29 23:58:11 +0000139do_test index-4.2 {
drhb24fcbe2000-05-29 23:30:50 +0000140 execsql {SELECT cnt FROM test1 WHERE power=4}
141} {2}
drh1b6a71f2000-05-29 23:58:11 +0000142do_test index-4.3 {
drhb24fcbe2000-05-29 23:30:50 +0000143 execsql {SELECT cnt FROM test1 WHERE power=1024}
144} {10}
drh1b6a71f2000-05-29 23:58:11 +0000145do_test index-4.4 {
drhb24fcbe2000-05-29 23:30:50 +0000146 execsql {SELECT power FROM test1 WHERE cnt=6}
147} {64}
drh1b6a71f2000-05-29 23:58:11 +0000148do_test index-4.5 {
drhb24fcbe2000-05-29 23:30:50 +0000149 execsql {DROP TABLE test1}
150} {}
151
152# Do not allow indices to be added to sqlite_master
153#
drh1b6a71f2000-05-29 23:58:11 +0000154do_test index-5.1 {
drhb24fcbe2000-05-29 23:30:50 +0000155 set v [catch {execsql {CREATE INDEX index1 ON sqlite_master(name)}} msg]
156 lappend v $msg
157} {1 {table sqlite_master may not have new indices added}}
drh1b6a71f2000-05-29 23:58:11 +0000158do_test index-5.2 {
drhb24fcbe2000-05-29 23:30:50 +0000159 execsql {SELECT name FROM sqlite_master}
160} {}
161
162# Do not allow indices with duplicate names to be added
163#
drh1b6a71f2000-05-29 23:58:11 +0000164do_test index-6.1 {
drhb24fcbe2000-05-29 23:30:50 +0000165 execsql {CREATE TABLE test1(f1 int, f2 int)}
166 execsql {CREATE TABLE test2(g1 real, g2 real)}
167 execsql {CREATE INDEX index1 ON test1(f1)}
168 set v [catch {execsql {CREATE INDEX index1 ON test2(g1)}} msg]
169 lappend v $msg
170} {1 {index "index1" already exists}}
drh1b6a71f2000-05-29 23:58:11 +0000171do_test index-6.1b {
drhb24fcbe2000-05-29 23:30:50 +0000172 execsql {SELECT name FROM sqlite_master ORDER BY name}
173} {index1 test1 test2}
drh1b6a71f2000-05-29 23:58:11 +0000174do_test index-6.2 {
drhb24fcbe2000-05-29 23:30:50 +0000175 set v [catch {execsql {CREATE INDEX test1 ON test2(g1)}} msg]
176 lappend v $msg
177} {1 {there is already a table named "test1"}}
drh1b6a71f2000-05-29 23:58:11 +0000178do_test index-6.2b {
drhb24fcbe2000-05-29 23:30:50 +0000179 execsql {SELECT name FROM sqlite_master ORDER BY name}
180} {index1 test1 test2}
drh1b6a71f2000-05-29 23:58:11 +0000181do_test index-6.3 {
drhb24fcbe2000-05-29 23:30:50 +0000182 execsql {DROP TABLE test1}
183 execsql {DROP TABLE test2}
184 execsql {SELECT name FROM sqlite_master ORDER BY name}
185} {}
186
187# Create a primary key
188#
drh1b6a71f2000-05-29 23:58:11 +0000189do_test index-7.1 {
drhb24fcbe2000-05-29 23:30:50 +0000190 execsql {CREATE TABLE test1(f1 int, f2 int primary key)}
191 for {set i 1} {$i<20} {incr i} {
192 execsql "INSERT INTO test1 VALUES($i,[expr {int(pow(2,$i))}])"
193 }
194 lsort -dictionary [glob testdb/test1*.tbl]
195} {testdb/test1.tbl testdb/test1__primary_key.tbl}
drh1b6a71f2000-05-29 23:58:11 +0000196do_test index-7.2 {
drhb24fcbe2000-05-29 23:30:50 +0000197 execsql {SELECT f1 FROM test1 WHERE f2=65536}
198} {16}
drh1b6a71f2000-05-29 23:58:11 +0000199do_test index-7.3 {
drhb24fcbe2000-05-29 23:30:50 +0000200 set code [execsql {EXPLAIN SELECT f1 FROM test1 WHERE f2=65536}]
201 expr {[lsearch $code test1__primary_key]>0}
202} {1}
drh1b6a71f2000-05-29 23:58:11 +0000203do_test index-7.4 {
204 execsql {DROP table test1}
205 execsql {SELECT name FROM sqlite_master}
206} {}
207
208# Make sure we cannot drop a non-existant table.
209#
210do_test index-8.1 {
211 set v [catch {execsql {DROP INDEX index1}} msg]
212 lappend v $msg
213} {1 {no such index: "index1"}}
214
215
drhb24fcbe2000-05-29 23:30:50 +0000216
217finish_test