github.com/jdgcs/sqlite3@v1.12.1-0.20210908114423-bc5f96e4dd51/testdata/tcl/func6.test (about) 1 # 2017-12-16 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 # 12 # Test cases for the sqlite_offset() function. 13 # 14 # Some of the tests in this file depend on the exact placement of content 15 # within b-tree pages. Such placement is at the implementations discretion, 16 # and so it is possible for results to change from one release to the next. 17 # 18 set testdir [file dirname $argv0] 19 source $testdir/tester.tcl 20 ifcapable !offset_sql_func { 21 finish_test 22 return 23 } 24 25 set bNullTrim 0 26 ifcapable null_trim { 27 set bNullTrim 1 28 } 29 30 do_execsql_test func6-100 { 31 PRAGMA page_size=4096; 32 PRAGMA auto_vacuum=NONE; 33 CREATE TABLE t1(a,b,c,d); 34 WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<100) 35 INSERT INTO t1(a,b,c,d) SELECT printf('abc%03x',x), x, 1000-x, NULL FROM c; 36 CREATE INDEX t1a ON t1(a); 37 CREATE INDEX t1bc ON t1(b,c); 38 CREATE TABLE t2(x TEXT PRIMARY KEY, y) WITHOUT ROWID; 39 INSERT INTO t2(x,y) SELECT a, b FROM t1; 40 } 41 42 # Load the contents of $file from disk and return it encoded as a hex 43 # string. 44 proc loadhex {file} { 45 set fd [open $file] 46 fconfigure $fd -translation binary -encoding binary 47 set data [read $fd] 48 close $fd 49 binary encode hex $data 50 } 51 52 # Each argument is either an integer between 0 and 65535, a text value, or 53 # an empty string representing an SQL NULL. This command builds an SQLite 54 # record containing the values passed as arguments and returns it encoded 55 # as a hex string. 56 proc hexrecord {args} { 57 set hdr "" 58 set body "" 59 60 if {$::bNullTrim} { 61 while {[llength $args] && [lindex $args end]=={}} { 62 set args [lrange $args 0 end-1] 63 } 64 } 65 66 foreach x $args { 67 if {$x==""} { 68 append hdr 00 69 } elseif {[string is integer $x]==0} { 70 set n [string length $x] 71 append hdr [format %02x [expr $n*2 + 13]] 72 append body [binary encode hex $x] 73 } elseif {$x == 0} { 74 append hdr 08 75 } elseif {$x == 1} { 76 append hdr 09 77 } elseif {$x <= 127} { 78 append hdr 01 79 append body [format %02x $x] 80 } else { 81 append hdr 02 82 append body [format %04x $x] 83 } 84 } 85 set res [format %02x [expr 1 + [string length $hdr]/2]] 86 append res $hdr 87 append res $body 88 } 89 90 # Argument $off is an offset into the database image encoded as a hex string 91 # in argument $hexdb. This command returns 0 if the offset contains the hex 92 # $hexrec, or throws an exception otherwise. 93 # 94 proc offset_contains_record {off hexdb hexrec} { 95 set n [string length $hexrec] 96 set off [expr $off*2] 97 if { [string compare $hexrec [string range $hexdb $off [expr $off+$n-1]]] } { 98 error "record not found!" 99 } 100 return 0 101 } 102 103 # This command is the implementation of SQL function "offrec()". The first 104 # argument to this is an offset value. The remaining values are used to 105 # formulate an SQLite record. If database file test.db does not contain 106 # an equivalent record at the specified offset, an exception is thrown. 107 # Otherwise, 0 is returned. 108 # 109 proc offrec {args} { 110 set offset [lindex $args 0] 111 set rec [hexrecord {*}[lrange $args 1 end]] 112 offset_contains_record $offset $::F $rec 113 } 114 set F [loadhex test.db] 115 db func offrec offrec 116 117 # Test the sanity of the tests. 118 if {$bNullTrim} { 119 set offset 8180 120 } else { 121 set offset 8179 122 } 123 do_execsql_test func6-105 { 124 SELECT sqlite_offset(d) FROM t1 ORDER BY rowid LIMIT 1; 125 } $offset 126 do_test func6-106 { 127 set r [hexrecord abc001 1 999 {}] 128 offset_contains_record $offset $F $r 129 } 0 130 131 set z100 [string trim [string repeat "0 " 100]] 132 133 # Test offsets within table b-tree t1. 134 do_execsql_test func6-110 { 135 SELECT offrec(sqlite_offset(d), a, b, c, d) FROM t1 ORDER BY rowid 136 } $z100 137 138 do_execsql_test func6-120 { 139 SELECT a, typeof(sqlite_offset(+a)) FROM t1 140 ORDER BY rowid LIMIT 2; 141 } {abc001 null abc002 null} 142 143 # Test offsets within index b-tree t1a. 144 do_execsql_test func6-130 { 145 SELECT offrec(sqlite_offset(a), a, rowid) FROM t1 ORDER BY a 146 } $z100 147 148 # Test offsets within table b-tree t1 with a temp b-tree ORDER BY. 149 do_execsql_test func6-140 { 150 SELECT offrec(sqlite_offset(d), a, b, c, d) FROM t1 ORDER BY a 151 } $z100 152 153 # Test offsets from both index t1a and table t1 in the same query. 154 do_execsql_test func6-150 { 155 SELECT offrec(sqlite_offset(a), a, rowid), 156 offrec(sqlite_offset(d), a, b, c, d) 157 FROM t1 ORDER BY a 158 } [concat $z100 $z100] 159 160 # Test offsets from both index t1bc and table t1 in the same query. 161 do_execsql_test func6-160 { 162 SELECT offrec(sqlite_offset(b), b, c, rowid), 163 offrec(sqlite_offset(c), b, c, rowid), 164 offrec(sqlite_offset(d), a, b, c, d) 165 FROM t1 166 ORDER BY b 167 } [concat $z100 $z100 $z100] 168 169 # Test offsets in WITHOUT ROWID table t2. 170 do_execsql_test func6-200 { 171 SELECT offrec( sqlite_offset(y), x, y ) FROM t2 ORDER BY x 172 } $z100 173 174 finish_test