Skip to content

Commit 15e6812

Browse files
committed
Bug#36606073: json_table and exists make a bug
When JSON_TABLE was used in an IN or EXISTS subquery, and referenced a table in the outer query block, wrong results were returned in some cases when semijoin transformation had been performed. The problem was that the semijoin transformation didn't call fix_after_pullout() on the argument of the JSON_TABLE expression, so that it still appeared to have an outer reference. Because of this, the table function had no lateral dependency on the outer table, and the optimizer could end up choosing a plan with the outer table inner to the table function. Fixed by implementing fix_after_pullout() on Table_function, and calling it from fix_tables_after_pullout(). Change-Id: I9e3de5710486c0af24fb9d5177a2f69cd195d330
1 parent 5dcd0b4 commit 15e6812

File tree

5 files changed

+54
-0
lines changed

5 files changed

+54
-0
lines changed

mysql-test/suite/json/r/json_table.result

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2252,3 +2252,14 @@ txt i
22522252
[2] 2
22532253
[3] 3
22542254
DROP TABLE t;
2255+
#
2256+
# Bug#36606073: json_table and exists make a bug
2257+
#
2258+
CREATE TABLE t(x VARCHAR(10));
2259+
INSERT INTO t VALUES ('[1]'), ('[2]'), ('[3]');
2260+
SELECT * FROM t WHERE EXISTS (
2261+
SELECT * FROM JSON_TABLE(x, '$[*]' COLUMNS (i INT PATH '$')) AS jt WHERE i = 2
2262+
);
2263+
x
2264+
[2]
2265+
DROP TABLE t;

mysql-test/suite/json/t/json_table.test

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1579,3 +1579,14 @@ SELECT *
15791579
FROM t, JSON_TABLE(txt, '$[*]' COLUMNS (i INT PATH '$')) AS jt
15801580
ORDER BY i;
15811581
DROP TABLE t;
1582+
1583+
--echo #
1584+
--echo # Bug#36606073: json_table and exists make a bug
1585+
--echo #
1586+
1587+
CREATE TABLE t(x VARCHAR(10));
1588+
INSERT INTO t VALUES ('[1]'), ('[2]'), ('[3]');
1589+
SELECT * FROM t WHERE EXISTS (
1590+
SELECT * FROM JSON_TABLE(x, '$[*]' COLUMNS (i INT PATH '$')) AS jt WHERE i = 2
1591+
);
1592+
DROP TABLE t;

sql/sql_resolver.cc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@
109109
#include "sql/sql_union.h" // Query_result_union
110110
#include "sql/system_variables.h"
111111
#include "sql/table.h"
112+
#include "sql/table_function.h"
112113
#include "sql/thd_raii.h"
113114
#include "sql/thr_malloc.h"
114115
#include "sql/visible_fields.h"
@@ -2164,6 +2165,11 @@ static void fix_tables_after_pullout(Query_block *parent_query_block,
21642165
"lateral CTE".
21652166
*/
21662167
}
2168+
2169+
if (tr->is_table_function()) {
2170+
tr->table_function->fix_after_pullout(parent_query_block,
2171+
removed_query_block);
2172+
}
21672173
}
21682174

21692175
/**

sql/table_function.cc

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,12 @@ bool Table_function::init_args() {
9595
return false;
9696
}
9797

98+
void Table_function::fix_after_pullout(Query_block *parent_query_block,
99+
Query_block *removed_query_block) {
100+
do_fix_after_pullout(parent_query_block, removed_query_block);
101+
table->pos_in_table_list->dep_tables = used_tables();
102+
}
103+
98104
/******************************************************************************
99105
Implementation of JSON_TABLE function
100106
******************************************************************************/
@@ -770,6 +776,11 @@ void Table_function_json::do_cleanup() {
770776
for (uint i = 0; i < m_all_columns.size(); i++) m_all_columns[i]->cleanup();
771777
}
772778

779+
void Table_function_json::do_fix_after_pullout(
780+
Query_block *parent_query_block, Query_block *removed_query_block) {
781+
source->fix_after_pullout(parent_query_block, removed_query_block);
782+
}
783+
773784
void JT_data_source::cleanup() {
774785
v.clear();
775786
producing_records = false;

sql/table_function.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,17 @@ class Table_function {
158158

159159
virtual bool walk(Item_processor processor, enum_walk walk, uchar *arg) = 0;
160160

161+
/**
162+
Fix after tables have been moved from one query_block level to the parent
163+
level, e.g by semijoin conversion.
164+
165+
@param parent_query_block query_block that tables are moved to.
166+
@param removed_query_block query_block that tables are moved away from,
167+
child of parent_query_block.
168+
*/
169+
void fix_after_pullout(Query_block *parent_query_block,
170+
Query_block *removed_query_block);
171+
161172
private:
162173
/**
163174
Get the list of fields to create the result table
@@ -173,6 +184,8 @@ class Table_function {
173184
virtual bool do_init_args() = 0;
174185
friend bool Table_ref::setup_table_function(THD *thd);
175186
virtual void do_cleanup() {}
187+
virtual void do_fix_after_pullout(Query_block *parent_query_block,
188+
Query_block *removed_query_block) = 0;
176189
};
177190

178191
/****************************************************************************
@@ -436,6 +449,8 @@ class Table_function_json final : public Table_function {
436449
List<Create_field> *get_field_list() override;
437450
bool do_init_args() override;
438451
void do_cleanup() override;
452+
void do_fix_after_pullout(Query_block *parent_query_block,
453+
Query_block *removed_query_block) override;
439454
};
440455

441456
/**

0 commit comments

Comments
 (0)