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