Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions test/distributed/cases/dml/insert/multi_insert_prepare.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
-- Multi-table INSERT: SQL PREPARE/EXECUTE binds markers in WHEN, VALUES and source.
drop database if exists multi_insert_prepare_db;
create database multi_insert_prepare_db;

create table multi_insert_prepare_db.src (id int primary key, kind varchar(16), amount int);
create table multi_insert_prepare_db.hit (id int primary key, amount int);
create table multi_insert_prepare_db.miss (id int primary key, amount int);
insert into multi_insert_prepare_db.src values (1, 'hot', 10), (2, 'cold', 20), (3, 'hot', 30);

prepare multi_insert_route from '
insert first
when kind = ? then into multi_insert_prepare_db.hit (id, amount) values (id + ?, amount + ?)
else into multi_insert_prepare_db.miss (id, amount) values (id + ?, amount + ?)
select id, kind, amount from multi_insert_prepare_db.src where id >= ?';

-- One prepared handle routes a subset to both targets. This binds all marker
-- positions, including the conditional predicate, the two VALUES lists and
-- the source WHERE clause.
set @kind = 'hot', @hit_id_offset = 10, @hit_amount_offset = 100,
@miss_id_offset = 1000, @miss_amount_offset = 2000, @min_id = 2;
execute multi_insert_route using @kind, @hit_id_offset, @hit_amount_offset,
@miss_id_offset, @miss_amount_offset, @min_id;
select * from multi_insert_prepare_db.hit order by id;
select * from multi_insert_prepare_db.miss order by id;

-- Reuse the same handle with a NULL WHEN argument. SQL three-valued logic
-- makes the WHEN not true, so every selected source row must reach ELSE.
delete from multi_insert_prepare_db.hit;
delete from multi_insert_prepare_db.miss;
set @kind = null, @hit_id_offset = 100, @hit_amount_offset = 1000,
@miss_id_offset = 2000, @miss_amount_offset = 3000, @min_id = 1;
execute multi_insert_route using @kind, @hit_id_offset, @hit_amount_offset,
@miss_id_offset, @miss_amount_offset, @min_id;
select * from multi_insert_prepare_db.hit order by id;
select * from multi_insert_prepare_db.miss order by id;

deallocate prepare multi_insert_route;
drop database multi_insert_prepare_db;
65 changes: 65 additions & 0 deletions test/distributed/cases/dml/insert/multi_insert_privilege.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
-- Multi-table INSERT checks SELECT on the source and INSERT on every target
-- before writing any target.
drop database if exists multi_insert_privilege_db;
drop user if exists multi_insert_privilege_user;
drop user if exists multi_insert_no_select_user;
drop role if exists multi_insert_privilege_role;
drop role if exists multi_insert_no_select_role;

create database multi_insert_privilege_db;
create table multi_insert_privilege_db.src (id int primary key, amount int);
create table multi_insert_privilege_db.allowed_target (id int primary key, amount int);
create table multi_insert_privilege_db.denied_target (id int primary key, amount int);
insert into multi_insert_privilege_db.src values (1, 10);

create role multi_insert_privilege_role;
create user multi_insert_privilege_user identified by '111' default role multi_insert_privilege_role;
grant connect on account * to multi_insert_privilege_role;
grant select on table multi_insert_privilege_db.src to multi_insert_privilege_role;
grant insert on table multi_insert_privilege_db.allowed_target to multi_insert_privilege_role;
grant multi_insert_privilege_role to multi_insert_privilege_user;

create role multi_insert_no_select_role;
create user multi_insert_no_select_user identified by '111' default role multi_insert_no_select_role;
grant connect on account * to multi_insert_no_select_role;
grant insert on table multi_insert_privilege_db.allowed_target to multi_insert_no_select_role;
grant insert on table multi_insert_privilege_db.denied_target to multi_insert_no_select_role;
grant multi_insert_no_select_role to multi_insert_no_select_user;

-- INSERT on every target does not permit reading the source. The rejected
-- statement must leave both targets unchanged.
-- @session:id=2&user=sys:multi_insert_no_select_user:multi_insert_no_select_role&password=111
insert all
into multi_insert_privilege_db.allowed_target (id, amount) values (id + 200, amount)
into multi_insert_privilege_db.denied_target (id, amount) values (id + 200, amount)
select id, amount from multi_insert_privilege_db.src;
-- @session
select count(*) from multi_insert_privilege_db.allowed_target;
select count(*) from multi_insert_privilege_db.denied_target;

-- Control: INSERT-only access to the single target is sufficient. The role
-- deliberately has no SELECT privilege on the target itself.
-- @session:id=1&user=sys:multi_insert_privilege_user:multi_insert_privilege_role&password=111
insert all
into multi_insert_privilege_db.allowed_target (id, amount) values (id, amount)
select id, amount from multi_insert_privilege_db.src;
-- @session
select * from multi_insert_privilege_db.allowed_target order by id;

-- The same role has no INSERT on denied_target. The statement must be denied
-- as a whole: allowed_target cannot receive the id + 100 row before the
-- privilege check for denied_target fails.
-- @session:id=1&user=sys:multi_insert_privilege_user:multi_insert_privilege_role&password=111
insert all
into multi_insert_privilege_db.allowed_target (id, amount) values (id + 100, amount)
into multi_insert_privilege_db.denied_target (id, amount) values (id + 100, amount)
select id, amount from multi_insert_privilege_db.src;
-- @session
select count(*) from multi_insert_privilege_db.allowed_target;
select count(*) from multi_insert_privilege_db.denied_target;

drop database multi_insert_privilege_db;
drop user multi_insert_privilege_user;
drop user multi_insert_no_select_user;
drop role multi_insert_privilege_role;
drop role multi_insert_no_select_role;
36 changes: 36 additions & 0 deletions test/distributed/result/dml/insert/multi_insert_prepare.result
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
drop database if exists multi_insert_prepare_db;
create database multi_insert_prepare_db;
create table multi_insert_prepare_db.src (id int primary key, kind varchar(16), amount int);
create table multi_insert_prepare_db.hit (id int primary key, amount int);
create table multi_insert_prepare_db.miss (id int primary key, amount int);
insert into multi_insert_prepare_db.src values (1, 'hot', 10), (2, 'cold', 20), (3, 'hot', 30);
prepare multi_insert_route from '
insert first
when kind = ? then into multi_insert_prepare_db.hit (id, amount) values (id + ?, amount + ?)
else into multi_insert_prepare_db.miss (id, amount) values (id + ?, amount + ?)
select id, kind, amount from multi_insert_prepare_db.src where id >= ?';
set @kind = 'hot', @hit_id_offset = 10, @hit_amount_offset = 100,
@miss_id_offset = 1000, @miss_amount_offset = 2000, @min_id = 2;
execute multi_insert_route using @kind, @hit_id_offset, @hit_amount_offset,
@miss_id_offset, @miss_amount_offset, @min_id;
select * from multi_insert_prepare_db.hit order by id;
➤ id[4,32,0] ¦ amount[4,32,0] 𝄀
13 ¦ 130
select * from multi_insert_prepare_db.miss order by id;
➤ id[4,32,0] ¦ amount[4,32,0] 𝄀
1002 ¦ 2020
delete from multi_insert_prepare_db.hit;
delete from multi_insert_prepare_db.miss;
set @kind = null, @hit_id_offset = 100, @hit_amount_offset = 1000,
@miss_id_offset = 2000, @miss_amount_offset = 3000, @min_id = 1;
execute multi_insert_route using @kind, @hit_id_offset, @hit_amount_offset,
@miss_id_offset, @miss_amount_offset, @min_id;
select * from multi_insert_prepare_db.hit order by id;
➤ id[4,32,0] ¦ amount[4,32,0]
select * from multi_insert_prepare_db.miss order by id;
➤ id[4,32,0] ¦ amount[4,32,0] 𝄀
2001 ¦ 3010 𝄀
2002 ¦ 3020 𝄀
2003 ¦ 3030
deallocate prepare multi_insert_route;
drop database multi_insert_prepare_db;
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
drop database if exists multi_insert_privilege_db;
drop user if exists multi_insert_privilege_user;
drop user if exists multi_insert_no_select_user;
drop role if exists multi_insert_privilege_role;
drop role if exists multi_insert_no_select_role;
create database multi_insert_privilege_db;
create table multi_insert_privilege_db.src (id int primary key, amount int);
create table multi_insert_privilege_db.allowed_target (id int primary key, amount int);
create table multi_insert_privilege_db.denied_target (id int primary key, amount int);
insert into multi_insert_privilege_db.src values (1, 10);
create role multi_insert_privilege_role;
create user multi_insert_privilege_user identified by '111' default role multi_insert_privilege_role;
grant connect on account * to multi_insert_privilege_role;
grant select on table multi_insert_privilege_db.src to multi_insert_privilege_role;
grant insert on table multi_insert_privilege_db.allowed_target to multi_insert_privilege_role;
grant multi_insert_privilege_role to multi_insert_privilege_user;
create role multi_insert_no_select_role;
create user multi_insert_no_select_user identified by '111' default role multi_insert_no_select_role;
grant connect on account * to multi_insert_no_select_role;
grant insert on table multi_insert_privilege_db.allowed_target to multi_insert_no_select_role;
grant insert on table multi_insert_privilege_db.denied_target to multi_insert_no_select_role;
grant multi_insert_no_select_role to multi_insert_no_select_user;
insert all
into multi_insert_privilege_db.allowed_target (id, amount) values (id + 200, amount)
into multi_insert_privilege_db.denied_target (id, amount) values (id + 200, amount)
select id, amount from multi_insert_privilege_db.src;
internal error: do not have privilege to execute the statement
select count(*) from multi_insert_privilege_db.allowed_target;
➤ count(*)[-5,64,0] 𝄀
0
select count(*) from multi_insert_privilege_db.denied_target;
➤ count(*)[-5,64,0] 𝄀
0
insert all
into multi_insert_privilege_db.allowed_target (id, amount) values (id, amount)
select id, amount from multi_insert_privilege_db.src;
select * from multi_insert_privilege_db.allowed_target order by id;
➤ id[4,32,0] ¦ amount[4,32,0] 𝄀
1 ¦ 10
insert all
into multi_insert_privilege_db.allowed_target (id, amount) values (id + 100, amount)
into multi_insert_privilege_db.denied_target (id, amount) values (id + 100, amount)
select id, amount from multi_insert_privilege_db.src;
internal error: do not have privilege to execute the statement
select count(*) from multi_insert_privilege_db.allowed_target;
➤ count(*)[-5,64,0] 𝄀
1
select count(*) from multi_insert_privilege_db.denied_target;
➤ count(*)[-5,64,0] 𝄀
0
drop database multi_insert_privilege_db;
drop user multi_insert_privilege_user;
drop user multi_insert_no_select_user;
drop role multi_insert_privilege_role;
drop role multi_insert_no_select_role;
Loading