Commit d0a6a788 authored by Sergei Petrunia's avatar Sergei Petrunia

MDEV-25822 JSON_TABLE: default values should allow non-string literals

(Polished initial patch by Alexey Botchkov)
Make the code handle DEFAULT values of any datatype

- Make Json_table_column::On_response::m_default be Item*, not LEX_STRING.
- Change the parser to use string literal non-terminals for producing
  the DEFAULT value
-- Also, stop updating json_table->m_text_literal_cs for the DEFAULT
   value literals as it is not used.
parent 231900e5
......@@ -1036,5 +1036,50 @@ id select_type table type possible_keys key key_len ref rows Extra
2 DEPENDENT SUBQUERY jt ALL NULL NULL NULL NULL 40 Table function: json_table
drop table t1;
#
# MDEV-25822: JSON_TABLE: default values should allow non-string literals
#
select * from json_table('{"a": "b"}', '$' columns(col1 varchar(32) path '$.fooo' default 0.5 on empty)) as T;
col1
0.5
select * from json_table('{"a": "b"}', '$' columns(col1 varchar(32) path '$.fooo' default 5 on empty)) as T;
col1
5
select * from json_table('{"a": "b"}', '$' columns(col1 varchar(32) path '$.fooo' default 'asdf' on empty)) as T;
col1
asdf
select * from json_table('{"a": "b"}', '$' columns(col1 varchar(32) path '$.fooo' default -0.5 on empty)) as T;
col1
-0.5
select * from json_table('{"a": "b"}', '$' columns(col1 varchar(32) path '$.fooo' default 18446744073709551615 on empty)) as T;
col1
18446744073709551615
select * from json_table('{"a": "b"}', '$' columns(col1 varchar(32) path '$.fooo' default DATE '2021-01-01' on empty)) as T;
col1
2021-01-01
create view v as select * from json_table('{"a": "b"}', '$' columns(col1 varchar(32) path '$.fooo' default 5 on empty)) as T;
select * from v;
col1
5
show create view v;
View Create View character_set_client collation_connection
v CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v` AS select `T`.`col1` AS `col1` from JSON_TABLE('{"a": "b"}', '$' COLUMNS (`col1` varchar(32) PATH '$.fooo' DEFAULT 5 ON EMPTY)) `T` latin1 latin1_swedish_ci
drop view v;
create view v as select * from json_table('{"a": "b"}', '$' columns(col1 varchar(32) path '$.fooo' default 18446744073709551615 on empty)) as T;
select * from v;
col1
18446744073709551615
show create view v;
View Create View character_set_client collation_connection
v CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v` AS select `T`.`col1` AS `col1` from JSON_TABLE('{"a": "b"}', '$' COLUMNS (`col1` varchar(32) PATH '$.fooo' DEFAULT 18446744073709551615 ON EMPTY)) `T` latin1 latin1_swedish_ci
drop view v;
create view v as select * from json_table('{"a": "b"}', '$' columns(col1 varchar(32) path '$.fooo' default 'asdf' on empty)) as T;
select * from v;
col1
asdf
show create view v;
View Create View character_set_client collation_connection
v CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v` AS select `T`.`col1` AS `col1` from JSON_TABLE('{"a": "b"}', '$' COLUMNS (`col1` varchar(32) PATH '$.fooo' DEFAULT 'asdf' ON EMPTY)) `T` latin1 latin1_swedish_ci
drop view v;
#
# End of 10.6 tests
#
......@@ -545,10 +545,12 @@ Warning 1366 Incorrect double value: 'asdf' for column ``.`(temporary)`.`f` at r
Warning 1366 Incorrect decimal value: 'asdf' for column ``.`(temporary)`.`d` at row 1
SELECT * FROM
JSON_TABLE('{}', '$' COLUMNS (x INT PATH '$.x' DEFAULT NULL ON EMPTY)) 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 'NULL ON EMPTY)) jt' at line 2
x
NULL
SELECT * FROM
JSON_TABLE('{}', '$' COLUMNS (x INT PATH '$.x' DEFAULT NULL ON ERROR)) 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 'NULL ON ERROR)) jt' at line 2
x
NULL
SELECT * FROM
JSON_TABLE('{}', '$' COLUMNS (x INT PATH '$.x' DEFAULT 0 ON EMPTY)) jt;
x
......@@ -561,12 +563,14 @@ SELECT * FROM
JSON_TABLE('{}', '$' COLUMNS (x DATE
PATH '$.x'
DEFAULT DATE'2020-01-01' ON EMPTY)) 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 'DATE'2020-01-01' ON EMPTY)) jt' at line 4
x
2020-01-01
SELECT * FROM
JSON_TABLE('{}', '$' COLUMNS (x DATE
PATH '$.x'
DEFAULT DATE'2020-01-01' ON ERROR)) 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 'DATE'2020-01-01' ON ERROR)) jt' at line 4
x
NULL
#
# Bug#25413069: SIG11 IN CHECK_COLUMN_GRANT_IN_TABLE_REF
#
......
......@@ -893,6 +893,30 @@ explain select c,
drop table t1;
--echo #
--echo # MDEV-25822: JSON_TABLE: default values should allow non-string literals
--echo #
select * from json_table('{"a": "b"}', '$' columns(col1 varchar(32) path '$.fooo' default 0.5 on empty)) as T;
select * from json_table('{"a": "b"}', '$' columns(col1 varchar(32) path '$.fooo' default 5 on empty)) as T;
select * from json_table('{"a": "b"}', '$' columns(col1 varchar(32) path '$.fooo' default 'asdf' on empty)) as T;
select * from json_table('{"a": "b"}', '$' columns(col1 varchar(32) path '$.fooo' default -0.5 on empty)) as T;
select * from json_table('{"a": "b"}', '$' columns(col1 varchar(32) path '$.fooo' default 18446744073709551615 on empty)) as T;
select * from json_table('{"a": "b"}', '$' columns(col1 varchar(32) path '$.fooo' default DATE '2021-01-01' on empty)) as T;
create view v as select * from json_table('{"a": "b"}', '$' columns(col1 varchar(32) path '$.fooo' default 5 on empty)) as T;
select * from v;
show create view v;
drop view v;
create view v as select * from json_table('{"a": "b"}', '$' columns(col1 varchar(32) path '$.fooo' default 18446744073709551615 on empty)) as T;
select * from v;
show create view v;
drop view v;
create view v as select * from json_table('{"a": "b"}', '$' columns(col1 varchar(32) path '$.fooo' default 'asdf' on empty)) as T;
select * from v;
show create view v;
drop view v;
--echo #
--echo # End of 10.6 tests
--echo #
......@@ -445,11 +445,8 @@ SELECT * FROM JSON_TABLE('"asdf"', '$' COLUMNS(
f FLOAT PATH '$',
d DECIMAL PATH '$')) AS jt;
# DEFAULT NULL is not accepted syntax.
--error ER_PARSE_ERROR
SELECT * FROM
JSON_TABLE('{}', '$' COLUMNS (x INT PATH '$.x' DEFAULT NULL ON EMPTY)) jt;
--error ER_PARSE_ERROR
SELECT * FROM
JSON_TABLE('{}', '$' COLUMNS (x INT PATH '$.x' DEFAULT NULL ON ERROR)) jt;
......@@ -457,13 +454,10 @@ SELECT * FROM
JSON_TABLE('{}', '$' COLUMNS (x INT PATH '$.x' DEFAULT 0 ON EMPTY)) jt;
SELECT * FROM
JSON_TABLE('{}', '$' COLUMNS (x INT PATH '$.x' DEFAULT 0 ON ERROR)) jt;
# We don't accept dates in DEFAULT
--error 1064
SELECT * FROM
JSON_TABLE('{}', '$' COLUMNS (x DATE
PATH '$.x'
DEFAULT DATE'2020-01-01' ON EMPTY)) jt;
--error 1064
SELECT * FROM
JSON_TABLE('{}', '$' COLUMNS (x DATE
PATH '$.x'
......
......@@ -1030,8 +1030,7 @@ int Json_table_column::On_response::respond(Json_table_column *jc, Field *f,
return 1;
case Json_table_column::RESPONSE_DEFAULT:
f->set_notnull();
f->store(m_default.str,
m_default.length, jc->m_defaults_cs);
m_default->save_in_field(f, TRUE);
break;
}
return 0;
......@@ -1041,7 +1040,11 @@ int Json_table_column::On_response::respond(Json_table_column *jc, Field *f,
int Json_table_column::On_response::print(const char *name, String *str) const
{
LEX_CSTRING resp;
const LEX_CSTRING *ds= NULL;
char valbuf[512];
String val(valbuf, sizeof(valbuf), str->charset());
String *ds= NULL;
if (m_response == Json_table_column::RESPONSE_NOT_SPECIFIED)
return 0;
......@@ -1056,7 +1059,7 @@ int Json_table_column::On_response::print(const char *name, String *str) const
case Json_table_column::RESPONSE_DEFAULT:
{
lex_string_set3(&resp, STRING_WITH_LEN("DEFAULT"));
ds= &m_default;
ds= m_default->val_str(&val);
break;
}
default:
......@@ -1065,9 +1068,14 @@ int Json_table_column::On_response::print(const char *name, String *str) const
}
return (str->append(' ') || str->append(resp) ||
(ds && (str->append(STRING_WITH_LEN(" '")) ||
str->append_for_single_quote(ds->str, ds->length) ||
str->append('\''))) ||
(ds &&
(str->append(' ') ||
(m_default->result_type()==STRING_RESULT && str->append('\''))||
str->append_for_single_quote(ds) ||
(m_default->result_type()==STRING_RESULT && str->append('\''))))||
str->append(STRING_WITH_LEN(" ON ")) ||
str->append(name, strlen(name)));
}
......
......@@ -140,7 +140,7 @@ class Json_table_column : public Sql_alloc
{
public:
Json_table_column::enum_on_response m_response;
LEX_CSTRING m_default;
Item *m_default;
int respond(Json_table_column *jc, Field *f, uint error_num);
int print(const char *name, String *str) const;
bool specified() const { return m_response != RESPONSE_NOT_SPECIFIED; }
......@@ -154,7 +154,6 @@ class Json_table_column : public Sql_alloc
Create_field *m_field;
Json_table_nested_path *m_nest;
CHARSET_INFO *m_explicit_cs;
CHARSET_INFO *m_defaults_cs;
void set(enum_type ctype)
{
......
......@@ -1328,7 +1328,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
TEXT_STRING
NCHAR_STRING
json_text_literal
json_text_literal_or_num
%type <lex_str_ptr>
opt_table_alias_clause
......@@ -1512,6 +1511,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
simple_target_specification
condition_number
opt_versioning_interval_start
json_default_literal
%type <item_param> param_marker
......@@ -11595,26 +11595,6 @@ json_text_literal:
}
;
json_text_literal_or_num:
json_text_literal
| NUM
{
Lex->json_table->m_text_literal_cs= NULL;
}
| LONG_NUM
{
Lex->json_table->m_text_literal_cs= NULL;
}
| DECIMAL_NUM
{
Lex->json_table->m_text_literal_cs= NULL;
}
| FLOAT_NUM
{
Lex->json_table->m_text_literal_cs= NULL;
}
;
join_table_list:
derived_table_list { MYSQL_YYABORT_UNLESS($$=$1); }
;
......@@ -11720,6 +11700,12 @@ json_opt_on_empty_or_error:
| json_on_empty_response json_on_error_response
;
json_default_literal:
literal
| signed_literal
;
json_on_response:
ERROR_SYM
{
......@@ -11729,12 +11715,10 @@ json_on_response:
{
$$.m_response= Json_table_column::RESPONSE_NULL;
}
| DEFAULT json_text_literal_or_num
| DEFAULT json_default_literal
{
$$.m_response= Json_table_column::RESPONSE_DEFAULT;
$$.m_default= $2;
Lex->json_table->m_cur_json_table_column->m_defaults_cs=
thd->variables.collation_connection;
}
;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment