From 8bbf6697cf262a76a6c544e45e3658cdfa5402ec Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Thu, 2 Nov 2023 14:57:37 +0100 Subject: [PATCH 1/3] MDEV-24784 JSON_ARRAYAGG charset issue set the proper charset for a temporary result --- mysql-test/main/func_json.result | 11 +++++++++++ mysql-test/main/func_json.test | 11 ++++++++++- sql/item_jsonfunc.cc | 7 +++++++ sql/item_jsonfunc.h | 1 + 4 files changed, 29 insertions(+), 1 deletion(-) diff --git a/mysql-test/main/func_json.result b/mysql-test/main/func_json.result index 29f8c383abb..540c8244611 100644 --- a/mysql-test/main/func_json.result +++ b/mysql-test/main/func_json.result @@ -1646,5 +1646,16 @@ SELECT JSON_OBJECTAGG('\\', 1); JSON_OBJECTAGG('\\', 1) {"\\":1} # +# MDEV-24784 JSON_ARRAYAGG charset issue +# +set names utf8; +select json_arrayagg('ä'), json_objectagg(1, 'ä'); +json_arrayagg('ä') json_objectagg(1, 'ä') +["ä"] {"1":"ä"} +set names latin1; +select json_arrayagg('ä'), json_objectagg(1, 'ä'); +json_arrayagg('ä') json_objectagg(1, 'ä') +["ä"] {"1":"ä"} +# # End of 10.5 tests # diff --git a/mysql-test/main/func_json.test b/mysql-test/main/func_json.test index c21fa8d05db..696ffa41a5a 100644 --- a/mysql-test/main/func_json.test +++ b/mysql-test/main/func_json.test @@ -1108,7 +1108,16 @@ SELECT JSON_OBJECTAGG('"', 1); SELECT JSON_OBJECTAGG('\"', 1); SELECT JSON_OBJECTAGG('\\', 1); +--echo # +--echo # MDEV-24784 JSON_ARRAYAGG charset issue +--echo # +--disable_service_connection +set names utf8; +select json_arrayagg('ä'), json_objectagg(1, 'ä'); +set names latin1; +select json_arrayagg('ä'), json_objectagg(1, 'ä'); +--enable_service_connection + --echo # --echo # End of 10.5 tests --echo # - diff --git a/sql/item_jsonfunc.cc b/sql/item_jsonfunc.cc index b85adeff05d..1105406c658 100644 --- a/sql/item_jsonfunc.cc +++ b/sql/item_jsonfunc.cc @@ -3907,6 +3907,13 @@ int Arg_comparator::compare_e_json_str_basic(Item *j, Item *s) return MY_TEST(sortcmp(res1, res2, compare_collation()) == 0); } +bool Item_func_json_arrayagg::fix_fields(THD *thd, Item **ref) +{ + bool res= Item_func_group_concat::fix_fields(thd, ref); + m_tmp_json.set_charset(collation.collation); + return res; +} + String *Item_func_json_arrayagg::get_str_from_item(Item *i, String *tmp) { diff --git a/sql/item_jsonfunc.h b/sql/item_jsonfunc.h index 4aaf66ec695..77936fcc4f4 100644 --- a/sql/item_jsonfunc.h +++ b/sql/item_jsonfunc.h @@ -570,6 +570,7 @@ public: } const char *func_name() const override { return "json_arrayagg("; } + bool fix_fields(THD *thd, Item **ref) override; enum Sumfunctype sum_func() const override { return JSON_ARRAYAGG_FUNC; } String* val_str(String *str) override; From 8aa2076426471a7496d448ce78921e8497b7b2ef Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Mon, 13 Nov 2023 18:41:22 +0100 Subject: [PATCH 2/3] Revert "MDEV-22243 type_test.type_test_double fails with 'NUMERIC_SCALE NULL'" This reverts commit 9d19b6526917c94ca03ef1b4c57152882b192cfe. --- .../type_test/type_test_double.result | 2 +- sql/field.cc | 54 ------------------- sql/field.h | 43 +++++++++++++-- 3 files changed, 39 insertions(+), 60 deletions(-) diff --git a/plugin/type_test/mysql-test/type_test/type_test_double.result b/plugin/type_test/mysql-test/type_test/type_test_double.result index edcfdc0eff8..6241ff95b8a 100644 --- a/plugin/type_test/mysql-test/type_test/type_test_double.result +++ b/plugin/type_test/mysql-test/type_test/type_test_double.result @@ -290,7 +290,7 @@ DATA_TYPE test_double CHARACTER_MAXIMUM_LENGTH NULL CHARACTER_OCTET_LENGTH NULL NUMERIC_PRECISION 22 -NUMERIC_SCALE NULL +NUMERIC_SCALE 31 DATETIME_PRECISION NULL CHARACTER_SET_NAME NULL COLLATION_NAME NULL diff --git a/sql/field.cc b/sql/field.cc index 0337b1e634e..53dc5f2e15a 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -4645,28 +4645,6 @@ bool Field_longlong::is_max() single precision float ****************************************************************************/ -Field_float::Field_float(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, - uchar null_bit_arg, - enum utype unireg_check_arg, - const LEX_CSTRING *field_name_arg, - uint8 dec_arg,bool zero_arg,bool unsigned_arg) - :Field_real(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, - unireg_check_arg, field_name_arg, - (dec_arg >= FLOATING_POINT_DECIMALS ? NOT_FIXED_DEC : dec_arg), - zero_arg, unsigned_arg) -{ -} - -Field_float::Field_float(uint32 len_arg, bool maybe_null_arg, - const LEX_CSTRING *field_name_arg, uint8 dec_arg) - :Field_real((uchar*) 0, len_arg, maybe_null_arg ? (uchar*) "": 0, (uint) 0, - NONE, field_name_arg, - (dec_arg >= FLOATING_POINT_DECIMALS ? NOT_FIXED_DEC : dec_arg), - 0, 0) -{ -} - - int Field_float::store(const char *from,size_t len,CHARSET_INFO *cs) { int error; @@ -4815,38 +4793,6 @@ Binlog_type_info Field_float::binlog_type_info() const double precision floating point numbers ****************************************************************************/ -Field_double::Field_double(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, - uchar null_bit_arg, - enum utype unireg_check_arg, - const LEX_CSTRING *field_name_arg, - uint8 dec_arg,bool zero_arg,bool unsigned_arg) - :Field_real(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, - unireg_check_arg, field_name_arg, - (dec_arg >= FLOATING_POINT_DECIMALS ? NOT_FIXED_DEC : dec_arg), - zero_arg, unsigned_arg) -{ -} - -Field_double::Field_double(uint32 len_arg, bool maybe_null_arg, - const LEX_CSTRING *field_name_arg, uint8 dec_arg) - :Field_real((uchar*) 0, len_arg, maybe_null_arg ? (uchar*) "" : 0, (uint) 0, - NONE, field_name_arg, - (dec_arg >= FLOATING_POINT_DECIMALS ? NOT_FIXED_DEC : dec_arg), - 0, 0) -{ -} - -Field_double::Field_double(uint32 len_arg, bool maybe_null_arg, - const LEX_CSTRING *field_name_arg, - uint8 dec_arg, bool not_fixed_arg) - :Field_real((uchar*) 0, len_arg, maybe_null_arg ? (uchar*) "" : 0, (uint) 0, - NONE, field_name_arg, - (dec_arg >= FLOATING_POINT_DECIMALS ? NOT_FIXED_DEC : dec_arg), - 0, 0) -{ - not_fixed= not_fixed_arg; -} - int Field_double::store(const char *from,size_t len,CHARSET_INFO *cs) { int error; diff --git a/sql/field.h b/sql/field.h index 057bd8453c5..804394c58a6 100644 --- a/sql/field.h +++ b/sql/field.h @@ -2842,9 +2842,22 @@ public: Field_float(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg, - uint8 dec_arg,bool zero_arg,bool unsigned_arg); + uint8 dec_arg,bool zero_arg,bool unsigned_arg) + :Field_real(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, + unireg_check_arg, field_name_arg, + dec_arg, zero_arg, unsigned_arg) + { + if (dec_arg >= FLOATING_POINT_DECIMALS) + dec_arg= NOT_FIXED_DEC; + } Field_float(uint32 len_arg, bool maybe_null_arg, - const LEX_CSTRING *field_name_arg, uint8 dec_arg); + const LEX_CSTRING *field_name_arg, uint8 dec_arg) + :Field_real((uchar*) 0, len_arg, maybe_null_arg ? (uchar*) "": 0, (uint) 0, + NONE, field_name_arg, dec_arg, 0, 0) + { + if (dec_arg >= FLOATING_POINT_DECIMALS) + dec_arg= NOT_FIXED_DEC; + } const Type_handler *type_handler() const override { return &type_handler_float; } enum ha_base_keytype key_type() const override { return HA_KEYTYPE_FLOAT; } @@ -2877,12 +2890,32 @@ public: Field_double(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg, - uint8 dec_arg,bool zero_arg,bool unsigned_arg); + uint8 dec_arg,bool zero_arg,bool unsigned_arg) + :Field_real(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, + unireg_check_arg, field_name_arg, + dec_arg, zero_arg, unsigned_arg) + { + if (dec_arg >= FLOATING_POINT_DECIMALS) + dec_arg= NOT_FIXED_DEC; + } Field_double(uint32 len_arg, bool maybe_null_arg, - const LEX_CSTRING *field_name_arg, uint8 dec_arg); + const LEX_CSTRING *field_name_arg, uint8 dec_arg) + :Field_real((uchar*) 0, len_arg, maybe_null_arg ? (uchar*) "" : 0, (uint) 0, + NONE, field_name_arg, dec_arg, 0, 0) + { + if (dec_arg >= FLOATING_POINT_DECIMALS) + dec_arg= NOT_FIXED_DEC; + } Field_double(uint32 len_arg, bool maybe_null_arg, const LEX_CSTRING *field_name_arg, - uint8 dec_arg, bool not_fixed_arg); + uint8 dec_arg, bool not_fixed_arg) + :Field_real((uchar*) 0, len_arg, maybe_null_arg ? (uchar*) "" : 0, (uint) 0, + NONE, field_name_arg, dec_arg, 0, 0) + { + not_fixed= not_fixed_arg; + if (dec_arg >= FLOATING_POINT_DECIMALS) + dec_arg= NOT_FIXED_DEC; + } void init_for_tmp_table(Field *org_field, TABLE *new_table) override { Field::init_for_tmp_table(org_field, new_table); From 9b7a1c0e922a52759ed761152dfbf57d3cd55316 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Mon, 13 Nov 2023 23:38:47 +0100 Subject: [PATCH 3/3] MDEV-22243 type_test.type_test_double fails with 'NUMERIC_SCALE NULL' 1. fix useless correction of dec_arg *after it was used* 2. use DECIMAL_NOT_SPECIFIED instead of NOT_FIXED_DEC, because the latter is defined conditionally and has a wrong value in plugins --- .../type_test/type_test_double.result | 2 +- sql/field.h | 38 +++++++------------ 2 files changed, 14 insertions(+), 26 deletions(-) diff --git a/plugin/type_test/mysql-test/type_test/type_test_double.result b/plugin/type_test/mysql-test/type_test/type_test_double.result index 6241ff95b8a..edcfdc0eff8 100644 --- a/plugin/type_test/mysql-test/type_test/type_test_double.result +++ b/plugin/type_test/mysql-test/type_test/type_test_double.result @@ -290,7 +290,7 @@ DATA_TYPE test_double CHARACTER_MAXIMUM_LENGTH NULL CHARACTER_OCTET_LENGTH NULL NUMERIC_PRECISION 22 -NUMERIC_SCALE 31 +NUMERIC_SCALE NULL DATETIME_PRECISION NULL CHARACTER_SET_NAME NULL COLLATION_NAME NULL diff --git a/sql/field.h b/sql/field.h index 804394c58a6..5a5184ed7d4 100644 --- a/sql/field.h +++ b/sql/field.h @@ -2105,7 +2105,7 @@ public: uchar null_bit_arg, utype unireg_check_arg, const LEX_CSTRING *field_name_arg, const DTCollation &collation); - uint decimals() const override { return is_created_from_null_item ? 0 : NOT_FIXED_DEC; } + uint decimals() const override { return is_created_from_null_item ? 0 : DECIMAL_NOT_SPECIFIED; } int save_in_field(Field *to) override { return save_in_field_str(to); } bool memcpy_field_possible(const Field *from) const override { @@ -2267,7 +2267,7 @@ public: Information_schema_numeric_attributes information_schema_numeric_attributes() const override { - return dec == NOT_FIXED_DEC ? + return dec == DECIMAL_NOT_SPECIFIED ? Information_schema_numeric_attributes(field_length) : Information_schema_numeric_attributes(field_length, dec); } @@ -2836,6 +2836,8 @@ public: integers. But in all other cases we treat it as TIME_RESULT! */ }; +static inline uint8 fix_dec_arg(uint8 dec_arg) +{ return dec_arg >= FLOATING_POINT_DECIMALS ? DECIMAL_NOT_SPECIFIED : dec_arg; } class Field_float final :public Field_real { public: @@ -2845,19 +2847,13 @@ public: uint8 dec_arg,bool zero_arg,bool unsigned_arg) :Field_real(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg, - dec_arg, zero_arg, unsigned_arg) - { - if (dec_arg >= FLOATING_POINT_DECIMALS) - dec_arg= NOT_FIXED_DEC; - } + fix_dec_arg(dec_arg), zero_arg, unsigned_arg) + { } Field_float(uint32 len_arg, bool maybe_null_arg, const LEX_CSTRING *field_name_arg, uint8 dec_arg) :Field_real((uchar*) 0, len_arg, maybe_null_arg ? (uchar*) "": 0, (uint) 0, - NONE, field_name_arg, dec_arg, 0, 0) - { - if (dec_arg >= FLOATING_POINT_DECIMALS) - dec_arg= NOT_FIXED_DEC; - } + NONE, field_name_arg, fix_dec_arg(dec_arg), 0, 0) + { } const Type_handler *type_handler() const override { return &type_handler_float; } enum ha_base_keytype key_type() const override { return HA_KEYTYPE_FLOAT; } @@ -2893,28 +2889,20 @@ public: uint8 dec_arg,bool zero_arg,bool unsigned_arg) :Field_real(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg, - dec_arg, zero_arg, unsigned_arg) - { - if (dec_arg >= FLOATING_POINT_DECIMALS) - dec_arg= NOT_FIXED_DEC; - } + fix_dec_arg(dec_arg), zero_arg, unsigned_arg) + { } Field_double(uint32 len_arg, bool maybe_null_arg, const LEX_CSTRING *field_name_arg, uint8 dec_arg) :Field_real((uchar*) 0, len_arg, maybe_null_arg ? (uchar*) "" : 0, (uint) 0, - NONE, field_name_arg, dec_arg, 0, 0) - { - if (dec_arg >= FLOATING_POINT_DECIMALS) - dec_arg= NOT_FIXED_DEC; - } + NONE, field_name_arg, fix_dec_arg(dec_arg), 0, 0) + { } Field_double(uint32 len_arg, bool maybe_null_arg, const LEX_CSTRING *field_name_arg, uint8 dec_arg, bool not_fixed_arg) :Field_real((uchar*) 0, len_arg, maybe_null_arg ? (uchar*) "" : 0, (uint) 0, - NONE, field_name_arg, dec_arg, 0, 0) + NONE, field_name_arg, fix_dec_arg(dec_arg), 0, 0) { not_fixed= not_fixed_arg; - if (dec_arg >= FLOATING_POINT_DECIMALS) - dec_arg= NOT_FIXED_DEC; } void init_for_tmp_table(Field *org_field, TABLE *new_table) override {