Commit fe127562 authored by Alexander Barkov's avatar Alexander Barkov

MDEV-12687 Split Item::send() into virtual method in Type_handler

parent ae5b31fe
......@@ -6861,127 +6861,11 @@ bool Item_time_literal::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date)
Pack data in buffer for sending.
*/
bool Item_null::send(Protocol *protocol, String *packet)
bool Item_null::send(Protocol *protocol, st_value *buffer)
{
return protocol->store_null();
}
/**
This is only called from items that is not of type item_field.
*/
bool Item::send(Protocol *protocol, String *buffer)
{
bool UNINIT_VAR(result); // Will be set if null_value == 0
enum_field_types f_type;
switch ((f_type=field_type())) {
default:
case MYSQL_TYPE_NULL:
case MYSQL_TYPE_DECIMAL:
case MYSQL_TYPE_ENUM:
case MYSQL_TYPE_SET:
case MYSQL_TYPE_TINY_BLOB:
case MYSQL_TYPE_MEDIUM_BLOB:
case MYSQL_TYPE_LONG_BLOB:
case MYSQL_TYPE_BLOB:
case MYSQL_TYPE_GEOMETRY:
case MYSQL_TYPE_STRING:
case MYSQL_TYPE_VAR_STRING:
case MYSQL_TYPE_VARCHAR:
case MYSQL_TYPE_BIT:
case MYSQL_TYPE_NEWDECIMAL:
{
String *res;
if ((res=val_str(buffer)))
{
DBUG_ASSERT(!null_value);
result= protocol->store(res->ptr(),res->length(),res->charset());
}
else
{
DBUG_ASSERT(null_value);
}
break;
}
case MYSQL_TYPE_TINY:
{
longlong nr;
nr= val_int();
if (!null_value)
result= protocol->store_tiny(nr);
break;
}
case MYSQL_TYPE_SHORT:
case MYSQL_TYPE_YEAR:
{
longlong nr;
nr= val_int();
if (!null_value)
result= protocol->store_short(nr);
break;
}
case MYSQL_TYPE_INT24:
case MYSQL_TYPE_LONG:
{
longlong nr;
nr= val_int();
if (!null_value)
result= protocol->store_long(nr);
break;
}
case MYSQL_TYPE_LONGLONG:
{
longlong nr;
nr= val_int();
if (!null_value)
result= protocol->store_longlong(nr, unsigned_flag);
break;
}
case MYSQL_TYPE_FLOAT:
{
float nr;
nr= (float) val_real();
if (!null_value)
result= protocol->store(nr, decimals, buffer);
break;
}
case MYSQL_TYPE_DOUBLE:
{
double nr= val_real();
if (!null_value)
result= protocol->store(nr, decimals, buffer);
break;
}
case MYSQL_TYPE_DATETIME:
case MYSQL_TYPE_DATE:
case MYSQL_TYPE_TIMESTAMP:
{
MYSQL_TIME tm;
get_date(&tm, sql_mode_for_dates(current_thd));
if (!null_value)
{
if (f_type == MYSQL_TYPE_DATE)
return protocol->store_date(&tm);
else
result= protocol->store(&tm, decimals);
}
break;
}
case MYSQL_TYPE_TIME:
{
MYSQL_TIME tm;
get_time(&tm);
if (!null_value)
result= protocol->store_time(&tm, decimals);
break;
}
}
if (null_value)
result= protocol->store_null();
return result;
}
/**
Check if an item is a constant one and can be cached.
......@@ -7053,7 +6937,7 @@ bool Item::find_item_processor(void *arg)
return (this == ((Item *) arg));
}
bool Item_field::send(Protocol *protocol, String *buffer)
bool Item_field::send(Protocol *protocol, st_value *buffer)
{
return protocol->store(result_field);
}
......@@ -7783,11 +7667,11 @@ void Item_ref::print(String *str, enum_query_type query_type)
}
bool Item_ref::send(Protocol *prot, String *tmp)
bool Item_ref::send(Protocol *prot, st_value *buffer)
{
if (result_field)
return prot->store(result_field);
return (*ref)->send(prot, tmp);
return (*ref)->send(prot, buffer);
}
......@@ -8142,7 +8026,7 @@ bool Item_cache_wrapper::fix_fields(THD *thd __attribute__((unused)),
return FALSE;
}
bool Item_cache_wrapper::send(Protocol *protocol, String *buffer)
bool Item_cache_wrapper::send(Protocol *protocol, st_value *buffer)
{
if (result_field)
return protocol->store(result_field);
......@@ -8473,7 +8357,7 @@ Item* Item_cache_wrapper::get_tmp_table_item(THD *thd)
}
bool Item_direct_view_ref::send(Protocol *protocol, String *buffer)
bool Item_direct_view_ref::send(Protocol *protocol, st_value *buffer)
{
if (check_null_ref())
return protocol->store_null();
......@@ -8850,7 +8734,7 @@ bool Item_default_value::get_date(MYSQL_TIME *ltime,ulonglong fuzzydate)
return Item_field::get_date(ltime, fuzzydate);
}
bool Item_default_value::send(Protocol *protocol, String *buffer)
bool Item_default_value::send(Protocol *protocol, st_value *buffer)
{
calculate();
return Item_field::send(protocol, buffer);
......@@ -8957,7 +8841,7 @@ bool Item_ignore_value::get_date(MYSQL_TIME *ltime, ulonglong fuzzydate)
return TRUE;
}
bool Item_ignore_value::send(Protocol *protocol, String *buffer)
bool Item_ignore_value::send(Protocol *protocol, st_value *buffer)
{
DBUG_ASSERT(0); // never should be called
return TRUE;
......
......@@ -55,6 +55,23 @@ struct st_value
C_MODE_END
template<size_t buffer_size>
class ValueBuffer: public st_value
{
char buffer[buffer_size];
void reset_buffer()
{
m_string.set(buffer, buffer_size, &my_charset_bin);
}
public:
ValueBuffer()
{
reset_buffer();
}
};
const char *dbug_print_item(Item *item);
class Protocol;
......@@ -693,7 +710,10 @@ class Item: public Value_source,
{ return NULL; }
virtual int save_safe_in_field(Field *field)
{ return save_in_field(field, 1); }
virtual bool send(Protocol *protocol, String *str);
virtual bool send(Protocol *protocol, st_value *buffer)
{
return type_handler()->Item_send(this, protocol, buffer);
}
virtual bool eq(const Item *, bool binary_cmp) const;
virtual enum_field_types field_type() const= 0;
virtual const Type_handler *type_handler() const
......@@ -2089,7 +2109,7 @@ class Item_sp_variable :public Item
inline bool const_item() const;
inline int save_in_field(Field *field, bool no_conversions);
inline bool send(Protocol *protocol, String *str);
inline bool send(Protocol *protocol, st_value *buffer);
bool check_vcol_func_processor(void *arg)
{
return mark_unsupported_function(m_name.str, arg, VCOL_IMPOSSIBLE);
......@@ -2110,9 +2130,9 @@ inline int Item_sp_variable::save_in_field(Field *field, bool no_conversions)
return this_item()->save_in_field(field, no_conversions);
}
inline bool Item_sp_variable::send(Protocol *protocol, String *str)
inline bool Item_sp_variable::send(Protocol *protocol, st_value *buffer)
{
return this_item()->send(protocol, str);
return this_item()->send(protocol, buffer);
}
......@@ -2398,9 +2418,9 @@ class Item_name_const : public Item
return value_item->save_in_field(field, no_conversions);
}
bool send(Protocol *protocol, String *str)
bool send(Protocol *protocol, st_value *buffer)
{
return value_item->send(protocol, str);
return value_item->send(protocol, buffer);
}
bool check_vcol_func_processor(void *arg)
{
......@@ -2532,7 +2552,6 @@ class Item_ident_for_show :public Item
{
Type_std_attributes::set(par_field);
}
enum Type type() const { return FIELD_ITEM; }
double val_real() { return field->val_real(); }
longlong val_int() { return field->val_int(); }
......@@ -2591,7 +2610,7 @@ class Item_field :public Item_ident
my_decimal *val_decimal_result(my_decimal *);
bool val_bool_result();
bool is_null_result();
bool send(Protocol *protocol, String *str_arg);
bool send(Protocol *protocol, st_value *buffer);
void reset_field(Field *f);
bool fix_fields(THD *, Item **);
void fix_after_pullout(st_select_lex *new_parent, Item **ref);
......@@ -2829,7 +2848,7 @@ class Item_null :public Item_basic_constant
my_decimal *val_decimal(my_decimal *);
int save_in_field(Field *field, bool no_conversions);
int save_safe_in_field(Field *field);
bool send(Protocol *protocol, String *str);
bool send(Protocol *protocol, st_value *buffer);
enum Item_result result_type () const { return STRING_RESULT; }
enum_field_types field_type() const { return MYSQL_TYPE_NULL; }
bool basic_const_item() const { return 1; }
......@@ -4229,7 +4248,7 @@ class Item_ref :public Item_ident
my_decimal *val_decimal_result(my_decimal *);
bool val_bool_result();
bool is_null_result();
bool send(Protocol *prot, String *tmp);
bool send(Protocol *prot, st_value *buffer);
void make_field(THD *thd, Send_field *field);
bool fix_fields(THD *, Item **);
void fix_after_pullout(st_select_lex *new_parent, Item **ref);
......@@ -4498,7 +4517,7 @@ class Item_cache_wrapper :public Item_result_field
bool val_bool();
bool is_null();
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate);
bool send(Protocol *protocol, String *buffer);
bool send(Protocol *protocol, st_value *buffer);
void save_org_in_field(Field *field,
fast_field_copier data __attribute__ ((__unused__)))
{
......@@ -4712,7 +4731,7 @@ class Item_direct_view_ref :public Item_direct_ref
}
return Item_direct_ref::get_date(ltime, fuzzydate);
}
bool send(Protocol *protocol, String *buffer);
bool send(Protocol *protocol, st_value *buffer);
void save_org_in_field(Field *field,
fast_field_copier data __attribute__ ((__unused__)))
{
......@@ -5226,7 +5245,7 @@ class Item_default_value : public Item_field
longlong val_int();
my_decimal *val_decimal(my_decimal *decimal_value);
bool get_date(MYSQL_TIME *ltime,ulonglong fuzzydate);
bool send(Protocol *protocol, String *buffer);
bool send(Protocol *protocol, st_value *buffer);
int save_in_field(Field *field_arg, bool no_conversions);
bool save_in_param(THD *thd, Item_param *param)
{
......@@ -5278,7 +5297,7 @@ class Item_ignore_value : public Item_default_value
longlong val_int();
my_decimal *val_decimal(my_decimal *decimal_value);
bool get_date(MYSQL_TIME *ltime,ulonglong fuzzydate);
bool send(Protocol *protocol, String *buffer);
bool send(Protocol *protocol, st_value *buffer);
};
......
......@@ -4980,7 +4980,7 @@ void Item_func_set_user_var::print_as_stmt(String *str,
args[0]->print_parenthesised(str, query_type, precedence());
}
bool Item_func_set_user_var::send(Protocol *protocol, String *str_arg)
bool Item_func_set_user_var::send(Protocol *protocol, st_value *buffer)
{
if (result_field)
{
......@@ -4988,7 +4988,7 @@ bool Item_func_set_user_var::send(Protocol *protocol, String *str_arg)
update();
return protocol->store(result_field);
}
return Item::send(protocol, str_arg);
return Item::send(protocol, buffer);
}
void Item_func_set_user_var::make_field(THD *thd, Send_field *tmp_field)
......
......@@ -2248,7 +2248,7 @@ class Item_func_set_user_var :public Item_func_user_var
bool is_null_result();
bool update_hash(void *ptr, uint length, enum Item_result type,
CHARSET_INFO *cs, bool unsigned_arg);
bool send(Protocol *protocol, String *str_arg);
bool send(Protocol *protocol, st_value *buffer);
void make_field(THD *thd, Send_field *tmp_field);
bool check(bool use_result_field);
void save_item_result(Item *item);
......
......@@ -791,8 +791,7 @@ bool Protocol::send_result_set_metadata(List<Item> *list, uint flags)
{
List_iterator_fast<Item> it(*list);
Item *item;
uchar buff[MAX_FIELD_WIDTH];
String tmp((char*) buff,sizeof(buff),&my_charset_bin);
ValueBuffer<MAX_FIELD_WIDTH> tmp;
Protocol_text prot(thd);
String *local_packet= prot.storage_packet();
CHARSET_INFO *thd_charset= thd->variables.character_set_results;
......@@ -800,7 +799,9 @@ bool Protocol::send_result_set_metadata(List<Item> *list, uint flags)
if (flags & SEND_NUM_ROWS)
{ // Packet with number of elements
uchar buff[MAX_INT_WIDTH];
uchar *pos= net_store_length(buff, list->elements);
DBUG_ASSERT(pos <= buff + sizeof(buff));
if (my_net_write(&thd->net, buff, (size_t) (pos-buff)))
DBUG_RETURN(1);
}
......@@ -968,15 +969,20 @@ bool Protocol::write()
bool Protocol::send_result_set_row(List<Item> *row_items)
{
char buffer[MAX_FIELD_WIDTH];
String str_buffer(buffer, sizeof (buffer), &my_charset_bin);
List_iterator_fast<Item> it(*row_items);
DBUG_ENTER("Protocol::send_result_set_row");
for (Item *item= it++; item; item= it++)
{
if (item->send(this, &str_buffer))
/*
ValueBuffer::m_string can be altered during Item::send().
It's important to declare value_buffer inside the loop,
to have ValueBuffer::m_string point to ValueBuffer::buffer
on every iteration.
*/
ValueBuffer<MAX_FIELD_WIDTH> value_buffer;
if (item->send(this, &value_buffer))
{
// If we're out of memory, reclaim some, to help us recover.
this->free();
......@@ -985,12 +991,6 @@ bool Protocol::send_result_set_row(List<Item> *row_items)
/* Item::send() may generate an error. If so, abort the loop. */
if (thd->is_error())
DBUG_RETURN(TRUE);
/*
Reset str_buffer to its original state, as it may have been altered in
Item::send().
*/
str_buffer.set(buffer, sizeof(buffer), &my_charset_bin);
}
DBUG_RETURN(FALSE);
......
......@@ -4061,3 +4061,114 @@ bool Type_handler_time_common::
}
/***************************************************************************/
bool Type_handler_null::
Item_send(Item *item, Protocol *protocol, st_value *buf) const
{
return protocol->store_null();
}
bool Type_handler::
Item_send_str(Item *item, Protocol *protocol, st_value *buf) const
{
String *res;
if ((res= item->val_str(&buf->m_string)))
{
DBUG_ASSERT(!item->null_value);
return protocol->store(res->ptr(), res->length(), res->charset());
}
DBUG_ASSERT(item->null_value);
return protocol->store_null();
}
bool Type_handler::
Item_send_tiny(Item *item, Protocol *protocol, st_value *buf) const
{
longlong nr= item->val_int();
if (!item->null_value)
return protocol->store_tiny(nr);
return protocol->store_null();
}
bool Type_handler::
Item_send_short(Item *item, Protocol *protocol, st_value *buf) const
{
longlong nr= item->val_int();
if (!item->null_value)
return protocol->store_short(nr);
return protocol->store_null();
}
bool Type_handler::
Item_send_long(Item *item, Protocol *protocol, st_value *buf) const
{
longlong nr= item->val_int();
if (!item->null_value)
return protocol->store_long(nr);
return protocol->store_null();
}
bool Type_handler::
Item_send_longlong(Item *item, Protocol *protocol, st_value *buf) const
{
longlong nr= item->val_int();
if (!item->null_value)
return protocol->store_longlong(nr, item->unsigned_flag);
return protocol->store_null();
}
bool Type_handler::
Item_send_float(Item *item, Protocol *protocol, st_value *buf) const
{
float nr= (float) item->val_real();
if (!item->null_value)
return protocol->store(nr, item->decimals, &buf->m_string);
return protocol->store_null();
}
bool Type_handler::
Item_send_double(Item *item, Protocol *protocol, st_value *buf) const
{
double nr= item->val_real();
if (!item->null_value)
return protocol->store(nr, item->decimals, &buf->m_string);
return protocol->store_null();
}
bool Type_handler::
Item_send_datetime(Item *item, Protocol *protocol, st_value *buf) const
{
item->get_date(&buf->value.m_time, sql_mode_for_dates(current_thd));
if (!item->null_value)
return protocol->store(&buf->value.m_time, item->decimals);
return protocol->store_null();
}
bool Type_handler::
Item_send_date(Item *item, Protocol *protocol, st_value *buf) const
{
item->get_date(&buf->value.m_time, sql_mode_for_dates(current_thd));
if (!item->null_value)
return protocol->store_date(&buf->value.m_time);
return protocol->store_null();
}
bool Type_handler::
Item_send_time(Item *item, Protocol *protocol, st_value *buf) const
{
item->get_time(&buf->value.m_time);
if (!item->null_value)
return protocol->store_time(&buf->value.m_time, item->decimals);
return protocol->store_null();
}
/***************************************************************************/
This diff is collapsed.
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