diff --git a/mysql-test/suite/json/r/json_table.result b/mysql-test/suite/json/r/json_table.result index 6f017c34133..75a7e884633 100644 --- a/mysql-test/suite/json/r/json_table.result +++ b/mysql-test/suite/json/r/json_table.result @@ -954,5 +954,32 @@ Warnings: Warning 1264 Out of range value for column 'converted' at row 2 Warning 1366 Incorrect integer value: 'foo' for column ``.`(temporary)`.`converted` at row 3 # +# MDEV-27696 Json table columns accept redundant COLLATE syntax +# +SELECT * FROM json_table('[{"name":"str"}]', '$[*]' + COLUMNS ( +name BLOB COLLATE `binary` PATH '$.name' + ) +) AS jt; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'COLLATE `binary` PATH '$.name' + ) +) AS jt' at line 3 +SELECT * FROM json_table('[{"name":"str"}]', '$[*]' + COLUMNS ( +name VARCHAR(10) COLLATE latin1_bin COLLATE latin1_swedish_ci PATH '$.name' + ) +) AS jt; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'COLLATE latin1_swedish_ci PATH '$.name' + ) +) AS jt' at line 3 +SELECT * FROM json_table('[{"name":"str"}]', '$[*]' + COLUMNS ( +name VARCHAR(10) BINARY COLLATE utf8_czech_ci path '$.name' + ) +) AS jt; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'COLLATE utf8_czech_ci path '$.name' + ) +) AS jt' at line 3 +# # End of 10.6 tests # diff --git a/mysql-test/suite/json/t/json_table.test b/mysql-test/suite/json/t/json_table.test index f250fcbf58a..2867c5f89d0 100644 --- a/mysql-test/suite/json/t/json_table.test +++ b/mysql-test/suite/json/t/json_table.test @@ -814,6 +814,34 @@ select * from json_table('{"a":"foo", "b":1, "c":1000}', '$.*' columns(converted select * from json_table('{"a":"foo", "b":1, "c":1000}', '$.*' columns(converted tinyint path '$', original text path '$')) as jt order by original; +--echo # +--echo # MDEV-27696 Json table columns accept redundant COLLATE syntax +--echo # + +--error ER_PARSE_ERROR +SELECT * FROM json_table('[{"name":"str"}]', '$[*]' + COLUMNS ( + name BLOB COLLATE `binary` PATH '$.name' + ) +) AS jt; + + +--error ER_PARSE_ERROR +SELECT * FROM json_table('[{"name":"str"}]', '$[*]' + COLUMNS ( + name VARCHAR(10) COLLATE latin1_bin COLLATE latin1_swedish_ci PATH '$.name' + ) +) AS jt; + + +--error ER_PARSE_ERROR +SELECT * FROM json_table('[{"name":"str"}]', '$[*]' + COLUMNS ( + name VARCHAR(10) BINARY COLLATE utf8_czech_ci path '$.name' + ) +) AS jt; + + --echo # --echo # End of 10.6 tests --echo # diff --git a/sql/json_table.cc b/sql/json_table.cc index aebc52b0832..1eda21112e2 100644 --- a/sql/json_table.cc +++ b/sql/json_table.cc @@ -851,9 +851,11 @@ TABLE *create_table_for_function(THD *thd, TABLE_LIST *sql_table) } -int Json_table_column::set(THD *thd, enum_type ctype, const LEX_CSTRING &path) +int Json_table_column::set(THD *thd, enum_type ctype, const LEX_CSTRING &path, + CHARSET_INFO *cs) { set(ctype); + m_explicit_cs= cs; if (json_path_setup(&m_path, thd->variables.collation_connection, (const uchar *) path.str, (const uchar *)(path.str + path.length))) { diff --git a/sql/json_table.h b/sql/json_table.h index 3560b4ca137..52cdae13e9b 100644 --- a/sql/json_table.h +++ b/sql/json_table.h @@ -159,7 +159,7 @@ public: { m_column_type= ctype; } - int set(THD *thd, enum_type ctype, const LEX_CSTRING &path); + int set(THD *thd, enum_type ctype, const LEX_CSTRING &path, CHARSET_INFO *cs); Json_table_column(Create_field *f, Json_table_nested_path *nest) : m_field(f), m_nest(nest), m_explicit_cs(NULL) { diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 34814d4afae..045006117b9 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -200,17 +200,6 @@ void _CONCAT_UNDERSCORED(turn_parser_debug_on,yyparse)() MYSQL_YYABORT; \ } while(0) -#define set_collation(X) \ - do { \ - if (X) \ - { \ - if (unlikely(Lex->charset && !my_charset_same(Lex->charset,X))) \ - my_yyabort_error((ER_COLLATION_CHARSET_MISMATCH, MYF(0), \ - X->coll_name.str,Lex->charset->cs_name.str)); \ - Lex->charset= X; \ - } \ - } while(0) - %} %union { @@ -1583,6 +1572,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); %type opt_collate + collate charset_name charset_or_alias charset_name_or_default @@ -6794,10 +6784,7 @@ charset_or_alias: } ; -collate: COLLATE_SYM collation_name_or_default - { - Lex->charset= $2; - } +collate: COLLATE_SYM collation_name_or_default { $$= $2; } ; opt_binary: @@ -6812,11 +6799,12 @@ binary: | BINARY charset_or_alias { bincmp_collation($2, true); } | charset_or_alias collate { - if (!my_charset_same(Lex->charset, $1)) + if (!my_charset_same($2, $1)) my_yyabort_error((ER_COLLATION_CHARSET_MISMATCH, MYF(0), - Lex->charset->coll_name.str, $1->cs_name.str)); + $2->coll_name.str, $1->cs_name.str)); + Lex->charset= $2; } - | collate { } + | collate { Lex->charset= $1; } ; opt_bin_mod: @@ -11629,7 +11617,7 @@ json_table_column_type: Lex->last_field->set_attributes(thd, $1, Lex->charset, COLUMN_DEFINITION_TABLE_FIELD); if (Lex->json_table->m_cur_json_table_column-> - set(thd, Json_table_column::PATH, $3)) + set(thd, Json_table_column::PATH, $3, Lex->charset)) { MYSQL_YYABORT; } @@ -11639,23 +11627,15 @@ json_table_column_type: Lex->last_field->set_attributes(thd, $1, Lex->charset, COLUMN_DEFINITION_TABLE_FIELD); Lex->json_table->m_cur_json_table_column-> - set(thd, Json_table_column::EXISTS_PATH, $4); + set(thd, Json_table_column::EXISTS_PATH, $4, Lex->charset); } ; json_table_field_type: field_type_numeric | field_type_temporal - | 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; - } + | field_type_string + | field_type_lob ; json_opt_on_empty_or_error: