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