Commit 9d834c76 authored by Alexander Barkov's avatar Alexander Barkov

MDEV-12932 Remove enum Cast_target and use Type_handler to handle CAST

parent f462bfc1
......@@ -36,68 +36,6 @@
#include "item_inetfunc.h"
#include "sql_time.h"
/*
=============================================================================
HELPER FUNCTIONS
=============================================================================
*/
static const char* item_name(Item *a, String *str)
{
if (a->name.str)
return a->name.str;
str->length(0);
a->print(str, QT_ORDINARY);
return str->c_ptr_safe();
}
static void wrong_precision_error(uint errcode, Item *a,
ulonglong number, uint maximum)
{
char buff[1024];
String buf(buff, sizeof(buff), system_charset_info);
my_error(errcode, MYF(0), number, item_name(a, &buf), maximum);
}
/**
Get precision and scale for a declaration
return
0 ok
1 error
*/
bool get_length_and_scale(ulonglong length, ulonglong decimals,
ulong *out_length, uint *out_decimals,
uint max_precision, uint max_scale,
Item *a)
{
if (length > (ulonglong) max_precision)
{
wrong_precision_error(ER_TOO_BIG_PRECISION, a, length, max_precision);
return 1;
}
if (decimals > (ulonglong) max_scale)
{
wrong_precision_error(ER_TOO_BIG_SCALE, a, decimals, max_scale);
return 1;
}
*out_decimals= (uint) decimals;
my_decimal_trim(&length, out_decimals);
*out_length= (ulong) length;
if (*out_length < *out_decimals)
{
my_error(ER_M_BIGGER_THAN_D, MYF(0), "");
return 1;
}
return 0;
}
/*
=============================================================================
LOCAL DECLARATIONS
......@@ -7270,114 +7208,6 @@ find_qualified_function_builder(THD *thd)
}
Item *
create_func_cast(THD *thd, Item *a, Cast_target cast_type,
const char *c_len, const char *c_dec,
CHARSET_INFO *cs)
{
Item *UNINIT_VAR(res);
ulonglong length= 0, decimals= 0;
int error;
/*
We don't have to check for error here as sql_yacc.yy has guaranteed
that the values are in range of ulonglong
*/
if (c_len)
length= (ulonglong) my_strtoll10(c_len, NULL, &error);
if (c_dec)
decimals= (ulonglong) my_strtoll10(c_dec, NULL, &error);
switch (cast_type) {
case ITEM_CAST_BINARY:
res= new (thd->mem_root) Item_func_binary(thd, a);
break;
case ITEM_CAST_SIGNED_INT:
res= new (thd->mem_root) Item_func_signed(thd, a);
break;
case ITEM_CAST_UNSIGNED_INT:
res= new (thd->mem_root) Item_func_unsigned(thd, a);
break;
case ITEM_CAST_DATE:
res= new (thd->mem_root) Item_date_typecast(thd, a);
break;
case ITEM_CAST_TIME:
if (decimals > MAX_DATETIME_PRECISION)
{
wrong_precision_error(ER_TOO_BIG_PRECISION, a, decimals,
MAX_DATETIME_PRECISION);
return 0;
}
res= new (thd->mem_root) Item_time_typecast(thd, a, (uint) decimals);
break;
case ITEM_CAST_DATETIME:
if (decimals > MAX_DATETIME_PRECISION)
{
wrong_precision_error(ER_TOO_BIG_PRECISION, a, decimals,
MAX_DATETIME_PRECISION);
return 0;
}
res= new (thd->mem_root) Item_datetime_typecast(thd, a, (uint) decimals);
break;
case ITEM_CAST_DECIMAL:
{
ulong len;
uint dec;
if (get_length_and_scale(length, decimals, &len, &dec,
DECIMAL_MAX_PRECISION, DECIMAL_MAX_SCALE,
a))
return NULL;
res= new (thd->mem_root) Item_decimal_typecast(thd, a, len, dec);
break;
}
case ITEM_CAST_DOUBLE:
{
ulong len;
uint dec;
if (!c_len)
{
length= DBL_DIG+7;
decimals= NOT_FIXED_DEC;
}
else if (get_length_and_scale(length, decimals, &len, &dec,
DECIMAL_MAX_PRECISION, NOT_FIXED_DEC-1,
a))
return NULL;
res= new (thd->mem_root) Item_double_typecast(thd, a, (uint) length,
(uint) decimals);
break;
}
case ITEM_CAST_CHAR:
{
int len= -1;
CHARSET_INFO *real_cs= (cs ? cs : thd->variables.collation_connection);
if (c_len)
{
if (length > MAX_FIELD_BLOBLENGTH)
{
char buff[1024];
String buf(buff, sizeof(buff), system_charset_info);
my_error(ER_TOO_BIG_DISPLAYWIDTH, MYF(0), item_name(a, &buf),
MAX_FIELD_BLOBLENGTH);
return NULL;
}
len= (int) length;
}
res= new (thd->mem_root) Item_char_typecast(thd, a, len, real_cs);
break;
}
default:
{
DBUG_ASSERT(0);
res= 0;
break;
}
}
return res;
}
static bool
have_important_literal_warnings(const MYSQL_TIME_STATUS *status)
{
......@@ -7535,7 +7365,7 @@ Item *create_func_dyncol_delete(THD *thd, Item *str, List<Item> &nums)
Item *create_func_dyncol_get(THD *thd, Item *str, Item *num,
Cast_target cast_type,
const Type_handler *handler,
const char *c_len, const char *c_dec,
CHARSET_INFO *cs)
{
......@@ -7543,5 +7373,6 @@ Item *create_func_dyncol_get(THD *thd, Item *str, Item *num,
if (!(res= new (thd->mem_root) Item_dyncol_get(thd, str, num)))
return res; // Return NULL
return create_func_cast(thd, res, cast_type, c_len, c_dec, cs);
return handler->create_typecast_item(thd, res,
Type_cast_attributes(c_len, c_dec, cs));
}
......@@ -157,20 +157,6 @@ class Create_udf_func : public Create_func
#endif
/**
Builder for cast expressions.
@param thd The current thread
@param a The item to cast
@param cast_type the type casted into
@param len TODO
@param dec TODO
@param cs The character set
*/
Item *
create_func_cast(THD *thd, Item *a, Cast_target cast_type,
const char *len, const char *dec,
CHARSET_INFO *cs);
Item *create_temporal_literal(THD *thd,
const char *str, uint length,
CHARSET_INFO *cs,
......@@ -194,7 +180,7 @@ Item *create_func_dyncol_add(THD *thd, Item *str,
List<DYNCALL_CREATE_DEF> &list);
Item *create_func_dyncol_delete(THD *thd, Item *str, List<Item> &nums);
Item *create_func_dyncol_get(THD *thd, Item *num, Item *str,
Cast_target cast_type,
const Type_handler *handler,
const char *c_len, const char *c_dec,
CHARSET_INFO *cs);
Item *create_func_dyncol_json(THD *thd, Item *str);
......
......@@ -2576,40 +2576,37 @@ class Item_func_is_used_lock :public Item_long_func
{ return get_item_copy<Item_func_is_used_lock>(thd, mem_root, this); }
};
/* For type casts */
enum Cast_target
{
ITEM_CAST_BINARY, ITEM_CAST_SIGNED_INT, ITEM_CAST_UNSIGNED_INT,
ITEM_CAST_DATE, ITEM_CAST_TIME, ITEM_CAST_DATETIME, ITEM_CAST_CHAR,
ITEM_CAST_DECIMAL, ITEM_CAST_DOUBLE
};
struct Lex_cast_type_st: public Lex_length_and_dec_st
{
private:
Cast_target m_type;
const Type_handler *m_type_handler;
public:
void set(Cast_target type, const char *length, const char *dec)
void set(const Type_handler *handler, const char *length, const char *dec)
{
m_type= type;
m_type_handler= handler;
Lex_length_and_dec_st::set(length, dec);
}
void set(Cast_target type, Lex_length_and_dec_st length_and_dec)
void set(const Type_handler *handler, Lex_length_and_dec_st length_and_dec)
{
m_type= type;
m_type_handler= handler;
Lex_length_and_dec_st::operator=(length_and_dec);
}
void set(Cast_target type, const char *length)
void set(const Type_handler *handler, const char *length)
{
set(handler, length, 0);
}
void set(const Type_handler *handler)
{
set(type, length, 0);
set(handler, 0, 0);
}
void set(Cast_target type)
const Type_handler *type_handler() const { return m_type_handler; }
Item *create_typecast_item(THD *thd, Item *item, CHARSET_INFO *cs= NULL)
{
set(type, 0, 0);
return m_type_handler->
create_typecast_item(thd, item,
Type_cast_attributes(length(), dec(), cs));
}
Cast_target type() const { return m_type; }
};
......
......@@ -30,6 +30,7 @@ Type_handler_short type_handler_short;
Type_handler_long type_handler_long;
Type_handler_int24 type_handler_int24;
Type_handler_longlong type_handler_longlong;
Type_handler_longlong type_handler_ulonglong; // Only used for CAST() for now
Type_handler_float type_handler_float;
Type_handler_double type_handler_double;
Type_handler_bit type_handler_bit;
......@@ -5215,3 +5216,165 @@ Item *Type_handler_row::
}
/***************************************************************************/
static const char* item_name(Item *a, String *str)
{
if (a->name.str)
return a->name.str;
str->length(0);
a->print(str, QT_ORDINARY);
return str->c_ptr_safe();
}
static void wrong_precision_error(uint errcode, Item *a,
ulonglong number, uint maximum)
{
StringBuffer<1024> buf(system_charset_info);
my_error(errcode, MYF(0), number, item_name(a, &buf), maximum);
}
/**
Get precision and scale for a declaration
return
0 ok
1 error
*/
bool get_length_and_scale(ulonglong length, ulonglong decimals,
ulong *out_length, uint *out_decimals,
uint max_precision, uint max_scale,
Item *a)
{
if (length > (ulonglong) max_precision)
{
wrong_precision_error(ER_TOO_BIG_PRECISION, a, length, max_precision);
return 1;
}
if (decimals > (ulonglong) max_scale)
{
wrong_precision_error(ER_TOO_BIG_SCALE, a, decimals, max_scale);
return 1;
}
*out_decimals= (uint) decimals;
my_decimal_trim(&length, out_decimals);
*out_length= (ulong) length;
if (*out_length < *out_decimals)
{
my_error(ER_M_BIGGER_THAN_D, MYF(0), "");
return 1;
}
return 0;
}
Item *Type_handler_longlong::
create_typecast_item(THD *thd, Item *item,
const Type_cast_attributes &attr) const
{
if (this != &type_handler_ulonglong)
return new (thd->mem_root) Item_func_signed(thd, item);
return new (thd->mem_root) Item_func_unsigned(thd, item);
}
Item *Type_handler_date_common::
create_typecast_item(THD *thd, Item *item,
const Type_cast_attributes &attr) const
{
return new (thd->mem_root) Item_date_typecast(thd, item);
}
Item *Type_handler_time_common::
create_typecast_item(THD *thd, Item *item,
const Type_cast_attributes &attr) const
{
if (attr.decimals() > MAX_DATETIME_PRECISION)
{
wrong_precision_error(ER_TOO_BIG_PRECISION, item, attr.decimals(),
MAX_DATETIME_PRECISION);
return 0;
}
return new (thd->mem_root)
Item_time_typecast(thd, item, (uint) attr.decimals());
}
Item *Type_handler_datetime_common::
create_typecast_item(THD *thd, Item *item,
const Type_cast_attributes &attr) const
{
if (attr.decimals() > MAX_DATETIME_PRECISION)
{
wrong_precision_error(ER_TOO_BIG_PRECISION, item, attr.decimals(),
MAX_DATETIME_PRECISION);
return 0;
}
return new (thd->mem_root)
Item_datetime_typecast(thd, item, (uint) attr.decimals());
}
Item *Type_handler_decimal_result::
create_typecast_item(THD *thd, Item *item,
const Type_cast_attributes &attr) const
{
ulong len;
uint dec;
if (get_length_and_scale(attr.length(), attr.decimals(), &len, &dec,
DECIMAL_MAX_PRECISION, DECIMAL_MAX_SCALE, item))
return NULL;
return new (thd->mem_root) Item_decimal_typecast(thd, item, len, dec);
}
Item *Type_handler_double::
create_typecast_item(THD *thd, Item *item,
const Type_cast_attributes &attr) const
{
ulong len;
uint dec;
if (!attr.length_specified())
return new (thd->mem_root) Item_double_typecast(thd, item,
DBL_DIG + 7,
NOT_FIXED_DEC);
if (get_length_and_scale(attr.length(), attr.decimals(), &len, &dec,
DECIMAL_MAX_PRECISION, NOT_FIXED_DEC - 1, item))
return NULL;
return new (thd->mem_root) Item_double_typecast(thd, item, len, dec);
}
Item *Type_handler_long_blob::
create_typecast_item(THD *thd, Item *item,
const Type_cast_attributes &attr) const
{
int len= -1;
CHARSET_INFO *real_cs= attr.charset() ?
attr.charset() :
thd->variables.collation_connection;
if (attr.length_specified())
{
if (attr.length() > MAX_FIELD_BLOBLENGTH)
{
char buff[1024];
String buf(buff, sizeof(buff), system_charset_info);
my_error(ER_TOO_BIG_DISPLAYWIDTH, MYF(0), item_name(item, &buf),
MAX_FIELD_BLOBLENGTH);
return NULL;
}
len= (int) attr.length();
}
return new (thd->mem_root) Item_char_typecast(thd, item, len, real_cs);
}
/***************************************************************************/
......@@ -488,6 +488,44 @@ class Type_all_attributes: public Type_std_attributes
};
class Type_cast_attributes
{
CHARSET_INFO *m_charset;
ulonglong m_length;
ulonglong m_decimals;
bool m_length_specified;
bool m_decimals_specified;
public:
Type_cast_attributes(const char *c_len, const char *c_dec, CHARSET_INFO *cs)
:m_charset(cs), m_length(0), m_decimals(0),
m_length_specified(false), m_decimals_specified(false)
{
set_length_and_dec(c_len, c_dec);
}
Type_cast_attributes(CHARSET_INFO *cs)
:m_charset(cs), m_length(0), m_decimals(0),
m_length_specified(false), m_decimals_specified(false)
{ }
void set_length_and_dec(const char *c_len, const char *c_dec)
{
int error;
/*
We don't have to check for error here as sql_yacc.yy has guaranteed
that the values are in range of ulonglong
*/
if ((m_length_specified= (c_len != NULL)))
m_length= (ulonglong) my_strtoll10(c_len, NULL, &error);
if ((m_decimals_specified= (c_dec != NULL)))
m_decimals= (ulonglong) my_strtoll10(c_dec, NULL, &error);
}
CHARSET_INFO *charset() const { return m_charset; }
bool length_specified() const { return m_length_specified; }
bool decimals_specified() const { return m_decimals_specified; }
ulonglong length() const { return m_length; }
ulonglong decimals() const { return m_decimals; }
};
class Name: private LEX_CSTRING
{
public:
......@@ -826,6 +864,12 @@ class Type_handler
Item *src,
const Item *cmp) const= 0;
virtual Item_cache *Item_get_cache(THD *thd, const Item *item) const= 0;
virtual Item *create_typecast_item(THD *thd, Item *item,
const Type_cast_attributes &attr) const
{
DBUG_ASSERT(0);
return NULL;
}
virtual bool set_comparator_func(Arg_comparator *cmp) const= 0;
virtual bool Item_hybrid_func_fix_attributes(THD *thd,
const char *name,
......@@ -1351,6 +1395,8 @@ class Type_handler_decimal_result: public Type_handler_numeric
const Type_std_attributes *item,
SORT_FIELD_ATTR *attr) const;
uint32 max_display_length(const Item *item) const;
Item *create_typecast_item(THD *thd, Item *item,
const Type_cast_attributes &attr) const;
uint Item_decimal_precision(const Item *item) const;
bool Item_save_in_value(Item *item, st_value *value) const;
bool Item_param_set_from_value(THD *thd,
......@@ -1773,6 +1819,8 @@ class Type_handler_longlong: public Type_handler_general_purpose_int
enum_field_types field_type() const { return MYSQL_TYPE_LONGLONG; }
uint32 max_display_length(const Item *item) const { return 20; }
uint32 calc_pack_length(uint32 length) const { return 8; }
Item *create_typecast_item(THD *thd, Item *item,
const Type_cast_attributes &attr) const;
bool Item_send(Item *item, Protocol *protocol, st_value *buf) const
{
return Item_send_longlong(item, protocol, buf);
......@@ -1926,6 +1974,8 @@ class Type_handler_double: public Type_handler_real_result
bool type_can_have_auto_increment_attribute() const { return true; }
uint32 max_display_length(const Item *item) const { return 53; }
uint32 calc_pack_length(uint32 length) const { return sizeof(double); }
Item *create_typecast_item(THD *thd, Item *item,
const Type_cast_attributes &attr) const;
bool Item_send(Item *item, Protocol *protocol, st_value *buf) const
{
return Item_send_double(item, protocol, buf);
......@@ -1955,6 +2005,8 @@ class Type_handler_time_common: public Type_handler_temporal_result
{
return MYSQL_TIMESTAMP_TIME;
}
Item *create_typecast_item(THD *thd, Item *item,
const Type_cast_attributes &attr) const;
uint Item_decimal_scale(const Item *item) const
{
return Item_decimal_scale_with_seconds(item);
......@@ -2054,6 +2106,8 @@ class Type_handler_date_common: public Type_handler_temporal_with_date
{
return MYSQL_TIMESTAMP_DATE;
}
Item *create_typecast_item(THD *thd, Item *item,
const Type_cast_attributes &attr) const;
bool Column_definition_fix_attributes(Column_definition *c) const;
uint Item_decimal_precision(const Item *item) const;
String *print_item_value(THD *thd, Item *item, String *str) const;
......@@ -2113,6 +2167,8 @@ class Type_handler_datetime_common: public Type_handler_temporal_with_date
{
return MYSQL_TIMESTAMP_DATETIME;
}
Item *create_typecast_item(THD *thd, Item *item,
const Type_cast_attributes &attr) const;
bool Column_definition_fix_attributes(Column_definition *c) const;
uint Item_decimal_scale(const Item *item) const
{
......@@ -2516,6 +2572,8 @@ class Type_handler_long_blob: public Type_handler_blob_common
const Name name() const { return m_name_longblob; }
enum_field_types field_type() const { return MYSQL_TYPE_LONG_BLOB; }
uint32 calc_pack_length(uint32 length) const;
Item *create_typecast_item(THD *thd, Item *item,
const Type_cast_attributes &attr) const;
Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const;
Field *make_table_field(const LEX_CSTRING *name,
......@@ -2783,6 +2841,7 @@ extern MYSQL_PLUGIN_IMPORT Type_handler_short type_handler_short;
extern MYSQL_PLUGIN_IMPORT Type_handler_int24 type_handler_int24;
extern MYSQL_PLUGIN_IMPORT Type_handler_long type_handler_long;
extern MYSQL_PLUGIN_IMPORT Type_handler_longlong type_handler_longlong;
extern MYSQL_PLUGIN_IMPORT Type_handler_longlong type_handler_ulonglong;
extern MYSQL_PLUGIN_IMPORT Type_handler_newdecimal type_handler_newdecimal;
extern MYSQL_PLUGIN_IMPORT Type_handler_olddecimal type_handler_olddecimal;
......
......@@ -9412,10 +9412,7 @@ column_default_non_parenthesized_expr:
}
| CAST_SYM '(' expr AS cast_type ')'
{
LEX *lex= Lex;
$$= create_func_cast(thd, $3, $5.type(), $5.length(), $5.dec(),
lex->charset);
if ($$ == NULL)
if (!($$= $5.create_typecast_item(thd, $3, Lex->charset)))
MYSQL_YYABORT;
}
| CASE_SYM opt_expr when_list opt_else END
......@@ -9426,9 +9423,7 @@ column_default_non_parenthesized_expr:
}
| CONVERT_SYM '(' expr ',' cast_type ')'
{
$$= create_func_cast(thd, $3, $5.type(), $5.length(), $5.dec(),
Lex->charset);
if ($$ == NULL)
if (!($$= $5.create_typecast_item(thd, $3, Lex->charset)))
MYSQL_YYABORT;
}
| CONVERT_SYM '(' expr USING charset_name ')'
......@@ -9507,9 +9502,8 @@ simple_expr:
| '(' parenthesized_expr ')' { $$= $2; }
| BINARY simple_expr %prec NEG
{
$$= create_func_cast(thd, $2, ITEM_CAST_CHAR, NULL, NULL,
&my_charset_bin);
if ($$ == NULL)
Type_cast_attributes at(&my_charset_bin);
if (!($$= type_handler_long_blob.create_typecast_item(thd, $2, at)))
MYSQL_YYABORT;
}
| simple_expr OR_OR_SYM simple_expr
......@@ -9954,7 +9948,7 @@ function_call_nonkeyword:
COLUMN_GET_SYM '(' expr ',' expr AS cast_type ')'
{
LEX *lex= Lex;
$$= create_func_dyncol_get(thd, $3, $5, $7.type(),
$$= create_func_dyncol_get(thd, $3, $5, $7.type_handler(),
$7.length(), $7.dec(),
lex->charset);
if ($$ == NULL)
......@@ -10777,34 +10771,34 @@ in_sum_expr:
cast_type:
BINARY opt_field_length
{ $$.set(ITEM_CAST_CHAR, $2); Lex->charset= &my_charset_bin; }
{ $$.set(&type_handler_long_blob, $2); Lex->charset= &my_charset_bin; }
| CHAR_SYM opt_field_length
{ Lex->charset= thd->variables.collation_connection; }
opt_binary
{ $$.set(ITEM_CAST_CHAR, $2); }
{ $$.set(&type_handler_long_blob, $2); }
| NCHAR_SYM opt_field_length
{
Lex->charset= national_charset_info;
$$.set(ITEM_CAST_CHAR, $2, 0);
$$.set(&type_handler_long_blob, $2, 0);
}
| cast_type_numeric { $$= $1; Lex->charset= NULL; }
| cast_type_temporal { $$= $1; Lex->charset= NULL; }
;
cast_type_numeric:
INT_SYM { $$.set(ITEM_CAST_SIGNED_INT); }
| SIGNED_SYM { $$.set(ITEM_CAST_SIGNED_INT); }
| SIGNED_SYM INT_SYM { $$.set(ITEM_CAST_SIGNED_INT); }
| UNSIGNED { $$.set(ITEM_CAST_UNSIGNED_INT); }
| UNSIGNED INT_SYM { $$.set(ITEM_CAST_UNSIGNED_INT); }
| DECIMAL_SYM float_options { $$.set(ITEM_CAST_DECIMAL, $2); }
| DOUBLE_SYM opt_precision { $$.set(ITEM_CAST_DOUBLE, $2); }
INT_SYM { $$.set(&type_handler_longlong); }
| SIGNED_SYM { $$.set(&type_handler_longlong); }
| SIGNED_SYM INT_SYM { $$.set(&type_handler_longlong); }
| UNSIGNED { $$.set(&type_handler_ulonglong); }
| UNSIGNED INT_SYM { $$.set(&type_handler_ulonglong); }
| DECIMAL_SYM float_options { $$.set(&type_handler_newdecimal, $2); }
| DOUBLE_SYM opt_precision { $$.set(&type_handler_double, $2); }
;
cast_type_temporal:
DATE_SYM { $$.set(ITEM_CAST_DATE); }
| TIME_SYM opt_field_length { $$.set(ITEM_CAST_TIME, 0, $2); }
| DATETIME opt_field_length { $$.set(ITEM_CAST_DATETIME, 0, $2); }
DATE_SYM { $$.set(&type_handler_newdate); }
| TIME_SYM opt_field_length { $$.set(&type_handler_time2, 0, $2); }
| DATETIME opt_field_length { $$.set(&type_handler_datetime2, 0, $2); }
;
opt_expr_list:
......
......@@ -9433,10 +9433,7 @@ column_default_non_parenthesized_expr:
}
| CAST_SYM '(' expr AS cast_type ')'
{
LEX *lex= Lex;
$$= create_func_cast(thd, $3, $5.type(), $5.length(), $5.dec(),
lex->charset);
if ($$ == NULL)
if (!($$= $5.create_typecast_item(thd, $3, Lex->charset)))
MYSQL_YYABORT;
}
| CASE_SYM opt_expr when_list opt_else END
......@@ -9447,9 +9444,7 @@ column_default_non_parenthesized_expr:
}
| CONVERT_SYM '(' expr ',' cast_type ')'
{
$$= create_func_cast(thd, $3, $5.type(), $5.length(), $5.dec(),
Lex->charset);
if ($$ == NULL)
if (!($$= $5.create_typecast_item(thd, $3, Lex->charset)))
MYSQL_YYABORT;
}
| CONVERT_SYM '(' expr USING charset_name ')'
......@@ -9559,9 +9554,8 @@ simple_expr:
| '(' parenthesized_expr ')' { $$= $2; }
| BINARY simple_expr %prec NEG
{
$$= create_func_cast(thd, $2, ITEM_CAST_CHAR, NULL, NULL,
&my_charset_bin);
if ($$ == NULL)
Type_cast_attributes at(&my_charset_bin);
if (!($$= type_handler_long_blob.create_typecast_item(thd, $2, at)))
MYSQL_YYABORT;
}
| simple_expr OR_OR_SYM simple_expr
......@@ -10009,7 +10003,7 @@ function_call_nonkeyword:
COLUMN_GET_SYM '(' expr ',' expr AS cast_type ')'
{
LEX *lex= Lex;
$$= create_func_dyncol_get(thd, $3, $5, $7.type(),
$$= create_func_dyncol_get(thd, $3, $5, $7.type_handler(),
$7.length(), $7.dec(),
lex->charset);
if ($$ == NULL)
......@@ -10832,42 +10826,42 @@ in_sum_expr:
cast_type:
BINARY opt_field_length
{ $$.set(ITEM_CAST_CHAR, $2); Lex->charset= &my_charset_bin; }
{ $$.set(&type_handler_long_blob, $2); Lex->charset= &my_charset_bin; }
| CHAR_SYM opt_field_length
{ Lex->charset= thd->variables.collation_connection; }
opt_binary
{ $$.set(ITEM_CAST_CHAR, $2); }
{ $$.set(&type_handler_long_blob, $2); }
| VARCHAR field_length
{ Lex->charset= thd->variables.collation_connection; }
opt_binary
{ $$.set(ITEM_CAST_CHAR, $2); }
{ $$.set(&type_handler_long_blob, $2); }
| VARCHAR2 field_length
{ Lex->charset= thd->variables.collation_connection; }
opt_binary
{ $$.set(ITEM_CAST_CHAR, $2); }
{ $$.set(&type_handler_long_blob, $2); }
| NCHAR_SYM opt_field_length
{
Lex->charset= national_charset_info;
$$.set(ITEM_CAST_CHAR, $2, 0);
$$.set(&type_handler_long_blob, $2, 0);
}
| cast_type_numeric { $$= $1; Lex->charset= NULL; }
| cast_type_temporal { $$= $1; Lex->charset= NULL; }
;
cast_type_numeric:
INT_SYM { $$.set(ITEM_CAST_SIGNED_INT); }
| SIGNED_SYM { $$.set(ITEM_CAST_SIGNED_INT); }
| SIGNED_SYM INT_SYM { $$.set(ITEM_CAST_SIGNED_INT); }
| UNSIGNED { $$.set(ITEM_CAST_UNSIGNED_INT); }
| UNSIGNED INT_SYM { $$.set(ITEM_CAST_UNSIGNED_INT); }
| DECIMAL_SYM float_options { $$.set(ITEM_CAST_DECIMAL, $2); }
| DOUBLE_SYM opt_precision { $$.set(ITEM_CAST_DOUBLE, $2); }
INT_SYM { $$.set(&type_handler_longlong); }
| SIGNED_SYM { $$.set(&type_handler_longlong); }
| SIGNED_SYM INT_SYM { $$.set(&type_handler_longlong); }
| UNSIGNED { $$.set(&type_handler_ulonglong); }
| UNSIGNED INT_SYM { $$.set(&type_handler_ulonglong); }
| DECIMAL_SYM float_options { $$.set(&type_handler_newdecimal, $2); }
| DOUBLE_SYM opt_precision { $$.set(&type_handler_double, $2); }
;
cast_type_temporal:
DATE_SYM { $$.set(ITEM_CAST_DATE); }
| TIME_SYM opt_field_length { $$.set(ITEM_CAST_TIME, 0, $2); }
| DATETIME opt_field_length { $$.set(ITEM_CAST_DATETIME, 0, $2); }
DATE_SYM { $$.set(&type_handler_newdate); }
| TIME_SYM opt_field_length { $$.set(&type_handler_time2, 0, $2); }
| DATETIME opt_field_length { $$.set(&type_handler_datetime2, 0, $2); }
;
opt_expr_list:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment