| OLD | NEW |
| (Empty) |
| 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.20 2009/06/29 06:00:37 danielk1977 Exp $ | |
| 16 | |
| 17 set testdir [file dirname $argv0] | |
| 18 source $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. | |
| 41 db close | |
| 42 set DB [sqlite3 db test.db; sqlite3_connection_pointer db] | |
| 43 sqlite3_rekey $DB {} | |
| 44 | |
| 45 # Create a table with one column for each type of affinity | |
| 46 do_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. | |
| 58 set values { | |
| 59 { 5.0 integer integer text real } | |
| 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 } | |
| 70 ifcapable {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 # | |
| 80 set tnum 1 | |
| 81 foreach 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 # | |
| 99 set tnum 1 | |
| 100 foreach 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 # | |
| 118 set tnum 1 | |
| 119 foreach 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 | |
| 130 execsql { | |
| 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. | |
| 137 proc record_sizes {rootpage} { | |
| 138 set bt [btree_open test.db 10 0] | |
| 139 btree_begin_transaction $bt | |
| 140 set c [btree_cursor $bt $rootpage 0] | |
| 141 btree_first $c | |
| 142 while 1 { | |
| 143 lappend res [btree_payload_size $c] | |
| 144 if {[btree_next $c]} break | |
| 145 } | |
| 146 btree_close_cursor $c | |
| 147 btree_close $bt | |
| 148 set res | |
| 149 } | |
| 150 | |
| 151 | |
| 152 # Create a table and insert some 1-byte integers. Make sure they | |
| 153 # can be read back OK. These should be 3 byte records. | |
| 154 do_test types-2.1.1 { | |
| 155 execsql { | |
| 156 CREATE TABLE t1(a integer); | |
| 157 INSERT INTO t1 VALUES(0); | |
| 158 INSERT INTO t1 VALUES(120); | |
| 159 INSERT INTO t1 VALUES(-120); | |
| 160 } | |
| 161 } {} | |
| 162 do_test types-2.1.2 { | |
| 163 execsql { | |
| 164 SELECT a FROM t1; | |
| 165 } | |
| 166 } {0 120 -120} | |
| 167 | |
| 168 # Try some 2-byte integers (4 byte records) | |
| 169 do_test types-2.1.3 { | |
| 170 execsql { | |
| 171 INSERT INTO t1 VALUES(30000); | |
| 172 INSERT INTO t1 VALUES(-30000); | |
| 173 } | |
| 174 } {} | |
| 175 do_test types-2.1.4 { | |
| 176 execsql { | |
| 177 SELECT a FROM t1; | |
| 178 } | |
| 179 } {0 120 -120 30000 -30000} | |
| 180 | |
| 181 # 4-byte integers (6 byte records) | |
| 182 do_test types-2.1.5 { | |
| 183 execsql { | |
| 184 INSERT INTO t1 VALUES(2100000000); | |
| 185 INSERT INTO t1 VALUES(-2100000000); | |
| 186 } | |
| 187 } {} | |
| 188 do_test types-2.1.6 { | |
| 189 execsql { | |
| 190 SELECT a FROM t1; | |
| 191 } | |
| 192 } {0 120 -120 30000 -30000 2100000000 -2100000000} | |
| 193 | |
| 194 # 8-byte integers (10 byte records) | |
| 195 do_test types-2.1.7 { | |
| 196 execsql { | |
| 197 INSERT INTO t1 VALUES(9000000*1000000*1000000); | |
| 198 INSERT INTO t1 VALUES(-9000000*1000000*1000000); | |
| 199 } | |
| 200 } {} | |
| 201 do_test types-2.1.8 { | |
| 202 execsql { | |
| 203 SELECT a FROM t1; | |
| 204 } | |
| 205 } [list 0 120 -120 30000 -30000 2100000000 -2100000000 \ | |
| 206 9000000000000000000 -9000000000000000000] | |
| 207 | |
| 208 # Check that all the record sizes are as we expected. | |
| 209 ifcapable legacyformat { | |
| 210 do_test types-2.1.9 { | |
| 211 set root [db eval {select rootpage from sqlite_master where name = 't1'}] | |
| 212 record_sizes $root | |
| 213 } {3 3 3 4 4 6 6 10 10} | |
| 214 } else { | |
| 215 do_test types-2.1.9 { | |
| 216 set root [db eval {select rootpage from sqlite_master where name = 't1'}] | |
| 217 record_sizes $root | |
| 218 } {2 3 3 4 4 6 6 10 10} | |
| 219 } | |
| 220 | |
| 221 # Insert some reals. These should be 10 byte records. | |
| 222 do_test types-2.2.1 { | |
| 223 execsql { | |
| 224 CREATE TABLE t2(a float); | |
| 225 INSERT INTO t2 VALUES(0.0); | |
| 226 INSERT INTO t2 VALUES(12345.678); | |
| 227 INSERT INTO t2 VALUES(-12345.678); | |
| 228 } | |
| 229 } {} | |
| 230 do_test types-2.2.2 { | |
| 231 execsql { | |
| 232 SELECT a FROM t2; | |
| 233 } | |
| 234 } {0.0 12345.678 -12345.678} | |
| 235 | |
| 236 # Check that all the record sizes are as we expected. | |
| 237 ifcapable legacyformat { | |
| 238 do_test types-2.2.3 { | |
| 239 set root [db eval {select rootpage from sqlite_master where name = 't2'}] | |
| 240 record_sizes $root | |
| 241 } {3 10 10} | |
| 242 } else { | |
| 243 do_test types-2.2.3 { | |
| 244 set root [db eval {select rootpage from sqlite_master where name = 't2'}] | |
| 245 record_sizes $root | |
| 246 } {2 10 10} | |
| 247 } | |
| 248 | |
| 249 # Insert a NULL. This should be a two byte record. | |
| 250 do_test types-2.3.1 { | |
| 251 execsql { | |
| 252 CREATE TABLE t3(a nullvalue); | |
| 253 INSERT INTO t3 VALUES(NULL); | |
| 254 } | |
| 255 } {} | |
| 256 do_test types-2.3.2 { | |
| 257 execsql { | |
| 258 SELECT a ISNULL FROM t3; | |
| 259 } | |
| 260 } {1} | |
| 261 | |
| 262 # Check that all the record sizes are as we expected. | |
| 263 do_test types-2.3.3 { | |
| 264 set root [db eval {select rootpage from sqlite_master where name = 't3'}] | |
| 265 record_sizes $root | |
| 266 } {2} | |
| 267 | |
| 268 # Insert a couple of strings. | |
| 269 do_test types-2.4.1 { | |
| 270 set string10 abcdefghij | |
| 271 set string500 [string repeat $string10 50] | |
| 272 set string500000 [string repeat $string10 50000] | |
| 273 | |
| 274 execsql " | |
| 275 CREATE TABLE t4(a string); | |
| 276 INSERT INTO t4 VALUES('$string10'); | |
| 277 INSERT INTO t4 VALUES('$string500'); | |
| 278 INSERT INTO t4 VALUES('$string500000'); | |
| 279 " | |
| 280 } {} | |
| 281 do_test types-2.4.2 { | |
| 282 execsql { | |
| 283 SELECT a FROM t4; | |
| 284 } | |
| 285 } [list $string10 $string500 $string500000] | |
| 286 | |
| 287 # Check that all the record sizes are as we expected. This is dependant on | |
| 288 # the database encoding. | |
| 289 if { $sqlite_options(utf16)==0 || [execsql {pragma encoding}] == "UTF-8" } { | |
| 290 do_test types-2.4.3 { | |
| 291 set root [db eval {select rootpage from sqlite_master where name = 't4'}] | |
| 292 record_sizes $root | |
| 293 } {12 503 500004} | |
| 294 } else { | |
| 295 do_test types-2.4.3 { | |
| 296 set root [db eval {select rootpage from sqlite_master where name = 't4'}] | |
| 297 record_sizes $root | |
| 298 } {22 1003 1000004} | |
| 299 } | |
| 300 | |
| 301 do_test types-2.5.1 { | |
| 302 execsql { | |
| 303 DROP TABLE t1; | |
| 304 DROP TABLE t2; | |
| 305 DROP TABLE t3; | |
| 306 DROP TABLE t4; | |
| 307 CREATE TABLE t1(a, b, c); | |
| 308 } | |
| 309 } {} | |
| 310 do_test types-2.5.2 { | |
| 311 set string10 abcdefghij | |
| 312 set string500 [string repeat $string10 50] | |
| 313 set string500000 [string repeat $string10 50000] | |
| 314 | |
| 315 execsql "INSERT INTO t1 VALUES(NULL, '$string10', 4000);" | |
| 316 execsql "INSERT INTO t1 VALUES('$string500', 4000, NULL);" | |
| 317 execsql "INSERT INTO t1 VALUES(4000, NULL, '$string500000');" | |
| 318 } {} | |
| 319 do_test types-2.5.3 { | |
| 320 execsql { | |
| 321 SELECT * FROM t1; | |
| 322 } | |
| 323 } [list {} $string10 4000 $string500 4000 {} 4000 {} $string500000] | |
| 324 | |
| 325 finish_test | |
| OLD | NEW |