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