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