Skip to content

Commit eb8ede1

Browse files
branch-4.0: [fix](block-rule) Skip SQL block rules check for EXPLAIN statements #59445 (#59509)
Cherry-picked from #59445 Co-authored-by: Chenjunwei <[email protected]>
1 parent 2f7461e commit eb8ede1

File tree

5 files changed

+381
-55
lines changed

5 files changed

+381
-55
lines changed

fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ExplainCommand.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,8 @@ public void run(ConnectContext ctx, StmtExecutor executor) throws Exception {
104104
}
105105
planner.plan(logicalPlanAdapter, ctx.getSessionVariable().toThrift());
106106
executor.setPlanner(planner);
107-
executor.checkBlockRules();
107+
// Skip SQL block rules check for EXPLAIN statements since they only show
108+
// the execution plan without actually executing the query
108109
if (showPlanProcess) {
109110
executor.handleExplainPlanProcessStmt(planner.getCascadesContext().getPlanProcesses());
110111
} else {

regression-test/suites/external_table_p0/hive/test_external_sql_block_rule.groovy

Lines changed: 80 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -24,81 +24,111 @@ suite("test_external_sql_block_rule", "external_docker,hive,external_docker_hive
2424

2525
String externalEnvIp = context.config.otherConfigs.get("externalEnvIp")
2626
String hms_port = context.config.otherConfigs.get("hive2HmsPort")
27+
String catalog_name = "test_hive2_external_sql_block_rule"
2728

28-
sql """drop catalog if exists test_hive2_external_sql_block_rule """
29+
sql """drop catalog if exists ${catalog_name}"""
2930

30-
sql """CREATE CATALOG test_hive2_external_sql_block_rule PROPERTIES (
31+
sql """CREATE CATALOG ${catalog_name} PROPERTIES (
3132
'type'='hms',
3233
'hive.metastore.uris' = 'thrift://${externalEnvIp}:${hms_port}',
3334
'hadoop.username' = 'hive'
3435
);"""
3536

36-
sql "use test_hive2_external_sql_block_rule.`default`";
37+
sql "use ${catalog_name}.`default`";
3738
qt_sql01 """select * from parquet_partition_table order by l_linenumber,l_orderkey limit 10;"""
3839

39-
sql """drop sql_block_rule if exists external_hive_partition"""
40-
sql """create sql_block_rule external_hive_partition properties("partition_num" = "3", "global" = "false");"""
41-
sql """drop sql_block_rule if exists external_hive_partition2"""
42-
sql """create sql_block_rule external_hive_partition2 properties("tablet_num" = "3", "global" = "false");"""
43-
sql """drop sql_block_rule if exists external_hive_partition3"""
44-
sql """create sql_block_rule external_hive_partition3 properties("cardinality" = "3", "global" = "false");"""
45-
// create 3 users
46-
sql """drop user if exists external_block_user1"""
47-
sql """create user external_block_user1;"""
48-
sql """SET PROPERTY FOR 'external_block_user1' 'sql_block_rules' = 'external_hive_partition';"""
49-
sql """grant all on *.*.* to external_block_user1;"""
50-
//cloud-mode
51-
if (isCloudMode()) {
52-
def clusters = sql " SHOW CLUSTERS; "
53-
assertTrue(!clusters.isEmpty())
54-
def validCluster = clusters[0][0]
55-
sql """GRANT USAGE_PRIV ON CLUSTER `${validCluster}` TO external_block_user1;""";
56-
}
40+
// Clean up existing rules and users
41+
sql """drop sql_block_rule if exists hive_partition_rule"""
42+
sql """drop sql_block_rule if exists hive_split_rule"""
43+
sql """drop sql_block_rule if exists hive_cardinality_rule"""
44+
sql """drop sql_block_rule if exists hive_regex_rule"""
45+
sql """drop user if exists hive_block_user1"""
46+
sql """drop user if exists hive_block_user2"""
47+
sql """drop user if exists hive_block_user3"""
48+
sql """drop user if exists hive_block_user4"""
49+
50+
// Create non-global rules (won't affect other parallel tests)
51+
sql """create sql_block_rule hive_partition_rule properties("partition_num" = "3", "global" = "false");"""
52+
sql """create sql_block_rule hive_split_rule properties("tablet_num" = "3", "global" = "false");"""
53+
sql """create sql_block_rule hive_cardinality_rule properties("cardinality" = "3", "global" = "false");"""
54+
sql """create sql_block_rule hive_regex_rule properties("sql" = "SELECT \\\\*", "global" = "false");"""
55+
56+
// Create test users and bind rules
57+
sql """create user hive_block_user1;"""
58+
sql """SET PROPERTY FOR 'hive_block_user1' 'sql_block_rules' = 'hive_partition_rule';"""
59+
sql """grant all on *.*.* to hive_block_user1;"""
60+
61+
sql """create user hive_block_user2;"""
62+
sql """SET PROPERTY FOR 'hive_block_user2' 'sql_block_rules' = 'hive_split_rule';"""
63+
sql """grant all on *.*.* to hive_block_user2;"""
64+
65+
sql """create user hive_block_user3;"""
66+
sql """SET PROPERTY FOR 'hive_block_user3' 'sql_block_rules' = 'hive_cardinality_rule';"""
67+
sql """grant all on *.*.* to hive_block_user3;"""
68+
69+
sql """create user hive_block_user4;"""
70+
sql """SET PROPERTY FOR 'hive_block_user4' 'sql_block_rules' = 'hive_regex_rule';"""
71+
sql """grant all on *.*.* to hive_block_user4;"""
5772

58-
sql """drop user if exists external_block_user2"""
59-
sql """create user external_block_user2;"""
60-
sql """SET PROPERTY FOR 'external_block_user2' 'sql_block_rules' = 'external_hive_partition2';"""
61-
sql """grant all on *.*.* to external_block_user2;"""
62-
//cloud-mode
73+
// cloud-mode: grant cluster privileges
6374
if (isCloudMode()) {
6475
def clusters = sql " SHOW CLUSTERS; "
6576
assertTrue(!clusters.isEmpty())
6677
def validCluster = clusters[0][0]
67-
sql """GRANT USAGE_PRIV ON CLUSTER `${validCluster}` TO external_block_user2;""";
78+
sql """GRANT USAGE_PRIV ON CLUSTER `${validCluster}` TO hive_block_user1;"""
79+
sql """GRANT USAGE_PRIV ON CLUSTER `${validCluster}` TO hive_block_user2;"""
80+
sql """GRANT USAGE_PRIV ON CLUSTER `${validCluster}` TO hive_block_user3;"""
81+
sql """GRANT USAGE_PRIV ON CLUSTER `${validCluster}` TO hive_block_user4;"""
6882
}
6983

70-
sql """drop user if exists external_block_user3"""
71-
sql """create user external_block_user3;"""
72-
sql """SET PROPERTY FOR 'external_block_user3' 'sql_block_rules' = 'external_hive_partition3';"""
73-
sql """grant all on *.*.* to external_block_user3;"""
74-
//cloud-mode
75-
if (isCloudMode()) {
76-
def clusters = sql " SHOW CLUSTERS; "
77-
assertTrue(!clusters.isEmpty())
78-
def validCluster = clusters[0][0]
79-
sql """GRANT USAGE_PRIV ON CLUSTER `${validCluster}` TO external_block_user3;""";
84+
// Test 1: partition_num rule
85+
connect('hive_block_user1', '', context.config.jdbcUrl) {
86+
test {
87+
sql """select * from ${catalog_name}.`default`.parquet_partition_table order by l_linenumber limit 10;"""
88+
exception """sql hits sql block rule: hive_partition_rule, reach partition_num : 3"""
89+
}
90+
// Test EXPLAIN should not be blocked
91+
sql """explain select * from ${catalog_name}.`default`.parquet_partition_table order by l_linenumber limit 10;"""
8092
}
8193

82-
// login as external_block_user1
83-
def result1 = connect('external_block_user1', '', context.config.jdbcUrl) {
94+
// Test 2: tablet_num (split) rule
95+
connect('hive_block_user2', '', context.config.jdbcUrl) {
8496
test {
85-
sql """select * from test_hive2_external_sql_block_rule.`default`.parquet_partition_table order by l_linenumber limit 10;"""
86-
exception """sql hits sql block rule: external_hive_partition, reach partition_num : 3"""
97+
sql """select * from ${catalog_name}.`default`.parquet_partition_table order by l_linenumber limit 10;"""
98+
exception """sql hits sql block rule: hive_split_rule, reach tablet_num : 3"""
8799
}
100+
// Test EXPLAIN should not be blocked
101+
sql """explain select * from ${catalog_name}.`default`.parquet_partition_table order by l_linenumber limit 10;"""
88102
}
89-
// login as external_block_user2
90-
def result2 = connect('external_block_user2', '', context.config.jdbcUrl) {
103+
104+
// Test 3: cardinality rule
105+
connect('hive_block_user3', '', context.config.jdbcUrl) {
91106
test {
92-
sql """select * from test_hive2_external_sql_block_rule.`default`.parquet_partition_table order by l_linenumber limit 10;"""
93-
exception """sql hits sql block rule: external_hive_partition2, reach tablet_num : 3"""
107+
sql """select * from ${catalog_name}.`default`.parquet_partition_table order by l_linenumber limit 10;"""
108+
exception """sql hits sql block rule: hive_cardinality_rule, reach cardinality : 3"""
94109
}
110+
// Test EXPLAIN should not be blocked
111+
sql """explain select * from ${catalog_name}.`default`.parquet_partition_table order by l_linenumber limit 10;"""
95112
}
96-
// login as external_block_user3
97-
def result3 = connect('external_block_user3', '', context.config.jdbcUrl) {
113+
114+
// Test 4: regex rule
115+
connect('hive_block_user4', '', context.config.jdbcUrl) {
98116
test {
99-
sql """select * from test_hive2_external_sql_block_rule.`default`.parquet_partition_table order by l_linenumber limit 10;"""
100-
exception """sql hits sql block rule: external_hive_partition3, reach cardinality : 3"""
117+
sql """SELECT * FROM ${catalog_name}.`default`.parquet_partition_table limit 10;"""
118+
exception """sql match regex sql block rule: hive_regex_rule"""
101119
}
120+
// Test EXPLAIN should not be blocked by regex rule
121+
sql """EXPLAIN SELECT * FROM ${catalog_name}.`default`.parquet_partition_table limit 10;"""
102122
}
103-
}
104123

124+
// Cleanup
125+
sql """drop user if exists hive_block_user1"""
126+
sql """drop user if exists hive_block_user2"""
127+
sql """drop user if exists hive_block_user3"""
128+
sql """drop user if exists hive_block_user4"""
129+
sql """drop sql_block_rule if exists hive_partition_rule"""
130+
sql """drop sql_block_rule if exists hive_split_rule"""
131+
sql """drop sql_block_rule if exists hive_cardinality_rule"""
132+
sql """drop sql_block_rule if exists hive_regex_rule"""
133+
sql """drop catalog if exists ${catalog_name}"""
134+
}
Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
// Licensed to the Apache Software Foundation (ASF) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The ASF licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
suite("test_iceberg_sql_block_rule", "p0,external,doris,external_docker,external_docker_doris") {
19+
String enabled = context.config.otherConfigs.get("enableIcebergTest")
20+
if (enabled == null || !enabled.equalsIgnoreCase("true")) {
21+
logger.info("disable iceberg test.")
22+
return
23+
}
24+
25+
String rest_port = context.config.otherConfigs.get("iceberg_rest_uri_port")
26+
String minio_port = context.config.otherConfigs.get("iceberg_minio_port")
27+
String externalEnvIp = context.config.otherConfigs.get("externalEnvIp")
28+
String catalog_name = "test_iceberg_sql_block_rule_ctl"
29+
String db_name = "iceberg_sql_block_rule_db"
30+
String table_name = "iceberg_sql_block_rule_tbl"
31+
32+
sql """drop catalog if exists ${catalog_name}"""
33+
sql """
34+
CREATE CATALOG ${catalog_name} PROPERTIES (
35+
'type'='iceberg',
36+
'iceberg.catalog.type'='rest',
37+
'uri' = 'http://${externalEnvIp}:${rest_port}',
38+
"s3.access_key" = "admin",
39+
"s3.secret_key" = "password",
40+
"s3.endpoint" = "http://${externalEnvIp}:${minio_port}",
41+
"s3.region" = "us-east-1"
42+
);"""
43+
44+
sql """switch ${catalog_name}"""
45+
sql """create database if not exists ${db_name}"""
46+
sql """use ${db_name}"""
47+
sql """drop table if exists ${table_name}"""
48+
sql """
49+
create table ${table_name} (
50+
id int,
51+
partition_key int,
52+
val string
53+
) PARTITION BY LIST (partition_key) ()
54+
"""
55+
sql """insert into ${table_name} values (1, 1, 'a')"""
56+
sql """insert into ${table_name} values (2, 2, 'b')"""
57+
sql """insert into ${table_name} values (3, 3, 'c')"""
58+
sql """insert into ${table_name} values (4, 4, 'd')"""
59+
60+
// Clean up existing rules and users
61+
sql """drop sql_block_rule if exists iceberg_partition_rule"""
62+
sql """drop sql_block_rule if exists iceberg_split_rule"""
63+
sql """drop sql_block_rule if exists iceberg_cardinality_rule"""
64+
sql """drop sql_block_rule if exists iceberg_regex_rule"""
65+
sql """drop user if exists iceberg_block_user1"""
66+
sql """drop user if exists iceberg_block_user2"""
67+
sql """drop user if exists iceberg_block_user3"""
68+
sql """drop user if exists iceberg_block_user4"""
69+
70+
// Create non-global rules (won't affect other parallel tests)
71+
sql """create sql_block_rule iceberg_partition_rule properties("partition_num" = "1", "global" = "false");"""
72+
sql """create sql_block_rule iceberg_split_rule properties("tablet_num" = "1", "global" = "false");"""
73+
sql """create sql_block_rule iceberg_cardinality_rule properties("cardinality" = "1", "global" = "false");"""
74+
sql """create sql_block_rule iceberg_regex_rule properties("sql" = "SELECT \\\\*", "global" = "false");"""
75+
76+
// Create test users and bind rules
77+
sql """create user iceberg_block_user1;"""
78+
sql """SET PROPERTY FOR 'iceberg_block_user1' 'sql_block_rules' = 'iceberg_partition_rule';"""
79+
sql """grant all on *.*.* to iceberg_block_user1;"""
80+
81+
sql """create user iceberg_block_user2;"""
82+
sql """SET PROPERTY FOR 'iceberg_block_user2' 'sql_block_rules' = 'iceberg_split_rule';"""
83+
sql """grant all on *.*.* to iceberg_block_user2;"""
84+
85+
sql """create user iceberg_block_user3;"""
86+
sql """SET PROPERTY FOR 'iceberg_block_user3' 'sql_block_rules' = 'iceberg_cardinality_rule';"""
87+
sql """grant all on *.*.* to iceberg_block_user3;"""
88+
89+
sql """create user iceberg_block_user4;"""
90+
sql """SET PROPERTY FOR 'iceberg_block_user4' 'sql_block_rules' = 'iceberg_regex_rule';"""
91+
sql """grant all on *.*.* to iceberg_block_user4;"""
92+
93+
// cloud-mode: grant cluster privileges
94+
if (isCloudMode()) {
95+
def clusters = sql " SHOW CLUSTERS; "
96+
assertTrue(!clusters.isEmpty())
97+
def validCluster = clusters[0][0]
98+
sql """GRANT USAGE_PRIV ON CLUSTER `${validCluster}` TO iceberg_block_user1;"""
99+
sql """GRANT USAGE_PRIV ON CLUSTER `${validCluster}` TO iceberg_block_user2;"""
100+
sql """GRANT USAGE_PRIV ON CLUSTER `${validCluster}` TO iceberg_block_user3;"""
101+
sql """GRANT USAGE_PRIV ON CLUSTER `${validCluster}` TO iceberg_block_user4;"""
102+
}
103+
104+
// Test 1: partition_num rule
105+
connect('iceberg_block_user1', '', context.config.jdbcUrl) {
106+
test {
107+
sql """select * from ${catalog_name}.${db_name}.${table_name}"""
108+
exception """sql hits sql block rule: iceberg_partition_rule, reach partition_num : 1"""
109+
}
110+
// Test EXPLAIN should not be blocked
111+
sql """explain select * from ${catalog_name}.${db_name}.${table_name}"""
112+
}
113+
114+
// Test 2: tablet_num (split) rule
115+
connect('iceberg_block_user2', '', context.config.jdbcUrl) {
116+
test {
117+
sql """select * from ${catalog_name}.${db_name}.${table_name}"""
118+
exception """sql hits sql block rule: iceberg_split_rule, reach tablet_num : 1"""
119+
}
120+
// Test EXPLAIN should not be blocked
121+
sql """explain select * from ${catalog_name}.${db_name}.${table_name}"""
122+
}
123+
124+
// Test 3: cardinality rule
125+
connect('iceberg_block_user3', '', context.config.jdbcUrl) {
126+
test {
127+
sql """select * from ${catalog_name}.${db_name}.${table_name}"""
128+
exception """sql hits sql block rule: iceberg_cardinality_rule, reach cardinality : 1"""
129+
}
130+
// Test EXPLAIN should not be blocked
131+
sql """explain select * from ${catalog_name}.${db_name}.${table_name}"""
132+
}
133+
134+
// Test 4: regex rule
135+
connect('iceberg_block_user4', '', context.config.jdbcUrl) {
136+
test {
137+
sql """SELECT * FROM ${catalog_name}.${db_name}.${table_name}"""
138+
exception """sql match regex sql block rule: iceberg_regex_rule"""
139+
}
140+
// Test EXPLAIN should not be blocked by regex rule
141+
sql """EXPLAIN SELECT * FROM ${catalog_name}.${db_name}.${table_name}"""
142+
}
143+
144+
// Cleanup
145+
sql """drop user if exists iceberg_block_user1"""
146+
sql """drop user if exists iceberg_block_user2"""
147+
sql """drop user if exists iceberg_block_user3"""
148+
sql """drop user if exists iceberg_block_user4"""
149+
sql """drop sql_block_rule if exists iceberg_partition_rule"""
150+
sql """drop sql_block_rule if exists iceberg_split_rule"""
151+
sql """drop sql_block_rule if exists iceberg_cardinality_rule"""
152+
sql """drop sql_block_rule if exists iceberg_regex_rule"""
153+
sql """drop table if exists ${table_name}"""
154+
sql """drop database if exists ${db_name}"""
155+
sql """drop catalog if exists ${catalog_name}"""
156+
}

0 commit comments

Comments
 (0)