Commit ee3a8cb0 authored by Alexander Barkov's avatar Alexander Barkov

MDEV-9215 Detect cmp_type() and result_type() from field_type()

Part5: Derive Item_param from Type_handler_hybrid_field_type
parent c3494e19
......@@ -2977,13 +2977,12 @@ default_set_param_func(Item_param *param,
Item_param::Item_param(THD *thd, uint pos_in_query_arg):
Type_handler_hybrid_field_type(MYSQL_TYPE_VARCHAR),
Item_basic_value(thd),
Rewritable_query_parameter(pos_in_query_arg, 1),
state(NO_VALUE),
item_result_type(STRING_RESULT),
/* Don't pretend to be a literal unless value for this item is set. */
item_type(PARAM_ITEM),
param_type(MYSQL_TYPE_VARCHAR),
set_param_func(default_set_param_func),
m_out_param_info(NULL)
{
......@@ -3183,25 +3182,25 @@ bool Item_param::set_from_user_var(THD *thd, const user_var_entry *entry)
DBUG_ENTER("Item_param::set_from_user_var");
if (entry && entry->value)
{
item_result_type= entry->type;
unsigned_flag= entry->unsigned_flag;
if (limit_clause_param)
{
bool unused;
set_int(entry->val_int(&unused), MY_INT64_NUM_DECIMAL_DIGITS);
item_type= Item::INT_ITEM;
set_handler_by_result_type(entry->type);
DBUG_RETURN(!unsigned_flag && value.integer < 0 ? 1 : 0);
}
switch (item_result_type) {
switch (entry->type) {
case REAL_RESULT:
set_double(*(double*)entry->value);
item_type= Item::REAL_ITEM;
param_type= MYSQL_TYPE_DOUBLE;
set_handler_by_field_type(MYSQL_TYPE_DOUBLE);
break;
case INT_RESULT:
set_int(*(longlong*)entry->value, MY_INT64_NUM_DECIMAL_DIGITS);
item_type= Item::INT_ITEM;
param_type= MYSQL_TYPE_LONGLONG;
set_handler_by_field_type(MYSQL_TYPE_LONGLONG);
break;
case STRING_RESULT:
{
......@@ -3224,7 +3223,7 @@ bool Item_param::set_from_user_var(THD *thd, const user_var_entry *entry)
charset of connection, so we have to set it later.
*/
item_type= Item::STRING_ITEM;
param_type= MYSQL_TYPE_VARCHAR;
set_handler_by_field_type(MYSQL_TYPE_VARCHAR);
if (set_str((const char *)entry->value, entry->length))
DBUG_RETURN(1);
......@@ -3240,7 +3239,7 @@ bool Item_param::set_from_user_var(THD *thd, const user_var_entry *entry)
my_decimal_precision_to_length_no_truncation(ent_value->precision(),
decimals, unsigned_flag);
item_type= Item::DECIMAL_ITEM;
param_type= MYSQL_TYPE_NEWDECIMAL;
set_handler_by_field_type(MYSQL_TYPE_NEWDECIMAL);
break;
}
case ROW_RESULT:
......@@ -3665,10 +3664,9 @@ void
Item_param::set_param_type_and_swap_value(Item_param *src)
{
Type_std_attributes::set(src);
param_type= src->param_type;
set_handler(src->type_handler());
set_param_func= src->set_param_func;
item_type= src->item_type;
item_result_type= src->item_result_type;
maybe_null= src->maybe_null;
null_value= src->null_value;
......@@ -3756,7 +3754,7 @@ Item_param::set_value(THD *thd, sp_rcontext *ctx, Item **it)
return FALSE;
}
item_result_type= arg->result_type();
set_handler_by_result_type(arg->result_type());
item_type= arg->type();
return FALSE;
}
......@@ -3775,7 +3773,7 @@ void
Item_param::set_out_param_info(Send_field *info)
{
m_out_param_info= info;
param_type= m_out_param_info->type;
set_handler_by_field_type(m_out_param_info->type);
}
......
......@@ -2594,11 +2594,22 @@ class Item_null_result :public Item_null
}
};
/* Item represents one placeholder ('?') of prepared statement */
/*
Item represents one placeholder ('?') of prepared statement
Notes:
Item_param::field_type() is used when this item is in a temporary table.
This is NOT placeholder metadata sent to client, as this value
is assigned after sending metadata (in setup_one_conversion_function).
For example in case of 'SELECT ?' you'll get MYSQL_TYPE_STRING both
in result set and placeholders metadata, no matter what type you will
supply for this placeholder in mysql_stmt_execute.
*/
class Item_param :public Item_basic_value,
private Settable_routine_parameter,
public Rewritable_query_parameter
public Rewritable_query_parameter,
public Type_handler_hybrid_field_type
{
public:
enum enum_item_param_state
......@@ -2645,25 +2656,18 @@ class Item_param :public Item_basic_value,
MYSQL_TIME time;
} value;
/* Cached values for virtual methods to save us one switch. */
enum Item_result item_result_type;
enum Type item_type;
/*
Used when this item is used in a temporary table.
This is NOT placeholder metadata sent to client, as this value
is assigned after sending metadata (in setup_one_conversion_function).
For example in case of 'SELECT ?' you'll get MYSQL_TYPE_STRING both
in result set and placeholders metadata, no matter what type you will
supply for this placeholder in mysql_stmt_execute.
*/
enum enum_field_types param_type;
enum_field_types field_type() const
{ return Type_handler_hybrid_field_type::field_type(); }
enum Item_result result_type () const
{ return Type_handler_hybrid_field_type::result_type(); }
enum Item_result cmp_type () const
{ return Type_handler_hybrid_field_type::cmp_type(); }
Item_param(THD *thd, uint pos_in_query_arg);
enum Item_result result_type () const { return item_result_type; }
enum Type type() const { return item_type; }
enum_field_types field_type() const { return param_type; }
double val_real();
longlong val_int();
......
......@@ -718,54 +718,44 @@ static void setup_one_conversion_function(THD *thd, Item_param *param,
case MYSQL_TYPE_TINY:
param->set_param_func= set_param_tiny;
param->item_type= Item::INT_ITEM;
param->item_result_type= INT_RESULT;
break;
case MYSQL_TYPE_SHORT:
param->set_param_func= set_param_short;
param->item_type= Item::INT_ITEM;
param->item_result_type= INT_RESULT;
break;
case MYSQL_TYPE_LONG:
param->set_param_func= set_param_int32;
param->item_type= Item::INT_ITEM;
param->item_result_type= INT_RESULT;
break;
case MYSQL_TYPE_LONGLONG:
param->set_param_func= set_param_int64;
param->item_type= Item::INT_ITEM;
param->item_result_type= INT_RESULT;
break;
case MYSQL_TYPE_FLOAT:
param->set_param_func= set_param_float;
param->item_type= Item::REAL_ITEM;
param->item_result_type= REAL_RESULT;
break;
case MYSQL_TYPE_DOUBLE:
param->set_param_func= set_param_double;
param->item_type= Item::REAL_ITEM;
param->item_result_type= REAL_RESULT;
break;
case MYSQL_TYPE_DECIMAL:
case MYSQL_TYPE_NEWDECIMAL:
param->set_param_func= set_param_decimal;
param->item_type= Item::DECIMAL_ITEM;
param->item_result_type= DECIMAL_RESULT;
break;
case MYSQL_TYPE_TIME:
param->set_param_func= set_param_time;
param->item_type= Item::STRING_ITEM;
param->item_result_type= STRING_RESULT;
break;
case MYSQL_TYPE_DATE:
param->set_param_func= set_param_date;
param->item_type= Item::STRING_ITEM;
param->item_result_type= STRING_RESULT;
break;
case MYSQL_TYPE_DATETIME:
case MYSQL_TYPE_TIMESTAMP:
param->set_param_func= set_param_datetime;
param->item_type= Item::STRING_ITEM;
param->item_result_type= STRING_RESULT;
break;
case MYSQL_TYPE_TINY_BLOB:
case MYSQL_TYPE_MEDIUM_BLOB:
......@@ -778,7 +768,6 @@ static void setup_one_conversion_function(THD *thd, Item_param *param,
DBUG_ASSERT(thd->variables.character_set_client);
param->value.cs_info.final_character_set_of_str_value= &my_charset_bin;
param->item_type= Item::STRING_ITEM;
param->item_result_type= STRING_RESULT;
break;
default:
/*
......@@ -808,10 +797,9 @@ static void setup_one_conversion_function(THD *thd, Item_param *param,
charset of connection, so we have to set it later.
*/
param->item_type= Item::STRING_ITEM;
param->item_result_type= STRING_RESULT;
}
}
param->param_type= (enum enum_field_types) param_type;
param->set_handler_by_field_type((enum enum_field_types) param_type);
}
#ifndef EMBEDDED_LIBRARY
......@@ -823,8 +811,8 @@ static void setup_one_conversion_function(THD *thd, Item_param *param,
*/
inline bool is_param_long_data_type(Item_param *param)
{
return ((param->param_type >= MYSQL_TYPE_TINY_BLOB) &&
(param->param_type <= MYSQL_TYPE_STRING));
return ((param->field_type() >= MYSQL_TYPE_TINY_BLOB) &&
(param->field_type() <= MYSQL_TYPE_STRING));
}
......@@ -1213,7 +1201,7 @@ static bool insert_params_from_vars_with_log(Prepared_statement *stmt,
the parameter's members that might be needed further
(e.g. value.cs_info.character_set_client is used in the query_val_str()).
*/
setup_one_conversion_function(thd, param, param->param_type);
setup_one_conversion_function(thd, param, param->field_type());
if (param->set_from_user_var(thd, entry))
DBUG_RETURN(1);
......
......@@ -318,6 +318,10 @@ class Type_handler_hybrid_field_type: public Type_handler
enum_field_types field_type() const { return m_type_handler->field_type(); }
Item_result result_type() const { return m_type_handler->result_type(); }
Item_result cmp_type() const { return m_type_handler->cmp_type(); }
void set_handler(const Type_handler *other)
{
m_type_handler= other;
}
const Type_handler *set_handler_by_result_type(Item_result type)
{
return (m_type_handler= get_handler_by_result_type(type));
......
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