MDEV-19125 Change Send_field::type from enum_field_types to Type_handler*

This commit is contained in:
Alexander Barkov 2019-04-01 20:29:45 +04:00
parent e10f9e6c81
commit 4d12a6458e
11 changed files with 222 additions and 95 deletions

View File

@ -1073,7 +1073,7 @@ bool Protocol_text::store_field_metadata(const THD * thd,
client_field->length= server_field.max_octet_length(charset_for_protocol,
thd_cs);
}
client_field->type= server_field.type;
client_field->type= server_field.type_handler()->type_code_for_protocol();
client_field->flags= (uint16) server_field.flags;
client_field->decimals= server_field.decimals;

View File

@ -1968,7 +1968,7 @@ void Field::make_send_field(Send_field *field)
}
field->col_name= field_name;
field->length=field_length;
field->type=type();
field->set_handler(type_handler());
field->flags=table->maybe_null ? (flags & ~NOT_NULL_FLAG) : flags;
field->decimals= 0;
}
@ -8743,6 +8743,20 @@ uint Field_blob::is_equal(Create_field *new_field)
}
void Field_blob::make_send_field(Send_field *field)
{
/*
Historically all BLOB variant Fields are displayed as MYSQL_TYPE_BLOB
in the result set metadata. Note, Item can work differently and
display the exact BLOB type, such as
MYSQL_TYPE_{TINY_BLOB|BLOB|MEDIUM_BLOB|LONG_BLOB}.
QQ: this should be made consistent eventually.
*/
Field_longstr::make_send_field(field);
field->set_handler(&type_handler_blob);
}
int Field_blob_compressed::store(const char *from, size_t length,
CHARSET_INFO *cs)
{
@ -10915,6 +10929,13 @@ bool Column_definition::set_compressed(const char *method)
}
Send_field::Send_field(THD *thd, Item *item)
{
item->make_send_field(thd, this);
normalize();
}
/**
maximum possible display length for blob.

View File

@ -3861,6 +3861,7 @@ public:
uint32 chars= octets / field_charset->mbminlen;
return Information_schema_character_attributes(octets, chars);
}
void make_send_field(Send_field *);
Copy_func *get_copy_func(const Field *from) const
{
/*
@ -4115,6 +4116,10 @@ public:
{
return Information_schema_character_attributes();
}
void make_send_field(Send_field *to)
{
Field_longstr::make_send_field(to);
}
bool can_optimize_range(const Item_bool_func *cond,
const Item *item,
bool is_eq_func) const;
@ -4994,14 +4999,15 @@ public:
A class for sending info to the client
*/
class Send_field :public Sql_alloc {
public:
class Send_field :public Sql_alloc,
public Type_handler_hybrid_field_type
{
public:
const char *db_name;
const char *table_name,*org_table_name;
LEX_CSTRING col_name, org_col_name;
ulong length;
uint flags, decimals;
enum_field_types type;
Send_field() {}
Send_field(Field *field)
{
@ -5009,11 +5015,12 @@ class Send_field :public Sql_alloc {
DBUG_ASSERT(table_name != 0);
normalize();
}
Send_field(THD *thd, Item *item);
Send_field(Field *field,
const char *db_name_arg,
const char *table_name_arg)
:db_name(db_name_arg),
:Type_handler_hybrid_field_type(field->type_handler()),
db_name(db_name_arg),
table_name(table_name_arg),
org_table_name(table_name_arg),
col_name(field->field_name),
@ -5021,33 +5028,25 @@ class Send_field :public Sql_alloc {
length(field->field_length),
flags(field->table->maybe_null ?
(field->flags & ~NOT_NULL_FLAG) : field->flags),
decimals(field->decimals()),
type(field->type())
decimals(field->decimals())
{
normalize();
}
// This should move to Type_handler eventually
static enum_field_types protocol_type_code(enum_field_types type)
{
/* Keep things compatible for old clients */
if (type == MYSQL_TYPE_VARCHAR)
return MYSQL_TYPE_VAR_STRING;
return type;
}
private:
void normalize()
{
/* limit number of decimals for float and double */
if (type == MYSQL_TYPE_FLOAT || type == MYSQL_TYPE_DOUBLE)
if (type_handler()->field_type() == MYSQL_TYPE_FLOAT ||
type_handler()->field_type() == MYSQL_TYPE_DOUBLE)
set_if_smaller(decimals, FLOATING_POINT_DECIMALS);
/* Keep things compatible for old clients */
type= protocol_type_code(type);
}
public:
// This should move to Type_handler eventually
uint32 max_char_length(CHARSET_INFO *cs) const
{
return type >= MYSQL_TYPE_TINY_BLOB && type <= MYSQL_TYPE_BLOB ?
return type_handler()->field_type() >= MYSQL_TYPE_TINY_BLOB &&
type_handler()->field_type() <= MYSQL_TYPE_BLOB ?
length / cs->mbminlen :
length / cs->mbmaxlen;
}
@ -5077,8 +5076,8 @@ class Send_field :public Sql_alloc {
bool is_sane() const
{
return (decimals <= FLOATING_POINT_DECIMALS ||
(type != MYSQL_TYPE_FLOAT && type != MYSQL_TYPE_DOUBLE)) &&
type != MYSQL_TYPE_VARCHAR;
(type_handler()->field_type() != MYSQL_TYPE_FLOAT &&
type_handler()->field_type() != MYSQL_TYPE_DOUBLE));
}
};

View File

@ -4696,7 +4696,7 @@ void
Item_param::set_out_param_info(Send_field *info)
{
m_out_param_info= info;
set_handler_by_field_type(m_out_param_info->type);
set_handler(m_out_param_info->type_handler());
}
@ -4737,16 +4737,7 @@ void Item_param::make_send_field(THD *thd, Send_field *field)
OUT-parameter info to fill out the names.
*/
field->db_name= m_out_param_info->db_name;
field->table_name= m_out_param_info->table_name;
field->org_table_name= m_out_param_info->org_table_name;
field->col_name= m_out_param_info->col_name;
field->org_col_name= m_out_param_info->org_col_name;
field->length= m_out_param_info->length;
field->flags= m_out_param_info->flags;
field->decimals= m_out_param_info->decimals;
field->type= m_out_param_info->type;
*field= *m_out_param_info;
}
bool Item_param::append_for_log(THD *thd, String *str)
@ -6124,7 +6115,7 @@ Item *Item_field::replace_equal_field(THD *thd, uchar *arg)
void Item::init_make_send_field(Send_field *tmp_field,
enum enum_field_types field_type_arg)
const Type_handler *h)
{
tmp_field->db_name= "";
tmp_field->org_table_name= "";
@ -6134,7 +6125,7 @@ void Item::init_make_send_field(Send_field *tmp_field,
tmp_field->flags= (maybe_null ? 0 : NOT_NULL_FLAG) |
(my_binary_compare(charset_for_protocol()) ?
BINARY_FLAG : 0);
tmp_field->type= field_type_arg;
tmp_field->set_handler(h);
tmp_field->length=max_length;
tmp_field->decimals=decimals;
if (unsigned_flag)
@ -6143,13 +6134,13 @@ void Item::init_make_send_field(Send_field *tmp_field,
void Item::make_send_field(THD *thd, Send_field *tmp_field)
{
init_make_send_field(tmp_field, field_type());
init_make_send_field(tmp_field, type_handler());
}
void Item_empty_string::make_send_field(THD *thd, Send_field *tmp_field)
{
init_make_send_field(tmp_field, string_type_handler()->field_type());
init_make_send_field(tmp_field, string_type_handler());
}

View File

@ -946,7 +946,7 @@ public:
void set_name(THD *thd, const char *str, size_t length, CHARSET_INFO *cs);
void set_name_no_truncate(THD *thd, const char *str, uint length,
CHARSET_INFO *cs);
void init_make_send_field(Send_field *tmp_field,enum enum_field_types type);
void init_make_send_field(Send_field *tmp_field, const Type_handler *h);
virtual void cleanup();
virtual void make_send_field(THD *thd, Send_field *field);

View File

@ -59,10 +59,6 @@ public:
virtual void set(longlong nr)=0;
const Type_handler *type_handler() const=0;
void set(const char *str) { set(str,(uint) strlen(str), default_charset()); }
void make_send_field(THD *thd, Send_field *tmp_field)
{
init_make_send_field(tmp_field,field_type());
}
unsigned int size_of() { return sizeof(*this);}
bool check_vcol_func_processor(void *arg)
{

View File

@ -756,7 +756,7 @@ void Protocol::init(THD *thd_arg)
packet= &thd->packet;
convert= &thd->convert_buffer;
#ifndef DBUG_OFF
field_types= 0;
field_handlers= 0;
#endif
}
@ -827,7 +827,7 @@ bool Protocol_text::store_field_metadata(const THD * thd,
thd_charset);
int4store(pos + 2, field_length);
}
pos[6]= field.type;
pos[6]= field.type_handler()->type_code_for_protocol();
int2store(pos + 7, field.flags);
pos[9]= (char) field.decimals;
pos[10]= 0; // For the future
@ -844,7 +844,7 @@ bool Protocol_text::store_field_metadata(const THD * thd,
pos[0]= 3;
int3store(pos + 1, field.length);
pos[4]= 1;
pos[5]= field.type;
pos[5]= field.type_handler()->type_code_for_protocol();
pos[6]= 3;
int2store(pos + 7, field.flags);
pos[9]= (char) field.decimals;
@ -890,8 +890,8 @@ bool Protocol::send_result_set_metadata(List<Item> *list, uint flags)
}
#ifndef DBUG_OFF
field_types= (enum_field_types*) thd->alloc(sizeof(field_types) *
list->elements);
field_handlers= (const Type_handler**) thd->alloc(sizeof(field_handlers[0]) *
list->elements);
#endif
for (uint pos= 0; (item=it++); pos++)
@ -902,7 +902,7 @@ bool Protocol::send_result_set_metadata(List<Item> *list, uint flags)
if (prot.write())
DBUG_RETURN(1);
#ifndef DBUG_OFF
field_types[pos]= Send_field::protocol_type_code(item->field_type());
field_handlers[pos]= item->type_handler();
#endif
}
@ -939,8 +939,8 @@ bool Protocol::send_list_fields(List<Field> *list, const TABLE_LIST *table_list)
Protocol_text prot(thd, thd->variables.net_buffer_length);
#ifndef DBUG_OFF
field_types= (enum_field_types*) thd->alloc(sizeof(field_types) *
list->elements);
field_handlers= (const Type_handler **) thd->alloc(sizeof(field_handlers[0]) *
list->elements);
#endif
for (uint pos= 0; (fld= it++); pos++)
@ -952,7 +952,12 @@ bool Protocol::send_list_fields(List<Field> *list, const TABLE_LIST *table_list)
if (prot.write())
DBUG_RETURN(1);
#ifndef DBUG_OFF
field_types[pos]= Send_field::protocol_type_code(fld->type());
/*
Historically all BLOB variant Fields are displayed as
MYSQL_TYPE_BLOB in metadata.
See Field_blob::make_send_field() for more comments.
*/
field_handlers[pos]= Send_field(fld).type_handler();
#endif
}
DBUG_RETURN(prepare_for_send(list->elements));
@ -974,9 +979,7 @@ bool Protocol::write()
bool Protocol_text::store_field_metadata(THD *thd, Item *item, uint pos)
{
Send_field field;
item->make_send_field(thd, &field);
field.normalize();
Send_field field(thd, item);
return store_field_metadata(thd, field, item->charset_for_protocol(), pos);
}
@ -1133,12 +1136,7 @@ bool Protocol_text::store(const char *from, size_t length,
CHARSET_INFO *fromcs, CHARSET_INFO *tocs)
{
#ifndef DBUG_OFF
DBUG_ASSERT(field_types == 0 ||
field_types[field_pos] == MYSQL_TYPE_DECIMAL ||
field_types[field_pos] == MYSQL_TYPE_BIT ||
field_types[field_pos] == MYSQL_TYPE_NEWDECIMAL ||
(field_types[field_pos] >= MYSQL_TYPE_ENUM &&
field_types[field_pos] <= MYSQL_TYPE_GEOMETRY));
DBUG_ASSERT(valid_handler(field_pos, PROTOCOL_SEND_STRING));
field_pos++;
#endif
return store_string_aux(from, length, fromcs, tocs);
@ -1152,14 +1150,8 @@ bool Protocol_text::store(const char *from, size_t length,
#ifndef DBUG_OFF
DBUG_PRINT("info", ("Protocol_text::store field %u (%u): %.*s", field_pos,
field_count, (int) length, (length == 0 ? "" : from)));
DBUG_ASSERT(field_types == 0 || field_pos < field_count);
DBUG_ASSERT(field_types == 0 ||
field_types[field_pos] == MYSQL_TYPE_DECIMAL ||
field_types[field_pos] == MYSQL_TYPE_BIT ||
field_types[field_pos] == MYSQL_TYPE_NEWDECIMAL ||
field_types[field_pos] == MYSQL_TYPE_NEWDATE ||
(field_types[field_pos] >= MYSQL_TYPE_ENUM &&
field_types[field_pos] <= MYSQL_TYPE_GEOMETRY));
DBUG_ASSERT(field_handlers == 0 || field_pos < field_count);
DBUG_ASSERT(valid_handler(field_pos, PROTOCOL_SEND_STRING));
field_pos++;
#endif
return store_string_aux(from, length, fromcs, tocs);
@ -1169,7 +1161,7 @@ bool Protocol_text::store(const char *from, size_t length,
bool Protocol_text::store_tiny(longlong from)
{
#ifndef DBUG_OFF
DBUG_ASSERT(field_types == 0 || field_types[field_pos] == MYSQL_TYPE_TINY);
DBUG_ASSERT(valid_handler(field_pos, PROTOCOL_SEND_TINY));
field_pos++;
#endif
char buff[22];
@ -1181,9 +1173,7 @@ bool Protocol_text::store_tiny(longlong from)
bool Protocol_text::store_short(longlong from)
{
#ifndef DBUG_OFF
DBUG_ASSERT(field_types == 0 ||
field_types[field_pos] == MYSQL_TYPE_YEAR ||
field_types[field_pos] == MYSQL_TYPE_SHORT);
DBUG_ASSERT(valid_handler(field_pos, PROTOCOL_SEND_SHORT));
field_pos++;
#endif
char buff[22];
@ -1196,9 +1186,7 @@ bool Protocol_text::store_short(longlong from)
bool Protocol_text::store_long(longlong from)
{
#ifndef DBUG_OFF
DBUG_ASSERT(field_types == 0 ||
field_types[field_pos] == MYSQL_TYPE_INT24 ||
field_types[field_pos] == MYSQL_TYPE_LONG);
DBUG_ASSERT(valid_handler(field_pos, PROTOCOL_SEND_LONG));
field_pos++;
#endif
char buff[22];
@ -1211,8 +1199,7 @@ bool Protocol_text::store_long(longlong from)
bool Protocol_text::store_longlong(longlong from, bool unsigned_flag)
{
#ifndef DBUG_OFF
DBUG_ASSERT(field_types == 0 ||
field_types[field_pos] == MYSQL_TYPE_LONGLONG);
DBUG_ASSERT(valid_handler(field_pos, PROTOCOL_SEND_LONGLONG));
field_pos++;
#endif
char buff[22];
@ -1226,8 +1213,7 @@ bool Protocol_text::store_longlong(longlong from, bool unsigned_flag)
bool Protocol_text::store_decimal(const my_decimal *d)
{
#ifndef DBUG_OFF
DBUG_ASSERT(field_types == 0 ||
field_types[field_pos] == MYSQL_TYPE_NEWDECIMAL);
DBUG_ASSERT(0); // This method is not used yet
field_pos++;
#endif
StringBuffer<DECIMAL_MAX_STR_LENGTH> str;
@ -1239,8 +1225,7 @@ bool Protocol_text::store_decimal(const my_decimal *d)
bool Protocol_text::store(float from, uint32 decimals, String *buffer)
{
#ifndef DBUG_OFF
DBUG_ASSERT(field_types == 0 ||
field_types[field_pos] == MYSQL_TYPE_FLOAT);
DBUG_ASSERT(valid_handler(field_pos, PROTOCOL_SEND_FLOAT));
field_pos++;
#endif
buffer->set_real((double) from, decimals, thd->charset());
@ -1251,8 +1236,7 @@ bool Protocol_text::store(float from, uint32 decimals, String *buffer)
bool Protocol_text::store(double from, uint32 decimals, String *buffer)
{
#ifndef DBUG_OFF
DBUG_ASSERT(field_types == 0 ||
field_types[field_pos] == MYSQL_TYPE_DOUBLE);
DBUG_ASSERT(valid_handler(field_pos, PROTOCOL_SEND_DOUBLE));
field_pos++;
#endif
buffer->set_real(from, decimals, thd->charset());
@ -1290,9 +1274,7 @@ bool Protocol_text::store(Field *field)
bool Protocol_text::store(MYSQL_TIME *tm, int decimals)
{
#ifndef DBUG_OFF
DBUG_ASSERT(field_types == 0 ||
field_types[field_pos] == MYSQL_TYPE_DATETIME ||
field_types[field_pos] == MYSQL_TYPE_TIMESTAMP);
DBUG_ASSERT(valid_handler(field_pos, PROTOCOL_SEND_DATETIME));
field_pos++;
#endif
char buff[MAX_DATE_STRING_REP_LENGTH];
@ -1304,8 +1286,7 @@ bool Protocol_text::store(MYSQL_TIME *tm, int decimals)
bool Protocol_text::store_date(MYSQL_TIME *tm)
{
#ifndef DBUG_OFF
DBUG_ASSERT(field_types == 0 ||
field_types[field_pos] == MYSQL_TYPE_DATE);
DBUG_ASSERT(valid_handler(field_pos, PROTOCOL_SEND_DATE));
field_pos++;
#endif
char buff[MAX_DATE_STRING_REP_LENGTH];
@ -1317,8 +1298,7 @@ bool Protocol_text::store_date(MYSQL_TIME *tm)
bool Protocol_text::store_time(MYSQL_TIME *tm, int decimals)
{
#ifndef DBUG_OFF
DBUG_ASSERT(field_types == 0 ||
field_types[field_pos] == MYSQL_TYPE_TIME);
DBUG_ASSERT(valid_handler(field_pos, PROTOCOL_SEND_TIME));
field_pos++;
#endif
char buff[MAX_DATE_STRING_REP_LENGTH];
@ -1475,8 +1455,7 @@ bool Protocol_binary::store_longlong(longlong from, bool unsigned_flag)
bool Protocol_binary::store_decimal(const my_decimal *d)
{
#ifndef DBUG_OFF
DBUG_ASSERT(field_types == 0 ||
field_types[field_pos] == MYSQL_TYPE_NEWDECIMAL);
DBUG_ASSERT(0); // This method is not used yet
field_pos++;
#endif
StringBuffer<DECIMAL_MAX_STR_LENGTH> str;

View File

@ -22,6 +22,7 @@
#include "sql_error.h"
#include "my_decimal.h" /* my_decimal */
#include "sql_type.h"
class i_string;
class Field;
@ -40,7 +41,12 @@ protected:
String *convert;
uint field_pos;
#ifndef DBUG_OFF
enum enum_field_types *field_types;
const Type_handler **field_handlers;
bool valid_handler(uint pos, protocol_send_type_t type) const
{
return field_handlers == 0 ||
field_handlers[field_pos]->protocol_send_type() == type;
}
#endif
uint field_count;
#ifndef EMBEDDED_LIBRARY

View File

@ -5289,6 +5289,7 @@ bool Protocol_local::store_longlong(longlong value, bool unsigned_flag)
bool Protocol_local::store_decimal(const my_decimal *value)
{
DBUG_ASSERT(0); // This method is not used yet
StringBuffer<DECIMAL_MAX_STR_LENGTH> str;
return value->to_string(&str) ? store_column(str.ptr(), str.length()) : true;
}

View File

@ -82,6 +82,21 @@ class Virtual_column_info;
#define my_charset_numeric my_charset_latin1
enum protocol_send_type_t
{
PROTOCOL_SEND_STRING,
PROTOCOL_SEND_FLOAT,
PROTOCOL_SEND_DOUBLE,
PROTOCOL_SEND_TINY,
PROTOCOL_SEND_SHORT,
PROTOCOL_SEND_LONG,
PROTOCOL_SEND_LONGLONG,
PROTOCOL_SEND_DATETIME,
PROTOCOL_SEND_DATE,
PROTOCOL_SEND_TIME
};
enum scalar_comparison_op
{
SCALAR_CMP_EQ,
@ -3185,6 +3200,11 @@ public:
DBUG_ASSERT(is_traditional_type());
return field_type();
}
virtual enum_field_types type_code_for_protocol() const
{
return field_type();
}
virtual protocol_send_type_t protocol_send_type() const= 0;
virtual Item_result result_type() const= 0;
virtual Item_result cmp_type() const= 0;
virtual enum_mysql_timestamp_type mysql_timestamp_type() const
@ -3706,6 +3726,11 @@ public:
DBUG_ASSERT(0);
return MYSQL_TYPE_NULL;
};
protocol_send_type_t protocol_send_type() const
{
DBUG_ASSERT(0);
return PROTOCOL_SEND_STRING;
}
Item_result result_type() const
{
return ROW_RESULT;
@ -4143,6 +4168,10 @@ public:
class Type_handler_decimal_result: public Type_handler_numeric
{
public:
protocol_send_type_t protocol_send_type() const
{
return PROTOCOL_SEND_STRING;
}
Item_result result_type() const { return DECIMAL_RESULT; }
Item_result cmp_type() const { return DECIMAL_RESULT; }
virtual ~Type_handler_decimal_result() {};
@ -4533,6 +4562,10 @@ class Type_handler_string_result: public Type_handler
{
uint Item_temporal_precision(THD *thd, Item *item, bool is_time) const;
public:
protocol_send_type_t protocol_send_type() const
{
return PROTOCOL_SEND_STRING;
}
Item_result result_type() const { return STRING_RESULT; }
Item_result cmp_type() const { return STRING_RESULT; }
CHARSET_INFO *charset_for_protocol(const Item *item) const;
@ -4692,6 +4725,10 @@ public:
virtual ~Type_handler_tiny() {}
const Name name() const { return m_name_tiny; }
enum_field_types field_type() const { return MYSQL_TYPE_TINY; }
protocol_send_type_t protocol_send_type() const
{
return PROTOCOL_SEND_TINY;
}
const Type_limits_int *type_limits_int_by_unsigned_flag(bool unsigned_fl) const
{
return unsigned_fl ? &m_limits_uint8 : &m_limits_sint8;
@ -4733,6 +4770,10 @@ public:
virtual ~Type_handler_short() {}
const Name name() const { return m_name_short; }
enum_field_types field_type() const { return MYSQL_TYPE_SHORT; }
protocol_send_type_t protocol_send_type() const
{
return PROTOCOL_SEND_SHORT;
}
bool Item_send(Item *item, Protocol *protocol, st_value *buf) const
{
return Item_send_short(item, protocol, buf);
@ -4774,6 +4815,10 @@ public:
virtual ~Type_handler_long() {}
const Name name() const { return m_name_int; }
enum_field_types field_type() const { return MYSQL_TYPE_LONG; }
protocol_send_type_t protocol_send_type() const
{
return PROTOCOL_SEND_LONG;
}
const Type_limits_int *type_limits_int_by_unsigned_flag(bool unsigned_fl) const
{
return unsigned_fl ? &m_limits_uint32 : &m_limits_sint32;
@ -4826,6 +4871,10 @@ public:
virtual ~Type_handler_longlong() {}
const Name name() const { return m_name_longlong; }
enum_field_types field_type() const { return MYSQL_TYPE_LONGLONG; }
protocol_send_type_t protocol_send_type() const
{
return PROTOCOL_SEND_LONGLONG;
}
const Type_limits_int *type_limits_int_by_unsigned_flag(bool unsigned_fl) const
{
return unsigned_fl ? &m_limits_uint64 : &m_limits_sint64;
@ -4882,6 +4931,10 @@ public:
virtual ~Type_handler_int24() {}
const Name name() const { return m_name_mediumint; }
enum_field_types field_type() const { return MYSQL_TYPE_INT24; }
protocol_send_type_t protocol_send_type() const
{
return PROTOCOL_SEND_LONG;
}
bool Item_send(Item *item, Protocol *protocol, st_value *buf) const
{
return Item_send_long(item, protocol, buf);
@ -4919,6 +4972,10 @@ public:
virtual ~Type_handler_year() {}
const Name name() const { return m_name_year; }
enum_field_types field_type() const { return MYSQL_TYPE_YEAR; }
protocol_send_type_t protocol_send_type() const
{
return PROTOCOL_SEND_SHORT;
}
uint32 max_display_length(const Item *item) const;
uint32 calc_pack_length(uint32 length) const { return 1; }
bool Item_send(Item *item, Protocol *protocol, st_value *buf) const
@ -4964,6 +5021,10 @@ public:
virtual ~Type_handler_bit() {}
const Name name() const { return m_name_bit; }
enum_field_types field_type() const { return MYSQL_TYPE_BIT; }
protocol_send_type_t protocol_send_type() const
{
return PROTOCOL_SEND_STRING;
}
uint32 max_display_length(const Item *item) const;
uint32 calc_pack_length(uint32 length) const { return length / 8; }
bool Item_send(Item *item, Protocol *protocol, st_value *buf) const
@ -5012,6 +5073,10 @@ public:
virtual ~Type_handler_float() {}
const Name name() const { return m_name_float; }
enum_field_types field_type() const { return MYSQL_TYPE_FLOAT; }
protocol_send_type_t protocol_send_type() const
{
return PROTOCOL_SEND_FLOAT;
}
bool type_can_have_auto_increment_attribute() const { return true; }
uint32 max_display_length(const Item *item) const { return 25; }
uint32 calc_pack_length(uint32 length) const { return sizeof(float); }
@ -5050,6 +5115,10 @@ public:
virtual ~Type_handler_double() {}
const Name name() const { return m_name_double; }
enum_field_types field_type() const { return MYSQL_TYPE_DOUBLE; }
protocol_send_type_t protocol_send_type() const
{
return PROTOCOL_SEND_DOUBLE;
}
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); }
@ -5089,6 +5158,10 @@ public:
virtual ~Type_handler_time_common() { }
const Name name() const { return m_name_time; }
enum_field_types field_type() const { return MYSQL_TYPE_TIME; }
protocol_send_type_t protocol_send_type() const
{
return PROTOCOL_SEND_TIME;
}
enum_mysql_timestamp_type mysql_timestamp_type() const
{
return MYSQL_TIMESTAMP_TIME;
@ -5245,6 +5318,10 @@ public:
const Name name() const { return m_name_date; }
const Type_handler *type_handler_for_comparison() const;
enum_field_types field_type() const { return MYSQL_TYPE_DATE; }
protocol_send_type_t protocol_send_type() const
{
return PROTOCOL_SEND_DATE;
}
enum_mysql_timestamp_type mysql_timestamp_type() const
{
return MYSQL_TIMESTAMP_DATE;
@ -5334,6 +5411,10 @@ public:
const Name name() const { return m_name_datetime; }
const Type_handler *type_handler_for_comparison() const;
enum_field_types field_type() const { return MYSQL_TYPE_DATETIME; }
protocol_send_type_t protocol_send_type() const
{
return PROTOCOL_SEND_DATETIME;
}
enum_mysql_timestamp_type mysql_timestamp_type() const
{
return MYSQL_TIMESTAMP_DATETIME;
@ -5443,6 +5524,10 @@ public:
const Type_handler *type_handler_for_comparison() const;
const Type_handler *type_handler_for_native_format() const;
enum_field_types field_type() const { return MYSQL_TYPE_TIMESTAMP; }
protocol_send_type_t protocol_send_type() const
{
return PROTOCOL_SEND_DATETIME;
}
enum_mysql_timestamp_type mysql_timestamp_type() const
{
return MYSQL_TIMESTAMP_DATETIME;
@ -5756,6 +5841,10 @@ public:
virtual ~Type_handler_varchar() {}
const Name name() const { return m_name_varchar; }
enum_field_types field_type() const { return MYSQL_TYPE_VARCHAR; }
enum_field_types type_code_for_protocol() const
{
return MYSQL_TYPE_VAR_STRING; // Keep things compatible for old clients
}
uint32 calc_pack_length(uint32 length) const
{
return (length + (length < 256 ? 1: 2));

View File

@ -8397,6 +8397,50 @@ static void test_list_fields()
}
static void test_list_fields_blob()
{
MYSQL_RES *result;
int rc;
myheader("test_list_fields_blob");
rc= mysql_query(mysql, "drop table if exists t1");
myquery(rc);
rc= mysql_query(mysql, "create table t1(c1 tinyblob, c2 blob, c3 mediumblob, c4 longblob)");
myquery(rc);
result= mysql_list_fields(mysql, "t1", NULL);
mytest(result);
rc= my_process_result_set(result);
DIE_UNLESS(rc == 0);
/*
All BLOB variant Fields are displayed as MYSQL_TYPE_BLOB in
the result set metadata. Note, some Items display the exact
BLOB type. This inconsistency should be fixed eventually.
*/
verify_prepare_field(result, 0, "c1", "c1", MYSQL_TYPE_BLOB,
"t1", "t1",
current_db, 255, NULL);
verify_prepare_field(result, 1, "c2", "c2", MYSQL_TYPE_BLOB,
"t1", "t1",
current_db, 65535, NULL);
verify_prepare_field(result, 2, "c3", "c3", MYSQL_TYPE_BLOB,
"t1", "t1",
current_db, 16777215, NULL);
verify_prepare_field(result, 3, "c4", "c4", MYSQL_TYPE_BLOB,
"t1", "t1",
current_db, 4294967295ULL, NULL);
mysql_free_result(result);
myquery(mysql_query(mysql, "drop table t1"));
}
static void test_list_fields_default()
{
int rc, i;
@ -20843,6 +20887,7 @@ static struct my_tests_st my_tests[]= {
{ "test_fetch_column", test_fetch_column },
{ "test_mem_overun", test_mem_overun },
{ "test_list_fields", test_list_fields },
{ "test_list_fields_blob", test_list_fields_blob },
{ "test_list_fields_default", test_list_fields_default },
{ "test_free_result", test_free_result },
{ "test_free_store_result", test_free_store_result },