]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Fix the expression comparison logic to take the COLLATE operator into account.
authordrh <drh@noemail.net>
Thu, 7 Jan 2010 15:17:02 +0000 (15:17 +0000)
committerdrh <drh@noemail.net>
Thu, 7 Jan 2010 15:17:02 +0000 (15:17 +0000)
Ticket [360c6073e197]

FossilOrigin-Name: 44bb1bfe5dedd8054ddd933941ee4112ed8d3b68

manifest
manifest.uuid
src/expr.c
src/insert.c
src/resolve.c
test/insert4.test
test/minmax3.test

index 87782cf36c42f4ce620bec5ea241560479a29fdf..47a1824e7488a287ed687657489ce84ae1df10b4 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,8 @@
-C Changes\sto\stest\scode\sso\sthat\stestfixture\scompiles\swhen\sOMIT_SHARED_CACHE\sand\sOMIT_UTF16\sare\sdefined.
-D 2010-01-07T11:27:31
+-----BEGIN PGP SIGNED MESSAGE-----
+Hash: SHA1
+
+C Fix\sthe\sexpression\scomparison\slogic\sto\stake\sthe\sCOLLATE\soperator\sinto\saccount.\nTicket\s[360c6073e197]
+D 2010-01-07T15:17:02
 F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
 F Makefile.in c5827ead754ab32b9585487177c93bb00b9497b3
 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
@@ -116,7 +119,7 @@ F src/callback.c 908f3e0172c3d4058f4ca0acd42c637c52e9669f
 F src/complete.c 4c8a742c4a4a6d9c835912648f5c8f032ea36c7b
 F src/date.c a79c0a8f219370b972e320741f995a3bef9df33f
 F src/delete.c 610dc008e88a9599f905f5cbe9577ac9c36e0581
-F src/expr.c d695300ba8b7a42d6b27a52d0288b974c89bf698
+F src/expr.c b186cb2a2bab8fae4bbee4582a1c92cfc8d6aad3
 F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
 F src/fkey.c e2116672a6bd610dc888e27df292ebc7999c9bb0
 F src/func.c 69906340991919b4933dd8630774ad069e4d582e
@@ -124,7 +127,7 @@ F src/global.c 75946a4a2ab41c6ae58f10ca0ed31b3449694b26
 F src/hash.c 458488dcc159c301b8e7686280ab209f1fb915af
 F src/hash.h 2894c932d84d9f892d4b4023a75e501f83050970
 F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08
-F src/insert.c f9c6098988675ac258b2f98ea5f7e370fc9990fa
+F src/insert.c 11eeb4f2e5d57b7c106f0c28eea8d0dd896dfd70
 F src/journal.c b0ea6b70b532961118ab70301c00a33089f9315c
 F src/legacy.c 9304428e71b1d622b764913e1432e69156814755
 F src/lempar.c 7f026423f4d71d989e719a743f98a1cbd4e6d99e
@@ -160,7 +163,7 @@ F src/pragma.c 6936d7df5e04b9f996f8f320d15e65b6944b2caa
 F src/prepare.c 170bd953058efe1c46b8ad9020d49cd6f40f0b45
 F src/printf.c 644bc7d59df3dc56d6d8b9a510914bfc6b51bc69
 F src/random.c cd4a67b3953b88019f8cd4ccd81394a8ddfaba50
-F src/resolve.c 69a45df25039eb58e321653914ad670ffe49d486
+F src/resolve.c 56ecd50851afa9dbcc1803ef86a9b17b3f3d3b89
 F src/rowset.c 69afa95a97c524ba6faf3805e717b5b7ae85a697
 F src/select.c 0109b993c360d649857523abb72919e1794f9b45
 F src/shell.c b95c5fcfe458027f192914a47474652969a1ec0f
@@ -433,7 +436,7 @@ F test/init.test 3f9e97948cf2335c08a5e3edc3df3a26cdaa76f2
 F test/insert.test aef273dd1cee84cc92407469e6bd1b3cdcb76908
 F test/insert2.test 4f3a04d168c728ed5ec2c88842e772606c7ce435
 F test/insert3.test 1b7db95a03ad9c5013fdf7d6722b6cd66ee55e30
-F test/insert4.test 6e382eaf7295a4463e6f29ea20fcd8e63d097eeb
+F test/insert4.test c1469999a58e86a85b74df645a820f4cc7a8273b
 F test/insert5.test 1f93cbe9742110119133d7e8e3ccfe6d7c249766
 F test/intarray.test 066b7d7ac38d25bf96f87f1b017bfc687551cdd4
 F test/interrupt.test 42e7cf98646fd9cb4a3b131a93ed3c50b9e149f1
@@ -500,7 +503,7 @@ F test/memsubsys1.test fd8a33046b6e758e3eb93747dc4eec21fe56bf64
 F test/memsubsys2.test 72a731225997ad5e8df89fdbeae9224616b6aecc
 F test/minmax.test 722d80816f7e096bf2c04f4111f1a6c1ba65453d
 F test/minmax2.test 33504c01a03bd99226144e4b03f7631a274d66e0
-F test/minmax3.test 94742aa922153953ce3562702815e4f1f079bdb8
+F test/minmax3.test a38686c33b07d595e98a2fc6d3aa84a5e886a972
 F test/misc1.test 1b89c02c4a33b49dee4cd1d20d161aaaba719075
 F test/misc2.test a628db7b03e18973e5d446c67696b03de718c9fd
 F test/misc3.test 72c5dc87a78e7865c5ec7a969fc572913dbe96b6
@@ -784,7 +787,14 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
 F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
-P 3b5ccd2682176929f4da8a3f39a7e8f58b179f18
-R af20b3790ea978fec44add9031dd631c
-U dan
-Z 0fa44c75cc7974ccbaf267c317a458e5
+P d6ee5ff6c815e3aadd92d331560b529394eae661
+R 8a8b46968fc71c4a14b23f3c5b724baa
+U drh
+Z 8aa04fbf144e000aa38deafde10e964c
+-----BEGIN PGP SIGNATURE-----
+Version: GnuPG v1.4.6 (GNU/Linux)
+
+iD8DBQFLRfryoxKgR168RlERAoWYAJkBzgNbrhQEOwANUltOu1MbTLB+fQCeNI4J
+z1KroLxlemLylQvQzuGxJ/c=
+=1fiA
+-----END PGP SIGNATURE-----
index 70cfccf4d097f40598f6c46bcad1c4e4225874ec..e5f5f65c2ac525a18da1a9a57824a03b85d87dbf 100644 (file)
@@ -1 +1 @@
-d6ee5ff6c815e3aadd92d331560b529394eae661
\ No newline at end of file
+44bb1bfe5dedd8054ddd933941ee4112ed8d3b68
\ No newline at end of file
index 6ba373875915dc50c6fd4a15fc3924378d26b679..34655f97a537b80c8193578d3c89b4c30e0ea5cf 100644 (file)
@@ -3415,57 +3415,61 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
 }
 
 /*
-** Do a deep comparison of two expression trees.  Return TRUE (non-zero)
-** if they are identical and return FALSE if they differ in any way.
+** Do a deep comparison of two expression trees.  Return 0 if the two
+** expressions are completely identical.  Return 1 if they differ only
+** by a COLLATE operator at the top level.  Return 2 if there are differences
+** other than the top-level COLLATE operator.
 **
-** Sometimes this routine will return FALSE even if the two expressions
+** Sometimes this routine will return 2 even if the two expressions
 ** really are equivalent.  If we cannot prove that the expressions are
-** identical, we return FALSE just to be safe.  So if this routine
-** returns false, then you do not really know for certain if the two
-** expressions are the same.  But if you get a TRUE return, then you
+** identical, we return 2 just to be safe.  So if this routine
+** returns 2, then you do not really know for certain if the two
+** expressions are the same.  But if you get a 0 or 1 return, then you
 ** can be sure the expressions are the same.  In the places where
-** this routine is used, it does not hurt to get an extra FALSE - that
+** this routine is used, it does not hurt to get an extra 2 - that
 ** just might result in some slightly slower code.  But returning
-** an incorrect TRUE could lead to a malfunction.
+** an incorrect 0 or 1 could lead to a malfunction.
 */
 int sqlite3ExprCompare(Expr *pA, Expr *pB){
   int i;
   if( pA==0||pB==0 ){
-    return pB==pA;
+    return pB==pA ? 0 : 2;
   }
   assert( !ExprHasAnyProperty(pA, EP_TokenOnly|EP_Reduced) );
   assert( !ExprHasAnyProperty(pB, EP_TokenOnly|EP_Reduced) );
   if( ExprHasProperty(pA, EP_xIsSelect) || ExprHasProperty(pB, EP_xIsSelect) ){
-    return 0;
+    return 2;
   }
-  if( (pA->flags & EP_Distinct)!=(pB->flags & EP_Distinct) ) return 0;
-  if( pA->op!=pB->op ) return 0;
-  if( !sqlite3ExprCompare(pA->pLeft, pB->pLeft) ) return 0;
-  if( !sqlite3ExprCompare(pA->pRight, pB->pRight) ) return 0;
+  if( (pA->flags & EP_Distinct)!=(pB->flags & EP_Distinct) ) return 2;
+  if( pA->op!=pB->op ) return 2;
+  if( sqlite3ExprCompare(pA->pLeft, pB->pLeft) ) return 2;
+  if( sqlite3ExprCompare(pA->pRight, pB->pRight) ) return 2;
 
   if( pA->x.pList && pB->x.pList ){
-    if( pA->x.pList->nExpr!=pB->x.pList->nExpr ) return 0;
+    if( pA->x.pList->nExpr!=pB->x.pList->nExpr ) return 2;
     for(i=0; i<pA->x.pList->nExpr; i++){
       Expr *pExprA = pA->x.pList->a[i].pExpr;
       Expr *pExprB = pB->x.pList->a[i].pExpr;
-      if( !sqlite3ExprCompare(pExprA, pExprB) ) return 0;
+      if( sqlite3ExprCompare(pExprA, pExprB) ) return 2;
     }
   }else if( pA->x.pList || pB->x.pList ){
-    return 0;
+    return 2;
   }
 
-  if( pA->iTable!=pB->iTable || pA->iColumn!=pB->iColumn ) return 0;
+  if( pA->iTable!=pB->iTable || pA->iColumn!=pB->iColumn ) return 2;
   if( ExprHasProperty(pA, EP_IntValue) ){
     if( !ExprHasProperty(pB, EP_IntValue) || pA->u.iValue!=pB->u.iValue ){
-      return 0;
+      return 2;
     }
   }else if( pA->op!=TK_COLUMN && pA->u.zToken ){
-    if( ExprHasProperty(pB, EP_IntValue) || NEVER(pB->u.zToken==0) ) return 0;
+    if( ExprHasProperty(pB, EP_IntValue) || NEVER(pB->u.zToken==0) ) return 2;
     if( sqlite3StrICmp(pA->u.zToken,pB->u.zToken)!=0 ){
-      return 0;
+      return 2;
     }
   }
-  return 1;
+  if( (pA->flags & EP_ExpCollate)!=(pB->flags & EP_ExpCollate) ) return 1;
+  if( (pA->flags & EP_ExpCollate)!=0 && pA->pColl!=pB->pColl ) return 2;
+  return 0;
 }
 
 
@@ -3596,7 +3600,7 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){
         */
         struct AggInfo_func *pItem = pAggInfo->aFunc;
         for(i=0; i<pAggInfo->nFunc; i++, pItem++){
-          if( sqlite3ExprCompare(pItem->pExpr, pExpr) ){
+          if( sqlite3ExprCompare(pItem->pExpr, pExpr)==0 ){
             break;
           }
         }
index 5266af32478e4b57a0d513968b04370567ea9d1d..9bd9085343add8868292fae94e215dba26b307ce 100644 (file)
@@ -1715,7 +1715,7 @@ static int xferOptimization(
     }
   }
 #ifndef SQLITE_OMIT_CHECK
-  if( pDest->pCheck && !sqlite3ExprCompare(pSrc->pCheck, pDest->pCheck) ){
+  if( pDest->pCheck && sqlite3ExprCompare(pSrc->pCheck, pDest->pCheck) ){
     return 0;   /* Tables have different CHECK constraints.  Ticket #2252 */
   }
 #endif
index 26a6cc03eb34872bbff6013d4cabe8f27f19862d..3b48baa6f35483fd58122fdae75a4580d2564954 100644 (file)
@@ -686,7 +686,7 @@ static int resolveOrderByTermToExprList(
   ** result-set entry.
   */
   for(i=0; i<pEList->nExpr; i++){
-    if( sqlite3ExprCompare(pEList->a[i].pExpr, pE) ){
+    if( sqlite3ExprCompare(pEList->a[i].pExpr, pE)<2 ){
       return i+1;
     }
   }
index 7e876122f02d6a1ad889f0427e8d3d47716260bb..0b069e996dd1a7495fae065f70e9ab7ba6d7beec 100644 (file)
@@ -301,6 +301,29 @@ do_test insert4-6.4 {
 } {0}
 
 
-
+do_test insert4-6.5 {
+  execsql {
+    CREATE TABLE t6a(x CHECK( x<>'abc' ));
+    INSERT INTO t6a VALUES('ABC');
+    SELECT * FROM t6a;
+  }
+} {ABC}
+do_test insert4-6.6 {
+  execsql {
+    CREATE TABLE t6b(x CHECK( x<>'abc' COLLATE nocase ));
+  }
+  catchsql {
+    INSERT INTO t6b SELECT * FROM t6a;
+  }
+} {1 {constraint failed}}
+do_test insert4-6.7 {
+  execsql {
+    DROP TABLE t6b;
+    CREATE TABLE t6b(x CHECK( x COLLATE nocase <>'abc' ));
+  }
+  catchsql {
+    INSERT INTO t6b SELECT * FROM t6a;
+  }
+} {1 {constraint failed}}
 
 finish_test
index 8e8164ac0ba5c14986b03c86e5d3ad34eae7b3f5..c387b041aa51a71ba8cd3f4059f4cc0c7ad14810 100644 (file)
@@ -174,7 +174,7 @@ do_test minmax3-2.8 {
   execsql { SELECT min(b) FROM t2 WHERE a = 3 AND b<1; }
 } {{}}
 
-do_test minmax3-2.1 {
+do_test minmax3-3.1 {
   execsql {
     DROP TABLE t2;
     CREATE TABLE t2(a, b);
@@ -192,26 +192,91 @@ do_test minmax3-2.1 {
     INSERT INTO t2 VALUES(3, 3);
   }
 } {}
-do_test minmax3-2.2 {
+do_test minmax3-3.2 {
   execsql { SELECT min(b) FROM t2 WHERE a = 1; }
 } {1}
-do_test minmax3-2.3 {
+do_test minmax3-3.3 {
   execsql { SELECT min(b) FROM t2 WHERE a = 1 AND b>1; }
 } {2}
-do_test minmax3-2.4 {
+do_test minmax3-3.4 {
   execsql { SELECT min(b) FROM t2 WHERE a = 1 AND b>-1; }
 } {1}
-do_test minmax3-2.5 {
+do_test minmax3-3.5 {
   execsql { SELECT min(b) FROM t2 WHERE a = 1; }
 } {1}
-do_test minmax3-2.6 {
+do_test minmax3-3.6 {
   execsql { SELECT min(b) FROM t2 WHERE a = 1 AND b<2; }
 } {1}
-do_test minmax3-2.7 {
+do_test minmax3-3.7 {
   execsql { SELECT min(b) FROM t2 WHERE a = 1 AND b<1; }
 } {{}}
-do_test minmax3-2.8 {
+do_test minmax3-3.8 {
   execsql { SELECT min(b) FROM t2 WHERE a = 3 AND b<1; }
 } {{}}
 
+do_test minmax3-4.1 {
+  execsql {
+    CREATE TABLE t4(x);
+    INSERT INTO t4 VALUES('abc');
+    INSERT INTO t4 VALUES('BCD');
+    SELECT max(x) FROM t4;
+  }
+} {abc}
+do_test minmax3-4.2 {
+  execsql {
+    SELECT max(x COLLATE nocase) FROM t4;
+  }
+} {BCD}
+do_test minmax3-4.3 {
+  execsql {
+    SELECT max(x), max(x COLLATE nocase) FROM t4;
+  }
+} {abc BCD}
+do_test minmax3-4.4 {
+  execsql {
+    SELECT max(x COLLATE binary), max(x COLLATE nocase) FROM t4;
+  }
+} {abc BCD}
+do_test minmax3-4.5 {
+  execsql {
+    SELECT max(x COLLATE nocase), max(x COLLATE rtrim) FROM t4;
+  }
+} {BCD abc}
+do_test minmax3-4.6 {
+  execsql {
+    SELECT max(x COLLATE nocase), max(x) FROM t4;
+  }
+} {BCD abc}
+do_test minmax3-4.10 {
+  execsql {
+    SELECT min(x) FROM t4;
+  }
+} {BCD}
+do_test minmax3-4.11 {
+  execsql {
+    SELECT min(x COLLATE nocase) FROM t4;
+  }
+} {abc}
+do_test minmax3-4.12 {
+  execsql {
+    SELECT min(x), min(x COLLATE nocase) FROM t4;
+  }
+} {BCD abc}
+do_test minmax3-4.13 {
+  execsql {
+    SELECT min(x COLLATE binary), min(x COLLATE nocase) FROM t4;
+  }
+} {BCD abc}
+do_test minmax3-4.14 {
+  execsql {
+    SELECT min(x COLLATE nocase), min(x COLLATE rtrim) FROM t4;
+  }
+} {abc BCD}
+do_test minmax3-4.15 {
+  execsql {
+    SELECT min(x COLLATE nocase), min(x) FROM t4;
+  }
+} {abc BCD}
+
+
 finish_test