🐛 fix(export): 修正带注释的 JOIN 查询结果导出校验

- 导出前缀判断增加前置 SQL 注释清理,避免合法 SELECT 被误判
- ExportQuery 统一复用 looksLikeSelectOrWith 逻辑,消除重复校验分支
- 补充带前置注释的 INNER JOIN 导出回归测试

Fixes #391
This commit is contained in:
Syngnat
2026-04-17 19:01:39 +08:00
parent 8a1a9a8fb8
commit 39f6fbbe1f
2 changed files with 44 additions and 3 deletions

View File

@@ -1700,8 +1700,36 @@ func exportInferObjectName(row map[string]interface{}) string {
return ""
}
func trimLeadingSQLComments(sql string) string {
trimmed := strings.TrimSpace(sql)
for trimmed != "" {
switch {
case strings.HasPrefix(trimmed, "--"):
if newline := strings.IndexByte(trimmed, '\n'); newline >= 0 {
trimmed = strings.TrimSpace(trimmed[newline+1:])
continue
}
return ""
case strings.HasPrefix(trimmed, "#"):
if newline := strings.IndexByte(trimmed, '\n'); newline >= 0 {
trimmed = strings.TrimSpace(trimmed[newline+1:])
continue
}
return ""
case strings.HasPrefix(trimmed, "/*"):
if end := strings.Index(trimmed, "*/"); end >= 0 {
trimmed = strings.TrimSpace(trimmed[end+2:])
continue
}
return ""
}
break
}
return trimmed
}
func looksLikeSelectOrWith(sql string) bool {
trimmed := strings.TrimSpace(strings.TrimSuffix(sql, ";"))
trimmed := trimLeadingSQLComments(strings.TrimSuffix(sql, ";"))
if trimmed == "" {
return false
}
@@ -1947,8 +1975,7 @@ func (a *App) ExportQuery(config connection.ConnectionConfig, dbName string, que
}
query = sanitizeSQLForPgLike(runConfig.Type, query)
lowerQuery := strings.ToLower(strings.TrimSpace(query))
if !(strings.HasPrefix(lowerQuery, "select") || strings.HasPrefix(lowerQuery, "with")) {
if !looksLikeSelectOrWith(query) {
return connection.QueryResult{Success: false, Message: "仅支持 SELECT/WITH 查询导出"}
}

View File

@@ -267,6 +267,20 @@ func TestGetExportQueryTimeout_CustomClickHouseUsesLongerMinimum(t *testing.T) {
}
}
func TestLooksLikeSelectOrWith_AllowsInnerJoinQueryAfterLeadingComments(t *testing.T) {
query := `
-- query result export
/* generated by query editor */
SELECT o.id, c.name
FROM orders o
INNER JOIN customers c ON c.id = o.customer_id
`
if !looksLikeSelectOrWith(query) {
t.Fatalf("带前置注释的 INNER JOIN 查询应允许导出query=%q", query)
}
}
func TestWriteRowsToFile_HTML_EscapeAndStyle(t *testing.T) {
f, err := os.CreateTemp("", "gonavi-export-*.html")
if err != nil {