xref: /sqlite-3.40.0/test/types.test (revision 75c014c3)
18d059845Sdanielk1977# 2001 September 15
28d059845Sdanielk1977#
38d059845Sdanielk1977# The author disclaims copyright to this source code.  In place of
48d059845Sdanielk1977# a legal notice, here is a blessing:
58d059845Sdanielk1977#
68d059845Sdanielk1977#    May you do good and not evil.
78d059845Sdanielk1977#    May you find forgiveness for yourself and forgive others.
88d059845Sdanielk1977#    May you share freely, never taking more than you give.
98d059845Sdanielk1977#
108d059845Sdanielk1977#***********************************************************************
11a37cdde0Sdanielk1977# This file implements regression tests for SQLite library. Specfically
12a37cdde0Sdanielk1977# it tests that the different storage classes (integer, real, text etc.)
13a37cdde0Sdanielk1977# all work correctly.
148d059845Sdanielk1977#
1596d48e96Sdanielk1977# $Id: types.test,v 1.20 2009/06/29 06:00:37 danielk1977 Exp $
168d059845Sdanielk1977
178d059845Sdanielk1977set testdir [file dirname $argv0]
188d059845Sdanielk1977source $testdir/tester.tcl
198d059845Sdanielk1977
20a37cdde0Sdanielk1977# Tests in this file are organized roughly as follows:
218d059845Sdanielk1977#
22a37cdde0Sdanielk1977# types-1.*.*: Test that values are stored using the expected storage
23a37cdde0Sdanielk1977#              classes when various forms of literals are inserted into
24a37cdde0Sdanielk1977#              columns with different affinities.
25a37cdde0Sdanielk1977# types-1.1.*: INSERT INTO <table> VALUES(...)
26a37cdde0Sdanielk1977# types-1.2.*: INSERT INTO <table> SELECT...
27a37cdde0Sdanielk1977# types-1.3.*: UPDATE <table> SET...
288d059845Sdanielk1977#
29a37cdde0Sdanielk1977# types-2.*.*: Check that values can be stored and retrieving using the
30a37cdde0Sdanielk1977#              various storage classes.
31a37cdde0Sdanielk1977# types-2.1.*: INTEGER
32a37cdde0Sdanielk1977# types-2.2.*: REAL
33a37cdde0Sdanielk1977# types-2.3.*: NULL
34a37cdde0Sdanielk1977# types-2.4.*: TEXT
35a37cdde0Sdanielk1977# types-2.5.*: Records with a few different storage classes.
368d059845Sdanielk1977#
37a37cdde0Sdanielk1977# types-3.*: Test that the '=' operator respects manifest types.
38a37cdde0Sdanielk1977#
39a37cdde0Sdanielk1977
4025d6543dSdrh# Disable encryption on the database for this test.
4125d6543dSdrhdb close
42a34c62d8Sdrhset DB [sqlite3 db test.db; sqlite3_connection_pointer db]
4325d6543dSdrhsqlite3_rekey $DB {}
44a37cdde0Sdanielk1977
45a37cdde0Sdanielk1977# Create a table with one column for each type of affinity
46a37cdde0Sdanielk1977do_test types-1.1.0 {
47a37cdde0Sdanielk1977  execsql {
48e2ea40d3Sdrh    CREATE TABLE t1(i integer, n numeric, t text, o blob);
49a37cdde0Sdanielk1977  }
50a37cdde0Sdanielk1977} {}
51a37cdde0Sdanielk1977
52a37cdde0Sdanielk1977# Each element of the following list represents one test case.
53a37cdde0Sdanielk1977#
54a37cdde0Sdanielk1977# The first value of each sub-list is an SQL literal. The following
55a37cdde0Sdanielk1977# four value are the storage classes that would be used if the
56a37cdde0Sdanielk1977# literal were inserted into a column with affinity INTEGER, NUMERIC, TEXT
57a37cdde0Sdanielk1977# or NONE, respectively.
58e2ea40d3Sdrhset values {
598a51256cSdrh  { 5.0    integer integer text real    }
608df447f0Sdrh  { 5.1    real    real    text real    }
6135bb9d02Sdanielk1977  { 5      integer integer text integer }
628df447f0Sdrh  { '5.0'  integer integer text text    }
638df447f0Sdrh  { '5.1'  real    real    text text    }
648df447f0Sdrh  { '-5.0' integer integer text text    }
658df447f0Sdrh  { '-5.0' integer integer text text    }
6635bb9d02Sdanielk1977  { '5'    integer integer text text    }
6735bb9d02Sdanielk1977  { 'abc'  text    text    text text    }
6835bb9d02Sdanielk1977  { NULL   null    null    null null    }
69a71aa001Sdrh}
70a71aa001Sdrhifcapable {bloblit} {
716bf89570Sdrh  lappend values  { X'00'  blob    blob    blob blob    }
72a71aa001Sdrh}
73a37cdde0Sdanielk1977
74a37cdde0Sdanielk1977# This code tests that the storage classes specified above (in the $values
75a37cdde0Sdanielk1977# table) are correctly assigned when values are inserted using a statement
76a37cdde0Sdanielk1977# of the form:
77a37cdde0Sdanielk1977#
78a37cdde0Sdanielk1977# INSERT INTO <table> VALUE(<values>);
79a37cdde0Sdanielk1977#
80a37cdde0Sdanielk1977set tnum 1
81a37cdde0Sdanielk1977foreach val $values {
82a37cdde0Sdanielk1977  set lit [lindex $val 0]
83a37cdde0Sdanielk1977  execsql "DELETE FROM t1;"
84a37cdde0Sdanielk1977  execsql "INSERT INTO t1 VALUES($lit, $lit, $lit, $lit);"
85a37cdde0Sdanielk1977  do_test types-1.1.$tnum {
86a37cdde0Sdanielk1977    execsql {
8735bb9d02Sdanielk1977      SELECT typeof(i), typeof(n), typeof(t), typeof(o) FROM t1;
88a37cdde0Sdanielk1977    }
89a37cdde0Sdanielk1977  } [lrange $val 1 end]
90a37cdde0Sdanielk1977  incr tnum
91a37cdde0Sdanielk1977}
92a37cdde0Sdanielk1977
93a37cdde0Sdanielk1977# This code tests that the storage classes specified above (in the $values
94a37cdde0Sdanielk1977# table) are correctly assigned when values are inserted using a statement
95a37cdde0Sdanielk1977# of the form:
96a37cdde0Sdanielk1977#
97a37cdde0Sdanielk1977# INSERT INTO t1 SELECT ....
98a37cdde0Sdanielk1977#
99a37cdde0Sdanielk1977set tnum 1
100a37cdde0Sdanielk1977foreach val $values {
101a37cdde0Sdanielk1977  set lit [lindex $val 0]
102a37cdde0Sdanielk1977  execsql "DELETE FROM t1;"
103a37cdde0Sdanielk1977  execsql "INSERT INTO t1 SELECT $lit, $lit, $lit, $lit;"
104a37cdde0Sdanielk1977  do_test types-1.2.$tnum {
105a37cdde0Sdanielk1977    execsql {
10635bb9d02Sdanielk1977      SELECT typeof(i), typeof(n), typeof(t), typeof(o) FROM t1;
107a37cdde0Sdanielk1977    }
108a37cdde0Sdanielk1977  } [lrange $val 1 end]
109a37cdde0Sdanielk1977  incr tnum
110a37cdde0Sdanielk1977}
111a37cdde0Sdanielk1977
112a37cdde0Sdanielk1977# This code tests that the storage classes specified above (in the $values
113a37cdde0Sdanielk1977# table) are correctly assigned when values are inserted using a statement
114a37cdde0Sdanielk1977# of the form:
115a37cdde0Sdanielk1977#
116a37cdde0Sdanielk1977# UPDATE <table> SET <column> = <value>;
117a37cdde0Sdanielk1977#
118a37cdde0Sdanielk1977set tnum 1
119a37cdde0Sdanielk1977foreach val $values {
120a37cdde0Sdanielk1977  set lit [lindex $val 0]
121a37cdde0Sdanielk1977  execsql "UPDATE t1 SET i = $lit, n = $lit, t = $lit, o = $lit;"
122a37cdde0Sdanielk1977  do_test types-1.3.$tnum {
123a37cdde0Sdanielk1977    execsql {
12435bb9d02Sdanielk1977      SELECT typeof(i), typeof(n), typeof(t), typeof(o) FROM t1;
125a37cdde0Sdanielk1977    }
126a37cdde0Sdanielk1977  } [lrange $val 1 end]
127a37cdde0Sdanielk1977  incr tnum
128a37cdde0Sdanielk1977}
129a37cdde0Sdanielk1977
130a37cdde0Sdanielk1977execsql {
131a37cdde0Sdanielk1977  DROP TABLE t1;
132a37cdde0Sdanielk1977}
1338d059845Sdanielk1977
1348d059845Sdanielk1977# Open the table with root-page $rootpage at the btree
1358d059845Sdanielk1977# level. Return a list that is the length of each record
1368d059845Sdanielk1977# in the table, in the tables default scanning order.
1378d059845Sdanielk1977proc record_sizes {rootpage} {
138*75c014c3Sdrh  set bt [btree_open test.db 10]
13996d48e96Sdanielk1977  btree_begin_transaction $bt
1408d059845Sdanielk1977  set c [btree_cursor $bt $rootpage 0]
1418d059845Sdanielk1977  btree_first $c
1428d059845Sdanielk1977  while 1 {
1438d059845Sdanielk1977    lappend res [btree_payload_size $c]
1448d059845Sdanielk1977    if {[btree_next $c]} break
1458d059845Sdanielk1977  }
1468d059845Sdanielk1977  btree_close_cursor $c
1478d059845Sdanielk1977  btree_close $bt
1488d059845Sdanielk1977  set res
1498d059845Sdanielk1977}
1508d059845Sdanielk1977
1518d059845Sdanielk1977
1528d059845Sdanielk1977# Create a table and insert some 1-byte integers. Make sure they
1538d059845Sdanielk1977# can be read back OK. These should be 3 byte records.
154a37cdde0Sdanielk1977do_test types-2.1.1 {
1558d059845Sdanielk1977  execsql {
1568d059845Sdanielk1977    CREATE TABLE t1(a integer);
1578d059845Sdanielk1977    INSERT INTO t1 VALUES(0);
1588d059845Sdanielk1977    INSERT INTO t1 VALUES(120);
1598d059845Sdanielk1977    INSERT INTO t1 VALUES(-120);
1608d059845Sdanielk1977  }
1618d059845Sdanielk1977} {}
162a37cdde0Sdanielk1977do_test types-2.1.2 {
1638d059845Sdanielk1977  execsql {
1648d059845Sdanielk1977    SELECT a FROM t1;
1658d059845Sdanielk1977  }
1668d059845Sdanielk1977} {0 120 -120}
1678d059845Sdanielk1977
1688d059845Sdanielk1977# Try some 2-byte integers (4 byte records)
169a37cdde0Sdanielk1977do_test types-2.1.3 {
1708d059845Sdanielk1977  execsql {
1718d059845Sdanielk1977    INSERT INTO t1 VALUES(30000);
1728d059845Sdanielk1977    INSERT INTO t1 VALUES(-30000);
1738d059845Sdanielk1977  }
1748d059845Sdanielk1977} {}
175a37cdde0Sdanielk1977do_test types-2.1.4 {
1768d059845Sdanielk1977  execsql {
1778d059845Sdanielk1977    SELECT a FROM t1;
1788d059845Sdanielk1977  }
1798d059845Sdanielk1977} {0 120 -120 30000 -30000}
1808d059845Sdanielk1977
1818d059845Sdanielk1977# 4-byte integers (6 byte records)
182a37cdde0Sdanielk1977do_test types-2.1.5 {
1838d059845Sdanielk1977  execsql {
1848d059845Sdanielk1977    INSERT INTO t1 VALUES(2100000000);
1858d059845Sdanielk1977    INSERT INTO t1 VALUES(-2100000000);
1868d059845Sdanielk1977  }
1878d059845Sdanielk1977} {}
188a37cdde0Sdanielk1977do_test types-2.1.6 {
1898d059845Sdanielk1977  execsql {
1908d059845Sdanielk1977    SELECT a FROM t1;
1918d059845Sdanielk1977  }
1928d059845Sdanielk1977} {0 120 -120 30000 -30000 2100000000 -2100000000}
1938d059845Sdanielk1977
1948d059845Sdanielk1977# 8-byte integers (10 byte records)
195a37cdde0Sdanielk1977do_test types-2.1.7 {
1968d059845Sdanielk1977  execsql {
1978d059845Sdanielk1977    INSERT INTO t1 VALUES(9000000*1000000*1000000);
1988d059845Sdanielk1977    INSERT INTO t1 VALUES(-9000000*1000000*1000000);
1998d059845Sdanielk1977  }
2008d059845Sdanielk1977} {}
201a37cdde0Sdanielk1977do_test types-2.1.8 {
2028d059845Sdanielk1977  execsql {
2038d059845Sdanielk1977    SELECT a FROM t1;
2048d059845Sdanielk1977  }
2058d059845Sdanielk1977} [list 0 120 -120 30000 -30000 2100000000 -2100000000 \
2068d059845Sdanielk1977        9000000000000000000 -9000000000000000000]
2078d059845Sdanielk1977
2088d059845Sdanielk1977# Check that all the record sizes are as we expected.
209ff91c454Sdrhifcapable legacyformat {
210ff91c454Sdrh  do_test types-2.1.9 {
211ff91c454Sdrh    set root [db eval {select rootpage from sqlite_master where name = 't1'}]
212ff91c454Sdrh    record_sizes $root
213ff91c454Sdrh  } {3 3 3 4 4 6 6 10 10}
214ff91c454Sdrh} else {
215a37cdde0Sdanielk1977  do_test types-2.1.9 {
2168d059845Sdanielk1977    set root [db eval {select rootpage from sqlite_master where name = 't1'}]
2178d059845Sdanielk1977    record_sizes $root
218d946db00Sdrh  } {2 3 3 4 4 6 6 10 10}
219ff91c454Sdrh}
2208d059845Sdanielk1977
2218d059845Sdanielk1977# Insert some reals. These should be 10 byte records.
222a37cdde0Sdanielk1977do_test types-2.2.1 {
2238d059845Sdanielk1977  execsql {
2248d059845Sdanielk1977    CREATE TABLE t2(a float);
225a37cdde0Sdanielk1977    INSERT INTO t2 VALUES(0.0);
226a37cdde0Sdanielk1977    INSERT INTO t2 VALUES(12345.678);
227a37cdde0Sdanielk1977    INSERT INTO t2 VALUES(-12345.678);
2288d059845Sdanielk1977  }
2298d059845Sdanielk1977} {}
230a37cdde0Sdanielk1977do_test types-2.2.2 {
2318d059845Sdanielk1977  execsql {
2328d059845Sdanielk1977    SELECT a FROM t2;
2338d059845Sdanielk1977  }
2348a51256cSdrh} {0.0 12345.678 -12345.678}
2358d059845Sdanielk1977
2368d059845Sdanielk1977# Check that all the record sizes are as we expected.
237ff91c454Sdrhifcapable legacyformat {
238ff91c454Sdrh  do_test types-2.2.3 {
239ff91c454Sdrh    set root [db eval {select rootpage from sqlite_master where name = 't2'}]
240ff91c454Sdrh    record_sizes $root
241ff91c454Sdrh  } {3 10 10}
242ff91c454Sdrh} else {
243a37cdde0Sdanielk1977  do_test types-2.2.3 {
2448d059845Sdanielk1977    set root [db eval {select rootpage from sqlite_master where name = 't2'}]
2458d059845Sdanielk1977    record_sizes $root
246d946db00Sdrh  } {2 10 10}
247ff91c454Sdrh}
2488d059845Sdanielk1977
2498d059845Sdanielk1977# Insert a NULL. This should be a two byte record.
250a37cdde0Sdanielk1977do_test types-2.3.1 {
2518d059845Sdanielk1977  execsql {
2528d059845Sdanielk1977    CREATE TABLE t3(a nullvalue);
2538d059845Sdanielk1977    INSERT INTO t3 VALUES(NULL);
2548d059845Sdanielk1977  }
2558d059845Sdanielk1977} {}
256a37cdde0Sdanielk1977do_test types-2.3.2 {
2578d059845Sdanielk1977  execsql {
2588d059845Sdanielk1977    SELECT a ISNULL FROM t3;
2598d059845Sdanielk1977  }
2608d059845Sdanielk1977} {1}
2618d059845Sdanielk1977
2628d059845Sdanielk1977# Check that all the record sizes are as we expected.
263a37cdde0Sdanielk1977do_test types-2.3.3 {
2648d059845Sdanielk1977  set root [db eval {select rootpage from sqlite_master where name = 't3'}]
2658d059845Sdanielk1977  record_sizes $root
266d3194f5aSdrh} {2}
2678d059845Sdanielk1977
2688d059845Sdanielk1977# Insert a couple of strings.
269a37cdde0Sdanielk1977do_test types-2.4.1 {
2708d059845Sdanielk1977  set string10 abcdefghij
2718d059845Sdanielk1977  set string500 [string repeat $string10 50]
2728d059845Sdanielk1977  set string500000 [string repeat $string10 50000]
2738d059845Sdanielk1977
2748d059845Sdanielk1977  execsql "
2758d059845Sdanielk1977    CREATE TABLE t4(a string);
2768d059845Sdanielk1977    INSERT INTO t4 VALUES('$string10');
2778d059845Sdanielk1977    INSERT INTO t4 VALUES('$string500');
2788d059845Sdanielk1977    INSERT INTO t4 VALUES('$string500000');
2798d059845Sdanielk1977  "
2808d059845Sdanielk1977} {}
281a37cdde0Sdanielk1977do_test types-2.4.2 {
2828d059845Sdanielk1977  execsql {
2838d059845Sdanielk1977    SELECT a FROM t4;
2848d059845Sdanielk1977  }
2858d059845Sdanielk1977} [list $string10 $string500 $string500000]
2868d059845Sdanielk1977
28793cd0395Sdanielk1977# Check that all the record sizes are as we expected. This is dependant on
28893cd0395Sdanielk1977# the database encoding.
2896c62608fSdrhif { $sqlite_options(utf16)==0 || [execsql {pragma encoding}] == "UTF-8" } {
290a37cdde0Sdanielk1977  do_test types-2.4.3 {
2918d059845Sdanielk1977    set root [db eval {select rootpage from sqlite_master where name = 't4'}]
2928d059845Sdanielk1977    record_sizes $root
293d3194f5aSdrh  } {12 503 500004}
29493cd0395Sdanielk1977} else {
29593cd0395Sdanielk1977  do_test types-2.4.3 {
29693cd0395Sdanielk1977    set root [db eval {select rootpage from sqlite_master where name = 't4'}]
29793cd0395Sdanielk1977    record_sizes $root
29893cd0395Sdanielk1977  } {22 1003 1000004}
29993cd0395Sdanielk1977}
3008d059845Sdanielk1977
301a37cdde0Sdanielk1977do_test types-2.5.1 {
3028d059845Sdanielk1977  execsql {
3038d059845Sdanielk1977    DROP TABLE t1;
3048d059845Sdanielk1977    DROP TABLE t2;
3058d059845Sdanielk1977    DROP TABLE t3;
3068d059845Sdanielk1977    DROP TABLE t4;
3078d059845Sdanielk1977    CREATE TABLE t1(a, b, c);
3088d059845Sdanielk1977  }
3098d059845Sdanielk1977} {}
310a37cdde0Sdanielk1977do_test types-2.5.2 {
3118d059845Sdanielk1977  set string10 abcdefghij
3128d059845Sdanielk1977  set string500 [string repeat $string10 50]
3138d059845Sdanielk1977  set string500000 [string repeat $string10 50000]
3148d059845Sdanielk1977
3158d059845Sdanielk1977  execsql "INSERT INTO t1 VALUES(NULL, '$string10', 4000);"
3168d059845Sdanielk1977  execsql "INSERT INTO t1 VALUES('$string500', 4000, NULL);"
3178d059845Sdanielk1977  execsql "INSERT INTO t1 VALUES(4000, NULL, '$string500000');"
3188d059845Sdanielk1977} {}
319a37cdde0Sdanielk1977do_test types-2.5.3 {
3208d059845Sdanielk1977  execsql {
3218d059845Sdanielk1977    SELECT * FROM t1;
3228d059845Sdanielk1977  }
3238d059845Sdanielk1977} [list {} $string10 4000 $string500 4000 {} 4000 {} $string500000]
3248d059845Sdanielk1977
3258d059845Sdanielk1977finish_test
326