List:Internals« Previous MessageNext Message »
From:monty Date:April 29 2005 4:03pm
Subject:bk commit into 4.1 tree (monty:1.2215) BUG#8872
View as plain text  
Below is the list of changes that have just been committed into a local
4.1 repository of monty. When monty does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html

ChangeSet
  1.2215 05/04/29 17:03:34 monty@stripped +11 -0
  CAST(string_argument AS UNSIGNED) didn't work for big integers above the signed range.
(Bug #7036)
  Produce warnings of wrong cast of strings to signed/unsigned.
  Don't block not resolved IP's if DNS server is down (Bug #8467)
  Fix compiler problems with MinGW (Bug #8872)

  sql/item_func.h
    1.122 05/04/29 17:03:21 monty@stripped +3 -6
    CAST(string_argument AS UNSIGNED) didn't work for big integers above the
    signed range. (Bug #7036)

  sql/item_func.cc
    1.240 05/04/29 17:03:21 monty@stripped +73 -0
    CAST(string_argument AS UNSIGNED) didn't work for big integers above the
    signed range. (Bug #7036)
    Produce warnings of wrong cast of strings to signed/unsigned

  sql/item.h
    1.177 05/04/29 17:03:19 monty@stripped +6 -1
    Added cast_to_int_type() to ensure that enums are casted as numbers

  sql/hostname.cc
    1.26 05/04/29 17:03:18 monty@stripped +8 -1
    Don't block not resolved IP's if DNS server is down (Bug #8467)

  sql/field.h
    1.127 05/04/29 17:03:18 monty@stripped +2 -0
    Added cast_to_int_type() to ensure that enums are casted as numbers

  mysys/default.c
    1.51 05/04/29 17:03:17 monty@stripped +58 -45
    Cleanup (combine identical code). 
    Done mainly by Jani

  mysql-test/t/cast.test
    1.16 05/04/29 17:03:16 monty@stripped +25 -1
    Test for cast to signed/unsigned outside of range (Bug #7036)

  mysql-test/r/cast.result
    1.22 05/04/29 17:03:15 monty@stripped +68 -3
    Test for cast to signed/unsigned outside of range (Bug #7036)

  include/my_global.h
    1.84 05/04/29 17:03:15 monty@stripped +2 -0
    Fix compiler problems with MinGW (Bug #8872)

  include/config-win.h
    1.52 05/04/29 17:03:15 monty@stripped +15 -2
    Fix compiler problems with MinGW (Bug #8872)

  configure.in
    1.367 05/04/29 17:03:14 monty@stripped +3 -0
    Fix compiler problems with MinGW (Bug #8872)

# This is a BitKeeper patch.  What follows are the unified diffs for the
# set of deltas contained in the patch.  The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User:	monty
# Host:	narttu.mysql.com
# Root:	/home/my/mysql-4.1

--- 1.366/configure.in	2005-04-27 22:40:10 +03:00
+++ 1.367/configure.in	2005-04-29 17:03:14 +03:00
@@ -1860,6 +1860,9 @@
 again]);
 fi
 fi
+AC_CHECK_TYPES([sigset_t, off_t], [], [], [#include <sys/types.h>])
+AC_CHECK_TYPES([size_t], [], [], [#include <stdio.h>])
+
 MYSQL_PTHREAD_YIELD
 
 ######################################################################

--- 1.51/include/config-win.h	2005-02-23 14:27:42 +02:00
+++ 1.52/include/config-win.h	2005-04-29 17:03:15 +03:00
@@ -106,20 +106,33 @@
 
 /* Type information */
 
+#if defined(__EMX__) || !defined(HAVE_UINT)
+#undef HAVE_UINT
+#define HAVE_UINT
 typedef unsigned short	ushort;
 typedef unsigned int	uint;
+#endif /* defined(__EMX__) || !defined(HAVE_UINT) */
+
 typedef unsigned __int64 ulonglong;	/* Microsofts 64 bit types */
 typedef __int64 longlong;
+#ifndef HAVE_SIGSET_T
 typedef int sigset_t;
+#endif
 #define longlong_defined
-/* off_t should not be __int64 because of conflicts in header files;
-   Use my_off_t or os_off_t instead */
+/*
+  off_t should not be __int64 because of conflicts in header files;
+  Use my_off_t or os_off_t instead
+*/
+#ifndef HAVE_OFF_T
 typedef long off_t;
+#endif
 typedef __int64 os_off_t;
 #ifdef _WIN64
 typedef UINT_PTR rf_SetTimer;
 #else
+#ifndef HAVE_SIZE_T
 typedef unsigned int size_t;
+#endif
 typedef uint rf_SetTimer;
 #endif
 

--- 1.50/mysys/default.c	2005-04-26 23:24:46 +03:00
+++ 1.51/mysys/default.c	2005-04-29 17:03:17 +03:00
@@ -319,6 +319,56 @@
 
 
 /*
+  Skip over keyword and get argument after keyword
+
+  SYNOPSIS
+   get_argument()
+   keyword		Include directive keyword
+   kwlen		Length of keyword
+   ptr			Pointer to the keword in the line under process
+   line			line number
+
+  RETURN
+   0	error
+   #	Returns pointer to the argument after the keyword.
+*/
+
+static char *get_argument(const char *keyword, uint kwlen,
+                          char *ptr, char *name, uint line)
+{
+  char *end;
+
+  /* Skip over "include / includedir keyword" and following whitespace */
+
+  for (ptr+= kwlen - 1;
+       my_isspace(&my_charset_latin1, ptr[0]);
+       ptr++)
+  {}
+
+  /*
+    Trim trailing whitespace from directory name
+    The -1 below is for the newline added by fgets()
+    Note that my_isspace() is true for \r and \n
+  */
+  for (end= ptr + strlen(ptr) - 1;
+       my_isspace(&my_charset_latin1, *(end - 1));
+       end--)
+  {}
+  end[0]= 0;                                    /* Cut off end space */
+
+  /* Print error msg if there is nothing after !include* directive */
+  if (end <= ptr)
+  {
+    fprintf(stderr,
+	    "error: Wrong '!%s' directive in config file: %s at line %d\n",
+	    keyword, name, line);
+    return 0;
+  }
+  return ptr;
+}
+
+
+/*
   Open a configuration file (if exists) and read given options from it
 
   SYNOPSIS
@@ -426,31 +476,10 @@
                     sizeof(includedir_keyword) - 1)) &&
           my_isspace(&my_charset_latin1, ptr[sizeof(includedir_keyword) - 1]))
       {
-        /* skip over "includedir" and following whitespace */
-        for (ptr+= sizeof(includedir_keyword) - 1;
-            my_isspace(&my_charset_latin1, ptr[0]); ptr++)
-        {}
-
-        /*
-          trim trailing whitespace from directory name
-          The -1 below is for the newline added by fgets()
-          Note that my_isspace() is true for \r and \n
-        */
-        for (end= ptr + strlen(ptr) - 1; 
-             my_isspace(&my_charset_latin1, *(end - 1));
-             end--)
-        {}
-        end[0]= 0;
-
-        /* print error msg if there is nothing after !includedir directive */
-        if (end <= ptr)
-        {
-          fprintf(stderr,
-                  "error: Wrong !includedir directive in config "
-                  "file: %s at line %d\n",
-                  name,line);
-          goto err;
-        }
+	if (!(ptr= get_argument(includedir_keyword,
+                                sizeof(includedir_keyword),
+                                ptr, name, line)))
+	  goto err;
 
         if (!(search_dir= my_dir(ptr, MYF(MY_WME))))
           goto err;
@@ -486,26 +515,10 @@
       else if ((!strncmp(ptr, include_keyword, sizeof(include_keyword) - 1)) &&
                my_isspace(&my_charset_latin1, ptr[sizeof(include_keyword)-1]))
       {
-        /* skip over `include' and following whitespace */
-        for (ptr+= sizeof(include_keyword) - 1;
-            my_isspace(&my_charset_latin1, ptr[0]); ptr++)
-        {}
-
-        /* trim trailing whitespace from filename */
-        for (end= ptr + strlen(ptr) - 1;
-             my_isspace(&my_charset_latin1, *(end - 1));
-             end--)
-        {}
-        end[0]= 0;
-
-        if (end <= ptr)
-        {
-          fprintf(stderr,
-                  "error: Wrong !include directive in config "
-                  "file: %s at line %d\n",
-                  name,line);
-          goto err;
-        }
+	if (!(ptr= get_argument(include_keyword,
+                                sizeof(include_keyword), ptr,
+                                name, line)))
+	  goto err;
 
         search_default_file_with_ext(args, alloc, "", "", ptr, group,
                                      recursion_level + 1);

--- 1.126/sql/field.h	2005-04-03 09:04:59 +03:00
+++ 1.127/sql/field.h	2005-04-29 17:03:18 +03:00
@@ -119,6 +119,7 @@
   virtual String *val_str(String*,String *)=0;
   virtual Item_result result_type () const=0;
   virtual Item_result cmp_type () const { return result_type(); }
+  virtual Item_result cast_to_int_type () const { return result_type(); }
   static enum_field_types field_type_merge(enum_field_types, enum_field_types);
   static Item_result result_merge_type(enum_field_types);
   bool eq(Field *field) { return ptr == field->ptr && null_ptr ==
field->null_ptr; }
@@ -1115,6 +1116,7 @@
   }
   enum_field_types type() const { return FIELD_TYPE_STRING; }
   enum Item_result cmp_type () const { return INT_RESULT; }
+  enum Item_result cast_to_int_type () const { return INT_RESULT; }
   enum ha_base_keytype key_type() const;
   int  store(const char *to,uint length,CHARSET_INFO *charset);
   int  store(double nr);

--- 1.25/sql/hostname.cc	2004-02-21 00:42:02 +02:00
+++ 1.26/sql/hostname.cc	2005-04-29 17:03:18 +03:00
@@ -177,7 +177,14 @@
 				 &tmp_errno)))
   {
     DBUG_PRINT("error",("gethostbyname_r returned %d",tmp_errno));
-    add_wrong_ip(in);
+    /*
+      Don't cache responses when the DSN server is down, as otherwise
+      transient DNS failure may leave any number of clients (those
+      that attempted to connect during the outage) unable to connect
+      indefinitely.
+    */
+    if (tmp_errno == HOST_NOT_FOUND || tmp_error == NO_DATA)
+      add_wrong_ip(in);
     my_gethostbyname_r_free();
     DBUG_RETURN(0);
   }

--- 1.176/sql/item.h	2005-03-31 11:47:30 +03:00
+++ 1.177/sql/item.h	2005-04-29 17:03:19 +03:00
@@ -180,7 +180,8 @@
   { return save_in_field(field, 1); }
   virtual bool send(Protocol *protocol, String *str);
   virtual bool eq(const Item *, bool binary_cmp) const;
-  virtual Item_result result_type () const { return REAL_RESULT; }
+  virtual Item_result result_type() const { return REAL_RESULT; }
+  virtual Item_result cast_to_int_type() const { return result_type(); }
   virtual enum_field_types field_type() const;
   virtual enum Type type() const =0;
   /* valXXX methods must return NULL or 0 or 0.0 if null_value is set. */
@@ -421,6 +422,10 @@
   enum Item_result result_type () const
   {
     return field->result_type();
+  }
+  Item_result cast_to_int_type() const
+  {
+    return field->cast_to_int_type();
   }
   enum_field_types field_type() const
   {

--- 1.239/sql/item_func.cc	2005-04-19 12:44:50 +03:00
+++ 1.240/sql/item_func.cc	2005-04-29 17:03:21 +03:00
@@ -582,12 +582,85 @@
 }
 
 
+longlong Item_func_signed::val_int_from_str(int *error)
+{
+  char buff[MAX_FIELD_WIDTH], *end;
+  String tmp(buff,sizeof(buff), &my_charset_bin), *res;
+  longlong value;
+
+  /*
+    For a string result, we must first get the string and then convert it
+    to a longlong
+  */
+
+  if (!(res= args[0]->val_str(&tmp)))
+  {
+    null_value= 1;
+    *error= 0;
+    return 0;
+  }
+  null_value= 0;
+  end= (char*) res->ptr()+ res->length();
+  value= my_strtoll10(res->ptr(), &end, error);
+  if (*error > 0 || end != res->ptr()+ res->length())
+    push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+                        ER_TRUNCATED_WRONG_VALUE,
+                        ER(ER_TRUNCATED_WRONG_VALUE), "INTEGER",
+                        res->c_ptr());
+  return value;
+}
+
+
+longlong Item_func_signed::val_int()
+{
+  longlong value;
+  int error;
+
+  if (args[0]->cast_to_int_type() != STRING_RESULT)
+  {
+    value= args[0]->val_int();
+    null_value= args[0]->null_value; 
+    return value;
+  }
+
+  value= val_int_from_str(&error);
+  if (value < 0 && error == 0)
+  {
+    push_warning(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
+                 "Cast to signed converted positive out-of-range integer to "
+                 "it's negative complement");
+  }
+  return value;
+}
+
+
 void Item_func_unsigned::print(String *str)
 {
   str->append("cast(", 5);
   args[0]->print(str);
   str->append(" as unsigned)", 13);
 
+}
+
+
+longlong Item_func_unsigned::val_int()
+{
+  longlong value;
+  int error;
+
+  if (args[0]->cast_to_int_type() != STRING_RESULT)
+  {
+    value= args[0]->val_int();
+    null_value= args[0]->null_value; 
+    return value;
+  }
+
+  value= val_int_from_str(&error);
+  if (error < 0)
+    push_warning(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
+                 "Cast to unsigned converted negative integer to it's "
+                 "positive complement");
+  return value;
 }
 
 

--- 1.121/sql/item_func.h	2005-03-30 10:13:21 +03:00
+++ 1.122/sql/item_func.h	2005-04-29 17:03:21 +03:00
@@ -226,12 +226,8 @@
     null_value= args[0]->null_value;
     return tmp;
   }
-  longlong val_int()
-  {
-    longlong tmp= args[0]->val_int();
-    null_value= args[0]->null_value; 
-    return tmp;
-  }
+  longlong val_int();
+  longlong val_int_from_str(int *error);
   void fix_length_and_dec()
   { max_length=args[0]->max_length; unsigned_flag=0; }
   void print(String *str);
@@ -245,6 +241,7 @@
   const char *func_name() const { return "cast_as_unsigned"; }
   void fix_length_and_dec()
   { max_length=args[0]->max_length; unsigned_flag=1; }
+  longlong val_int();
   void print(String *str);
 };
 

--- 1.83/include/my_global.h	2005-04-26 14:15:10 +03:00
+++ 1.84/include/my_global.h	2005-04-29 17:03:15 +03:00
@@ -393,6 +393,8 @@
 #endif
 
 #if defined(__EMX__) || !defined(HAVE_UINT)
+#undef HAVE_UINT
+#define HAVE_UINT
 typedef unsigned int uint;
 typedef unsigned short ushort;
 #endif

--- 1.21/mysql-test/r/cast.result	2004-12-30 12:38:29 +02:00
+++ 1.22/mysql-test/r/cast.result	2005-04-29 17:03:15 +03:00
@@ -4,9 +4,6 @@
 select CAST(CAST(1-2 AS UNSIGNED) AS SIGNED INTEGER);
 CAST(CAST(1-2 AS UNSIGNED) AS SIGNED INTEGER)
 -1
-select CONVERT('-1',UNSIGNED);
-CONVERT('-1',UNSIGNED)
-18446744073709551615
 select cast(-5 as unsigned) | 1, cast(-5 as unsigned) & -1;
 cast(-5 as unsigned) | 1	cast(-5 as unsigned) & -1
 18446744073709551611	18446744073709551611
@@ -57,6 +54,41 @@
 select CAST(DATE "2004-01-22 21:45:33" AS BINARY(4));
 CAST(DATE "2004-01-22 21:45:33" AS BINARY(4))
 2004
+select cast('18446744073709551616' as unsigned);
+cast('18446744073709551616' as unsigned)
+18446744073709551615
+Warnings:
+Warning	1292	Truncated incorrect INTEGER value: '18446744073709551616'
+select cast('18446744073709551616' as signed);
+cast('18446744073709551616' as signed)
+-1
+Warnings:
+Warning	1292	Truncated incorrect INTEGER value: '18446744073709551616'
+select cast('9223372036854775809' as signed);
+cast('9223372036854775809' as signed)
+-9223372036854775807
+Warnings:
+Warning	1105	Cast to signed converted positive out-of-range integer to it's negative
complement
+select cast('-1' as unsigned);
+cast('-1' as unsigned)
+18446744073709551615
+Warnings:
+Warning	1105	Cast to unsigned converted negative integer to it's positive complement
+select cast('abc' as signed);
+cast('abc' as signed)
+0
+Warnings:
+Warning	1292	Truncated incorrect INTEGER value: 'abc'
+select cast('1a' as signed);
+cast('1a' as signed)
+1
+Warnings:
+Warning	1292	Truncated incorrect INTEGER value: '1a'
+select cast('' as signed);
+cast('' as signed)
+0
+Warnings:
+Warning	1292	Truncated incorrect INTEGER value: ''
 set names binary;
 select cast(_latin1'test' as char character set latin2);
 cast(_latin1'test' as char character set latin2)
@@ -187,3 +219,36 @@
 select timediff(cast('1 12:00:00' as time), '12:00:00');
 timediff(cast('1 12:00:00' as time), '12:00:00')
 24:00:00
+select cast(18446744073709551615 as unsigned);
+cast(18446744073709551615 as unsigned)
+18446744073709551615
+select cast(18446744073709551615 as signed);
+cast(18446744073709551615 as signed)
+-1
+select cast('18446744073709551615' as unsigned);
+cast('18446744073709551615' as unsigned)
+18446744073709551615
+select cast('18446744073709551615' as signed);
+cast('18446744073709551615' as signed)
+-1
+Warnings:
+Warning	1105	Cast to signed converted positive out-of-range integer to it's negative
complement
+select cast('9223372036854775807' as signed);
+cast('9223372036854775807' as signed)
+9223372036854775807
+select cast(concat('184467440','73709551615') as unsigned);
+cast(concat('184467440','73709551615') as unsigned)
+18446744073709551615
+select cast(concat('184467440','73709551615') as signed);
+cast(concat('184467440','73709551615') as signed)
+-1
+Warnings:
+Warning	1105	Cast to signed converted positive out-of-range integer to it's negative
complement
+select cast(repeat('1',20) as unsigned);
+cast(repeat('1',20) as unsigned)
+11111111111111111111
+select cast(repeat('1',20) as signed);
+cast(repeat('1',20) as signed)
+-7335632962598440505
+Warnings:
+Warning	1105	Cast to signed converted positive out-of-range integer to it's negative
complement

--- 1.15/mysql-test/t/cast.test	2004-12-30 12:38:29 +02:00
+++ 1.16/mysql-test/t/cast.test	2005-04-29 17:03:16 +03:00
@@ -4,7 +4,6 @@
 
 select CAST(1-2 AS UNSIGNED);
 select CAST(CAST(1-2 AS UNSIGNED) AS SIGNED INTEGER);
-select CONVERT('-1',UNSIGNED);
 select cast(-5 as unsigned) | 1, cast(-5 as unsigned) & -1;
 select cast(-5 as unsigned) -1, cast(-5 as unsigned) + 1;
 select ~5, cast(~5 as signed);
@@ -22,6 +21,15 @@
 select CONVERT(DATE "2004-01-22 21:45:33",BINARY(4));
 select CAST(DATE "2004-01-22 21:45:33" AS BINARY(4));
 
+# out-of-range cases
+select cast('18446744073709551616' as unsigned);
+select cast('18446744073709551616' as signed);
+select cast('9223372036854775809' as signed);
+select cast('-1' as unsigned);
+select cast('abc' as signed);
+select cast('1a' as signed);
+select cast('' as signed);
+
 #
 # Character set convertion
 #
@@ -118,3 +126,19 @@
 select timediff(cast('2004-12-30 12:00:00' as time), '12:00:00');
 # Still we should not throw away "days" part of time value
 select timediff(cast('1 12:00:00' as time), '12:00:00');
+
+#
+# Bug #7036: Casting from string to unsigned would cap value of result at
+# maximum signed value instead of maximum unsigned value
+#
+select cast(18446744073709551615 as unsigned);
+select cast(18446744073709551615 as signed);
+select cast('18446744073709551615' as unsigned);
+select cast('18446744073709551615' as signed);
+select cast('9223372036854775807' as signed);
+
+select cast(concat('184467440','73709551615') as unsigned);
+select cast(concat('184467440','73709551615') as signed);
+
+select cast(repeat('1',20) as unsigned);
+select cast(repeat('1',20) as signed);
Thread
bk commit into 4.1 tree (monty:1.2215) BUG#8872monty29 Apr