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