Skip to content

Commit f43c316

Browse files
committed
Bug#36542023: Simplify the find_field function interfaces
The existing functions for resolving column references are still present, but interfaces have been simplified and made more consistent. Error handling is separated out and an error is now indicated with a true function return, as usual. Generally, a successful resolver function call will return one out of three responses: - column was not found, or - column was found and resolved to a field reference, or - column was found and resolved to an indirect reference (Item_ref). The arguments could be simpler, but this subdivision is there for efficiency: a field reference is usually used to resolve an Item_field object, however it may also be used to populate some indirect reference object (Item_ref) later on. Thus, it makes sense to keep the field reference until we know what to do with it. Interfaces for iterating over natural join columns and view columns have been changed from operating on Item pointers to Item_ident pointers, since they only work with field objects and reference objects. This simplified the code, since some asserts and casts could be removed. The old slightly confusing enum find_item_error_report_type for reporting or ignoring certain error conditions has been replaced with a bitmask specifying which errors to possibly return. Old asserts marked 'WL#6570 remove-after-qa' are deleted. The patch also fixes the problem in bug 36704815 by not checking derived tables when the column reference contains a database name. New tests are added for this case. Specific changes, per function: find_field_in_tables() - Irrelevant argument register_tree_change is deleted. - Improved asserts for valid column name search. - Shortcut for item->m_table_ref != nullptr is removed. find_field_in_table_ref() - Irrelevant arguments register_tree_change and cached_field_index_ptr are deleted. find_field_in_table() - Irrelevant arguments field_index_ptr, register_tree_change and actual_table have been deleted. - Improved asserts of input arguments (Table_ref argument). - Removed check for empty database name. find_field_in_table_sef() - Only cosmetic changes. find_field_in_view() - Irrelevant arguments register_tree_change and actual_table are deleted. - The possible alias name of a column is passed explicitly, instead of being picked up from the "ref" argument. - ps_arena_holder is removed since this function is only called during resolving. - Successful outcome is reported as field not found, base table field found or reference found. find_field_in_natural_join() - Irrelevant arguments register_tree_change and actual_table are deleted. - ps_arena_holder was deleted, since function is only called by resolver. - Explicit call to nj_col->table_field->fix_fields() was irrelevant and has been removed. Item_field::fix_fields() - Special call to rf->fix_fields() was irrelevant and hence deleted. Item_field::fix_outer_field() - A new argument "complete" is used to signal that the object returned from this function is fully resolved. - The field_found variable is removed since it is no longer used. - The field upward_lookup is replaced with has_outer_context, since it better describes what is being tested. (It is used to report error in the case that Item_field::fix_fields() did not find a field reference and there are no possible outer references to resolve). Item_ref::fix_fields() - Mostly unchanged, only adapted to new call interfaces. - ps_arena_holder was deleted, since function is only called by resolver. - Some redundant code is removed and substituted with asserts. Change-Id: I11c51c25f30c4f85abefa9d326c2336bc31bb7d7
1 parent 47883ee commit f43c316

13 files changed

+725
-873
lines changed

mysql-test/include/with_non_recursive.inc

+4-3
Original file line numberDiff line numberDiff line change
@@ -226,15 +226,16 @@ FROM qn;
226226
--error ER_PARSE_ERROR
227227
with test.qn as (select "with") select * from test.qn;
228228

229-
--echo # Adding a db. prefix to a field still resolves to the QN; it's a bit awkward as
230-
--echo # the QN doesn't belong to a db, but it's the same with derived table:
229+
--echo # Adding a database prefix to a field does not resolve to the QN:
230+
--error ER_BAD_FIELD_ERROR
231231
select test.qn.a from (select "with" as a) qn;
232232

233-
--echo # OTOH, db. prefix in FROM doesn't resolve to QN, which is good
233+
--echo # database prefix in FROM does not resolve to QN:
234234
with qn as (select "with") select * from qn;
235235
with qn as (select "with") select * from test.qn;
236236
with qn as (select "with" as a) select a from qn;
237237
with qn as (select "with" as a) select qn.a from qn;
238+
--error ER_BAD_FIELD_ERROR
238239
with qn as (select "with" as a) select test.qn.a from qn;
239240
with qn as (select "with" as a) select a from test.qn;
240241
with qn as (select "with" as a) select qn.a from test.qn;

mysql-test/r/derived.result

+8-4
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
1-
drop table if exists t1,t2,t3;
2-
select * from (select 2 from DUAL) b;
1+
select * from (select 2 from DUAL) AS b;
32
2
43
2
5-
SELECT 1 as a FROM (SELECT 1 UNION SELECT a) b;
4+
SELECT 1 as a FROM (SELECT 1 UNION SELECT a) AS b;
65
ERROR 42S22: Unknown column 'a' in 'field list'
7-
SELECT 1 as a FROM (SELECT a UNION SELECT 1) b;
6+
SELECT 1 as a FROM (SELECT a UNION SELECT 1) AS b;
87
ERROR 42S22: Unknown column 'a' in 'field list'
8+
select dt.a from (select 1 as a) as dt;
9+
a
10+
1
11+
select test.dt.a from (select 1 as a) as dt;
12+
ERROR 42S22: Unknown column 'test.dt.a' in 'field list'
913
CREATE TABLE t1 (a int not null, b char (10) not null);
1014
insert into t1 values(1,'a'),(2,'b'),(3,'c'),(3,'c');
1115
CREATE TABLE t2 (a int not null, b char (10) not null);

mysql-test/r/with_non_recursive.result

+8-14
Original file line numberDiff line numberDiff line change
@@ -244,12 +244,10 @@ inner outer
244244
# Qualified name isn't allowed after WITH:
245245
with test.qn as (select "with") select * from test.qn;
246246
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '.qn as (select "with") select * from test.qn' at line 1
247-
# Adding a db. prefix to a field still resolves to the QN; it's a bit awkward as
248-
# the QN doesn't belong to a db, but it's the same with derived table:
247+
# Adding a database prefix to a field does not resolve to the QN:
249248
select test.qn.a from (select "with" as a) qn;
250-
a
251-
with
252-
# OTOH, db. prefix in FROM doesn't resolve to QN, which is good
249+
ERROR 42S22: Unknown column 'test.qn.a' in 'field list'
250+
# database prefix in FROM does not resolve to QN:
253251
with qn as (select "with") select * from qn;
254252
with
255253
with
@@ -263,8 +261,7 @@ with qn as (select "with" as a) select qn.a from qn;
263261
a
264262
with
265263
with qn as (select "with" as a) select test.qn.a from qn;
266-
a
267-
with
264+
ERROR 42S22: Unknown column 'test.qn.a' in 'field list'
268265
with qn as (select "with" as a) select a from test.qn;
269266
a
270267
tmp
@@ -1355,12 +1352,10 @@ inner outer
13551352
# Qualified name isn't allowed after WITH:
13561353
with test.qn as (select "with") select * from test.qn;
13571354
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '.qn as (select "with") select * from test.qn' at line 1
1358-
# Adding a db. prefix to a field still resolves to the QN; it's a bit awkward as
1359-
# the QN doesn't belong to a db, but it's the same with derived table:
1355+
# Adding a database prefix to a field does not resolve to the QN:
13601356
select test.qn.a from (select "with" as a) qn;
1361-
a
1362-
with
1363-
# OTOH, db. prefix in FROM doesn't resolve to QN, which is good
1357+
ERROR 42S22: Unknown column 'test.qn.a' in 'field list'
1358+
# database prefix in FROM does not resolve to QN:
13641359
with qn as (select "with") select * from qn;
13651360
with
13661361
with
@@ -1374,8 +1369,7 @@ with qn as (select "with" as a) select qn.a from qn;
13741369
a
13751370
with
13761371
with qn as (select "with" as a) select test.qn.a from qn;
1377-
a
1378-
with
1372+
ERROR 42S22: Unknown column 'test.qn.a' in 'field list'
13791373
with qn as (select "with" as a) select a from test.qn;
13801374
a
13811375
tmp

mysql-test/t/derived.test

+9-9
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,16 @@
77
--source include/force_myisam_default.inc
88
--source include/have_myisam.inc
99

10-
# Initialize
11-
--disable_warnings
12-
drop table if exists t1,t2,t3;
13-
--enable_warnings
10+
select * from (select 2 from DUAL) AS b;
11+
-- error ER_BAD_FIELD_ERROR
12+
SELECT 1 as a FROM (SELECT 1 UNION SELECT a) AS b;
13+
-- error ER_BAD_FIELD_ERROR
14+
SELECT 1 as a FROM (SELECT a UNION SELECT 1) AS b;
15+
16+
select dt.a from (select 1 as a) as dt;
17+
-- error ER_BAD_FIELD_ERROR
18+
select test.dt.a from (select 1 as a) as dt;
1419

15-
select * from (select 2 from DUAL) b;
16-
-- error 1054
17-
SELECT 1 as a FROM (SELECT 1 UNION SELECT a) b;
18-
-- error 1054
19-
SELECT 1 as a FROM (SELECT a UNION SELECT 1) b;
2020
CREATE TABLE t1 (a int not null, b char (10) not null);
2121
insert into t1 values(1,'a'),(2,'b'),(3,'c'),(3,'c');
2222
CREATE TABLE t2 (a int not null, b char (10) not null);

sql/auth/sql_authorization.cc

+12-10
Original file line numberDiff line numberDiff line change
@@ -2674,20 +2674,22 @@ int mysql_table_grant(THD *thd, Table_ref *table_list,
26742674
return true; /* purecov: inspected */
26752675
}
26762676
while ((column = column_iter++)) {
2677-
uint unused_field_idx = NO_FIELD_INDEX;
2678-
Table_ref *dummy;
2679-
Field *f = find_field_in_table_ref(
2680-
thd, table_list, column->column.ptr(), column->column.length(),
2681-
column->column.ptr(), nullptr, nullptr, nullptr,
2682-
// check that we have the
2683-
// to-be-granted privilege:
2684-
column->rights, false, &unused_field_idx, false, &dummy);
2685-
if (f == (Field *)nullptr) {
2677+
Field *field;
2678+
Find_field_result found;
2679+
if (find_field_in_table_ref(
2680+
thd, table_list, column->column.ptr(), column->column.length(),
2681+
column->column.ptr(), nullptr, nullptr,
2682+
// check that we have the to-be-granted privilege:
2683+
column->rights, false, &found, &field, nullptr)) {
2684+
return true;
2685+
}
2686+
assert(found != VIEW_FIELD_FOUND);
2687+
if (found != BASE_FIELD_FOUND) {
26862688
my_error(ER_BAD_FIELD_ERROR, MYF(0), column->column.c_ptr(),
26872689
table_list->alias);
26882690
return true;
26892691
}
2690-
if (f == (Field *)-1) return true;
2692+
assert(field != nullptr);
26912693
column_priv |= column->rights;
26922694
}
26932695
close_mysql_tables(thd);

0 commit comments

Comments
 (0)