]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Fix arithmetic operators so that they do not change the affinity of their
authordrh <drh@noemail.net>
Mon, 24 Mar 2014 15:00:15 +0000 (15:00 +0000)
committerdrh <drh@noemail.net>
Mon, 24 Mar 2014 15:00:15 +0000 (15:00 +0000)
input operands.  Ticket [a8a0d2996a].

FossilOrigin-Name: 221f8f944703108e47d789fa8ce6c00fe2abcbb6

manifest
manifest.uuid
src/vdbe.c
test/tkt-a8a0d2996a.test [new file with mode: 0644]

index 3c6309f95b4452ebba597dc0baf9e77ec0a674fa..9e30ebbe2c7afff956f38c7090e3a5751f83fc79 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Avoid\sattempting\sto\smmap\smemory\sfrom\san\soffset\sthat\sis\snot\sa\smultiple\sof\sthe\ssystem\spage\ssize\son\ssystems\swith\spage\ssizes\slarger\sthan\s32KB.
-D 2014-03-24T11:23:17.736
+C Fix\sarithmetic\soperators\sso\sthat\sthey\sdo\snot\schange\sthe\saffinity\sof\stheir\ninput\soperands.\s\sTicket\s[a8a0d2996a].
+D 2014-03-24T15:00:15.271
 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
 F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81
 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -278,7 +278,7 @@ F src/update.c 5b3e74a03b3811e586b4f2b4cbd7c49f01c93115
 F src/utf.c 6dc9ec9f1b3db43ae8ba0365377f11df1ee4c01c
 F src/util.c c46c90459ef9bdc0c6c73803cf4c55425b4771cf
 F src/vacuum.c 3728d74919d4fb1356f9e9a13e27773db60b7179
-F src/vdbe.c 5c0feeb6c9e6a0e0cc2a9715aa6045830643809d
+F src/vdbe.c 74c7386e83eee56f921a17bb4a0396c9551f5bc7
 F src/vdbe.h fb2c48c198300a7c632f09fc940011d2ad2fc2ae
 F src/vdbeInt.h 2b9a6849166d0014c843ae3fd83a062be4efa325
 F src/vdbeapi.c 0ed6053f947edd0b30f64ce5aeb811872a3450a4
@@ -892,6 +892,7 @@ F test/tkt-94c04eaadb.test f738c57c7f68ab8be1c054415af7774617cb6223
 F test/tkt-9d68c883.test 458f7d82a523d7644b54b497c986378a7d8c8b67
 F test/tkt-9f2eb3abac.test 85bc63e749f050e6a61c8f9207f1eee65c9d3395
 F test/tkt-a7b7803e.test 159ef554234fa1f9fb318c751b284bd1cf858da4
+F test/tkt-a8a0d2996a.test eb597379dbcefa24765763d7f682c00cb5924fa9
 F test/tkt-b1d3a2e531.test 8f7576e41ca179289ee1a8fee28386fd8e4b0550
 F test/tkt-b351d95f9.test d14a503c414c5c58fdde3e80f9a3cfef986498c0
 F test/tkt-b72787b1.test a95e8cdad0b98af1853ac7f0afd4ab27b77bf5f3
@@ -1158,7 +1159,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01
 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff
-P 641408a1395bfc911ca619ef9e5f073b913d856b e3d2be3ba47cdaafd26347620ae3bc2813203f16
-R aadeef09c98319ee1e1acbdf39605080
-U dan
-Z a7c50b19ab534dd04ee960894cca4791
+P db7d62c8d58eb1e8654a762c9b199ae4e2759038
+R c2ec5fb627231252d937ea015ddf100a
+U drh
+Z 7360db1b973f463e9c0480db05633068
index 3a417781637269cb4221fddd7f1f5c0d6e55f54a..9344d796515d24f6ec5ad29b4cd6bb9c26f90480 100644 (file)
@@ -1 +1 @@
-db7d62c8d58eb1e8654a762c9b199ae4e2759038
\ No newline at end of file
+221f8f944703108e47d789fa8ce6c00fe2abcbb6
\ No newline at end of file
index b70c5e1c9d1e0e34e3212666d3446434126c1ca3..84f720b526a5c653fc7e0937a08f147eb953fd91 100644 (file)
@@ -310,6 +310,29 @@ void sqlite3ValueApplyAffinity(
   applyAffinity((Mem *)pVal, affinity, enc);
 }
 
+/*
+** Return the numeric type for pMem, either MEM_Int or MEM_Real or both or
+** none.  
+**
+** Unlike applyNumericAffinity(), this routine does not modify pMem->flags.
+** But it does set pMem->r and pMem->u.i appropriately.
+*/
+static u16 numericType(Mem *pMem){
+  if( pMem->flags & (MEM_Int|MEM_Real) ){
+    return pMem->flags & (MEM_Int|MEM_Real);
+  }
+  if( pMem->flags & (MEM_Str|MEM_Blob) ){
+    if( sqlite3AtoF(pMem->z, &pMem->r, pMem->n, pMem->enc)==0 ){
+      return 0;
+    }
+    if( sqlite3Atoi64(pMem->z, &pMem->u.i, pMem->n, pMem->enc)==SQLITE_OK ){
+      return MEM_Int;
+    }
+    return MEM_Real;
+  }
+  return 0;
+}
+
 #ifdef SQLITE_DEBUG
 /*
 ** Write a nice string representation of the contents of cell pMem
@@ -1351,20 +1374,22 @@ case OP_Multiply:              /* same as TK_STAR, in1, in2, out3 */
 case OP_Divide:                /* same as TK_SLASH, in1, in2, out3 */
 case OP_Remainder: {           /* same as TK_REM, in1, in2, out3 */
   char bIntint;   /* Started out as two integer operands */
-  int flags;      /* Combined MEM_* flags from both inputs */
+  u16 flags;      /* Combined MEM_* flags from both inputs */
+  u16 type1;      /* Numeric type of left operand */
+  u16 type2;      /* Numeric type of right operand */
   i64 iA;         /* Integer value of left operand */
   i64 iB;         /* Integer value of right operand */
   double rA;      /* Real value of left operand */
   double rB;      /* Real value of right operand */
 
   pIn1 = &aMem[pOp->p1];
-  applyNumericAffinity(pIn1);
+  type1 = numericType(pIn1);
   pIn2 = &aMem[pOp->p2];
-  applyNumericAffinity(pIn2);
+  type2 = numericType(pIn2);
   pOut = &aMem[pOp->p3];
   flags = pIn1->flags | pIn2->flags;
   if( (flags & MEM_Null)!=0 ) goto arithmetic_result_is_null;
-  if( (pIn1->flags & pIn2->flags & MEM_Int)==MEM_Int ){
+  if( (type1 & type2 & MEM_Int)!=0 ){
     iA = pIn1->u.i;
     iB = pIn2->u.i;
     bIntint = 1;
@@ -1420,7 +1445,7 @@ fp_math:
     }
     pOut->r = rB;
     MemSetTypeFlag(pOut, MEM_Real);
-    if( (flags & MEM_Real)==0 && !bIntint ){
+    if( ((type1|type2)&MEM_Real)==0 && !bIntint ){
       sqlite3VdbeIntegerAffinity(pOut);
     }
 #endif
diff --git a/test/tkt-a8a0d2996a.test b/test/tkt-a8a0d2996a.test
new file mode 100644 (file)
index 0000000..6b15e41
--- /dev/null
@@ -0,0 +1,93 @@
+# 2014-03-24
+#
+# 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.
+#
+#***********************************************************************
+# 
+# Tests to verify that arithmetic operators do not change the type of
+# input operands.  Ticket [a8a0d2996a]
+#
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+set testprefix tkt-a8a0d2996a
+
+do_execsql_test 1.0 {
+  CREATE TABLE t(x,y);
+  INSERT INTO t VALUES('1','1');
+  SELECT typeof(x), typeof(y) FROM t WHERE 1=x+0 AND y=='1';
+} {text text}
+do_execsql_test 1.1 {
+  SELECT typeof(x), typeof(y) FROM t WHERE 1=x-0 AND y=='1';
+} {text text}
+do_execsql_test 1.2 {
+  SELECT typeof(x), typeof(y) FROM t WHERE 1=x*1 AND y=='1';
+} {text text}
+do_execsql_test 1.3 {
+  SELECT typeof(x), typeof(y) FROM t WHERE 1=x/1 AND y=='1';
+} {text text}
+do_execsql_test 1.4 {
+  SELECT typeof(x), typeof(y) FROM t WHERE 1=x%4 AND y=='1';
+} {text text}
+
+do_execsql_test 2.0 {
+  UPDATE t SET x='1xyzzy';
+  SELECT typeof(x), typeof(y) FROM t WHERE 1=x+0 AND y=='1';
+} {text text}
+do_execsql_test 2.1 {
+  SELECT typeof(x), typeof(y) FROM t WHERE 1=x-0 AND y=='1';
+} {text text}
+do_execsql_test 2.2 {
+  SELECT typeof(x), typeof(y) FROM t WHERE 1=x*1 AND y=='1';
+} {text text}
+do_execsql_test 2.3 {
+  SELECT typeof(x), typeof(y) FROM t WHERE 1=x/1 AND y=='1';
+} {text text}
+do_execsql_test 2.4 {
+  SELECT typeof(x), typeof(y) FROM t WHERE 1=x%4 AND y=='1';
+} {text text}
+
+
+do_execsql_test 3.0 {
+  UPDATE t SET x='1.0';
+  SELECT typeof(x), typeof(y) FROM t WHERE 1=x+0 AND y=='1';
+} {text text}
+do_execsql_test 3.1 {
+  SELECT typeof(x), typeof(y) FROM t WHERE 1=x-0 AND y=='1';
+} {text text}
+do_execsql_test 3.2 {
+  SELECT typeof(x), typeof(y) FROM t WHERE 1=x*1 AND y=='1';
+} {text text}
+do_execsql_test 3.3 {
+  SELECT typeof(x), typeof(y) FROM t WHERE 1=x/1 AND y=='1';
+} {text text}
+do_execsql_test 3.4 {
+  SELECT typeof(x), typeof(y) FROM t WHERE 1=x%4 AND y=='1';
+} {text text}
+
+do_execsql_test 4.0 {
+  SELECT 1+1.;
+} {2.0}
+do_execsql_test 4.1 {
+  SELECT '1.23e64'/'1.0000e+62';
+} {123.0}
+do_execsql_test 4.2 {
+  SELECT '100x'+'-2y';
+} {98}
+do_execsql_test 4.3 {
+  SELECT '100x'+'4.5y';
+} {104.5}
+do_execsql_test 4.4 {
+  SELECT '-9223372036854775807x'-'1x';
+} {-9.22337203685478e+18}
+do_execsql_test 4.5 {
+  SELECT '9223372036854775806x'+'1x';
+} {9.22337203685478e+18}
+do_execsql_test 4.6 {
+  SELECT '1234x'/'10y';
+} {123.4}