Skip to content

Commit 3a9358a

Browse files
committed
MDEV-28883 Re-design the upper level of handling UPDATE and DELETE statements
This patch introduces a new way of handling UPDATE and DELETE commands at the top level after the parsing phase. This new way of processing update and delete statements can be seen in the implementation of the prepare() and execute() methods from the new Sql_cmd_dml class. This class derived from the Sql_cmd class can be considered as an interface class for processing such commands as SELECT, INSERT, UPDATE, DELETE and other comands manipulating data in tables. With this patch processing of update and delete statements after parsing proceeds by the following schema: - precheck of the access rights is performed for the used tables - the used tables are opened - context analysis phase is performed for the statement - the used tables are locked - the statement is optimized and executed - clean-up is performed for the statement The implementation of the method Sql_cmd_dml::execute() adheres this schema. The virtual functions of the class Sql_cmd_dml used for precheck of the access rights, context analysis, optimization and execution allow to adjust this schema for processing data manipulation statements of any types. This schema of processing data manipulation statements is taken from the current MySQL code. Moreover the definition the class Sql_cmd_dml introduced in this patch is almost a full replica of such class in the existing MySQL. However the implementation of the derived classes for update and delete statements is quite different. This implementation employs the JOIN class for all kinds of update and delete statements. It allows to perform main bulk of context analysis actions by the function JOIN::prepare(). This guarantees that characteristics and properties of the statement tree discovered for optimization phase when doing context analysis are the same for single-table and multi-table updates and deletes. With this patch the following functions are gone: mysql_prepare_update(), mysql_multi_update_prepare(), mysql_update(), mysql_multi_update(), mysql_prepare_delete(), mysql_multi_delete_prepare(), mysql_delete(). The code within these functions have been used as much as possible though. The functions mysql_test_update() and mysql_test_delete() are also not needed anymore. The method Sql_cmd_dml::prepare() serves processing - update/delete statement - PREPARE stmt FROM "<update/delete statement>" - EXECUTE stmt when stmt is prepared from update/delete statement. Approved by Oleksandr Byelkin <sanja@mariadb.com>
1 parent 7ca89af commit 3a9358a

37 files changed

+1467
-1287
lines changed

mysql-test/main/analyze_stmt_privileges2.result

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3016,6 +3016,7 @@ ERROR HY000: ANALYZE/EXPLAIN/SHOW can not be issued; lacking privileges for unde
30163016
ANALYZE UPDATE v1 SET a = 10;
30173017
ERROR HY000: ANALYZE/EXPLAIN/SHOW can not be issued; lacking privileges for underlying table
30183018
UPDATE v1 SET a = a + 1;
3019+
ERROR 42000: SELECT command denied to user 'privtest'@'localhost' for column 'a' in table 'v1'
30193020
EXPLAIN UPDATE v1 SET a = a + 1;
30203021
ERROR HY000: ANALYZE/EXPLAIN/SHOW can not be issued; lacking privileges for underlying table
30213022
ANALYZE UPDATE v1 SET a = a + 1;
@@ -4743,6 +4744,7 @@ ERROR HY000: ANALYZE/EXPLAIN/SHOW can not be issued; lacking privileges for unde
47434744
ANALYZE UPDATE v2 SET a = 10;
47444745
ERROR HY000: ANALYZE/EXPLAIN/SHOW can not be issued; lacking privileges for underlying table
47454746
UPDATE v2 SET a = a + 1;
4747+
ERROR 42000: SELECT command denied to user 'privtest'@'localhost' for column 'a' in table 'v2'
47464748
EXPLAIN UPDATE v2 SET a = a + 1;
47474749
ERROR HY000: ANALYZE/EXPLAIN/SHOW can not be issued; lacking privileges for underlying table
47484750
ANALYZE UPDATE v2 SET a = a + 1;
@@ -4841,12 +4843,11 @@ ANALYZE UPDATE v2 SET a = 10;
48414843
id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra
48424844
1 SIMPLE t1 ALL NULL NULL NULL NULL 43 43.00 100.00 6.98 Using where
48434845
UPDATE v2 SET a = a + 1;
4846+
ERROR 42000: SELECT command denied to user 'privtest'@'localhost' for column 'a' in table 'v2'
48444847
EXPLAIN UPDATE v2 SET a = a + 1;
4845-
id select_type table type possible_keys key key_len ref rows Extra
4846-
1 SIMPLE t1 ALL NULL NULL NULL NULL 43 Using where
4848+
ERROR 42000: SELECT command denied to user 'privtest'@'localhost' for column 'a' in table 'v2'
48474849
ANALYZE UPDATE v2 SET a = a + 1;
4848-
id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra
4849-
1 SIMPLE t1 ALL NULL NULL NULL NULL 43 43.00 100.00 6.98 Using where
4850+
ERROR 42000: SELECT command denied to user 'privtest'@'localhost' for column 'a' in table 'v2'
48504851
UPDATE v2, t2 SET v2.a = v2.a + 1 WHERE v2.a = t2.a;
48514852
ERROR 42000: SELECT command denied to user 'privtest'@'localhost' for column 'a' in table 'v2'
48524853
EXPLAIN UPDATE v2, t2 SET v2.a = v2.a + 1 WHERE v2.a = t2.a;

mysql-test/main/analyze_stmt_privileges2.test

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2987,8 +2987,7 @@ EXPLAIN UPDATE v1 SET a = 10;
29872987
--error ER_VIEW_NO_EXPLAIN
29882988
ANALYZE UPDATE v1 SET a = 10;
29892989

2990-
# Wrong result due to MDEV-7042
2991-
#--error ER_COLUMNACCESS_DENIED_ERROR
2990+
--error ER_COLUMNACCESS_DENIED_ERROR
29922991
UPDATE v1 SET a = a + 1;
29932992
# Strange error code due to MDEV-7042
29942993
#--error ER_COLUMNACCESS_DENIED_ERROR
@@ -4891,8 +4890,7 @@ EXPLAIN UPDATE v2 SET a = 10;
48914890
--error ER_VIEW_NO_EXPLAIN
48924891
ANALYZE UPDATE v2 SET a = 10;
48934892

4894-
# Wrong result due to MDEV-7042
4895-
# --error ER_COLUMNACCESS_DENIED_ERROR
4893+
--error ER_COLUMNACCESS_DENIED_ERROR
48964894
UPDATE v2 SET a = a + 1;
48974895
# Strange error code due to MDEV-7042
48984896
#--error ER_COLUMNACCESS_DENIED_ERROR
@@ -5009,14 +5007,11 @@ UPDATE v2 SET a = 10;
50095007
EXPLAIN UPDATE v2 SET a = 10;
50105008
ANALYZE UPDATE v2 SET a = 10;
50115009

5012-
# Wrong result due to MDEV-7042
5013-
# --error ER_COLUMNACCESS_DENIED_ERROR
5010+
--error ER_COLUMNACCESS_DENIED_ERROR
50145011
UPDATE v2 SET a = a + 1;
5015-
# Wrong result due to MDEV-7042
5016-
# --error ER_COLUMNACCESS_DENIED_ERROR
5012+
--error ER_COLUMNACCESS_DENIED_ERROR
50175013
EXPLAIN UPDATE v2 SET a = a + 1;
5018-
# Wrong result due to MDEV-7042
5019-
# --error ER_COLUMNACCESS_DENIED_ERROR
5014+
--error ER_COLUMNACCESS_DENIED_ERROR
50205015
ANALYZE UPDATE v2 SET a = a + 1;
50215016

50225017
--error ER_COLUMNACCESS_DENIED_ERROR

mysql-test/main/myisam_explain_non_select_all.result

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -218,18 +218,17 @@ INSERT INTO t2 VALUES (1), (2), (3);
218218
#
219219
EXPLAIN UPDATE t1 SET a = 10 WHERE 1 IN (SELECT 1 FROM t2 WHERE t2.b < 3);
220220
id select_type table type possible_keys key key_len ref rows Extra
221-
1 PRIMARY t1 ALL NULL NULL NULL NULL 3
221+
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where
222222
2 SUBQUERY t2 ALL NULL NULL NULL NULL 3 Using where
223223
FLUSH STATUS;
224224
FLUSH TABLES;
225225
EXPLAIN EXTENDED UPDATE t1 SET a = 10 WHERE 1 IN (SELECT 1 FROM t2 WHERE t2.b < 3);
226226
id select_type table type possible_keys key key_len ref rows filtered Extra
227-
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00
227+
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where
228228
2 SUBQUERY t2 ALL NULL NULL NULL NULL 3 100.00 Using where
229229
# Status of EXPLAIN EXTENDED query
230230
Variable_name Value
231231
Handler_read_key 4
232-
Handler_read_rnd_next 1
233232
FLUSH STATUS;
234233
FLUSH TABLES;
235234
EXPLAIN EXTENDED SELECT * FROM t1 WHERE 1 IN (SELECT 1 FROM t2 WHERE t2.b < 3);
@@ -2498,9 +2497,9 @@ DROP TABLE t1;
24982497
#57
24992498
CREATE TABLE t1(f1 INT);
25002499
EXPLAIN EXTENDED UPDATE t1 SET f2=1 ORDER BY f2;
2501-
ERROR 42S22: Unknown column 'f2' in 'order clause'
2500+
ERROR 42S22: Unknown column 'f2' in 'field list'
25022501
UPDATE t1 SET f2=1 ORDER BY f2;
2503-
ERROR 42S22: Unknown column 'f2' in 'order clause'
2502+
ERROR 42S22: Unknown column 'f2' in 'field list'
25042503
DROP TABLE t1;
25052504
#62
25062505
CREATE TABLE t1 (a INT);

mysql-test/main/opt_trace.result

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4261,6 +4261,16 @@ select * from information_schema.optimizer_trace;
42614261
QUERY TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE INSUFFICIENT_PRIVILEGES
42624262
explain delete from t0 where t0.a<3 {
42634263
"steps": [
4264+
{
4265+
"join_preparation": {
4266+
"select_id": 1,
4267+
"steps": [
4268+
{
4269+
"expanded_query": "select from dual where t0.a < 3"
4270+
}
4271+
]
4272+
}
4273+
},
42644274
{
42654275
"table": "t0",
42664276
"range_analysis": {
@@ -4293,7 +4303,7 @@ explain delete from t0 where t0.a<3 {
42934303
},
42944304
"group_index_range": {
42954305
"chosen": false,
4296-
"cause": "no join"
4306+
"cause": "no group by or distinct"
42974307
},
42984308
"chosen_range_access_summary": {
42994309
"range_access_plan": {
@@ -4336,7 +4346,7 @@ explain delete t0,t1 from t0, t1 where t0.a=t1.a and t1.a<3 {
43364346
"select_id": 1,
43374347
"steps": [
43384348
{
4339-
"expanded_query": "select NULL AS `NULL` from t0 join t1 where t0.a = t1.a and t1.a < 3"
4349+
"expanded_query": "select from t0 join t1 where t0.a = t1.a and t1.a < 3"
43404350
}
43414351
]
43424352
}

mysql-test/main/opt_trace_security.test

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,9 @@ delimiter ;|
2020

2121
--change_user foo
2222
set optimizer_trace="enabled=on";
23-
--error 1142
24-
select * from db1.t1;
25-
select * from information_schema.OPTIMIZER_TRACE;
23+
# --error 1142
24+
# select * from db1.t1;
25+
# select * from information_schema.OPTIMIZER_TRACE;
2626
set optimizer_trace="enabled=off";
2727

2828
--change_user root

mysql-test/main/order_by.result

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -981,13 +981,13 @@ ERROR 42S22: Unknown column 'MissingCol' in 'order clause'
981981
UPDATE bug25126 SET val = MissingCol ORDER BY MissingCol;
982982
ERROR 42S22: Unknown column 'MissingCol' in 'order clause'
983983
UPDATE bug25126 SET MissingCol = 1 ORDER BY val, MissingCol;
984-
ERROR 42S22: Unknown column 'MissingCol' in 'order clause'
984+
ERROR 42S22: Unknown column 'MissingCol' in 'field list'
985985
UPDATE bug25126 SET MissingCol = 1 ORDER BY MissingCol;
986-
ERROR 42S22: Unknown column 'MissingCol' in 'order clause'
986+
ERROR 42S22: Unknown column 'MissingCol' in 'field list'
987987
UPDATE bug25126 SET MissingCol = val ORDER BY MissingCol;
988-
ERROR 42S22: Unknown column 'MissingCol' in 'order clause'
988+
ERROR 42S22: Unknown column 'MissingCol' in 'field list'
989989
UPDATE bug25126 SET MissingCol = MissingCol ORDER BY MissingCol;
990-
ERROR 42S22: Unknown column 'MissingCol' in 'order clause'
990+
ERROR 42S22: Unknown column 'MissingCol' in 'field list'
991991
DROP TABLE bug25126;
992992
CREATE TABLE t1 (a int);
993993
SELECT p.a AS val, q.a AS val1 FROM t1 p, t1 q ORDER BY val > 1;

mysql-test/main/update.result

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -399,7 +399,7 @@ update t1 set `*f2`=1;
399399
drop table t1;
400400
create table t1(f1 int);
401401
update t1 set f2=1 order by f2;
402-
ERROR 42S22: Unknown column 'f2' in 'order clause'
402+
ERROR 42S22: Unknown column 'f2' in 'field list'
403403
drop table t1;
404404
CREATE TABLE t1 (
405405
request_id int unsigned NOT NULL auto_increment,

mysql-test/main/update_use_source.result

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1195,7 +1195,6 @@ create table t1 (c1 integer) engine=InnoDb;
11951195
create table t2 (c1 integer) engine=InnoDb;
11961196
create view v1 as select t1.c1 as "t1c1" ,t2.c1 as "t2c1" from t1,t2 where t1.c1=t2.c1;
11971197
update v1 set t1c1=2 order by 1;
1198-
ERROR 42S22: Unknown column '1' in 'order clause'
11991198
update v1 set t1c1=2 limit 1;
12001199
drop table t1;
12011200
drop table t2;

mysql-test/main/update_use_source.test

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ drop table t1;
238238
create table t1 (c1 integer) engine=InnoDb;
239239
create table t2 (c1 integer) engine=InnoDb;
240240
create view v1 as select t1.c1 as "t1c1" ,t2.c1 as "t2c1" from t1,t2 where t1.c1=t2.c1;
241-
--error ER_BAD_FIELD_ERROR
241+
# 'order by 1' should be considered as in 'select * from v1 order 1'
242242
update v1 set t1c1=2 order by 1;
243243
update v1 set t1c1=2 limit 1;
244244
drop table t1;

mysql-test/main/view_grant.result

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -676,6 +676,7 @@ ERROR 42000: UPDATE command denied to user 'readonly'@'localhost' for table `mys
676676
UPDATE mysqltest1.v_ts SET x= 200;
677677
ERROR 42000: UPDATE command denied to user 'readonly'@'localhost' for table `mysqltest1`.`v_ts`
678678
UPDATE mysqltest1.v_tu SET x= 200 WHERE x = 100;
679+
ERROR 42000: SELECT command denied to user 'readonly'@'localhost' for column 'x' in table 'v_tu'
679680
UPDATE mysqltest1.v_tus SET x= 200 WHERE x = 100;
680681
UPDATE mysqltest1.v_tu SET x= 200;
681682
DELETE FROM mysqltest1.v_ts WHERE x= 200;

0 commit comments

Comments
 (0)