1*784141eaSdan# 2010 July 16 2*784141eaSdan# 3*784141eaSdan# The author disclaims copyright to this source code. In place of 4*784141eaSdan# a legal notice, here is a blessing: 5*784141eaSdan# 6*784141eaSdan# May you do good and not evil. 7*784141eaSdan# May you find forgiveness for yourself and forgive others. 8*784141eaSdan# May you share freely, never taking more than you give. 9*784141eaSdan# 10*784141eaSdan#*********************************************************************** 11*784141eaSdan# 12*784141eaSdan# This file implements tests to verify that the "testable statements" in 13*784141eaSdan# the lang_expr.html document are correct. 14*784141eaSdan# 15*784141eaSdan 16*784141eaSdanset testdir [file dirname $argv0] 17*784141eaSdansource $testdir/tester.tcl 18*784141eaSdansource $testdir/malloc_common.tcl 19*784141eaSdan 20*784141eaSdan# Set up three global variables: 21*784141eaSdan# 22*784141eaSdan# ::opname An array mapping from SQL operator to an easy to parse 23*784141eaSdan# name. The names are used as part of test case names. 24*784141eaSdan# 25*784141eaSdan# ::opprec An array mapping from SQL operator to a numeric 26*784141eaSdan# precedence value. Operators that group more tightly 27*784141eaSdan# have lower numeric precedences. 28*784141eaSdan# 29*784141eaSdan# ::oplist A list of all SQL operators supported by SQLite. 30*784141eaSdan# 31*784141eaSdanforeach {op opn} { 32*784141eaSdan || cat * mul / div % mod + add 33*784141eaSdan - sub << lshift >> rshift & bitand | bitor 34*784141eaSdan < less <= lesseq > more >= moreeq = eq1 35*784141eaSdan == eq2 <> ne1 != ne2 IS is LIKE like 36*784141eaSdan GLOB glob AND and OR or MATCH match REGEXP regexp 37*784141eaSdan {IS NOT} isnt 38*784141eaSdan} { 39*784141eaSdan set ::opname($op) $opn 40*784141eaSdan} 41*784141eaSdanset oplist [list] 42*784141eaSdanforeach {prec opl} { 43*784141eaSdan 1 || 44*784141eaSdan 2 {* / %} 45*784141eaSdan 3 {+ -} 46*784141eaSdan 4 {<< >> & |} 47*784141eaSdan 5 {< <= > >=} 48*784141eaSdan 6 {= == != <> IS {IS NOT} LIKE GLOB MATCH REGEXP} 49*784141eaSdan 7 AND 50*784141eaSdan 8 OR 51*784141eaSdan} { 52*784141eaSdan foreach op $opl { 53*784141eaSdan set ::opprec($op) $prec 54*784141eaSdan lappend oplist $op 55*784141eaSdan } 56*784141eaSdan} 57*784141eaSdan 58*784141eaSdan 59*784141eaSdan# Hook in definitions of MATCH and REGEX. The following implementations 60*784141eaSdan# cause MATCH and REGEX to behave similarly to the == operator. 61*784141eaSdan# 62*784141eaSdanproc matchfunc {a b} { return [expr {$a==$b}] } 63*784141eaSdanproc regexfunc {a b} { return [expr {$a==$b}] } 64*784141eaSdandb func match -argcount 2 matchfunc 65*784141eaSdandb func regexp -argcount 2 regexfunc 66*784141eaSdan 67*784141eaSdan#------------------------------------------------------------------------- 68*784141eaSdan# Test cases e_expr-1.* attempt to verify that all binary operators listed 69*784141eaSdan# in the documentation exist and that the relative precedences of the 70*784141eaSdan# operators are also as the documentation suggests. 71*784141eaSdan# 72*784141eaSdan# EVIDENCE-OF: R-15514-65163 SQLite understands the following binary 73*784141eaSdan# operators, in order from highest to lowest precedence: || * / % + - 74*784141eaSdan# << >> & | < <= > >= = == != <> IS IS 75*784141eaSdan# NOT IN LIKE GLOB MATCH REGEXP AND OR 76*784141eaSdan# 77*784141eaSdan# EVIDENCE-OF: R-38759-38789 Operators IS and IS NOT have the same 78*784141eaSdan# precedence as =. 79*784141eaSdan# 80*784141eaSdan 81*784141eaSdan 82*784141eaSdan# TODO: These tests are currently omitted because one or two cases 83*784141eaSdan# related to LIKE/GLOB/MATCH/REGEXP fail. After this case is fixed, 84*784141eaSdan# reinstate these tests. 85*784141eaSdan# 86*784141eaSdanif 0 { 87*784141eaSdan 88*784141eaSdanunset -nocomplain untested 89*784141eaSdanforeach op1 $oplist { 90*784141eaSdan foreach op2 $oplist { 91*784141eaSdan set untested($op1,$op2) 1 92*784141eaSdan foreach {tn A B C} { 93*784141eaSdan 1 22 45 66 94*784141eaSdan 2 0 0 0 95*784141eaSdan 3 0 0 1 96*784141eaSdan 4 0 1 0 97*784141eaSdan 5 0 1 1 98*784141eaSdan 6 1 0 0 99*784141eaSdan 7 1 0 1 100*784141eaSdan 8 1 1 0 101*784141eaSdan 9 1 1 1 102*784141eaSdan 10 5 6 1 103*784141eaSdan 11 1 5 6 104*784141eaSdan 12 1 5 5 105*784141eaSdan 13 5 5 1 106*784141eaSdan 107*784141eaSdan 14 5 2 1 108*784141eaSdan 15 1 4 1 109*784141eaSdan 16 -1 0 1 110*784141eaSdan 17 0 1 -1 111*784141eaSdan 112*784141eaSdan } { 113*784141eaSdan set testname "e_expr-1.$opname($op1).$opname($op2).$tn" 114*784141eaSdan 115*784141eaSdan # If $op2 groups more tightly than $op1, then the result 116*784141eaSdan # of executing $sql1 whould be the same as executing $sql3. 117*784141eaSdan # If $op1 groups more tightly, or if $op1 and $op2 have 118*784141eaSdan # the same precedence, then executing $sql1 should return 119*784141eaSdan # the same value as $sql2. 120*784141eaSdan # 121*784141eaSdan set sql1 "SELECT $A $op1 $B $op2 $C" 122*784141eaSdan set sql2 "SELECT ($A $op1 $B) $op2 $C" 123*784141eaSdan set sql3 "SELECT $A $op1 ($B $op2 $C)" 124*784141eaSdan 125*784141eaSdan set a2 [db one $sql2] 126*784141eaSdan set a3 [db one $sql3] 127*784141eaSdan 128*784141eaSdan do_execsql_test $testname $sql1 [list [ 129*784141eaSdan expr {$opprec($op2) < $opprec($op1) ? $a3 : $a2} 130*784141eaSdan ]] 131*784141eaSdan 132*784141eaSdan if {$a2 != $a3} { unset -nocomplain untested($op1,$op2) } 133*784141eaSdan } 134*784141eaSdan } 135*784141eaSdan} 136*784141eaSdan 137*784141eaSdanforeach op {* AND OR + || & |} { unset untested($op,$op) } 138*784141eaSdanunset untested(+,-) ;# Since (a+b)-c == a+(b-c) 139*784141eaSdanunset untested(*,<<) ;# Since (a*b)<<c == a*(b<<c) 140*784141eaSdan 141*784141eaSdando_test e_expr-1.1 { array names untested } {} 142*784141eaSdan 143*784141eaSdan# At one point, test 1.2.2 was failing. Instead of the correct result, it 144*784141eaSdan# was returning {1 1 0}. This would seem to indicate that LIKE has the 145*784141eaSdan# same precedence as '<'. Which is incorrect. It has lower precedence. 146*784141eaSdan# 147*784141eaSdando_execsql_test e_expr-1.2.1 { 148*784141eaSdan SELECT 0 < 2 LIKE 1, (0 < 2) LIKE 1, 0 < (2 LIKE 1) 149*784141eaSdan} {1 1 0} 150*784141eaSdando_execsql_test e_expr-1.2.2 { 151*784141eaSdan SELECT 0 LIKE 0 < 2, (0 LIKE 0) < 2, 0 LIKE (0 < 2) 152*784141eaSdan} {0 1 0} 153*784141eaSdan 154*784141eaSdan# Showing that LIKE and == have the same precedence 155*784141eaSdan# 156*784141eaSdando_execsql_test e_expr-1.2.3 { 157*784141eaSdan SELECT 2 LIKE 2 == 1, (2 LIKE 2) == 1, 2 LIKE (2 == 1) 158*784141eaSdan} {1 1 0} 159*784141eaSdando_execsql_test e_expr-1.2.4 { 160*784141eaSdan SELECT 2 == 2 LIKE 1, (2 == 2) LIKE 1, 2 == (2 LIKE 1) 161*784141eaSdan} {1 1 0} 162*784141eaSdan 163*784141eaSdan# Showing that < groups more tightly than == (< has higher precedence). 164*784141eaSdan# 165*784141eaSdando_execsql_test e_expr-1.2.5 { 166*784141eaSdan SELECT 0 < 2 == 1, (0 < 2) == 1, 0 < (2 == 1) 167*784141eaSdan} {1 1 0} 168*784141eaSdando_execsql_test e_expr-1.6 { 169*784141eaSdan SELECT 0 == 0 < 2, (0 == 0) < 2, 0 == (0 < 2) 170*784141eaSdan} {0 1 0} 171*784141eaSdan 172*784141eaSdan} 173*784141eaSdan 174*784141eaSdan#------------------------------------------------------------------------- 175*784141eaSdan# Check that the four unary prefix operators mentioned in the 176*784141eaSdan# documentation exist. 177*784141eaSdan# 178*784141eaSdan# EVIDENCE-OF: R-13958-53419 Supported unary prefix operators are these: 179*784141eaSdan# - + ~ NOT 180*784141eaSdan# 181*784141eaSdando_execsql_test e_expr-2.1 { SELECT - 10 } {-10} 182*784141eaSdando_execsql_test e_expr-2.2 { SELECT + 10 } {10} 183*784141eaSdando_execsql_test e_expr-2.3 { SELECT ~ 10 } {-11} 184*784141eaSdando_execsql_test e_expr-2.4 { SELECT NOT 10 } {0} 185*784141eaSdan 186*784141eaSdan#------------------------------------------------------------------------- 187*784141eaSdan# Tests for the two statements made regarding the unary + operator. 188*784141eaSdan# 189*784141eaSdan# EVIDENCE-OF: R-53670-03373 The unary operator + is a no-op. 190*784141eaSdan# 191*784141eaSdan# EVIDENCE-OF: R-19480-30968 It can be applied to strings, numbers, 192*784141eaSdan# blobs or NULL and it always returns a result with the same value as 193*784141eaSdan# the operand. 194*784141eaSdan# 195*784141eaSdanforeach {tn literal type} { 196*784141eaSdan 1 'helloworld' text 197*784141eaSdan 2 45 integer 198*784141eaSdan 3 45.2 real 199*784141eaSdan 4 45.0 real 200*784141eaSdan 5 X'ABCDEF' blob 201*784141eaSdan 6 NULL null 202*784141eaSdan} { 203*784141eaSdan set sql " SELECT quote( + $literal ), typeof( + $literal) " 204*784141eaSdan do_execsql_test e_expr-3.$tn $sql [list $literal $type] 205*784141eaSdan} 206*784141eaSdan 207*784141eaSdan#------------------------------------------------------------------------- 208*784141eaSdan# Check that both = and == are both acceptable as the "equals" operator. 209*784141eaSdan# Similarly, either != or <> work as the not-equals operator. 210*784141eaSdan# 211*784141eaSdan# EVIDENCE-OF: R-03679-60639 Equals can be either = or ==. 212*784141eaSdan# 213*784141eaSdan# EVIDENCE-OF: R-30082-38996 The non-equals operator can be either != or 214*784141eaSdan# <>. 215*784141eaSdan# 216*784141eaSdanforeach {tn literal different} { 217*784141eaSdan 1 'helloworld' '12345' 218*784141eaSdan 2 22 23 219*784141eaSdan 3 'xyz' X'78797A' 220*784141eaSdan 4 X'78797A00' 'xyz' 221*784141eaSdan} { 222*784141eaSdan do_execsql_test e_expr-4.$tn " 223*784141eaSdan SELECT $literal = $literal, $literal == $literal, 224*784141eaSdan $literal = $different, $literal == $different, 225*784141eaSdan $literal = NULL, $literal == NULL, 226*784141eaSdan $literal != $literal, $literal <> $literal, 227*784141eaSdan $literal != $different, $literal <> $different, 228*784141eaSdan $literal != NULL, $literal != NULL 229*784141eaSdan 230*784141eaSdan " {1 1 0 0 {} {} 0 0 1 1 {} {}} 231*784141eaSdan} 232*784141eaSdan 233*784141eaSdan#------------------------------------------------------------------------- 234*784141eaSdan# Test the || operator. 235*784141eaSdan# 236*784141eaSdan# EVIDENCE-OF: R-44409-62641 The || operator is "concatenate" - it joins 237*784141eaSdan# together the two strings of its operands. 238*784141eaSdan# 239*784141eaSdanforeach {tn a b} { 240*784141eaSdan 1 'helloworld' '12345' 241*784141eaSdan 2 22 23 242*784141eaSdan} { 243*784141eaSdan set as [db one "SELECT $a"] 244*784141eaSdan set bs [db one "SELECT $b"] 245*784141eaSdan 246*784141eaSdan do_execsql_test e_expr-5.$tn "SELECT $a || $b" [list "${as}${bs}"] 247*784141eaSdan} 248*784141eaSdan 249*784141eaSdan#------------------------------------------------------------------------- 250*784141eaSdan# Test the % operator. 251*784141eaSdan# 252*784141eaSdan# EVIDENCE-OF: R-08914-63790 The operator % outputs the value of its 253*784141eaSdan# left operand modulo its right operand. 254*784141eaSdan# 255*784141eaSdando_execsql_test e_expr-6.1 {SELECT 72%5} {2} 256*784141eaSdando_execsql_test e_expr-6.2 {SELECT 72%-5} {2} 257*784141eaSdando_execsql_test e_expr-6.3 {SELECT -72%-5} {-2} 258*784141eaSdando_execsql_test e_expr-6.4 {SELECT -72%5} {-2} 259*784141eaSdan 260*784141eaSdan#------------------------------------------------------------------------- 261*784141eaSdan# Test that the results of all binary operators are either numeric or 262*784141eaSdan# NULL, except for the || operator, which may evaluate to either a text 263*784141eaSdan# value or NULL. 264*784141eaSdan# 265*784141eaSdan# EVIDENCE-OF: R-20665-17792 The result of any binary operator is either 266*784141eaSdan# a numeric value or NULL, except for the || concatenation operator 267*784141eaSdan# which always evaluates to either NULL or a text value. 268*784141eaSdan# 269*784141eaSdanset literals { 270*784141eaSdan 1 'abc' 2 'hexadecimal' 3 '' 271*784141eaSdan 4 123 5 -123 6 0 272*784141eaSdan 7 123.4 8 0.0 9 -123.4 273*784141eaSdan 10 X'ABCDEF' 11 X'' 12 X'0000' 274*784141eaSdan 13 NULL 275*784141eaSdan} 276*784141eaSdanforeach op $oplist { 277*784141eaSdan foreach {n1 rhs} $literals { 278*784141eaSdan foreach {n2 lhs} $literals { 279*784141eaSdan 280*784141eaSdan set t [db one " SELECT typeof($lhs $op $rhs) "] 281*784141eaSdan do_test e_expr-7.$opname($op).$n1.$n2 { 282*784141eaSdan expr { 283*784141eaSdan ($op=="||" && ($t == "text" || $t == "null")) 284*784141eaSdan || ($op!="||" && ($t == "integer" || $t == "real" || $t == "null")) 285*784141eaSdan } 286*784141eaSdan } 1 287*784141eaSdan 288*784141eaSdan }} 289*784141eaSdan} 290*784141eaSdan 291*784141eaSdan#------------------------------------------------------------------------- 292*784141eaSdan# Test the IS and IS NOT operators. 293*784141eaSdan# 294*784141eaSdan# EVIDENCE-OF: R-24731-45773 The IS and IS NOT operators work like = and 295*784141eaSdan# != except when one or both of the operands are NULL. 296*784141eaSdan# 297*784141eaSdan# EVIDENCE-OF: R-06325-15315 In this case, if both operands are NULL, 298*784141eaSdan# then the IS operator evaluates to 1 (true) and the IS NOT operator 299*784141eaSdan# evaluates to 0 (false). 300*784141eaSdan# 301*784141eaSdan# EVIDENCE-OF: R-19812-36779 If one operand is NULL and the other is 302*784141eaSdan# not, then the IS operator evaluates to 0 (false) and the IS NOT 303*784141eaSdan# operator is 1 (true). 304*784141eaSdan# 305*784141eaSdan# EVIDENCE-OF: R-61975-13410 It is not possible for an IS or IS NOT 306*784141eaSdan# expression to evaluate to NULL. 307*784141eaSdan# 308*784141eaSdando_execsql_test e_expr-8.1.1 { SELECT NULL IS NULL } {1} 309*784141eaSdando_execsql_test e_expr-8.1.2 { SELECT 'ab' IS NULL } {0} 310*784141eaSdando_execsql_test e_expr-8.1.3 { SELECT NULL IS 'ab' } {0} 311*784141eaSdando_execsql_test e_expr-8.1.4 { SELECT 'ab' IS 'ab' } {1} 312*784141eaSdando_execsql_test e_expr-8.1.5 { SELECT NULL == NULL } {{}} 313*784141eaSdando_execsql_test e_expr-8.1.6 { SELECT 'ab' == NULL } {{}} 314*784141eaSdando_execsql_test e_expr-8.1.7 { SELECT NULL == 'ab' } {{}} 315*784141eaSdando_execsql_test e_expr-8.1.8 { SELECT 'ab' == 'ab' } {1} 316*784141eaSdando_execsql_test e_expr-8.1.9 { SELECT NULL IS NOT NULL } {0} 317*784141eaSdando_execsql_test e_expr-8.1.10 { SELECT 'ab' IS NOT NULL } {1} 318*784141eaSdando_execsql_test e_expr-8.1.11 { SELECT NULL IS NOT 'ab' } {1} 319*784141eaSdando_execsql_test e_expr-8.1.12 { SELECT 'ab' IS NOT 'ab' } {0} 320*784141eaSdando_execsql_test e_expr-8.1.13 { SELECT NULL != NULL } {{}} 321*784141eaSdando_execsql_test e_expr-8.1.14 { SELECT 'ab' != NULL } {{}} 322*784141eaSdando_execsql_test e_expr-8.1.15 { SELECT NULL != 'ab' } {{}} 323*784141eaSdando_execsql_test e_expr-8.1.16 { SELECT 'ab' != 'ab' } {0} 324*784141eaSdan 325*784141eaSdanforeach {n1 rhs} $literals { 326*784141eaSdan foreach {n2 lhs} $literals { 327*784141eaSdan if {$rhs!="NULL" && $lhs!="NULL"} { 328*784141eaSdan set eq [execsql "SELECT $lhs = $rhs, $lhs != $rhs"] 329*784141eaSdan } else { 330*784141eaSdan set eq [list [expr {$lhs=="NULL" && $rhs=="NULL"}] \ 331*784141eaSdan [expr {$lhs!="NULL" || $rhs!="NULL"}] 332*784141eaSdan ] 333*784141eaSdan } 334*784141eaSdan set test e_expr-8.2.$n1.$n2 335*784141eaSdan do_execsql_test $test.1 "SELECT $lhs IS $rhs, $lhs IS NOT $rhs" $eq 336*784141eaSdan do_execsql_test $test.2 " 337*784141eaSdan SELECT ($lhs IS $rhs) IS NULL, ($lhs IS NOT $rhs) IS NULL 338*784141eaSdan " {0 0} 339*784141eaSdan } 340*784141eaSdan} 341*784141eaSdan 342*784141eaSdanfinish_test 343