diff --git a/manifest b/manifest index ecec19fcc6..85667fe53f 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Require\sthe\sINSTEAD\sOF\ssyntax\sto\screate\striggers\son\sdatabase\sviews.\s(CVS\s591) -D 2002-05-26T23:24:41 +C Bug\sfixes\sand\sadditional\stest\scases\sfor\sthe\sdistinct-NULL\spatch.\s(CVS\s592) +D 2002-05-27T01:04:51 F Makefile.in 6291a33b87d2a395aafd7646ee1ed562c6f2c28c F Makefile.template 4e11752e0b5c7a043ca50af4296ec562857ba495 F README a4c0ba11354ef6ba0776b400d057c59da47a4cc0 @@ -52,7 +52,7 @@ F src/tokenize.c facec7dc0b4a13e17ad67702f548dac2f7c6a732 F src/trigger.c b7a93ffa7b91dafff433e6c87d603bfb1d50e3ee F src/update.c f68375173bf5338cae3e97012708e10f206aedd9 F src/util.c a9f6e6f03e8b7137204ac15b35a58f321e38037e -F src/vdbe.c caa269517b2392986c8f55401f272e76b9de82d9 +F src/vdbe.c ccbee9fb9b98a2fc75400865d69531da36cbf0f1 F src/vdbe.h b8706429131c14b307a07aab7e47f95a9da53610 F src/where.c b054f2f23127bd57eb5f973bcd38764b875d73fe F test/all.test e4d3821eeba751829b419cd47814bd20af4286d1 @@ -63,8 +63,8 @@ F test/btree3.test 9caa9e22491dd8cd8aa36d7ac3b48b089817c895 F test/conflict.test 5149646703d3930c9111068b5cda7e2e938476e3 F test/copy.test b3cefcb520c64d7e7dfedbab06b4d4c31fa5b99a F test/delete.test c904a62129fe102b314a96111a8417f10249e4d8 -F test/expr.test bfb773721e69566d2a7565c7f03b466e1f33a53f -F test/func.test d34e461f0acb0cf2978a4b3a3e098460f2ea8fbc +F test/expr.test 518ee35ec8d2c8883544d75a031219c75391fb21 +F test/func.test 1505ac9ebc11ca5c0300192d1519a542d5cbcfe1 F test/in.test c09312672e3f0709fa02c8e2e9cd8fb4bd6269aa F test/index.test c8a471243bbf878974b99baf5badd59407237cf3 F test/insert.test 58d44c19b3557f67f4aeb5110ed9ef02038c3684 @@ -76,7 +76,7 @@ F test/limit.test 6f98bcefc92209103bb3764c81975a6ec21d6702 F test/lock.test 3fcfd46a73119f6a18094673328a32c7b3047a8f F test/main.test c66b564554b770ee7fdbf6a66c0cd90329bc2c85 F test/malloc.test 7ba32a9ebd3aeed52ae4aaa6d42ca37e444536fd -F test/minmax.test fb6ab400271ae1f5bc88617c2882f2f081ea8e6d +F test/minmax.test c50bcc760433acd7ca8e22bc4c525b9ae82762e2 F test/misc1.test df281e9b26cd1db5808939c7cf2703072d555be0 F test/misuse.test a3aa2b18a97e4c409a1fcaff5151a4dd804a0162 F test/notnull.test b1f3e42fc475b0b5827b27b2e9b562081995ff30 @@ -86,10 +86,10 @@ F test/printf.test 3cb415073754cb8ff076f26173143c3cd293a9da F test/quick.test 6f023c7a73fc413e6d65b7a1879c79764038dc05 F test/quote.test 08f23385c685d3dc7914ec760d492cacea7f6e3d F test/rowid.test 4c55943300cddf73dd0f88d40a268cab14c83274 -F test/select1.test 6ba20b52d563b7fb917d8a61a7560d02f90a1a52 +F test/select1.test 4e1ac9cc3cbf5b3ceae388fb3d4ca1b9f9a1cc15 F test/select2.test aceea74fd895b9d007512f72499db589735bd8e4 F test/select3.test 9469c332250a75a0ef1771fb5da62dc04ec77f18 -F test/select4.test 0bc0065102573c6b71003292fd4a5def63923c61 +F test/select4.test 2ea8c7b7feceb853da167a39e4cce996a5c3ad88 F test/select5.test c2a6c4a003316ee42cbbd689eebef8fdce0db2ac F test/select6.test efb8d0c07a440441db87db2c4ade6904e1407e85 F test/sort.test 3b996ce7ca385f9cd559944ac0f4027a23aa546b @@ -135,7 +135,7 @@ F www/speed.tcl da8afcc1d3ccc5696cfb388a68982bc3d9f7f00f F www/sqlite.tcl 8b5884354cb615049aed83039f8dfe1552a44279 F www/tclsqlite.tcl 1db15abeb446aad0caf0b95b8b9579720e4ea331 F www/vdbe.tcl 2013852c27a02a091d39a766bc87cff329f21218 -P 46ce1a9ab6e527958ebc757fa2175c488299cd84 -R 35b518a6cb0a7aed91c92408e7bd6686 -U danielk1977 -Z 9e3f1ec0355281ef07dac5144d661dfb +P d9e48cd5180e2aae7672b9d54e18c37d0fe5258a +R fc93e940356a8b3ec291e98d6e7a4c6b +U drh +Z b54c0b1652f6c89ad5dde6fb5c2177ec diff --git a/manifest.uuid b/manifest.uuid index 6cf893c246..c1e4a62103 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -d9e48cd5180e2aae7672b9d54e18c37d0fe5258a \ No newline at end of file +0e268d0c0faa02c3f95e1567cf631b7a04bfbdf0 \ No newline at end of file diff --git a/src/vdbe.c b/src/vdbe.c index fa558eb7cc..19d7ed78d7 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -30,7 +30,7 @@ ** But other routines are also provided to help in building up ** a program instruction by instruction. ** -** $Id: vdbe.c,v 1.149 2002/05/26 20:54:34 drh Exp $ +** $Id: vdbe.c,v 1.150 2002/05/27 01:04:51 drh Exp $ */ #include "sqliteInt.h" #include @@ -2132,38 +2132,47 @@ case OP_Ge: { ** Pop two values off the stack. Take the logical AND of the ** two values and push the resulting boolean value back onto the ** stack. -** If either operand is NULL, the result is NULL. */ /* Opcode: Or * * * ** ** Pop two values off the stack. Take the logical OR of the ** two values and push the resulting boolean value back onto the ** stack. -** If either operand is NULL, the result is NULL. */ case OP_And: case OP_Or: { int tos = p->tos; int nos = tos - 1; - int c; + int v1, v2; /* 0==TRUE, 1==FALSE, 2==UNKNOWN or NULL */ + VERIFY( if( nos<0 ) goto not_enough_stack; ) - if( (aStack[tos].flags | aStack[nos].flags) & STK_Null ){ - POPSTACK; - Release(p, nos); - aStack[nos].flags = STK_Null; - break; - } - Integerify(p, tos); - Integerify(p, nos); - if( pOp->opcode==OP_And ){ - c = aStack[tos].i && aStack[nos].i; + if( aStack[tos].flags & STK_Null ){ + v1 = 2; }else{ - c = aStack[tos].i || aStack[nos].i; + Integerify(p, tos); + v1 = aStack[tos].i==0; + } + if( aStack[nos].flags & STK_Null ){ + v2 = 2; + }else{ + Integerify(p, nos); + v2 = aStack[nos].i==0; + } + if( pOp->opcode==OP_And ){ + static const unsigned char and_logic[] = { 0, 1, 2, 1, 1, 1, 2, 1, 2 }; + v1 = and_logic[v1*3+v2]; + }else{ + static const unsigned char or_logic[] = { 0, 0, 0, 0, 1, 2, 0, 2, 2 }; + v1 = or_logic[v1*3+v2]; } POPSTACK; - Release(p, nos); - aStack[nos].i = c; - aStack[nos].flags = STK_Int; + Release(p, nos); + if( v1==2 ){ + aStack[nos].flags = STK_Null; + }else{ + aStack[nos].i = v1==0; + aStack[nos].flags = STK_Int; + } break; } diff --git a/test/expr.test b/test/expr.test index 0d93df6627..2d2a96a0b2 100644 --- a/test/expr.test +++ b/test/expr.test @@ -11,7 +11,7 @@ # This file implements regression tests for SQLite library. The # focus of this file is testing expressions. # -# $Id: expr.test,v 1.20 2002/05/26 20:54:34 drh Exp $ +# $Id: expr.test,v 1.21 2002/05/27 01:04:51 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl @@ -82,6 +82,47 @@ test_expr expr-1.53 {i1=099999999999, i2=99999999999} {i1i2} 0 test_expr expr-1.56 {i1=25, i2=11} {i1%i2} 3 +test_expr expr-1.58 {i1=NULL, i2=1} {coalesce(i1+i2,99)} 99 +test_expr expr-1.59 {i1=1, i2=NULL} {coalesce(i1+i2,99)} 99 +test_expr expr-1.60 {i1=NULL, i2=NULL} {coalesce(i1+i2,99)} 99 +test_expr expr-1.61 {i1=NULL, i2=1} {coalesce(i1-i2,99)} 99 +test_expr expr-1.62 {i1=1, i2=NULL} {coalesce(i1-i2,99)} 99 +test_expr expr-1.63 {i1=NULL, i2=NULL} {coalesce(i1-i2,99)} 99 +test_expr expr-1.64 {i1=NULL, i2=1} {coalesce(i1*i2,99)} 99 +test_expr expr-1.65 {i1=1, i2=NULL} {coalesce(i1*i2,99)} 99 +test_expr expr-1.66 {i1=NULL, i2=NULL} {coalesce(i1*i2,99)} 99 +test_expr expr-1.67 {i1=NULL, i2=1} {coalesce(i1/i2,99)} 99 +test_expr expr-1.68 {i1=1, i2=NULL} {coalesce(i1/i2,99)} 99 +test_expr expr-1.69 {i1=NULL, i2=NULL} {coalesce(i1/i2,99)} 99 +test_expr expr-1.70 {i1=NULL, i2=1} {coalesce(i1i2,99)} 99 +test_expr expr-1.72 {i1=NULL, i2=NULL} {coalesce(i1<=i2,99)} 99 +test_expr expr-1.73 {i1=NULL, i2=1} {coalesce(i1>=i2,99)} 99 +test_expr expr-1.74 {i1=1, i2=NULL} {coalesce(i1!=i2,99)} 99 +test_expr expr-1.75 {i1=NULL, i2=NULL} {coalesce(i1==i2,99)} 99 +test_expr expr-1.76 {i1=NULL, i2=NULL} {coalesce(not i1,99)} 99 +test_expr expr-1.77 {i1=NULL, i2=NULL} {coalesce(-i1,99)} 99 +test_expr expr-1.78 {i1=NULL, i2=NULL} {coalesce(i1 IS NULL AND i2=5,99)} 99 +test_expr expr-1.79 {i1=NULL, i2=NULL} {coalesce(i1 IS NULL OR i2=5,99)} 1 +test_expr expr-1.80 {i1=NULL, i2=NULL} {coalesce(i1=5 AND i2 IS NULL,99)} 99 +test_expr expr-1.81 {i1=NULL, i2=NULL} {coalesce(i1=5 OR i2 IS NULL,99)} 1 +test_expr expr-1.82 {i1=NULL, i2=3} {coalesce(min(i1,i2,1),99)} 99 +test_expr expr-1.83 {i1=NULL, i2=3} {coalesce(max(i1,i2,1),99)} 99 +test_expr expr-1.84 {i1=3, i2=NULL} {coalesce(min(i1,i2,1),99)} 99 +test_expr expr-1.85 {i1=3, i2=NULL} {coalesce(max(i1,i2,1),99)} 99 +test_expr expr-1.86 {i1=3, i2=8} {5 between i1 and i2} 1 +test_expr expr-1.87 {i1=3, i2=8} {5 not between i1 and i2} 0 +test_expr expr-1.88 {i1=3, i2=8} {55 between i1 and i2} 0 +test_expr expr-1.89 {i1=3, i2=8} {55 not between i1 and i2} 1 +test_expr expr-1.90 {i1=3, i2=NULL} {5 between i1 and i2} {{}} +test_expr expr-1.91 {i1=3, i2=NULL} {5 not between i1 and i2} {{}} +test_expr expr-1.92 {i1=3, i2=NULL} {2 between i1 and i2} 0 +test_expr expr-1.93 {i1=3, i2=NULL} {2 not between i1 and i2} 1 +test_expr expr-1.94 {i1=NULL, i2=8} {2 between i1 and i2} {{}} +test_expr expr-1.95 {i1=NULL, i2=8} {2 not between i1 and i2} {{}} +test_expr expr-1.94 {i1=NULL, i2=8} {55 between i1 and i2} 0 +test_expr expr-1.95 {i1=NULL, i2=8} {55 not between i1 and i2} 1 + test_expr expr-2.1 {r1=1.23, r2=2.34} {r1+r2} 3.57 test_expr expr-2.2 {r1=1.23, r2=2.34} {r1-r2} -1.11 @@ -107,6 +148,7 @@ test_expr expr-2.21 {r1=2.34, r2=2.34} {r2==r1} 1 test_expr expr-2.22 {r1=1.23, r2=2.34} {min(r1,r2,r1+r2,r1-r2)} {-1.11} test_expr expr-2.23 {r1=1.23, r2=2.34} {max(r1,r2,r1+r2,r1-r2)} {3.57} test_expr expr-2.24 {r1=25.0, r2=11.0} {r1%r2} 3 +test_expr expr-2.25 {r1=1.23, r2=NULL} {coalesce(r1+r2,99.0)} 99.0 test_expr expr-3.1 {t1='abc', t2='xyz'} {t11e10} {{} 1} +test_expr2 expr-7.41 {a BETWEEN -1 AND 1} {1} +test_expr2 expr-7.42 {a NOT BETWEEN 2 AND 100} {1} + +test_expr2 expr-7.50 {((a between 1 and 2 OR 0) AND 1) OR 0} {1 2} +test_expr2 expr-7.51 {((a not between 3 and 100 OR 0) AND 1) OR 0} {1 2} +test_expr2 expr-7.52 {((a in (1,2) OR 0) AND 1) OR 0} {1 2} +test_expr2 expr-7.53 {((a not in (3,4,5,6,7,8,9,10) OR 0) AND a<11) OR 0} {1 2} +test_expr2 expr-7.54 {((a>0 OR 0) AND a<3) OR 0} {1 2} +test_expr2 expr-7.55 {((a in (1,2) OR 0) IS NULL AND 1) OR 0} {{}} +test_expr2 expr-7.56 {((a not in (3,4,5,6,7,8,9,10) IS NULL OR 0) AND 1) OR 0} \ + {{}} +test_expr2 expr-7.57 {((a>0 IS NULL OR 0) AND 1) OR 0} {{}} + + finish_test diff --git a/test/func.test b/test/func.test index 64888211b8..79821ed166 100644 --- a/test/func.test +++ b/test/func.test @@ -11,7 +11,7 @@ # This file implements regression tests for SQLite library. The # focus of this file is testing built-in functions. # -# $Id: func.test,v 1.10 2002/04/06 14:10:47 drh Exp $ +# $Id: func.test,v 1.11 2002/05/27 01:04:51 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl @@ -55,8 +55,8 @@ do_test func-1.3 { ORDER BY length(t1)} } {2 1 4 2 7 1 8 1} do_test func-1.4 { - execsql {SELECT length(a) FROM t2} -} {1 0 3 0 5} + execsql {SELECT coalesce(length(a),-1) FROM t2} +} {1 -1 3 -1 5} # Check out the substr() function # @@ -197,8 +197,8 @@ do_test func-4.11 { catchsql {SELECT round() FROM t1 ORDER BY a} } {1 {wrong number of arguments to function round()}} do_test func-4.12 { - execsql {SELECT round(a,2) FROM t2} -} {1.00 0.00 345.00 0.00 67890.00} + execsql {SELECT coalesce(round(a,2),'nil') FROM t2} +} {1.00 nil 345.00 nil 67890.00} do_test func-4.13 { execsql {SELECT round(t1,2) FROM tbl1} } {0.00 0.00 0.00 0.00 0.00} diff --git a/test/minmax.test b/test/minmax.test index 3639e793a7..1355121b1d 100644 --- a/test/minmax.test +++ b/test/minmax.test @@ -13,7 +13,7 @@ # aggregate min() and max() functions and which are handled as # as a special case. # -# $Id: minmax.test,v 1.1 2002/02/19 22:42:06 drh Exp $ +# $Id: minmax.test,v 1.2 2002/05/27 01:04:51 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl @@ -122,5 +122,11 @@ do_test minmax-3.3 { set sqlite_search_count } {0} +do_test minmax-4.1 { + execsql { + SELECT coalesce(min(x),-1), coalesce(max(x),-1) FROM + (SELECT * FROM t1 UNION SELECT NULL as 'x', NULL as 'y') + } +} {-1 -1} finish_test diff --git a/test/select1.test b/test/select1.test index 304181bf47..8a59498a01 100644 --- a/test/select1.test +++ b/test/select1.test @@ -11,7 +11,7 @@ # This file implements regression tests for SQLite library. The # focus of this file is testing the SELECT statement. # -# $Id: select1.test,v 1.26 2002/05/24 20:31:38 drh Exp $ +# $Id: select1.test,v 1.27 2002/05/27 01:04:51 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl @@ -188,8 +188,8 @@ do_test select1-2.13 { } {0 34} do_test select1-2.13.1 { execsql {SELECT coalesce(max(a),'xyzzy') FROM t3} -} {abc} -do_test select1-2.13.1 { +} {xyzzy} +do_test select1-2.13.2 { execsql {SELECT max(coalesce(a,'xyzzy')) FROM t3} } {xyzzy} do_test select1-2.14 { @@ -468,10 +468,12 @@ do_test select1-8.3 { } {11 33} do_test select1-8.4 { execsql { - SELECT f1/(f1-11), min(f1/(f1-11),5), max(f1/(f1-33),6) + SELECT coalesce(f1/(f1-11),'x'), + coalesce(min(f1/(f1-11),5),'y'), + coalesce(max(f1/(f1-33),6),'z') FROM test1 ORDER BY f1 } -} {{} {} 6 1.5 1.5 6} +} {x y 6 1.5 1.5 z} do_test select1-8.5 { execsql { SELECT min(1,2,3), -max(1,2,3) diff --git a/test/select4.test b/test/select4.test index 2b47b35743..cfa8eca8e7 100644 --- a/test/select4.test +++ b/test/select4.test @@ -12,7 +12,7 @@ # focus of this file is testing UNION, INTERSECT and EXCEPT operators # in SELECT statements. # -# $Id: select4.test,v 1.7 2002/05/26 20:54:35 drh Exp $ +# $Id: select4.test,v 1.8 2002/05/27 01:04:51 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl @@ -290,6 +290,14 @@ do_test select4-6.6 { } } {1 2} +# Test distinctness of NULL in other ways. +# +do_test select4-6.7 { + execsql { + SELECT NULL EXCEPT SELECT NULL + } +} {{}} + # Make sure column names are correct when a compound select appears as # an expression in the WHERE clause.