xref: /sqlite-3.40.0/test/types.test (revision cc195879)
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.9 2004/06/30 03:08:25 drh 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 blob);
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 {
55  { 5.0    integer real    text real    }
56  { 5      integer integer text integer }
57  { '5.0'  integer real    text text    }
58  { '-5.0' integer real    text text    }
59  { '-5.0' integer real    text text    }
60  { '5'    integer integer text text    }
61  { 'abc'  text    text    text text    }
62  { NULL   null    null    null null    }
63  { X'00'  blob    blob    blob blob    }
64}
65
66# This code tests that the storage classes specified above (in the $values
67# table) are correctly assigned when values are inserted using a statement
68# of the form:
69#
70# INSERT INTO <table> VALUE(<values>);
71#
72set tnum 1
73foreach val $values {
74  set lit [lindex $val 0]
75  execsql "DELETE FROM t1;"
76  execsql "INSERT INTO t1 VALUES($lit, $lit, $lit, $lit);"
77  do_test types-1.1.$tnum {
78    execsql {
79      SELECT typeof(i), typeof(n), typeof(t), typeof(o) FROM t1;
80    }
81  } [lrange $val 1 end]
82  incr tnum
83}
84
85# This code tests that the storage classes specified above (in the $values
86# table) are correctly assigned when values are inserted using a statement
87# of the form:
88#
89# INSERT INTO t1 SELECT ....
90#
91set tnum 1
92foreach val $values {
93  set lit [lindex $val 0]
94  execsql "DELETE FROM t1;"
95  execsql "INSERT INTO t1 SELECT $lit, $lit, $lit, $lit;"
96  do_test types-1.2.$tnum {
97    execsql {
98      SELECT typeof(i), typeof(n), typeof(t), typeof(o) FROM t1;
99    }
100  } [lrange $val 1 end]
101  incr tnum
102}
103
104# This code tests that the storage classes specified above (in the $values
105# table) are correctly assigned when values are inserted using a statement
106# of the form:
107#
108# UPDATE <table> SET <column> = <value>;
109#
110set tnum 1
111foreach val $values {
112  set lit [lindex $val 0]
113  execsql "UPDATE t1 SET i = $lit, n = $lit, t = $lit, o = $lit;"
114  do_test types-1.3.$tnum {
115    execsql {
116      SELECT typeof(i), typeof(n), typeof(t), typeof(o) FROM t1;
117    }
118  } [lrange $val 1 end]
119  incr tnum
120}
121
122execsql {
123  DROP TABLE t1;
124}
125
126# Open the table with root-page $rootpage at the btree
127# level. Return a list that is the length of each record
128# in the table, in the tables default scanning order.
129proc record_sizes {rootpage} {
130  set bt [btree_open test.db 10 0]
131  set c [btree_cursor $bt $rootpage 0]
132  btree_first $c
133  while 1 {
134    lappend res [btree_payload_size $c]
135    if {[btree_next $c]} break
136  }
137  btree_close_cursor $c
138  btree_close $bt
139  set res
140}
141
142
143# Create a table and insert some 1-byte integers. Make sure they
144# can be read back OK. These should be 3 byte records.
145do_test types-2.1.1 {
146  execsql {
147    CREATE TABLE t1(a integer);
148    INSERT INTO t1 VALUES(0);
149    INSERT INTO t1 VALUES(120);
150    INSERT INTO t1 VALUES(-120);
151  }
152} {}
153do_test types-2.1.2 {
154  execsql {
155    SELECT a FROM t1;
156  }
157} {0 120 -120}
158
159# Try some 2-byte integers (4 byte records)
160do_test types-2.1.3 {
161  execsql {
162    INSERT INTO t1 VALUES(30000);
163    INSERT INTO t1 VALUES(-30000);
164  }
165} {}
166do_test types-2.1.4 {
167  execsql {
168    SELECT a FROM t1;
169  }
170} {0 120 -120 30000 -30000}
171
172# 4-byte integers (6 byte records)
173do_test types-2.1.5 {
174  execsql {
175    INSERT INTO t1 VALUES(2100000000);
176    INSERT INTO t1 VALUES(-2100000000);
177  }
178} {}
179do_test types-2.1.6 {
180  execsql {
181    SELECT a FROM t1;
182  }
183} {0 120 -120 30000 -30000 2100000000 -2100000000}
184
185# 8-byte integers (10 byte records)
186do_test types-2.1.7 {
187  execsql {
188    INSERT INTO t1 VALUES(9000000*1000000*1000000);
189    INSERT INTO t1 VALUES(-9000000*1000000*1000000);
190  }
191} {}
192do_test types-2.1.8 {
193  execsql {
194    SELECT a FROM t1;
195  }
196} [list 0 120 -120 30000 -30000 2100000000 -2100000000 \
197        9000000000000000000 -9000000000000000000]
198
199# Check that all the record sizes are as we expected.
200do_test types-2.1.9 {
201  set root [db eval {select rootpage from sqlite_master where name = 't1'}]
202  record_sizes $root
203} {3 3 3 4 4 6 6 10 10}
204
205# Insert some reals. These should be 10 byte records.
206do_test types-2.2.1 {
207  execsql {
208    CREATE TABLE t2(a float);
209    INSERT INTO t2 VALUES(0.0);
210    INSERT INTO t2 VALUES(12345.678);
211    INSERT INTO t2 VALUES(-12345.678);
212  }
213} {}
214do_test types-2.2.2 {
215  execsql {
216    SELECT a FROM t2;
217  }
218} {0 12345.678 -12345.678}
219
220# Check that all the record sizes are as we expected.
221do_test types-2.2.3 {
222  set root [db eval {select rootpage from sqlite_master where name = 't2'}]
223  record_sizes $root
224} {10 10 10}
225
226# Insert a NULL. This should be a two byte record.
227do_test types-2.3.1 {
228  execsql {
229    CREATE TABLE t3(a nullvalue);
230    INSERT INTO t3 VALUES(NULL);
231  }
232} {}
233do_test types-2.3.2 {
234  execsql {
235    SELECT a ISNULL FROM t3;
236  }
237} {1}
238
239# Check that all the record sizes are as we expected.
240do_test types-2.3.3 {
241  set root [db eval {select rootpage from sqlite_master where name = 't3'}]
242  record_sizes $root
243} {2}
244
245# Insert a couple of strings.
246do_test types-2.4.1 {
247  set string10 abcdefghij
248  set string500 [string repeat $string10 50]
249  set string500000 [string repeat $string10 50000]
250
251  execsql "
252    CREATE TABLE t4(a string);
253    INSERT INTO t4 VALUES('$string10');
254    INSERT INTO t4 VALUES('$string500');
255    INSERT INTO t4 VALUES('$string500000');
256  "
257} {}
258do_test types-2.4.2 {
259  execsql {
260    SELECT a FROM t4;
261  }
262} [list $string10 $string500 $string500000]
263
264# Check that all the record sizes are as we expected. This is dependant on
265# the database encoding.
266if { [execsql {pragma encoding}] == "UTF-8" } {
267  do_test types-2.4.3 {
268    set root [db eval {select rootpage from sqlite_master where name = 't4'}]
269    record_sizes $root
270  } {12 503 500004}
271} else {
272  do_test types-2.4.3 {
273    set root [db eval {select rootpage from sqlite_master where name = 't4'}]
274    record_sizes $root
275  } {22 1003 1000004}
276}
277
278do_test types-2.5.1 {
279  execsql {
280    DROP TABLE t1;
281    DROP TABLE t2;
282    DROP TABLE t3;
283    DROP TABLE t4;
284    CREATE TABLE t1(a, b, c);
285  }
286} {}
287do_test types-2.5.2 {
288  set string10 abcdefghij
289  set string500 [string repeat $string10 50]
290  set string500000 [string repeat $string10 50000]
291
292  execsql "INSERT INTO t1 VALUES(NULL, '$string10', 4000);"
293  execsql "INSERT INTO t1 VALUES('$string500', 4000, NULL);"
294  execsql "INSERT INTO t1 VALUES(4000, NULL, '$string500000');"
295} {}
296do_test types-2.5.3 {
297  execsql {
298    SELECT * FROM t1;
299  }
300} [list {} $string10 4000 $string500 4000 {} 4000 {} $string500000]
301
302finish_test
303