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