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