Skip to content

Commit

Permalink
MDEV-25202: JSON_TABLE: Early table reference leads to unexpected res…
Browse files Browse the repository at this point in the history
…ult set

(Also fixes MDEV-25254).
Re-work Name Resolution for the argument of JSON_TABLE(json_doc, ....)
function. The json_doc argument can refer to other tables, but it can
only refer to the tables that precede[*] the JSON_TABLE(...) call.

[*] - For queries with RIGHT JOINs, the "preceding" is determined after
the query is normalized by converting RIGHT JOIN into left one.

The implementation is as follows:
- Table function arguments use their own Name_resolution_context.

- The Name_resolution_context now has a bitmap of tables that should be
  ignored when searching for a field.

- get_disallowed_table_deps() walks the TABLE_LIST::nested_join tree
  and computes a bitmap of tables that do not "precede" the given
  JSON_TABLE(...) invocation  (according the above definition of
  "preceding").
  • Loading branch information
spetrunia authored and Alexey Botchkov committed Apr 21, 2021
1 parent 13390a7 commit 84cf9c2
Show file tree
Hide file tree
Showing 16 changed files with 398 additions and 39 deletions.
88 changes: 84 additions & 4 deletions mysql-test/suite/json/r/json_table.result
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ item_name item_props color
Laptop {"color": "black", "price": 1000} black
Jeans {"color": "blue", "price": 50} blue
select * from t1 right join json_table(t1.item_props,'$' columns( color varchar(100) path '$.color')) as T on 1;
ERROR 42000: Cross dependency found in OUTER JOIN; examine your ON conditions
ERROR 42S22: Unknown column 't1.item_props' in 'JSON_TABLE argument'
DROP TABLE t1;
select * from JSON_TABLE( '[ {"xa": 1, "b": [11,111]}, {"a": 2, "b": [22,222]}, {"a":3}]', '$[*]' COLUMNS( a INT PATH '$.a' default '101' on empty, NESTED PATH '$.b[*]' COLUMNS (b INT PATH '$'))) as jt;
a b
Expand Down Expand Up @@ -251,8 +251,12 @@ SELECT t1.x*2 m, jt.* FROM t1,
JSON_TABLE(m, '$[*]' COLUMNS (i INT PATH '$')) jt;
ERROR 42S22: Unknown column 'm' in 'JSON_TABLE argument'
DROP TABLE t1;
select * from json_table(JS3.size, '$' columns (size INT PATH '$.size')) as JS1, json_table(JS1.size, '$' columns (size INT PATH '$.size')) as JS2, json_table(JS1.size, '$' columns (size INT PATH '$.size')) as JS3 where 1;
ERROR 42S02: Unknown table 'JS3' in JSON_TABLE argument
select *
from
json_table(JS3.size, '$' columns (size INT PATH '$.size')) as JS1,
json_table(JS1.size, '$' columns (size INT PATH '$.size')) as JS2,
json_table(JS1.size, '$' columns (size INT PATH '$.size')) as JS3 where 1;
ERROR 42S22: Unknown column 'JS3.size' in 'JSON_TABLE argument'
create table t1 (json varchar(100) character set utf8);
insert into t1 values ('{"value":"АБВ"}');
create table tj1 as
Expand All @@ -279,7 +283,7 @@ test.t1 analyze status Engine-independent statistics collected
test.t1 analyze Warning Engine-independent statistics are not collected for column 'f1'
test.t1 analyze status OK
SELECT * FROM JSON_TABLE(tt3.f1, "$" COLUMNS (id FOR ORDINALITY)) AS tbl STRAIGHT_JOIN t1 AS tt3;
ERROR 42S02: Unknown table 'tt3' in JSON_TABLE argument
ERROR 42S22: Unknown column 'tt3.f1' in 'JSON_TABLE argument'
SELECT * FROM t1 as jj1,
(SELECT tt2.*
FROM
Expand Down Expand Up @@ -589,5 +593,81 @@ f
NULL
DROP TABLE t1;
#
# MDEV-25254: JSON_TABLE: Inconsistent name resolution with right joins
#
CREATE TABLE t1 (a INT);
SELECT * FROM t1 RIGHT JOIN JSON_TABLE(t1.a,'$' COLUMNS(o FOR ORDINALITY)) jt ON TRUE;
ERROR 42S22: Unknown column 't1.a' in 'JSON_TABLE argument'
CREATE VIEW v AS
SELECT * FROM t1 RIGHT JOIN JSON_TABLE(t1.a,'$' COLUMNS(o FOR ORDINALITY)) jt ON TRUE;
ERROR 42S22: Unknown column 't1.a' in 'JSON_TABLE argument'
insert into t1 values (1),(2),(3);
SELECT * FROM t1 RIGHT JOIN JSON_TABLE(t1.a,'$' COLUMNS(o FOR ORDINALITY)) jt ON TRUE;
ERROR 42S22: Unknown column 't1.a' in 'JSON_TABLE argument'
drop table t1;
#
# MDEV-25202: JSON_TABLE: Early table reference leads to unexpected result set, server crash
#
CREATE TABLE t1 (o INT);
INSERT INTO t1 VALUES (1),(2);
CREATE TABLE t2 (a INT);
INSERT INTO t2 VALUES (3),(4);
SELECT * FROM JSON_TABLE(a, '$' COLUMNS(o FOR ORDINALITY)) AS jt1 NATURAL JOIN t1 JOIN t2;
ERROR 42S22: Unknown column 'a' in 'JSON_TABLE argument'
SELECT * FROM JSON_TABLE(a, '$' COLUMNS(o FOR ORDINALITY)) AS jt1 NATURAL JOIN t1 STRAIGHT_JOIN t2;
ERROR 42S22: Unknown column 'a' in 'JSON_TABLE argument'
drop table t1,t2;
# Now, try a JSON_TABLE that has a subquery that has an outside reference:
create table t1(a int, js varchar(32));
create table t2(a varchar(100));
insert into t2 values('');
explain
select *
from
t1 left join
json_table(concat('',js),
'$' columns ( color varchar(32) path '$.color')
) as JT on 1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
explain
select *
from
t1 right join
json_table(concat('',js),
'$' columns ( color varchar(32) path '$.color')
) as JT on 1;
ERROR 42S22: Unknown column 'js' in 'JSON_TABLE argument'
explain
select *
from
t1 left join
json_table((select concat(a,js) from t2),
'$' columns ( color varchar(32) path '$.color')
) as JT on 1;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
2 SUBQUERY t2 system NULL NULL NULL NULL 1
explain
select *
from
t1 right join
json_table((select concat(a,js) from t2),
'$' columns ( color varchar(32) path '$.color')
) as JT on 1;
ERROR 42S22: Unknown column 'js' in 'field list'
drop table t1,t2;
#
# MDEV-25256: JSON_TABLE: Error ER_VIEW_INVALID upon running query via view
#
SELECT * FROM
JSON_TABLE('[]', '$' COLUMNS(a TEXT PATH '$[*]')) AS jt1
RIGHT JOIN JSON_TABLE(jt1.a, '$' COLUMNS(o2 FOR ORDINALITY)) AS jt2
ON(1)
RIGHT JOIN JSON_TABLE('[]', '$' COLUMNS(o3 FOR ORDINALITY)) AS jt3
ON(1)
WHERE 0;
ERROR 42S22: Unknown column 'jt1.a' in 'JSON_TABLE argument'
#
# End of 10.6 tests
#
21 changes: 10 additions & 11 deletions mysql-test/suite/json/r/json_table_mysql.result
Original file line number Diff line number Diff line change
Expand Up @@ -640,13 +640,13 @@ DEALLOCATE PREPARE stmt;
CREATE TABLE t1 (id INT, jc JSON);
SELECT * FROM t1 RIGHT JOIN JSON_TABLE(t1.jc, '$' COLUMNS
(id FOR ORDINALITY)) as jt ON t1.jc=jt.id;
id jc id
ERROR 42S22: Unknown column 't1.jc' in 'JSON_TABLE argument'
SELECT * FROM JSON_TABLE(t1.jc, '$' COLUMNS
(id FOR ORDINALITY)) as jt LEFT JOIN t1 ON t1.jc=jt.id;
ERROR 42S02: Unknown table 't1' in JSON_TABLE argument
ERROR 42S22: Unknown column 't1.jc' in 'JSON_TABLE argument'
SELECT * FROM JSON_TABLE(t1.jc, '$' COLUMNS
(id FOR ORDINALITY)) as jt RIGHT JOIN t1 ON t1.jc=jt.id;
ERROR 42S02: Unknown table 't1' in JSON_TABLE argument
id id jc
SELECT * FROM t1 LEFT JOIN JSON_TABLE(t1.jc, '$' COLUMNS
(id FOR ORDINALITY)) as jt ON t1.jc=jt.id;
id jc id
Expand All @@ -667,34 +667,33 @@ SELECT * FROM t1 AS t1o RIGHT JOIN
(t1 AS t1i JOIN JSON_TABLE(t1o.jc, '$' COLUMNS
(id FOR ORDINALITY)) as jt ON t1i.jc=jt.id)
ON t1o.id=t1i.id;
id jc id jc id
ERROR 42S22: Unknown column 't1o.jc' in 'JSON_TABLE argument'
SELECT * FROM t1 AS t1o RIGHT JOIN
(t1 AS t1i RIGHT JOIN JSON_TABLE(t1o.jc, '$' COLUMNS
(id FOR ORDINALITY)) as jt ON t1i.jc=jt.id)
ON t1o.id=t1i.id;
id jc id jc id
ERROR 42S22: Unknown column 't1o.jc' in 'JSON_TABLE argument'
WITH qn AS
(SELECT jt.* FROM t1 RIGHT JOIN JSON_TABLE(t1.jc, '$' COLUMNS
(id FOR ORDINALITY)) as jt ON t1.jc=jt.id)
SELECT * from qn;
id
ERROR 42S22: Unknown column 't1.jc' in 'JSON_TABLE argument'
WITH qn AS
(SELECT 1 UNION
SELECT jt.id FROM t1 RIGHT JOIN JSON_TABLE(t1.jc, '$' COLUMNS
(id FOR ORDINALITY)) as jt ON t1.jc=jt.id)
SELECT * from qn;
1
1
ERROR 42S22: Unknown column 't1.jc' in 'JSON_TABLE argument'
SELECT * FROM t1 AS t1o RIGHT JOIN
(t1 AS t1i JOIN JSON_TABLE(t1o.jc, '$' COLUMNS
(id FOR ORDINALITY)) as jt ON t1i.jc=jt.id)
ON t1o.id=t1i.id;
id jc id jc id
ERROR 42S22: Unknown column 't1o.jc' in 'JSON_TABLE argument'
SELECT * FROM t1 AS t1o RIGHT JOIN
(t1 AS t1i RIGHT JOIN JSON_TABLE(t1o.jc, '$' COLUMNS
(id FOR ORDINALITY)) as jt ON t1i.jc=jt.id)
ON t1o.id=t1i.id;
id jc id jc id
ERROR 42S22: Unknown column 't1o.jc' in 'JSON_TABLE argument'
INSERT INTO t1 VALUES(1,"1"),(2,"4"),(3,"3");
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
Expand All @@ -717,7 +716,7 @@ LEFT JOIN
JSON_TABLE(t1.jc, '$' COLUMNS (id FOR ORDINALITY)) as jt ON t1.jc=jt.id
RIGHT JOIN
JSON_TABLE(jt.id, '$' COLUMNS (id FOR ORDINALITY)) as jt1 ON jt.id=jt1.id;
ERROR 42000: Cross dependency found in OUTER JOIN; examine your ON conditions
ERROR 42S22: Unknown column 'jt.id' in 'JSON_TABLE argument'
DROP TABLE t1;
#
# Bug#25525409: ASSERTION `TABLE_LIST->TABLE' FAILED IN SQL/SQL_BASE.CC
Expand Down
103 changes: 99 additions & 4 deletions mysql-test/suite/json/t/json_table.test
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ insert into t1 values ('Jeans', '{"color": "blue", "price": 50}');

select * from t1 left join json_table(t1.item_props,'$' columns( color varchar(100) path '$.color')) as T on 1;

--error ER_WRONG_OUTER_JOIN
--error ER_BAD_FIELD_ERROR
select * from t1 right join json_table(t1.item_props,'$' columns( color varchar(100) path '$.color')) as T on 1;

DROP TABLE t1;
Expand Down Expand Up @@ -173,8 +173,12 @@ SELECT t1.x*2 m, jt.* FROM t1,
JSON_TABLE(m, '$[*]' COLUMNS (i INT PATH '$')) jt;
DROP TABLE t1;

--error ER_UNKNOWN_TABLE
select * from json_table(JS3.size, '$' columns (size INT PATH '$.size')) as JS1, json_table(JS1.size, '$' columns (size INT PATH '$.size')) as JS2, json_table(JS1.size, '$' columns (size INT PATH '$.size')) as JS3 where 1;
--error ER_BAD_FIELD_ERROR
select *
from
json_table(JS3.size, '$' columns (size INT PATH '$.size')) as JS1,
json_table(JS1.size, '$' columns (size INT PATH '$.size')) as JS2,
json_table(JS1.size, '$' columns (size INT PATH '$.size')) as JS3 where 1;

create table t1 (json varchar(100) character set utf8);
insert into t1 values ('{"value":"АБВ"}');
Expand All @@ -195,7 +199,7 @@ INSERT INTO t1 VALUES
(6, '{\"1\": 6}');
ANALYZE TABLE t1;

--error ER_UNKNOWN_TABLE
--error ER_BAD_FIELD_ERROR
SELECT * FROM JSON_TABLE(tt3.f1, "$" COLUMNS (id FOR ORDINALITY)) AS tbl STRAIGHT_JOIN t1 AS tt3;
--error ER_BAD_FIELD_ERROR
SELECT * FROM t1 as jj1,
Expand Down Expand Up @@ -460,6 +464,97 @@ CREATE TABLE t1 AS SELECT * FROM JSON_TABLE('{"x":1}', '$' COLUMNS(f DATE PATH '
SELECT * FROM t1;
DROP TABLE t1;

--echo #
--echo # MDEV-25254: JSON_TABLE: Inconsistent name resolution with right joins
--echo #
CREATE TABLE t1 (a INT);
--error ER_BAD_FIELD_ERROR
SELECT * FROM t1 RIGHT JOIN JSON_TABLE(t1.a,'$' COLUMNS(o FOR ORDINALITY)) jt ON TRUE;

--error ER_BAD_FIELD_ERROR
CREATE VIEW v AS
SELECT * FROM t1 RIGHT JOIN JSON_TABLE(t1.a,'$' COLUMNS(o FOR ORDINALITY)) jt ON TRUE;

insert into t1 values (1),(2),(3);
--error ER_BAD_FIELD_ERROR
SELECT * FROM t1 RIGHT JOIN JSON_TABLE(t1.a,'$' COLUMNS(o FOR ORDINALITY)) jt ON TRUE;

drop table t1;
--echo #
--echo # MDEV-25202: JSON_TABLE: Early table reference leads to unexpected result set, server crash
--echo #
CREATE TABLE t1 (o INT);
INSERT INTO t1 VALUES (1),(2);

CREATE TABLE t2 (a INT);
INSERT INTO t2 VALUES (3),(4);

--error ER_BAD_FIELD_ERROR
SELECT * FROM JSON_TABLE(a, '$' COLUMNS(o FOR ORDINALITY)) AS jt1 NATURAL JOIN t1 JOIN t2;

--error ER_BAD_FIELD_ERROR
SELECT * FROM JSON_TABLE(a, '$' COLUMNS(o FOR ORDINALITY)) AS jt1 NATURAL JOIN t1 STRAIGHT_JOIN t2;

drop table t1,t2;

--echo # Now, try a JSON_TABLE that has a subquery that has an outside reference:

create table t1(a int, js varchar(32));

create table t2(a varchar(100));
insert into t2 values('');

# First, without subquery:
explain
select *
from
t1 left join
json_table(concat('',js),
'$' columns ( color varchar(32) path '$.color')
) as JT on 1;

--error ER_BAD_FIELD_ERROR
explain
select *
from
t1 right join
json_table(concat('',js),
'$' columns ( color varchar(32) path '$.color')
) as JT on 1;

# Now, with subquery:
explain
select *
from
t1 left join
json_table((select concat(a,js) from t2),
'$' columns ( color varchar(32) path '$.color')
) as JT on 1;

--error ER_BAD_FIELD_ERROR
explain
select *
from
t1 right join
json_table((select concat(a,js) from t2),
'$' columns ( color varchar(32) path '$.color')
) as JT on 1;

drop table t1,t2;

--echo #
--echo # MDEV-25256: JSON_TABLE: Error ER_VIEW_INVALID upon running query via view
--echo #

--error ER_BAD_FIELD_ERROR
SELECT * FROM
JSON_TABLE('[]', '$' COLUMNS(a TEXT PATH '$[*]')) AS jt1
RIGHT JOIN JSON_TABLE(jt1.a, '$' COLUMNS(o2 FOR ORDINALITY)) AS jt2
ON(1)
RIGHT JOIN JSON_TABLE('[]', '$' COLUMNS(o3 FOR ORDINALITY)) AS jt3
ON(1)
WHERE 0;


--echo #
--echo # End of 10.6 tests
Expand Down
14 changes: 11 additions & 3 deletions mysql-test/suite/json/t/json_table_mysql.test
Original file line number Diff line number Diff line change
Expand Up @@ -549,15 +549,17 @@ CREATE TABLE t1 (id INT, jc JSON);

# psergey!
#--error ER_UNKNOWN_TABLE
--error ER_BAD_FIELD_ERROR
SELECT * FROM t1 RIGHT JOIN JSON_TABLE(t1.jc, '$' COLUMNS
(id FOR ORDINALITY)) as jt ON t1.jc=jt.id;

# psergey!
--error ER_UNKNOWN_TABLE
#--error ER_UNKNOWN_TABLE
--error ER_BAD_FIELD_ERROR
SELECT * FROM JSON_TABLE(t1.jc, '$' COLUMNS
(id FOR ORDINALITY)) as jt LEFT JOIN t1 ON t1.jc=jt.id;

--error ER_UNKNOWN_TABLE
#--error ER_UNKNOWN_TABLE
SELECT * FROM JSON_TABLE(t1.jc, '$' COLUMNS
(id FOR ORDINALITY)) as jt RIGHT JOIN t1 ON t1.jc=jt.id;

Expand All @@ -580,39 +582,45 @@ EXPLAIN SELECT * FROM t1 t1o RIGHT JOIN t1 ON t1o.id=t1.id

# psergey:
#--error ER_BAD_FIELD_ERROR
--error ER_BAD_FIELD_ERROR
SELECT * FROM t1 AS t1o RIGHT JOIN
(t1 AS t1i JOIN JSON_TABLE(t1o.jc, '$' COLUMNS
(id FOR ORDINALITY)) as jt ON t1i.jc=jt.id)
ON t1o.id=t1i.id;

# psergey:
#--error ER_UNKNOWN_TABLE
--error ER_BAD_FIELD_ERROR
SELECT * FROM t1 AS t1o RIGHT JOIN
(t1 AS t1i RIGHT JOIN JSON_TABLE(t1o.jc, '$' COLUMNS
(id FOR ORDINALITY)) as jt ON t1i.jc=jt.id)
ON t1o.id=t1i.id;

# psergey:
#--error ER_UNKNOWN_TABLE
--error ER_BAD_FIELD_ERROR
WITH qn AS
(SELECT jt.* FROM t1 RIGHT JOIN JSON_TABLE(t1.jc, '$' COLUMNS
(id FOR ORDINALITY)) as jt ON t1.jc=jt.id)
SELECT * from qn;

#--error ER_UNKNOWN_TABLE
--error ER_BAD_FIELD_ERROR
WITH qn AS
(SELECT 1 UNION
SELECT jt.id FROM t1 RIGHT JOIN JSON_TABLE(t1.jc, '$' COLUMNS
(id FOR ORDINALITY)) as jt ON t1.jc=jt.id)
SELECT * from qn;

#--error ER_BAD_FIELD_ERROR
--error ER_BAD_FIELD_ERROR
SELECT * FROM t1 AS t1o RIGHT JOIN
(t1 AS t1i JOIN JSON_TABLE(t1o.jc, '$' COLUMNS
(id FOR ORDINALITY)) as jt ON t1i.jc=jt.id)
ON t1o.id=t1i.id;

#--error ER_UNKNOWN_TABLE
--error ER_BAD_FIELD_ERROR
SELECT * FROM t1 AS t1o RIGHT JOIN
(t1 AS t1i RIGHT JOIN JSON_TABLE(t1o.jc, '$' COLUMNS
(id FOR ORDINALITY)) as jt ON t1i.jc=jt.id)
Expand All @@ -628,7 +636,7 @@ SELECT * FROM t1 LEFT JOIN JSON_TABLE(t1.jc, '$' COLUMNS
EXPLAIN SELECT * FROM t1 LEFT JOIN JSON_TABLE(t1.jc, '$' COLUMNS
(id INT PATH '$')) as jt ON t1.id=jt.id;

--error ER_WRONG_OUTER_JOIN
--error ER_BAD_FIELD_ERROR
SELECT * FROM t1
LEFT JOIN
JSON_TABLE(t1.jc, '$' COLUMNS (id FOR ORDINALITY)) as jt ON t1.jc=jt.id
Expand Down
Loading

0 comments on commit 84cf9c2

Please sign in to comment.