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