Skip to content

Commit fb851dc

Browse files
authored
Merge pull request #3109 from huajianxiaowanzi/liulonghui
fix: enable the subquery function to recognize subqueries in the FROM clause
2 parents 328afe4 + 30179b5 commit fb851dc

File tree

3 files changed

+20
-10
lines changed

3 files changed

+20
-10
lines changed

sqle/driver/mysql/rule/ai/util/extractor.go

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -158,12 +158,23 @@ type SubqueryExprExtractor struct {
158158
expr []*ast.SubqueryExpr
159159
}
160160

161-
func (te *SubqueryExprExtractor) Enter(in ast.Node) (node ast.Node, skipChildren bool) {
162-
e, ok := in.(*ast.SubqueryExpr)
163-
if !ok {
161+
func (te *SubqueryExprExtractor) Enter(in ast.Node) (ast.Node, bool) {
162+
// 情况 1: WHERE、IN、EXISTS 中的子查询
163+
if sub, ok := in.(*ast.SubqueryExpr); ok {
164+
te.expr = append(te.expr, sub)
164165
return in, false
165166
}
166-
te.expr = append(te.expr, e)
167+
168+
// 情况 2: FROM 中的子查询(即 SelectStmt 嵌套在 TableSource 中)
169+
if ts, ok := in.(*ast.TableSource); ok {
170+
if sel, ok := ts.Source.(*ast.SelectStmt); ok {
171+
// 包装成 SubqueryExpr 形式以便统一处理
172+
te.expr = append(te.expr, &ast.SubqueryExpr{
173+
Query: sel,
174+
})
175+
}
176+
}
177+
167178
return in, false
168179
}
169180

sqle/driver/mysql/rule_00108_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,15 +72,15 @@ func TestRuleSQLE00108(t *testing.T) {
7272
nil, newTestResult())
7373

7474
// 这个子查询中实际扫描表的子查询 只有1个,因此不算违规
75-
runAIRuleCase(rule, t, "case 15: SELECT语句中使用JOIN的ON条件中嵌套子查询5层, 但是实际扫描表的子查询只有1次,因此不算违规",
75+
runAIRuleCase(rule, t, "case 15: SELECT语句中使用JOIN的ON条件中嵌套子查询5层",
7676
"SELECT st1.id FROM st1 JOIN st_class ON st1.cid in (SELECT cid FROM (SELECT cid FROM (SELECT cid FROM (SELECT cid FROM (SELECT cid FROM st_class WHERE cname = 'class2') AS sub1) AS sub2) AS sub3) AS sub4);",
7777
session.NewAIMockContext().WithSQL("CREATE TABLE st1 (id INT, cid INT); CREATE TABLE st_class (cid INT, cname VARCHAR(50));"),
7878
nil, newTestResult())
7979

80-
runAIRuleCase(rule, t, "case 16: SELECT语句中使用JOIN的ON条件中嵌套子查询6层, 但是实际扫描表的子查询只有2次,因此不算违规",
80+
runAIRuleCase(rule, t, "case 16: SELECT语句中使用JOIN的ON条件中嵌套子查询6层, 违规",
8181
"SELECT st1.id FROM st1 JOIN st_class ON st1.cid in (SELECT cid FROM (SELECT cid FROM (SELECT cid FROM (SELECT cid FROM (SELECT cid FROM st_class WHERE cname in (SELECT cname FROM st_class WHERE cname = 'class2')) AS sub1) AS sub2) AS sub3) AS sub4);",
8282
session.NewAIMockContext().WithSQL("CREATE TABLE st1 (id INT, cid INT); CREATE TABLE st_class (cid INT, cname VARCHAR(50));"),
83-
nil, newTestResult())
83+
nil, newTestResult().addResult(ruleName))
8484

8585
runAIRuleCase(rule, t, "case 17: SELECT语句中 查询列中, 嵌套子查询2层",
8686
"SELECT 1, st1.id, (SELECT (SELECT id0 FROM exist_db.exist_tb_1 WHERE id1 = 'value') xx2 FROM exist_db.exist_tb_1 WHERE id1 = 'value') xxx FROM st1;",

sqle/driver/mysql/rule_00109_test.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,12 +71,11 @@ func TestRuleSQLE00109(t *testing.T) {
7171
WithSQL("CREATE TABLE orders_archive (id INT, amount DECIMAL(10,2));"),
7272
nil, newTestResult())
7373

74-
// 特殊情况:解析器好像对from中嵌套的子查询 ,会被视作为属于非实际路由的子查询,因此没有累计(相当于只是个外壳嵌套而已,因此这里可以视作为不违规
75-
runAIRuleCase(rule, t, "case 9: SELECT ... UNION ALL SELECT语句中的子查询使用LIMIT,但是这里子查询其实是可以直接push到外层的,可以不算做子查询",
74+
runAIRuleCase(rule, t, "case 9: SELECT ... UNION ALL SELECT语句中的子查询使用LIMIT",
7675
"SELECT * FROM (SELECT id FROM products LIMIT 1) AS sub UNION ALL SELECT * FROM products;",
7776
session.NewAIMockContext().
7877
WithSQL("CREATE TABLE products (id INT, name VARCHAR(100));"),
79-
nil, newTestResult())
78+
nil, newTestResult().addResult(ruleName))
8079

8180
runAIRuleCase(rule, t, "case 10: SELECT ... UNION ALL SELECT语句中的子查询不使用LIMIT",
8281
"SELECT * FROM (SELECT id FROM products) AS sub UNION ALL SELECT * FROM products;",

0 commit comments

Comments
 (0)