]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Add new test file e_expr.test.
authordan <dan@noemail.net>
Sat, 17 Jul 2010 18:44:49 +0000 (18:44 +0000)
committerdan <dan@noemail.net>
Sat, 17 Jul 2010 18:44:49 +0000 (18:44 +0000)
FossilOrigin-Name: cbcf8abbb2cb3e603cc3da45075f6b076e5cad56

manifest
manifest.uuid
test/e_expr.test [new file with mode: 0644]

index 93265c273e833107e4c66ecb974e3fb379396219..6dfd9869ce627e40d939d20e59f8fd405ce3dc6a 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Do\snot\srun\sjournal3.test\swith\sthe\sinmemory_journal\spermutation.
-D 2010-07-17T09:27:31
+C Add\snew\stest\sfile\se_expr.test.
+D 2010-07-17T18:44:49
 F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
 F Makefile.in ec08dc838fd8110fe24c92e5130bcd91cbb1ff2e
 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
@@ -340,6 +340,7 @@ F test/descidx2.test 9f1a0c83fd57f8667c82310ca21b30a350888b5d
 F test/descidx3.test fe720e8b37d59f4cef808b0bf4e1b391c2e56b6f
 F test/diskfull.test 0cede7ef9d8f415d9d3944005c76be7589bb5ebb
 F test/distinctagg.test 1a6ef9c87a58669438fc771450d7a72577417376
+F test/e_expr.test 68532b32ca29cf399bbb951f46a906c452ada668
 F test/e_fkey.test 6721a741c6499b3ab7e5385923233343c8f1ad05
 F test/e_fts3.test 75bb0aee26384ef586165e21018a17f7cd843469
 F test/enc.test e54531cd6bf941ee6760be041dff19a104c7acea
@@ -836,7 +837,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
 F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
-P 1218d3703ad23d01ce0d7cbcabdc9e0d864f8717
-R 131c874797e36bc1ae5ed7d7ff386c83
+P e1d228e992fe8da1fc5aef95d9bc8be62c6b46c7
+R 052d9ddc87605f8176899391baedd484
 U dan
-Z 4948c684a3d7cde65d8b8528e6a96683
+Z a94751afe56623aed508c4e989148fe1
index 18d79ff3c7d715a093e0397d0fda966ec00af911..080a5dea7ed3c4c4631f9202de4aea6ca0298c1e 100644 (file)
@@ -1 +1 @@
-e1d228e992fe8da1fc5aef95d9bc8be62c6b46c7
\ No newline at end of file
+cbcf8abbb2cb3e603cc3da45075f6b076e5cad56
\ No newline at end of file
diff --git a/test/e_expr.test b/test/e_expr.test
new file mode 100644 (file)
index 0000000..c9edaeb
--- /dev/null
@@ -0,0 +1,342 @@
+# 2010 July 16
+#
+# The author disclaims copyright to this source code.  In place of
+# a legal notice, here is a blessing:
+#
+#    May you do good and not evil.
+#    May you find forgiveness for yourself and forgive others.
+#    May you share freely, never taking more than you give.
+#
+#***********************************************************************
+#
+# This file implements tests to verify that the "testable statements" in 
+# the lang_expr.html document are correct.
+#
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+source $testdir/malloc_common.tcl
+
+# Set up three global variables:
+#
+#   ::opname         An array mapping from SQL operator to an easy to parse
+#                    name. The names are used as part of test case names.
+#
+#   ::opprec         An array mapping from SQL operator to a numeric
+#                    precedence value. Operators that group more tightly
+#                    have lower numeric precedences.
+#
+#   ::oplist         A list of all SQL operators supported by SQLite.
+#
+foreach {op opn} {
+      ||   cat     *   mul       /  div       %     mod       +      add
+      -    sub     <<  lshift    >> rshift    &     bitand    |      bitor
+      <    less    <=  lesseq    >  more      >=    moreeq    =      eq1
+      ==   eq2     <>  ne1       != ne2       IS    is        LIKE   like
+      GLOB glob    AND and       OR or        MATCH match     REGEXP regexp
+      {IS NOT} isnt
+} {
+  set ::opname($op) $opn
+}
+set oplist [list]
+foreach {prec opl} {
+  1   ||
+  2   {* / %}
+  3   {+ -}
+  4   {<< >> & |}
+  5   {< <= > >=}
+  6   {= == != <> IS {IS NOT} LIKE GLOB MATCH REGEXP}
+  7   AND
+  8   OR
+} {
+  foreach op $opl { 
+    set ::opprec($op) $prec 
+    lappend oplist $op
+  }
+}
+
+
+# Hook in definitions of MATCH and REGEX. The following implementations
+# cause MATCH and REGEX to behave similarly to the == operator.
+#
+proc matchfunc {a b} { return [expr {$a==$b}] }
+proc regexfunc {a b} { return [expr {$a==$b}] }
+db func match  -argcount 2 matchfunc
+db func regexp -argcount 2 regexfunc
+
+#-------------------------------------------------------------------------
+# Test cases e_expr-1.* attempt to verify that all binary operators listed
+# in the documentation exist and that the relative precedences of the
+# operators are also as the documentation suggests.
+#
+# EVIDENCE-OF: R-15514-65163 SQLite understands the following binary
+# operators, in order from highest to lowest precedence: || * / % + -
+# << >> & | < <= > >= = == != <> IS IS
+# NOT IN LIKE GLOB MATCH REGEXP AND OR
+#
+# EVIDENCE-OF: R-38759-38789 Operators IS and IS NOT have the same
+# precedence as =.
+#
+
+
+# TODO: These tests are currently omitted because one or two cases
+# related to LIKE/GLOB/MATCH/REGEXP fail. After this case is fixed,
+# reinstate these tests.
+#
+if 0 {
+
+unset -nocomplain untested
+foreach op1 $oplist {
+  foreach op2 $oplist {
+    set untested($op1,$op2) 1
+    foreach {tn A B C} {
+       1     22   45    66
+       2      0    0     0
+       3      0    0     1
+       4      0    1     0
+       5      0    1     1
+       6      1    0     0
+       7      1    0     1
+       8      1    1     0
+       9      1    1     1
+      10      5    6     1
+      11      1    5     6
+      12      1    5     5
+      13      5    5     1
+
+      14      5    2     1
+      15      1    4     1
+      16     -1    0     1
+      17      0    1    -1
+
+    } {
+      set testname "e_expr-1.$opname($op1).$opname($op2).$tn"
+
+      # If $op2 groups more tightly than $op1, then the result
+      # of executing $sql1 whould be the same as executing $sql3.
+      # If $op1 groups more tightly, or if $op1 and $op2 have 
+      # the same precedence, then executing $sql1 should return
+      # the same value as $sql2.
+      #
+      set sql1 "SELECT $A $op1 $B $op2 $C"
+      set sql2 "SELECT ($A $op1 $B) $op2 $C"
+      set sql3 "SELECT $A $op1 ($B $op2 $C)"
+
+      set a2 [db one $sql2]
+      set a3 [db one $sql3]
+
+      do_execsql_test $testname $sql1 [list [
+        expr {$opprec($op2) < $opprec($op1) ? $a3 : $a2}
+      ]]
+
+      if {$a2 != $a3} { unset -nocomplain untested($op1,$op2) }
+    }
+  }
+}
+
+foreach op {* AND OR + || & |} { unset untested($op,$op) }
+unset untested(+,-)  ;#       Since    (a+b)-c == a+(b-c)
+unset untested(*,<<) ;#       Since    (a*b)<<c == a*(b<<c)
+
+do_test e_expr-1.1 { array names untested } {}
+
+# At one point, test 1.2.2 was failing. Instead of the correct result, it
+# was returning {1 1 0}. This would seem to indicate that LIKE has the
+# same precedence as '<'. Which is incorrect. It has lower precedence.
+#
+do_execsql_test e_expr-1.2.1 { 
+  SELECT 0 < 2 LIKE 1,   (0 < 2) LIKE 1,   0 < (2 LIKE 1)
+} {1 1 0}
+do_execsql_test e_expr-1.2.2 { 
+  SELECT 0 LIKE 0 < 2,   (0 LIKE 0) < 2,   0 LIKE (0 < 2)
+} {0 1 0}
+
+# Showing that LIKE and == have the same precedence
+#
+do_execsql_test e_expr-1.2.3 { 
+  SELECT 2 LIKE 2 == 1,   (2 LIKE 2) == 1,    2 LIKE (2 == 1)
+} {1 1 0}
+do_execsql_test e_expr-1.2.4 { 
+  SELECT 2 == 2 LIKE 1,   (2 == 2) LIKE 1,    2 == (2 LIKE 1)
+} {1 1 0}
+
+# Showing that < groups more tightly than == (< has higher precedence). 
+#
+do_execsql_test e_expr-1.2.5 { 
+  SELECT 0 < 2 == 1,   (0 < 2) == 1,   0 < (2 == 1)
+} {1 1 0}
+do_execsql_test e_expr-1.6 { 
+  SELECT 0 == 0 < 2,   (0 == 0) < 2,   0 == (0 < 2)
+} {0 1 0}
+
+}
+
+#-------------------------------------------------------------------------
+# Check that the four unary prefix operators mentioned in the 
+# documentation exist.
+#
+# EVIDENCE-OF: R-13958-53419 Supported unary prefix operators are these:
+# - + ~ NOT
+#
+do_execsql_test e_expr-2.1 { SELECT -   10   } {-10}
+do_execsql_test e_expr-2.2 { SELECT +   10   } {10}
+do_execsql_test e_expr-2.3 { SELECT ~   10   } {-11}
+do_execsql_test e_expr-2.4 { SELECT NOT 10   } {0}
+
+#-------------------------------------------------------------------------
+# Tests for the two statements made regarding the unary + operator.
+#
+# EVIDENCE-OF: R-53670-03373 The unary operator + is a no-op.
+#
+# EVIDENCE-OF: R-19480-30968 It can be applied to strings, numbers,
+# blobs or NULL and it always returns a result with the same value as
+# the operand.
+#
+foreach {tn literal type} {
+  1     'helloworld'   text
+  2     45             integer
+  3     45.2           real
+  4     45.0           real
+  5     X'ABCDEF'      blob
+  6     NULL           null
+} {
+  set sql " SELECT quote( + $literal ), typeof( + $literal) "
+  do_execsql_test e_expr-3.$tn $sql [list $literal $type]
+}
+
+#-------------------------------------------------------------------------
+# Check that both = and == are both acceptable as the "equals" operator.
+# Similarly, either != or <> work as the not-equals operator.
+#
+# EVIDENCE-OF: R-03679-60639 Equals can be either = or ==.
+#
+# EVIDENCE-OF: R-30082-38996 The non-equals operator can be either != or
+# <>.
+#
+foreach {tn literal different} {
+  1   'helloworld'  '12345'
+  2   22            23
+  3   'xyz'         X'78797A'
+  4   X'78797A00'   'xyz'
+} {
+  do_execsql_test e_expr-4.$tn "
+    SELECT $literal  = $literal,   $literal == $literal,
+           $literal  = $different, $literal == $different,
+           $literal  = NULL,       $literal == NULL,
+           $literal != $literal,   $literal <> $literal,
+           $literal != $different, $literal <> $different,
+           $literal != NULL,       $literal != NULL
+
+  " {1 1 0 0 {} {} 0 0 1 1 {} {}}
+}
+
+#-------------------------------------------------------------------------
+# Test the || operator.
+#
+# EVIDENCE-OF: R-44409-62641 The || operator is "concatenate" - it joins
+# together the two strings of its operands.
+#
+foreach {tn a b} {
+  1   'helloworld'  '12345'
+  2   22            23
+} {
+  set as [db one "SELECT $a"]
+  set bs [db one "SELECT $b"]
+  
+  do_execsql_test e_expr-5.$tn "SELECT $a || $b" [list "${as}${bs}"]
+}
+
+#-------------------------------------------------------------------------
+# Test the % operator.
+#
+# EVIDENCE-OF: R-08914-63790 The operator % outputs the value of its
+# left operand modulo its right operand.
+#
+do_execsql_test e_expr-6.1 {SELECT  72%5}  {2}
+do_execsql_test e_expr-6.2 {SELECT  72%-5} {2}
+do_execsql_test e_expr-6.3 {SELECT -72%-5} {-2}
+do_execsql_test e_expr-6.4 {SELECT -72%5}  {-2}
+
+#-------------------------------------------------------------------------
+# Test that the results of all binary operators are either numeric or 
+# NULL, except for the || operator, which may evaluate to either a text
+# value or NULL.
+#
+# EVIDENCE-OF: R-20665-17792 The result of any binary operator is either
+# a numeric value or NULL, except for the || concatenation operator
+# which always evaluates to either NULL or a text value.
+#
+set literals {
+  1 'abc'        2 'hexadecimal'       3 ''
+  4 123          5 -123                6 0
+  7 123.4        8 0.0                 9 -123.4
+ 10 X'ABCDEF'   11 X''                12 X'0000'
+ 13     NULL
+}
+foreach op $oplist {
+  foreach {n1 rhs} $literals { 
+  foreach {n2 lhs} $literals {
+
+    set t [db one " SELECT typeof($lhs $op $rhs) "]
+    do_test e_expr-7.$opname($op).$n1.$n2 {
+      expr {
+           ($op=="||" && ($t == "text" || $t == "null"))
+        || ($op!="||" && ($t == "integer" || $t == "real" || $t == "null"))
+      }
+    } 1
+
+  }}
+}
+
+#-------------------------------------------------------------------------
+# Test the IS and IS NOT operators.
+#
+# EVIDENCE-OF: R-24731-45773 The IS and IS NOT operators work like = and
+# != except when one or both of the operands are NULL.
+#
+# EVIDENCE-OF: R-06325-15315 In this case, if both operands are NULL,
+# then the IS operator evaluates to 1 (true) and the IS NOT operator
+# evaluates to 0 (false).
+#
+# EVIDENCE-OF: R-19812-36779 If one operand is NULL and the other is
+# not, then the IS operator evaluates to 0 (false) and the IS NOT
+# operator is 1 (true).
+#
+# EVIDENCE-OF: R-61975-13410 It is not possible for an IS or IS NOT
+# expression to evaluate to NULL.
+#
+do_execsql_test e_expr-8.1.1  { SELECT NULL IS     NULL } {1}
+do_execsql_test e_expr-8.1.2  { SELECT 'ab' IS     NULL } {0}
+do_execsql_test e_expr-8.1.3  { SELECT NULL IS     'ab' } {0}
+do_execsql_test e_expr-8.1.4  { SELECT 'ab' IS     'ab' } {1}
+do_execsql_test e_expr-8.1.5  { SELECT NULL ==     NULL } {{}}
+do_execsql_test e_expr-8.1.6  { SELECT 'ab' ==     NULL } {{}}
+do_execsql_test e_expr-8.1.7  { SELECT NULL ==     'ab' } {{}}
+do_execsql_test e_expr-8.1.8  { SELECT 'ab' ==     'ab' } {1}
+do_execsql_test e_expr-8.1.9  { SELECT NULL IS NOT NULL } {0}
+do_execsql_test e_expr-8.1.10 { SELECT 'ab' IS NOT NULL } {1}
+do_execsql_test e_expr-8.1.11 { SELECT NULL IS NOT 'ab' } {1}
+do_execsql_test e_expr-8.1.12 { SELECT 'ab' IS NOT 'ab' } {0}
+do_execsql_test e_expr-8.1.13 { SELECT NULL !=     NULL } {{}}
+do_execsql_test e_expr-8.1.14 { SELECT 'ab' !=     NULL } {{}}
+do_execsql_test e_expr-8.1.15 { SELECT NULL !=     'ab' } {{}}
+do_execsql_test e_expr-8.1.16 { SELECT 'ab' !=     'ab' } {0}
+
+foreach {n1 rhs} $literals { 
+  foreach {n2 lhs} $literals {
+    if {$rhs!="NULL" && $lhs!="NULL"} {
+      set eq [execsql "SELECT $lhs = $rhs, $lhs != $rhs"]
+    } else {
+      set eq [list [expr {$lhs=="NULL" && $rhs=="NULL"}] \
+                   [expr {$lhs!="NULL" || $rhs!="NULL"}]
+      ]
+    }
+    set test e_expr-8.2.$n1.$n2
+    do_execsql_test $test.1 "SELECT $lhs IS $rhs, $lhs IS NOT $rhs" $eq
+    do_execsql_test $test.2 "
+      SELECT ($lhs IS $rhs) IS NULL, ($lhs IS NOT $rhs) IS NULL
+    " {0 0}
+  }
+}
+
+finish_test