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