-
-
Notifications
You must be signed in to change notification settings - Fork 141
Expand file tree
/
Copy pathSQLImportPlugin.swift
More file actions
114 lines (95 loc) · 3.41 KB
/
SQLImportPlugin.swift
File metadata and controls
114 lines (95 loc) · 3.41 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
//
// SQLImportPlugin.swift
// SQLImportPlugin
//
import Foundation
import SwiftUI
import TableProPluginKit
@Observable
final class SQLImportPlugin: ImportFormatPlugin {
static let pluginName = "SQL Import"
static let pluginVersion = "1.0.0"
static let pluginDescription = "Import data from SQL files"
static let formatId = "sql"
static let formatDisplayName = "SQL"
static let acceptedFileExtensions = ["sql", "gz"]
static let iconName = "doc.text"
var options = SQLImportOptions()
required init() {}
func optionsView() -> AnyView? {
AnyView(SQLImportOptionsView(plugin: self))
}
func performImport(
source: any PluginImportSource,
sink: any PluginImportDataSink,
progress: PluginImportProgress
) async throws -> PluginImportResult {
let startTime = Date()
var executedCount = 0
// Estimate total from file size (~500 bytes per statement)
let fileSizeBytes = source.fileSizeBytes()
let estimatedTotal = max(1, Int(fileSizeBytes / 500))
progress.setEstimatedTotal(estimatedTotal)
do {
// Disable FK checks if enabled
if options.disableForeignKeyChecks {
try await sink.disableForeignKeyChecks()
}
// Begin transaction if enabled
if options.wrapInTransaction {
try await sink.beginTransaction()
}
// Stream and execute statements
let stream = try await source.statements()
for try await (statement, lineNumber) in stream {
try progress.checkCancellation()
do {
try await sink.execute(statement: statement)
executedCount += 1
progress.incrementStatement()
} catch {
throw PluginImportError.statementFailed(
statement: statement,
line: lineNumber,
underlyingError: error
)
}
}
// Commit transaction
if options.wrapInTransaction {
try await sink.commitTransaction()
}
// Re-enable FK checks
if options.disableForeignKeyChecks {
try await sink.enableForeignKeyChecks()
}
} catch {
let importError = error
// Rollback on error
if options.wrapInTransaction {
do {
try await sink.rollbackTransaction()
} catch {
throw PluginImportError.rollbackFailed(underlyingError: importError)
}
}
// Re-enable FK checks (best-effort)
if options.disableForeignKeyChecks {
try? await sink.enableForeignKeyChecks()
}
// Re-throw cancellation as-is, wrap others
if importError is PluginImportCancellationError {
throw importError
}
if importError is PluginImportError {
throw importError
}
throw PluginImportError.importFailed(importError.localizedDescription)
}
progress.finalize()
return PluginImportResult(
executedStatements: executedCount,
executionTime: Date().timeIntervalSince(startTime)
)
}
}