xref: /sqlite-3.40.0/test/types.test (revision a37cdde0)
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. Specfically
12# it tests that the different storage classes (integer, real, text etc.)
13# all work correctly.
14#
15# $Id: types.test,v 1.2 2004/05/16 11:15:42 danielk1977 Exp $
16
17set testdir [file dirname $argv0]
18source $testdir/tester.tcl
19
20# Tests in this file are organized roughly as follows:
21#
22# types-1.*.*: Test that values are stored using the expected storage
23#              classes when various forms of literals are inserted into
24#              columns with different affinities.
25# types-1.1.*: INSERT INTO <table> VALUES(...)
26# types-1.2.*: INSERT INTO <table> SELECT...
27# types-1.3.*: UPDATE <table> SET...
28#
29# types-2.*.*: Check that values can be stored and retrieving using the
30#              various storage classes.
31# types-2.1.*: INTEGER
32# types-2.2.*: REAL
33# types-2.3.*: NULL
34# types-2.4.*: TEXT
35# types-2.5.*: Records with a few different storage classes.
36#
37# types-3.*: Test that the '=' operator respects manifest types.
38#
39
40
41# Create a table with one column for each type of affinity
42do_test types-1.1.0 {
43  execsql {
44    CREATE TABLE t1(i integer, n numeric, t text, o);
45  }
46} {}
47
48# Each element of the following list represents one test case.
49#
50# The first value of each sub-list is an SQL literal. The following
51# four value are the storage classes that would be used if the
52# literal were inserted into a column with affinity INTEGER, NUMERIC, TEXT
53# or NONE, respectively.
54set values [list \
55  [list 5.0   INTEGER REAL    TEXT REAL] \
56  [list 5     INTEGER INTEGER TEXT INTEGER] \
57  [list '5.0' INTEGER REAL    TEXT TEXT] \
58  [list '5'   INTEGER INTEGER TEXT TEXT] \
59  [list 'abc' TEXT    TEXT    TEXT TEXT] \
60  [list NULL  NULL    NULL    NULL NULL] \
61]
62
63# This code tests that the storage classes specified above (in the $values
64# table) are correctly assigned when values are inserted using a statement
65# of the form:
66#
67# INSERT INTO <table> VALUE(<values>);
68#
69set tnum 1
70foreach val $values {
71  set lit [lindex $val 0]
72  execsql "DELETE FROM t1;"
73  execsql "INSERT INTO t1 VALUES($lit, $lit, $lit, $lit);"
74  do_test types-1.1.$tnum {
75    execsql {
76      SELECT classof(i), classof(n), classof(t), classof(o) FROM t1;
77    }
78  } [lrange $val 1 end]
79  incr tnum
80}
81
82# This code tests that the storage classes specified above (in the $values
83# table) are correctly assigned when values are inserted using a statement
84# of the form:
85#
86# INSERT INTO t1 SELECT ....
87#
88set tnum 1
89foreach val $values {
90  set lit [lindex $val 0]
91  execsql "DELETE FROM t1;"
92  execsql "INSERT INTO t1 SELECT $lit, $lit, $lit, $lit;"
93  do_test types-1.2.$tnum {
94    execsql {
95      SELECT classof(i), classof(n), classof(t), classof(o) FROM t1;
96    }
97  } [lrange $val 1 end]
98  incr tnum
99}
100
101# This code tests that the storage classes specified above (in the $values
102# table) are correctly assigned when values are inserted using a statement
103# of the form:
104#
105# UPDATE <table> SET <column> = <value>;
106#
107set tnum 1
108foreach val $values {
109  set lit [lindex $val 0]
110  execsql "UPDATE t1 SET i = $lit, n = $lit, t = $lit, o = $lit;"
111  do_test types-1.3.$tnum {
112    execsql {
113      SELECT classof(i), classof(n), classof(t), classof(o) FROM t1;
114    }
115  } [lrange $val 1 end]
116  incr tnum
117}
118
119execsql {
120  DROP TABLE t1;
121}
122
123# Open the table with root-page $rootpage at the btree
124# level. Return a list that is the length of each record
125# in the table, in the tables default scanning order.
126proc record_sizes {rootpage} {
127  set bt [btree_open test.db 10 0]
128  set c [btree_cursor $bt $rootpage 0]
129  btree_first $c
130  while 1 {
131    lappend res [btree_payload_size $c]
132    if {[btree_next $c]} break
133  }
134  btree_close_cursor $c
135  btree_close $bt
136  set res
137}
138
139
140# Create a table and insert some 1-byte integers. Make sure they
141# can be read back OK. These should be 3 byte records.
142do_test types-2.1.1 {
143  execsql {
144    CREATE TABLE t1(a integer);
145    INSERT INTO t1 VALUES(0);
146    INSERT INTO t1 VALUES(120);
147    INSERT INTO t1 VALUES(-120);
148  }
149} {}
150do_test types-2.1.2 {
151  execsql {
152    SELECT a FROM t1;
153  }
154} {0 120 -120}
155
156# Try some 2-byte integers (4 byte records)
157do_test types-2.1.3 {
158  execsql {
159    INSERT INTO t1 VALUES(30000);
160    INSERT INTO t1 VALUES(-30000);
161  }
162} {}
163do_test types-2.1.4 {
164  execsql {
165    SELECT a FROM t1;
166  }
167} {0 120 -120 30000 -30000}
168
169# 4-byte integers (6 byte records)
170do_test types-2.1.5 {
171  execsql {
172    INSERT INTO t1 VALUES(2100000000);
173    INSERT INTO t1 VALUES(-2100000000);
174  }
175} {}
176do_test types-2.1.6 {
177  execsql {
178    SELECT a FROM t1;
179  }
180} {0 120 -120 30000 -30000 2100000000 -2100000000}
181
182# 8-byte integers (10 byte records)
183do_test types-2.1.7 {
184  execsql {
185    INSERT INTO t1 VALUES(9000000*1000000*1000000);
186    INSERT INTO t1 VALUES(-9000000*1000000*1000000);
187  }
188} {}
189do_test types-2.1.8 {
190  execsql {
191    SELECT a FROM t1;
192  }
193} [list 0 120 -120 30000 -30000 2100000000 -2100000000 \
194        9000000000000000000 -9000000000000000000]
195
196# Check that all the record sizes are as we expected.
197do_test types-2.1.9 {
198  set root [db eval {select rootpage from sqlite_master where name = 't1'}]
199  record_sizes $root
200} {3 3 3 4 4 6 6 10 10}
201
202# Insert some reals. These should be 10 byte records.
203do_test types-2.2.1 {
204  execsql {
205    CREATE TABLE t2(a float);
206    INSERT INTO t2 VALUES(0.0);
207    INSERT INTO t2 VALUES(12345.678);
208    INSERT INTO t2 VALUES(-12345.678);
209  }
210} {}
211do_test types-2.2.2 {
212  execsql {
213    SELECT a FROM t2;
214  }
215} {0 12345.678 -12345.678}
216
217# Check that all the record sizes are as we expected.
218do_test types-2.2.3 {
219  set root [db eval {select rootpage from sqlite_master where name = 't2'}]
220  record_sizes $root
221} {10 10 10}
222
223# Insert a NULL. This should be a two byte record.
224do_test types-2.3.1 {
225  execsql {
226    CREATE TABLE t3(a nullvalue);
227    INSERT INTO t3 VALUES(NULL);
228  }
229} {}
230do_test types-2.3.2 {
231  execsql {
232    SELECT a ISNULL FROM t3;
233  }
234} {1}
235
236# Check that all the record sizes are as we expected.
237do_test types-2.3.3 {
238  set root [db eval {select rootpage from sqlite_master where name = 't3'}]
239  record_sizes $root
240} {2}
241
242# Insert a couple of strings.
243do_test types-2.4.1 {
244  set string10 abcdefghij
245  set string500 [string repeat $string10 50]
246  set string500000 [string repeat $string10 50000]
247
248  execsql "
249    CREATE TABLE t4(a string);
250    INSERT INTO t4 VALUES('$string10');
251    INSERT INTO t4 VALUES('$string500');
252    INSERT INTO t4 VALUES('$string500000');
253  "
254} {}
255do_test types-2.4.2 {
256  execsql {
257    SELECT a FROM t4;
258  }
259} [list $string10 $string500 $string500000]
260
261# Check that all the record sizes are as we expected.
262do_test types-2.4.3 {
263  set root [db eval {select rootpage from sqlite_master where name = 't4'}]
264  record_sizes $root
265} {13 504 500005}
266
267do_test types-2.5.1 {
268  execsql {
269    DROP TABLE t1;
270    DROP TABLE t2;
271    DROP TABLE t3;
272    DROP TABLE t4;
273    CREATE TABLE t1(a, b, c);
274  }
275} {}
276do_test types-2.5.2 {
277  set string10 abcdefghij
278  set string500 [string repeat $string10 50]
279  set string500000 [string repeat $string10 50000]
280
281  execsql "INSERT INTO t1 VALUES(NULL, '$string10', 4000);"
282  execsql "INSERT INTO t1 VALUES('$string500', 4000, NULL);"
283  execsql "INSERT INTO t1 VALUES(4000, NULL, '$string500000');"
284} {}
285do_test types-2.5.3 {
286  execsql {
287    SELECT * FROM t1;
288  }
289} [list {} $string10 4000 $string500 4000 {} 4000 {} $string500000]
290
291finish_test
292
293