From a5b454f98a5823cd48fac06cc5d50d54a59ebfc9 Mon Sep 17 00:00:00 2001 From: Alexey Botchkov Date: Tue, 13 Apr 2021 03:28:56 +0400 Subject: [PATCH] MDEV-25259 JSON_TABLE: Illegal mix of collations upon executing query with combination of charsets via view. now the ::print printed too much. Limit it for fields with no CHARSET possible. --- sql/field.cc | 11 +++++++++++ sql/field.h | 7 +------ sql/json_table.cc | 4 ++-- sql/json_table.h | 2 +- sql/sql_yacc.yy | 2 ++ 5 files changed, 17 insertions(+), 9 deletions(-) diff --git a/sql/field.cc b/sql/field.cc index 22b56a4647a..fcae0f5bf11 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -2331,6 +2331,17 @@ bool Field_str::can_be_substituted_to_equal_item(const Context &ctx, } +void Field_str::change_charset(const DTCollation &new_cs) +{ + if (!has_charset()) + return; + + field_length= (field_length * new_cs.collation->mbmaxlen) / + m_collation.collation->mbmaxlen; + m_collation= new_cs; +} + + void Field_num::make_send_field(Send_field *field) { Field::make_send_field(field); diff --git a/sql/field.h b/sql/field.h index b312b10881f..d808a9b0401 100644 --- a/sql/field.h +++ b/sql/field.h @@ -2111,12 +2111,7 @@ public: { return m_collation; } - void change_charset(const DTCollation &new_cs) override - { - field_length= (field_length * new_cs.collation->mbmaxlen) / - m_collation.collation->mbmaxlen; - m_collation= new_cs; - } + void change_charset(const DTCollation &new_cs) override; bool binary() const override { return field_charset() == &my_charset_bin; } uint32 max_display_length() const override { return field_length; } uint32 character_octet_length() const override { return field_length; } diff --git a/sql/json_table.cc b/sql/json_table.cc index 550209c804d..9c14473598d 100644 --- a/sql/json_table.cc +++ b/sql/json_table.cc @@ -926,7 +926,7 @@ bool Create_json_table::add_json_table_fields(THD *thd, TABLE *table, executing a prepared statement for the second time. */ sql_f->length= sql_f->char_length; - if (!(jc->m_explicit_cs= sql_f->charset)) + if (!sql_f->charset) sql_f->charset= &my_charset_utf8mb4_general_ci; if (sql_f->prepare_stage1(thd, thd->mem_root, table->file, @@ -1098,7 +1098,7 @@ int Json_table_column::print(THD *thd, Field **f, String *str) (*f)->sql_type(column_type); if (str->append(column_type) || - (m_explicit_cs && + ((*f)->has_charset() && m_explicit_cs && (str->append(" CHARSET ") || str->append(m_explicit_cs->csname))) || str->append(m_column_type == PATH ? " PATH " : " EXISTS PATH ") || print_path(str, &m_path)) diff --git a/sql/json_table.h b/sql/json_table.h index 04b0e6c07d2..09e4295d80c 100644 --- a/sql/json_table.h +++ b/sql/json_table.h @@ -161,7 +161,7 @@ public: } int set(THD *thd, enum_type ctype, const LEX_CSTRING &path); Json_table_column(Create_field *f, Json_table_nested_path *nest) : - m_field(f), m_nest(nest) + m_field(f), m_nest(nest), m_explicit_cs(NULL) { m_on_error.m_response= RESPONSE_NOT_SPECIFIED; m_on_empty.m_response= RESPONSE_NOT_SPECIFIED; diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index a0b948b0555..4d677c519f2 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -11634,10 +11634,12 @@ json_table_field_type: | field_type_string opt_collate { set_collation($2); + Lex->json_table->m_cur_json_table_column->m_explicit_cs= Lex->charset; } | field_type_lob opt_collate { set_collation($2); + Lex->json_table->m_cur_json_table_column->m_explicit_cs= Lex->charset; } ;