🐛 fix(external-sql): 修复外部 SQL 文件丢失后标签无法关闭

- 后端读取 SQL 文件失败时返回 file_not_found 结构化错误码
- 前端识别文件被删除或移动的场景,允许用户确认关闭标签
- 保留权限、网络盘异常等非缺失错误的关闭拦截,避免误丢草稿
- 补充前后端测试覆盖缺失文件识别与标签关闭提示
Close #566
This commit is contained in:
Syngnat
2026-06-16 08:48:43 +08:00
parent c70eb7157f
commit 0816702084
6 changed files with 175 additions and 52 deletions

View File

@@ -30,6 +30,8 @@ import (
const minExportQueryTimeout = 5 * time.Minute
const minClickHouseExportQueryTimeout = 2 * time.Hour
const maxSQLFileSizeBytes int64 = 50 * 1024 * 1024
const sqlFileErrorCodeNotFound = "file_not_found"
const sqlFileBatchMaxStatements = 1000
const sqlFileBatchMaxBytes = 4 * 1024 * 1024
const sqlFileProgressStatementInterval = 100
@@ -321,7 +323,11 @@ func readSQLFileByPath(filePath string) connection.QueryResult {
fi, err := os.Stat(selection)
if err != nil {
return connection.QueryResult{Success: false, Message: fmt.Sprintf("无法读取文件信息: %v", err)}
data := map[string]interface{}{"filePath": selection}
if os.IsNotExist(err) {
data["errorCode"] = sqlFileErrorCodeNotFound
}
return connection.QueryResult{Success: false, Message: fmt.Sprintf("无法读取文件信息: %v", err), Data: data}
}
if fi.IsDir() {
return connection.QueryResult{Success: false, Message: "所选路径不是 SQL 文件"}

View File

@@ -302,6 +302,26 @@ func TestReadSQLFileByPathReturnsLargeFileMetadata(t *testing.T) {
}
}
func TestReadSQLFileByPathMarksMissingFile(t *testing.T) {
filePath := filepath.Join(t.TempDir(), "missing.sql")
result := readSQLFileByPath(filePath)
if result.Success {
t.Fatalf("expected missing sql file read to fail, got %#v", result)
}
data, ok := result.Data.(map[string]interface{})
if !ok {
t.Fatalf("expected error metadata map, got %#v", result.Data)
}
if data["errorCode"] != sqlFileErrorCodeNotFound {
t.Fatalf("expected file_not_found error code, got %#v", data["errorCode"])
}
if data["filePath"] != filePath {
t.Fatalf("expected filePath %q, got %#v", filePath, data["filePath"])
}
}
func TestReadSQLFileWithMetadataByPathReturnsSmallFileContentAndPath(t *testing.T) {
filePath := filepath.Join(t.TempDir(), "report.sql")
if err := os.WriteFile(filePath, []byte("select 1;"), 0o644); err != nil {