mirror of
https://github.com/MariaDB/server.git
synced 2025-08-08 11:22:35 +03:00
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.
This commit is contained in:
@@ -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
|
2 DEPENDENT SUBQUERY jt ALL NULL NULL NULL NULL 40 Table function: json_table
|
||||||
drop table t1;
|
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
|
# 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
|
Warning 1366 Incorrect decimal value: 'asdf' for column ``.`(temporary)`.`d` at row 1
|
||||||
SELECT * FROM
|
SELECT * FROM
|
||||||
JSON_TABLE('{}', '$' COLUMNS (x INT PATH '$.x' DEFAULT NULL ON EMPTY)) jt;
|
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
|
SELECT * FROM
|
||||||
JSON_TABLE('{}', '$' COLUMNS (x INT PATH '$.x' DEFAULT NULL ON ERROR)) jt;
|
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
|
SELECT * FROM
|
||||||
JSON_TABLE('{}', '$' COLUMNS (x INT PATH '$.x' DEFAULT 0 ON EMPTY)) jt;
|
JSON_TABLE('{}', '$' COLUMNS (x INT PATH '$.x' DEFAULT 0 ON EMPTY)) jt;
|
||||||
x
|
x
|
||||||
@@ -561,12 +563,14 @@ SELECT * FROM
|
|||||||
JSON_TABLE('{}', '$' COLUMNS (x DATE
|
JSON_TABLE('{}', '$' COLUMNS (x DATE
|
||||||
PATH '$.x'
|
PATH '$.x'
|
||||||
DEFAULT DATE'2020-01-01' ON EMPTY)) jt;
|
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
|
SELECT * FROM
|
||||||
JSON_TABLE('{}', '$' COLUMNS (x DATE
|
JSON_TABLE('{}', '$' COLUMNS (x DATE
|
||||||
PATH '$.x'
|
PATH '$.x'
|
||||||
DEFAULT DATE'2020-01-01' ON ERROR)) jt;
|
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
|
# Bug#25413069: SIG11 IN CHECK_COLUMN_GRANT_IN_TABLE_REF
|
||||||
#
|
#
|
||||||
|
@@ -893,6 +893,30 @@ explain select c,
|
|||||||
|
|
||||||
drop table t1;
|
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 #
|
||||||
--echo # End of 10.6 tests
|
--echo # End of 10.6 tests
|
||||||
--echo #
|
--echo #
|
||||||
|
@@ -445,11 +445,8 @@ SELECT * FROM JSON_TABLE('"asdf"', '$' COLUMNS(
|
|||||||
f FLOAT PATH '$',
|
f FLOAT PATH '$',
|
||||||
d DECIMAL PATH '$')) AS jt;
|
d DECIMAL PATH '$')) AS jt;
|
||||||
|
|
||||||
# DEFAULT NULL is not accepted syntax.
|
|
||||||
--error ER_PARSE_ERROR
|
|
||||||
SELECT * FROM
|
SELECT * FROM
|
||||||
JSON_TABLE('{}', '$' COLUMNS (x INT PATH '$.x' DEFAULT NULL ON EMPTY)) jt;
|
JSON_TABLE('{}', '$' COLUMNS (x INT PATH '$.x' DEFAULT NULL ON EMPTY)) jt;
|
||||||
--error ER_PARSE_ERROR
|
|
||||||
SELECT * FROM
|
SELECT * FROM
|
||||||
JSON_TABLE('{}', '$' COLUMNS (x INT PATH '$.x' DEFAULT NULL ON ERROR)) jt;
|
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;
|
JSON_TABLE('{}', '$' COLUMNS (x INT PATH '$.x' DEFAULT 0 ON EMPTY)) jt;
|
||||||
SELECT * FROM
|
SELECT * FROM
|
||||||
JSON_TABLE('{}', '$' COLUMNS (x INT PATH '$.x' DEFAULT 0 ON ERROR)) jt;
|
JSON_TABLE('{}', '$' COLUMNS (x INT PATH '$.x' DEFAULT 0 ON ERROR)) jt;
|
||||||
# We don't accept dates in DEFAULT
|
|
||||||
--error 1064
|
|
||||||
SELECT * FROM
|
SELECT * FROM
|
||||||
JSON_TABLE('{}', '$' COLUMNS (x DATE
|
JSON_TABLE('{}', '$' COLUMNS (x DATE
|
||||||
PATH '$.x'
|
PATH '$.x'
|
||||||
DEFAULT DATE'2020-01-01' ON EMPTY)) jt;
|
DEFAULT DATE'2020-01-01' ON EMPTY)) jt;
|
||||||
--error 1064
|
|
||||||
SELECT * FROM
|
SELECT * FROM
|
||||||
JSON_TABLE('{}', '$' COLUMNS (x DATE
|
JSON_TABLE('{}', '$' COLUMNS (x DATE
|
||||||
PATH '$.x'
|
PATH '$.x'
|
||||||
|
@@ -1030,8 +1030,7 @@ int Json_table_column::On_response::respond(Json_table_column *jc, Field *f,
|
|||||||
return 1;
|
return 1;
|
||||||
case Json_table_column::RESPONSE_DEFAULT:
|
case Json_table_column::RESPONSE_DEFAULT:
|
||||||
f->set_notnull();
|
f->set_notnull();
|
||||||
f->store(m_default.str,
|
m_default->save_in_field(f, TRUE);
|
||||||
m_default.length, jc->m_defaults_cs);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return 0;
|
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
|
int Json_table_column::On_response::print(const char *name, String *str) const
|
||||||
{
|
{
|
||||||
LEX_CSTRING resp;
|
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)
|
if (m_response == Json_table_column::RESPONSE_NOT_SPECIFIED)
|
||||||
return 0;
|
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:
|
case Json_table_column::RESPONSE_DEFAULT:
|
||||||
{
|
{
|
||||||
lex_string_set3(&resp, STRING_WITH_LEN("DEFAULT"));
|
lex_string_set3(&resp, STRING_WITH_LEN("DEFAULT"));
|
||||||
ds= &m_default;
|
ds= m_default->val_str(&val);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@@ -1065,9 +1068,14 @@ int Json_table_column::On_response::print(const char *name, String *str) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (str->append(' ') || str->append(resp) ||
|
return (str->append(' ') || str->append(resp) ||
|
||||||
(ds && (str->append(STRING_WITH_LEN(" '")) ||
|
(ds &&
|
||||||
str->append_for_single_quote(ds->str, ds->length) ||
|
(str->append(' ') ||
|
||||||
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(STRING_WITH_LEN(" ON ")) ||
|
||||||
str->append(name, strlen(name)));
|
str->append(name, strlen(name)));
|
||||||
}
|
}
|
||||||
|
@@ -140,7 +140,7 @@ public:
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Json_table_column::enum_on_response m_response;
|
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 respond(Json_table_column *jc, Field *f, uint error_num);
|
||||||
int print(const char *name, String *str) const;
|
int print(const char *name, String *str) const;
|
||||||
bool specified() const { return m_response != RESPONSE_NOT_SPECIFIED; }
|
bool specified() const { return m_response != RESPONSE_NOT_SPECIFIED; }
|
||||||
@@ -154,7 +154,6 @@ public:
|
|||||||
Create_field *m_field;
|
Create_field *m_field;
|
||||||
Json_table_nested_path *m_nest;
|
Json_table_nested_path *m_nest;
|
||||||
CHARSET_INFO *m_explicit_cs;
|
CHARSET_INFO *m_explicit_cs;
|
||||||
CHARSET_INFO *m_defaults_cs;
|
|
||||||
|
|
||||||
void set(enum_type ctype)
|
void set(enum_type ctype)
|
||||||
{
|
{
|
||||||
|
@@ -1328,7 +1328,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
|
|||||||
TEXT_STRING
|
TEXT_STRING
|
||||||
NCHAR_STRING
|
NCHAR_STRING
|
||||||
json_text_literal
|
json_text_literal
|
||||||
json_text_literal_or_num
|
|
||||||
|
|
||||||
%type <lex_str_ptr>
|
%type <lex_str_ptr>
|
||||||
opt_table_alias_clause
|
opt_table_alias_clause
|
||||||
@@ -1512,6 +1511,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
|
|||||||
simple_target_specification
|
simple_target_specification
|
||||||
condition_number
|
condition_number
|
||||||
opt_versioning_interval_start
|
opt_versioning_interval_start
|
||||||
|
json_default_literal
|
||||||
|
|
||||||
%type <item_param> param_marker
|
%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:
|
join_table_list:
|
||||||
derived_table_list { MYSQL_YYABORT_UNLESS($$=$1); }
|
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_on_empty_response json_on_error_response
|
||||||
;
|
;
|
||||||
|
|
||||||
|
json_default_literal:
|
||||||
|
literal
|
||||||
|
| signed_literal
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
json_on_response:
|
json_on_response:
|
||||||
ERROR_SYM
|
ERROR_SYM
|
||||||
{
|
{
|
||||||
@@ -11729,12 +11715,10 @@ json_on_response:
|
|||||||
{
|
{
|
||||||
$$.m_response= Json_table_column::RESPONSE_NULL;
|
$$.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_response= Json_table_column::RESPONSE_DEFAULT;
|
||||||
$$.m_default= $2;
|
$$.m_default= $2;
|
||||||
Lex->json_table->m_cur_json_table_column->m_defaults_cs=
|
|
||||||
thd->variables.collation_connection;
|
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user