1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-30 16:24:05 +03:00

MDEV-18408 Assertion `0' failed in Item::val_native_result / Timestamp_or_zero_datetime_native_null::Timestamp_or_zero_datetime_native_null upon mysqld_list_fields after crash recovery

The problem happened because Item_ident_for_show did not implement val_native().

Solution:

- Removing class Item_ident_for_show
- Implementing a new method Protocol::send_list_fields() instead,
  which accepts a List<Field> instead of List<Item> as input.
  Now no any Item creation is done during mysqld_list_fields().

Adding helper methods, to reuse the code easier:
- Moved a part of Protocol::send_result_set_metadata(),
  responsible for sending an individual field metadata,
  into a new method Protocol_text::store_field_metadata().
  Reusing it in both send_list_fields() and send_result_set_metadata().
- Adding Protocol_text::store_field_metadata()
- Adding Protocol_text::store_field_metadata_for_list_fields()

Note, this patch also automatically fixed another bug:

MDEV-18685 mysql_list_fields() returns DEFAULT 0 instead of DEFAULT NULL for view columns

The reason for this bug was that Item_ident_for_show::val_xxx() and get_date()
did not check field->is_null() before calling field->val_xxx()/get_date().
Now the default value is correctly sent by Protocol_text::store(Field*).
This commit is contained in:
Alexander Barkov
2019-02-21 21:44:44 +04:00
parent 1ab2e7573a
commit b25ad1bc47
8 changed files with 411 additions and 271 deletions

View File

@ -25,8 +25,10 @@
class i_string;
class Field;
class Send_field;
class THD;
class Item_param;
struct TABLE_LIST;
typedef struct st_mysql_field MYSQL_FIELD;
typedef struct st_mysql_rows MYSQL_ROWS;
@ -75,8 +77,9 @@ public:
virtual ~Protocol() {}
void init(THD* thd_arg);
enum { SEND_NUM_ROWS= 1, SEND_DEFAULTS= 2, SEND_EOF= 4 };
enum { SEND_NUM_ROWS= 1, SEND_EOF= 2 };
virtual bool send_result_set_metadata(List<Item> *list, uint flags);
bool send_list_fields(List<Field> *list, const TABLE_LIST *table_list);
bool send_result_set_row(List<Item> *row_items);
bool store(I_List<i_string> *str_list);
@ -113,6 +116,15 @@ public:
virtual bool store(const char *from, size_t length, CHARSET_INFO *cs)=0;
virtual bool store(const char *from, size_t length,
CHARSET_INFO *fromcs, CHARSET_INFO *tocs)=0;
bool store_str(const char *s, CHARSET_INFO *fromcs, CHARSET_INFO *tocs)
{
DBUG_ASSERT(s);
return store(s, (uint) strlen(s), fromcs, tocs);
}
bool store_str(const LEX_CSTRING &s, CHARSET_INFO *fromcs, CHARSET_INFO *tocs)
{
return store(s.str, (uint) s.length, fromcs, tocs);
}
virtual bool store(float from, uint32 decimals, String *buffer)=0;
virtual bool store(double from, uint32 decimals, String *buffer)=0;
virtual bool store(MYSQL_TIME *time, int decimals)=0;
@ -122,7 +134,8 @@ public:
virtual bool send_out_parameters(List<Item_param> *sp_params)=0;
#ifdef EMBEDDED_LIBRARY
int begin_dataset();
bool begin_dataset();
bool begin_dataset(THD *thd, uint numfields);
virtual void remove_last_row() {}
#else
void remove_last_row() {}
@ -150,7 +163,12 @@ public:
class Protocol_text :public Protocol
{
public:
Protocol_text(THD *thd_arg) :Protocol(thd_arg) {}
Protocol_text(THD *thd_arg, ulong prealloc= 0)
:Protocol(thd_arg)
{
if (prealloc)
packet->alloc(prealloc);
}
virtual void prepare_for_resend();
virtual bool store_null();
virtual bool store_tiny(longlong from);
@ -172,6 +190,13 @@ public:
#ifdef EMBEDDED_LIBRARY
void remove_last_row();
#endif
bool store_field_metadata(const THD *thd, const Send_field &field,
CHARSET_INFO *charset_for_protocol,
uint pos);
bool store_field_metadata(THD *thd, Item *item, uint pos);
bool store_field_metadata_for_list_fields(const THD *thd, Field *field,
const TABLE_LIST *table_list,
uint pos);
virtual enum enum_protocol_type type() { return PROTOCOL_TEXT; };
};