summaryrefslogtreecommitdiff
path: root/sql/item_timefunc.cc
diff options
context:
space:
mode:
authorAlexander Barkov <bar@mariadb.com>2019-10-11 14:50:11 +0400
committerAlexander Barkov <bar@mariadb.com>2019-10-11 14:50:11 +0400
commitb5fae7f743d2b2c71ee23b0daf51c2be294733eb (patch)
treea2609d62812fbd397f7c6ab165f33032f0f45dd1 /sql/item_timefunc.cc
parentd04f2de80a96b3ff9290ee27507195bfb01fc77f (diff)
downloadmariadb-git-b5fae7f743d2b2c71ee23b0daf51c2be294733eb.tar.gz
MDEV-20795 CAST(inet6 AS BINARY) returns wrong result
Diffstat (limited to 'sql/item_timefunc.cc')
-rw-r--r--sql/item_timefunc.cc86
1 files changed, 85 insertions, 1 deletions
diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc
index 86e81fa5bf7..da67e1ca371 100644
--- a/sql/item_timefunc.cc
+++ b/sql/item_timefunc.cc
@@ -2326,7 +2326,7 @@ uint Item_char_typecast::adjusted_length_with_warn(uint length)
}
-String *Item_char_typecast::val_str(String *str)
+String *Item_char_typecast::val_str_generic(String *str)
{
DBUG_ASSERT(fixed == 1);
String *res;
@@ -2382,11 +2382,75 @@ end:
}
+String *Item_char_typecast::val_str_binary_from_native(String *str)
+{
+ DBUG_ASSERT(fixed == 1);
+ DBUG_ASSERT(cast_cs == &my_charset_bin);
+ NativeBuffer<STRING_BUFFER_USUAL_SIZE> native;
+
+ if (args[0]->val_native(current_thd, &native))
+ {
+ null_value= 1;
+ return 0;
+ }
+
+ if (has_explicit_length())
+ {
+ cast_length= adjusted_length_with_warn(cast_length);
+ if (cast_length > native.length())
+ {
+ // add trailing 0x00s
+ DBUG_ASSERT(cast_length <= current_thd->variables.max_allowed_packet);
+ str->alloc(cast_length);
+ str->copy(native.ptr(), native.length(), &my_charset_bin);
+ bzero((char*) str->end(), cast_length - str->length());
+ str->length(cast_length);
+ }
+ else
+ str->copy(native.ptr(), cast_length, &my_charset_bin);
+ }
+ else
+ str->copy(native.ptr(), native.length(), &my_charset_bin);
+
+ return ((null_value= (str->length() >
+ adjusted_length_with_warn(str->length())))) ? 0 : str;
+}
+
+
+class Item_char_typecast_func_handler: public Item_handled_func::Handler_str
+{
+public:
+ const Type_handler *return_type_handler() const
+ {
+ return &type_handler_varchar;
+ }
+ const Type_handler *
+ type_handler_for_create_select(const Item_handled_func *item) const
+ {
+ return return_type_handler()->type_handler_for_tmp_table(item);
+ }
+
+ bool fix_length_and_dec(Item_handled_func *item) const
+ {
+ return false;
+ }
+ String *val_str(Item_handled_func *item, String *to) const
+ {
+ DBUG_ASSERT(dynamic_cast<const Item_char_typecast*>(item));
+ return static_cast<Item_char_typecast*>(item)->val_str_generic(to);
+ }
+};
+
+
+static const Item_char_typecast_func_handler item_char_typecast_func_handler;
+
+
void Item_char_typecast::fix_length_and_dec_numeric()
{
fix_length_and_dec_internal(from_cs= cast_cs->mbminlen == 1 ?
cast_cs :
&my_charset_latin1);
+ set_func_handler(&item_char_typecast_func_handler);
}
@@ -2395,6 +2459,24 @@ void Item_char_typecast::fix_length_and_dec_generic()
fix_length_and_dec_internal(from_cs= args[0]->dynamic_result() ?
0 :
args[0]->collation.collation);
+ set_func_handler(&item_char_typecast_func_handler);
+}
+
+
+void Item_char_typecast::fix_length_and_dec_str()
+{
+ fix_length_and_dec_generic();
+ m_suppress_warning_to_error_escalation= true;
+ set_func_handler(&item_char_typecast_func_handler);
+}
+
+
+void
+Item_char_typecast::fix_length_and_dec_native_to_binary(uint32 octet_length)
+{
+ collation.set(&my_charset_bin, DERIVATION_IMPLICIT);
+ max_length= has_explicit_length() ? (uint32) cast_length : octet_length;
+ maybe_null|= current_thd->is_strict_mode();
}
@@ -2438,6 +2520,8 @@ void Item_char_typecast::fix_length_and_dec_internal(CHARSET_INFO *from_cs)
(cast_cs == &my_charset_bin ? 1 :
args[0]->collation.collation->mbmaxlen));
max_length= char_length * cast_cs->mbmaxlen;
+ // Add NULL-ability in strict mode. See Item_str_func::fix_fields()
+ maybe_null= maybe_null || current_thd->is_strict_mode();
}