Changeset: d9e7bfe93ede for MonetDB
URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=d9e7bfe93ede
Added Files:
        sql/test/BugTracker-2014/Tests/hexadecimal_literals.Bug-3621.sql
        sql/test/BugTracker-2014/Tests/hexadecimal_literals.Bug-3621.stable.err
        sql/test/BugTracker-2014/Tests/hexadecimal_literals.Bug-3621.stable.out
Modified Files:
        sql/server/sql_parser.y
        sql/test/BugTracker-2009/Tests/bit_and.SF-2850341.sql
        sql/test/BugTracker-2009/Tests/bit_and.SF-2850341.stable.err
        sql/test/BugTracker-2009/Tests/bit_and.SF-2850341.stable.out
        sql/test/BugTracker-2014/Tests/All
Branch: Oct2014
Log Message:

fixed handling of hexadeximal literals in SQL:

- type "long (int)" is EVIL --- we need to use type "lng" instead !

- determine smallest suitable type based on actualy value,
  not on number of hexadecimal digits
  (i.e., in particular ignore/skip leading zeros)

- use tinyint as smallest type (not only smallint)

- avoid treating valid hex values as NULL:
  hex                 was                      is
  0x8000              NULL (smallint)       32768 (int)
  0x80000000          NULL (int)       2147483648 (bigint)
  0x8000000000000000  NULL (bigint)    ERROR (value too large)

- avoid negative values:
  hex                                  was                     is
  0x8001                            -32767 (smallint)       32769 (int)
  0xffff                                -1 (smallint)       65535 (int)
  0x80000001                   -2147483647 (int)       2147483649 (bigint)
  0xffffffff                            -1 (int)       4294967295 (bigint)
  0x8000000000000001  -9223372036854775807 (bigint)    ERROR (value too large)
  0xffffffffffffffff                    -1 (bigint)    ERROR (value too large)

  (leading sign (-0x...) is handled separatelyu elsewhere)


(These fixed have been triggered by bug 3621.)


diffs (truncated from 1621 to 300 lines):

diff --git a/sql/server/sql_parser.y b/sql/server/sql_parser.y
--- a/sql/server/sql_parser.y
+++ b/sql/server/sql_parser.y
@@ -4050,32 +4050,50 @@ literal:
  |  HEXADECIMAL { int len = _strlen($1), i = 2, err = 0;
                  char * hexa = $1;
                  sql_subtype t;
-                 long res = 0;
-
-                 while (i<len)
-                 {
-                       res <<= 4;
-                       if ('0'<= hexa[i] && hexa[i] <= '9')
-                               res = res + (hexa[i] - '0');
-                       else if ('A' <= hexa[i] && hexa[i] <= 'F')
-                               res = res + (hexa[i] - 'A' + 10);
-                       else if ('a' <= hexa[i] && hexa[i] <= 'f')
-                               res = res + (hexa[i] - 'a' + 10);
-                       else
-                               err = 1; 
+                 lng res = 0;
+
+                 /* skip leading '0' */
+                 while (i < len && hexa[i] == '0')
                        i++;
-                 }
-               
-                 if ( i >= 2 && i <= 6)
-                       sql_find_subtype(&t, "smallint", 16, 0);
-                 else if ( i > 6 && i <= 10)
-                       sql_find_subtype(&t, "int", 32, 0);
-                 else if ( i > 10 && i <= 18)
-                       sql_find_subtype(&t, "bigint", 64, 0);
+
+                 /* we only support positive values that fit in a signed 
64-bit type,
+                  * i.e., max. 63 bit => < 2^63 => < 0x8000000000000000
+                  * (leading sign (-0x...) is handled separately elsewhere)
+                  */
+                 if (len - i < 16 || (len - i == 16 && hexa[i] < '8'))
+                       while (err == 0 && i < len)
+                       {
+                               res <<= 4;
+                               if ('0'<= hexa[i] && hexa[i] <= '9')
+                                       res = res + (hexa[i] - '0');
+                               else if ('A' <= hexa[i] && hexa[i] <= 'F')
+                                       res = res + (hexa[i] - 'A' + 10);
+                               else if ('a' <= hexa[i] && hexa[i] <= 'f')
+                                       res = res + (hexa[i] - 'a' + 10);
+                               else
+                                       err = 1;
+                               i++;
+                       }
                  else
                        err = 1;
-                 
-                 if (err) {
+
+                 if (err == 0) {
+                       assert(res >= 0);
+
+                       /* use smallest type that can accommodate the given 
value */
+                       if (res <= GDK_bte_max)
+                               sql_find_subtype(&t, "tinyint", 8, 0 );
+                       else if (res <= GDK_sht_max)
+                               sql_find_subtype(&t, "smallint", 16, 0 );
+                       else if (res <= GDK_int_max)
+                               sql_find_subtype(&t, "int", 32, 0 );
+                       else if (res <= GDK_lng_max)
+                               sql_find_subtype(&t, "bigint", 64, 0 );
+                       else
+                               err = 1;
+                 }
+
+                 if (err != 0) {
                        char *msg = sql_message("\b22003!invalid hexadecimal 
number or hexadecimal too large (%s)", $1);
 
                        yyerror(m, msg);
diff --git a/sql/test/BugTracker-2009/Tests/bit_and.SF-2850341.sql 
b/sql/test/BugTracker-2009/Tests/bit_and.SF-2850341.sql
--- a/sql/test/BugTracker-2009/Tests/bit_and.SF-2850341.sql
+++ b/sql/test/BugTracker-2009/Tests/bit_and.SF-2850341.sql
@@ -1,1 +1,3 @@
+select bit_and(3749090034127126942, -1);
+select bit_and(3749090034127126942, 0x7fffffffffffffff);
 select bit_and(3749090034127126942, 0xffffffffffffffff);
diff --git a/sql/test/BugTracker-2009/Tests/bit_and.SF-2850341.stable.err 
b/sql/test/BugTracker-2009/Tests/bit_and.SF-2850341.stable.err
--- a/sql/test/BugTracker-2009/Tests/bit_and.SF-2850341.stable.err
+++ b/sql/test/BugTracker-2009/Tests/bit_and.SF-2850341.stable.err
@@ -67,6 +67,10 @@ stderr of test 'bit_and.SF-2850341` in d
 # 22:31:14 >  mclient -lsql -umonetdb -Pmonetdb --host=alf --port=36767 
 # 22:31:14 >  
 
+MAPI  = (monetdb) /var/tmp/mtest-28528/.s.monetdb.33240
+QUERY = select bit_and(3749090034127126942, 0xffffffffffffffff);
+ERROR = !invalid hexadecimal number or hexadecimal too large 
(0xffffffffffffffff) in: "select bit_and(3749090034127126942, 
0xffffffffffffffff"
+        !syntax error, unexpected ')' in: ")"
 
 # 22:31:14 >  
 # 22:31:14 >  Done.
diff --git a/sql/test/BugTracker-2009/Tests/bit_and.SF-2850341.stable.out 
b/sql/test/BugTracker-2009/Tests/bit_and.SF-2850341.stable.out
--- a/sql/test/BugTracker-2009/Tests/bit_and.SF-2850341.stable.out
+++ b/sql/test/BugTracker-2009/Tests/bit_and.SF-2850341.stable.out
@@ -24,14 +24,21 @@ Ready.
 # 22:31:14 >  mclient -lsql -umonetdb -Pmonetdb --host=alf --port=36767 
 # 22:31:14 >  
 
-#select bit_and(3749090034127126942, 0xffffffffffffffff);
+#select bit_and(3749090034127126942, -1);
 % .L # table_name
 % bit_and_single_value # name
 % bigint # type
 % 19 # length
 [ 3749090034127126942  ]
 
-# 22:31:14 >  
-# 22:31:14 >  Done.
-# 22:31:14 >  
+#select bit_and(3749090034127126942, 0x7fffffffffffffff);
+% .L # table_name
+% bit_and_single_value # name
+% bigint # type
+% 19 # length
+[ 3749090034127126942  ]
 
+# 18:18:45 >  
+# 18:18:45 >  "Done."
+# 18:18:45 >  
+
diff --git a/sql/test/BugTracker-2014/Tests/All 
b/sql/test/BugTracker-2014/Tests/All
--- a/sql/test/BugTracker-2014/Tests/All
+++ b/sql/test/BugTracker-2014/Tests/All
@@ -49,3 +49,4 @@ copy_decimal_into.Bug-3596
 queueError.Bug-3604
 querylog.Bug-3607
 fk-property-assert.Bug-3612
+hexadecimal_literals.Bug-3621
diff --git a/sql/test/BugTracker-2014/Tests/hexadecimal_literals.Bug-3621.sql 
b/sql/test/BugTracker-2014/Tests/hexadecimal_literals.Bug-3621.sql
new file mode 100644
--- /dev/null
+++ b/sql/test/BugTracker-2014/Tests/hexadecimal_literals.Bug-3621.sql
@@ -0,0 +1,213 @@
+select 0x0;
+select 0x1;
+select 0x2;
+select 0x3;
+select 0x4;
+select 0x5;
+select 0x6;
+select 0x7;
+select 0x8;
+select 0x9;
+select 0xa;
+select 0xA;
+select 0xb;
+select 0xB;
+select 0xc;
+select 0xC;
+select 0xd;
+select 0xD;
+select 0xe;
+select 0xE;
+select 0xf;
+select 0xF;
+select 0xg;
+select 0xG;
+
+select 0x00;
+select 0x0000;
+select 0x00000000;
+select 0x0000000000000000;
+select 0x00000000000000000000000000000000;
+select 0x01;
+select 0x0001;
+select 0x00000001;
+select 0x0000000000000001;
+select 0x00000000000000000000000000000001;
+select 0x7f;
+select 0x007f;
+select 0x0000007f;
+select 0x000000000000007f;
+select 0x0000000000000000000000000000007f;
+select 0x80;
+select 0x0080;
+select 0x00000080;
+select 0x0000000000000080;
+select 0x00000000000000000000000000000080;
+select 0x81;
+select 0x0081;
+select 0x00000081;
+select 0x0000000000000081;
+select 0x00000000000000000000000000000081;
+select 0xff;
+select 0x00ff;
+select 0x000000ff;
+select 0x00000000000000ff;
+select 0x000000000000000000000000000000ff;
+select 0x7fff;
+select 0x00007fff;
+select 0x0000000000007fff;
+select 0x00000000000000000000000000007fff;
+select 0x8000;
+select 0x00008000;
+select 0x0000000000008000;
+select 0x00000000000000000000000000008000;
+select 0x8001;
+select 0x00008001;
+select 0x0000000000008001;
+select 0x00000000000000000000000000008001;
+select 0xffff;
+select 0x0000ffff;
+select 0x000000000000ffff;
+select 0x0000000000000000000000000000ffff;
+select 0x7fffffff;
+select 0x000000007fffffff;
+select 0x0000000000000000000000007fffffff;
+select 0x80000000;
+select 0x0000000080000000;
+select 0x00000000000000000000000080000000;
+select 0x80000001;
+select 0x0000000080000001;
+select 0x00000000000000000000000080000001;
+select 0xffffffff;
+select 0x00000000ffffffff;
+select 0x000000000000000000000000ffffffff;
+select 0x7fffffffffffffff;
+select 0x00000000000000007fffffffffffffff;
+select 0x8000000000000000;
+select 0x00000000000000008000000000000000;
+select 0x8000000000000001;
+select 0x00000000000000008000000000000001;
+select 0xffffffffffffffff;
+select 0x0000000000000000ffffffffffffffff;
+select 0x7fffffffffffffffffffffffffffffff;
+select 0x80000000000000000000000000000000;
+select 0x80000000000000000000000000000001;
+select 0xffffffffffffffffffffffffffffffff;
+
+select 0x12;
+select 0x123;
+select 0x1234;
+select 0x12345;
+select 0x12345678;
+select 0x123456789;
+select 0x123456789abcdef0;
+select 0x123456789abcdef01;
+select 0x123456789abcdef0123456789abcdef0;
+select 0x123456789abcdef0123456789abcdef01;
+
+select -0x0;
+select -0x1;
+select -0x2;
+select -0x3;
+select -0x4;
+select -0x5;
+select -0x6;
+select -0x7;
+select -0x8;
+select -0x9;
+select -0xa;
+select -0xA;
+select -0xb;
+select -0xB;
+select -0xc;
+select -0xC;
+select -0xd;
+select -0xD;
+select -0xe;
+select -0xE;
+select -0xf;
+select -0xF;
+select -0xg;
+select -0xG;
+
+select -0x00;
+select -0x0000;
+select -0x00000000;
+select -0x0000000000000000;
+select -0x00000000000000000000000000000000;
+select -0x01;
+select -0x0001;
+select -0x00000001;
+select -0x0000000000000001;
+select -0x00000000000000000000000000000001;
+select -0x7f;
+select -0x007f;
+select -0x0000007f;
+select -0x000000000000007f;
+select -0x0000000000000000000000000000007f;
+select -0x80;
+select -0x0080;
+select -0x00000080;
+select -0x0000000000000080;
+select -0x00000000000000000000000000000080;
+select -0x81;
+select -0x0081;
+select -0x00000081;
+select -0x0000000000000081;
+select -0x00000000000000000000000000000081;
+select -0xff;
+select -0x00ff;
+select -0x000000ff;
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to