summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
Diffstat (limited to 'sql')
-rw-r--r--sql/field.h2
-rw-r--r--sql/hostname.cc9
-rw-r--r--sql/item.h7
-rw-r--r--sql/item_func.cc73
-rw-r--r--sql/item_func.h9
5 files changed, 92 insertions, 8 deletions
diff --git a/sql/field.h b/sql/field.h
index 5dc124aba35..f19771c3f9c 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -119,6 +119,7 @@ public:
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 @@ public:
}
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);
diff --git a/sql/hostname.cc b/sql/hostname.cc
index c74d230bbcb..fe2fad6f3b2 100644
--- a/sql/hostname.cc
+++ b/sql/hostname.cc
@@ -177,7 +177,14 @@ my_string ip_to_hostname(struct in_addr *in, uint *errors)
&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);
}
diff --git a/sql/item.h b/sql/item.h
index d949095b455..d576fbbc60a 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -180,7 +180,8 @@ public:
{ 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. */
@@ -422,6 +423,10 @@ public:
{
return field->result_type();
}
+ Item_result cast_to_int_type() const
+ {
+ return field->cast_to_int_type();
+ }
enum_field_types field_type() const
{
return field->type();
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 2b38584fe23..1b80ef06251 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -582,6 +582,58 @@ void Item_func_signed::print(String *str)
}
+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);
@@ -591,6 +643,27 @@ void Item_func_unsigned::print(String *str)
}
+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;
+}
+
+
double Item_func_plus::val()
{
DBUG_ASSERT(fixed == 1);
diff --git a/sql/item_func.h b/sql/item_func.h
index 3a309f4ae99..288db3a148c 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -226,12 +226,8 @@ public:
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 @@ public:
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);
};