diff --git a/PHASE13-NOTES.md b/PHASE13-NOTES.md
new file mode 100644
index 0000000..7147553
--- /dev/null
+++ b/PHASE13-NOTES.md
@@ -0,0 +1,10 @@
+# Phase 13 — Administration enhancements
+
+- Added Server Error Log view (reads `performance_schema.error_log`, available on supported MySQL versions and with appropriate privileges).
+- Added filter/search for administration result tables.
+- Added optional 5-second auto-refresh of administration data.
+- Added account selection and read-only `SHOW GRANTS` inspector to Users and Privileges.
+- Existing backup/restore functionality preserved.
+- No user account or server mutations are performed by these features.
+
+**Validation:** Source-level checks and ZIP integrity only; full macOS Xcode build and live-server tests are still required.
diff --git a/WorkbenchReplacement/MainView.swift b/WorkbenchReplacement/MainView.swift
index 8db8e29..e599aae 100644
--- a/WorkbenchReplacement/MainView.swift
+++ b/WorkbenchReplacement/MainView.swift
@@ -282,7 +282,8 @@ struct MainView: View {
.serverStatus,
.clientConnections,
.users,
- .variables
+ .variables,
+ .serverLogs
]
)
@@ -1272,11 +1273,13 @@ enum WorkbenchAdminPage: String, CaseIterable, Identifiable {
case dashboard = "Dashboard"
case performanceReports = "Performance Reports"
case performanceSchema = "Performance Schema Setup"
+ case serverLogs = "Server Error Log"
var id: String { rawValue }
var icon: String {
switch self {
+ case .serverLogs: return "text.alignleft"
case .serverStatus: return "server.rack"
case .clientConnections: return "person.2"
case .users: return "person.crop.circle.badge.checkmark"
@@ -1289,6 +1292,8 @@ enum WorkbenchAdminPage: String, CaseIterable, Identifiable {
var statement: String {
switch self {
+ case .serverLogs:
+ return "SELECT LOGGED, PRIO, ERROR_CODE, SUBSYSTEM, DATA FROM performance_schema.error_log ORDER BY LOGGED DESC LIMIT 500"
case .serverStatus:
return """
SHOW GLOBAL STATUS WHERE Variable_name IN (
@@ -1359,6 +1364,19 @@ struct WorkbenchAdministrationView: View {
@State private var loading = false
@State private var errorMessage: String?
@State private var lastUpdated: Date?
+ @State private var searchText = ""
+ @State private var autoRefresh = false
+ @State private var selectedAccount: String? = nil
+ @State private var grants: [String] = []
+ @State private var grantsError: String? = nil
+ @State private var showingGrants = false
+
+ private var filteredRows: [[String]] {
+ guard !searchText.isEmpty else { return result.rows }
+ return result.rows.filter { row in
+ row.contains { $0.localizedCaseInsensitiveContains(searchText) }
+ }
+ }
var body: some View {
VStack(spacing: 0) {
@@ -1399,6 +1417,31 @@ struct WorkbenchAdministrationView: View {
resultContent
}
+ if page == .users && !result.rows.isEmpty {
+ HStack {
+ Picker("Account", selection: $selectedAccount) {
+ Text("Select account").tag(String?.none)
+ ForEach(result.rows.indices, id: \.self) { i in
+ let row = result.rows[i]
+ if row.count >= 2 {
+ Text("\(row[0])@\(row[1])")
+ .tag(Optional("\(row[0])\u{001f}\(row[1])"))
+ }
+ }
+ }
+ .frame(maxWidth: 320)
+ Button("Show Grants") {
+ Task { await showGrants() }
+ }
+ .disabled(selectedAccount == nil)
+ Spacer()
+ Text("Read-only account inspection")
+ .foregroundStyle(.secondary)
+ }
+ .padding(.horizontal, 16)
+ .padding(.vertical, 8)
+ }
+
Divider()
footer
@@ -1407,6 +1450,32 @@ struct WorkbenchAdministrationView: View {
.task(id: "\(page.id)-\(profile?.id.uuidString ?? "")") {
await refresh()
}
+ .task(id: "\(page.id)-\(autoRefresh)-\(profile?.id.uuidString ?? "")") {
+ while autoRefresh && !Task.isCancelled {
+ try? await Task.sleep(for: .seconds(5))
+ if Task.isCancelled || !autoRefresh { break }
+ await refresh()
+ }
+ }
+ .sheet(isPresented: $showingGrants) {
+ VStack(alignment: .leading, spacing: 12) {
+ Text("Grants: \(selectedAccount ?? "")")
+ .font(.title2.bold())
+ if let grantsError {
+ Text(grantsError).foregroundStyle(.red)
+ } else {
+ ScrollView {
+ Text(grants.joined(separator: "\n\n"))
+ .font(.system(.body, design: .monospaced))
+ .textSelection(.enabled)
+ .frame(maxWidth: .infinity, alignment: .leading)
+ }
+ }
+ Button("Close") { showingGrants = false }
+ }
+ .padding(20)
+ .frame(minWidth: 580, minHeight: 300)
+ }
}
private var header: some View {
@@ -1427,6 +1496,16 @@ struct WorkbenchAdministrationView: View {
Spacer()
+ if page != .dashboard && page != .serverStatus {
+ TextField("Filter results", text: $searchText)
+ .textFieldStyle(.roundedBorder)
+ .frame(width: 175)
+ }
+
+ Toggle("Auto-refresh", isOn: $autoRefresh)
+ .toggleStyle(.checkbox)
+ .help("Refresh every five seconds")
+
Button {
Task { await refresh() }
} label: {
@@ -1499,7 +1578,7 @@ struct WorkbenchAdministrationView: View {
} else {
NativeResultGrid(
columns: result.columns,
- rows: result.rows
+ rows: filteredRows
)
.frame(
maxWidth: .infinity,
@@ -1528,6 +1607,29 @@ struct WorkbenchAdministrationView: View {
.frame(height: 30)
}
+ @MainActor
+ private func showGrants() async {
+ guard let profile, let selectedAccount else { return }
+ let components = selectedAccount.split(separator: "\u{001f}", omittingEmptySubsequences: false)
+ guard components.count == 2 else { return }
+ func quoted(_ text: String) -> String {
+ "'" + text.replacingOccurrences(of: "'", with: "''") + "'"
+ }
+ grants = []
+ grantsError = nil
+ showingGrants = true
+ do {
+ let sql = "SHOW GRANTS FOR \(quoted(String(components[0])))@\(quoted(String(components[1])))"
+ let response = try await NativeMySQLRunner.run(
+ profile: profile, database: "",
+ password: PasswordStore.read(profile.id), sql: sql
+ )
+ grants = response.rows.compactMap { $0.first }
+ } catch {
+ grantsError = error.localizedDescription
+ }
+ }
+
@MainActor
private func refresh() async {
guard let profile else {
diff --git a/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/MainView.o b/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/MainView.o
index 0e3df09..2ff5cca 100644
Binary files a/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/MainView.o and b/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/MainView.o differ
diff --git a/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/MainView.stringsdata b/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/MainView.stringsdata
index 34f30c6..8a0a862 100644
--- a/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/MainView.stringsdata
+++ b/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/MainView.stringsdata
@@ -55,7 +55,7 @@
"key": "Set as Default Schema",
"location": {
"startingColumn": 24,
- "startingLine": 381
+ "startingLine": 382
}
},
{
@@ -63,7 +63,7 @@
"key": "Refresh Tables",
"location": {
"startingColumn": 24,
- "startingLine": 385
+ "startingLine": 386
}
},
{
@@ -71,7 +71,7 @@
"key": "Load Tables",
"location": {
"startingColumn": 28,
- "startingLine": 455
+ "startingLine": 456
}
},
{
@@ -79,7 +79,7 @@
"key": "Tables",
"location": {
"startingColumn": 22,
- "startingLine": 428
+ "startingLine": 429
}
},
{
@@ -87,7 +87,7 @@
"key": "Select First 100 Rows",
"location": {
"startingColumn": 20,
- "startingLine": 511
+ "startingLine": 512
}
},
{
@@ -95,7 +95,7 @@
"key": "New Query Tab",
"location": {
"startingColumn": 19,
- "startingLine": 632
+ "startingLine": 633
}
},
{
@@ -103,7 +103,7 @@
"key": "Default Schema:",
"location": {
"startingColumn": 18,
- "startingLine": 657
+ "startingLine": 658
}
},
{
@@ -111,7 +111,7 @@
"key": "SQL Editor",
"location": {
"startingColumn": 18,
- "startingLine": 667
+ "startingLine": 668
}
},
{
@@ -119,7 +119,7 @@
"key": "Execute SQL",
"location": {
"startingColumn": 19,
- "startingLine": 645
+ "startingLine": 646
}
},
{
@@ -127,7 +127,7 @@
"key": "Format SQL",
"location": {
"startingColumn": 19,
- "startingLine": 652
+ "startingLine": 653
}
},
{
@@ -135,7 +135,7 @@
"key": "%lld",
"location": {
"startingColumn": 26,
- "startingLine": 707
+ "startingLine": 708
}
},
{
@@ -143,7 +143,7 @@
"key": "Result Grid",
"location": {
"startingColumn": 22,
- "startingLine": 739
+ "startingLine": 740
}
},
{
@@ -151,7 +151,7 @@
"key": "No query results",
"location": {
"startingColumn": 26,
- "startingLine": 757
+ "startingLine": 758
}
},
{
@@ -159,7 +159,7 @@
"key": "Action Output",
"location": {
"startingColumn": 22,
- "startingLine": 779
+ "startingLine": 780
}
},
{
@@ -167,7 +167,7 @@
"key": "UTF-8",
"location": {
"startingColumn": 18,
- "startingLine": 854
+ "startingLine": 855
}
},
{
@@ -175,7 +175,7 @@
"key": "Connection Settings",
"location": {
"startingColumn": 18,
- "startingLine": 1029
+ "startingLine": 1030
}
},
{
@@ -183,7 +183,7 @@
"key": "Connection Name",
"location": {
"startingColumn": 21,
- "startingLine": 1034
+ "startingLine": 1035
}
},
{
@@ -191,7 +191,7 @@
"key": "Hostname",
"location": {
"startingColumn": 21,
- "startingLine": 1039
+ "startingLine": 1040
}
},
{
@@ -199,7 +199,7 @@
"key": "Port",
"location": {
"startingColumn": 21,
- "startingLine": 1044
+ "startingLine": 1045
}
},
{
@@ -207,7 +207,7 @@
"key": "Username",
"location": {
"startingColumn": 21,
- "startingLine": 1050
+ "startingLine": 1051
}
},
{
@@ -215,7 +215,7 @@
"key": "Password (macOS Keychain)",
"location": {
"startingColumn": 21,
- "startingLine": 1055
+ "startingLine": 1056
}
},
{
@@ -223,7 +223,7 @@
"key": "Default Schema",
"location": {
"startingColumn": 21,
- "startingLine": 1060
+ "startingLine": 1061
}
},
{
@@ -231,7 +231,7 @@
"key": "Cancel",
"location": {
"startingColumn": 24,
- "startingLine": 1068
+ "startingLine": 1069
}
},
{
@@ -239,7 +239,7 @@
"key": "Save",
"location": {
"startingColumn": 24,
- "startingLine": 1072
+ "startingLine": 1073
}
},
{
@@ -247,7 +247,7 @@
"key": "The server did not return any columns.",
"location": {
"startingColumn": 25,
- "startingLine": 1394
+ "startingLine": 1412
}
},
{
@@ -255,7 +255,7 @@
"key": "Loading %@…",
"location": {
"startingColumn": 30,
- "startingLine": 1372
+ "startingLine": 1390
}
},
{
@@ -263,7 +263,7 @@
"key": "No Data",
"location": {
"startingColumn": 21,
- "startingLine": 1391
+ "startingLine": 1409
}
},
{
@@ -271,7 +271,7 @@
"key": "Unable to Load %@",
"location": {
"startingColumn": 25,
- "startingLine": 1378
+ "startingLine": 1396
}
},
{
@@ -279,295 +279,55 @@
"key": "Retry",
"location": {
"startingColumn": 28,
- "startingLine": 1384
+ "startingLine": 1402
}
},
{
"comment": "",
- "key": "Refresh",
+ "key": "Read-only account inspection",
"location": {
- "startingColumn": 23,
+ "startingColumn": 26,
+ "startingLine": 1438
+ }
+ },
+ {
+ "comment": "",
+ "key": "Account",
+ "location": {
+ "startingColumn": 28,
+ "startingLine": 1422
+ }
+ },
+ {
+ "comment": "",
+ "key": "Show Grants",
+ "location": {
+ "startingColumn": 28,
"startingLine": 1433
}
},
{
"comment": "",
- "key": "SQL Editor",
- "location": {
- "startingColumn": 23,
- "startingLine": 1440
- }
- },
- {
- "comment": "",
- "key": "Not loaded",
- "location": {
- "startingColumn": 22,
- "startingLine": 1518
- }
- },
- {
- "comment": "",
- "key": "Updated %@",
- "location": {
- "startingColumn": 21,
- "startingLine": 1515
- }
- },
- {
- "comment": "",
- "key": "%lld rows",
- "location": {
- "startingColumn": 18,
- "startingLine": 1523
- }
- },
- {
- "comment": "",
- "key": "Import SQL into %@?",
- "location": {
- "startingColumn": 13,
- "startingLine": 1789
- }
- },
- {
- "comment": "",
- "key": "Operation",
- "location": {
- "startingColumn": 20,
- "startingLine": 1603
- }
- },
- {
- "comment": "",
- "key": "Data Export",
- "location": {
- "startingColumn": 22,
- "startingLine": 1604
- }
- },
- {
- "comment": "",
- "key": "Data Import / Restore",
- "location": {
- "startingColumn": 22,
- "startingLine": 1605
- }
- },
- {
- "comment": "",
- "key": "MySQL Connection",
- "location": {
- "startingColumn": 26,
- "startingLine": 1612
- }
- },
- {
- "comment": "",
- "key": "Export Options",
+ "key": "Select account",
"location": {
"startingColumn": 30,
- "startingLine": 1636
+ "startingLine": 1423
}
},
{
"comment": "",
- "key": "Import Options",
- "location": {
- "startingColumn": 30,
- "startingLine": 1692
- }
- },
- {
- "comment": "",
- "key": "Progress",
- "location": {
- "startingColumn": 26,
- "startingLine": 1704
- }
- },
- {
- "comment": "",
- "key": "Connection",
- "location": {
- "startingColumn": 36,
- "startingLine": 1614
- }
- },
- {
- "comment": "",
- "key": "Database",
- "location": {
- "startingColumn": 28,
- "startingLine": 1618
- }
- },
- {
- "comment": "",
- "key": "Select Database",
- "location": {
- "startingColumn": 30,
- "startingLine": 1619
- }
- },
- {
- "comment": "",
- "key": "Refresh Databases",
- "location": {
- "startingColumn": 32,
- "startingLine": 1627
- }
- },
- {
- "comment": "",
- "key": "No tables found. Select a database or refresh the list.",
- "location": {
- "startingColumn": 34,
- "startingLine": 1658
- }
- },
- {
- "comment": "",
- "key": "InnoDB data is exported using a consistent snapshot and a single streamed query per table. Tables without unique indexes are supported.",
- "location": {
- "startingColumn": 30,
- "startingLine": 1687
- }
- },
- {
- "comment": "",
- "key": "Table structure",
- "location": {
- "startingColumn": 32,
- "startingLine": 1638
- }
- },
- {
- "comment": "",
- "key": "Table data",
- "location": {
- "startingColumn": 32,
- "startingLine": 1639
- }
- },
- {
- "comment": "",
- "key": "Add DROP TABLE IF EXISTS",
- "location": {
- "startingColumn": 32,
- "startingLine": 1640
- }
- },
- {
- "comment": "",
- "key": "Include views (definitions)",
- "location": {
- "startingColumn": 32,
- "startingLine": 1642
- }
- },
- {
- "comment": "",
- "key": "Include triggers",
- "location": {
- "startingColumn": 32,
- "startingLine": 1644
- }
- },
- {
- "comment": "",
- "key": "Include stored procedures and functions",
- "location": {
- "startingColumn": 32,
- "startingLine": 1646
- }
- },
- {
- "comment": "",
- "key": "Loading tables…",
- "location": {
- "startingColumn": 57,
- "startingLine": 1656
- }
- },
- {
- "comment": "",
- "key": "Tables (%lld selected)",
- "location": {
- "startingColumn": 34,
- "startingLine": 1649
- }
- },
- {
- "comment": "",
- "key": "All",
- "location": {
- "startingColumn": 36,
- "startingLine": 1651
- }
- },
- {
- "comment": "",
- "key": "None",
- "location": {
- "startingColumn": 36,
- "startingLine": 1652
- }
- },
- {
- "comment": "",
- "key": "Refresh",
- "location": {
- "startingColumn": 36,
- "startingLine": 1653
- }
- },
- {
- "comment": "",
- "key": "Views (%lld selected)",
+ "key": "%@@%@",
"location": {
"startingColumn": 38,
- "startingLine": 1672
+ "startingLine": 1427
}
},
{
"comment": "",
- "key": "All",
+ "key": "Grants: %@",
"location": {
- "startingColumn": 40,
- "startingLine": 1674
- }
- },
- {
- "comment": "",
- "key": "None",
- "location": {
- "startingColumn": 40,
- "startingLine": 1675
- }
- },
- {
- "comment": "",
- "key": "Import SQL statements into the selected database.",
- "location": {
- "startingColumn": 30,
- "startingLine": 1694
- }
- },
- {
- "comment": "",
- "key": "Supports MySQL DELIMITER directives, triggers and stored routines. Import is not transactional; use a verified backup before restoring.",
- "location": {
- "startingColumn": 30,
- "startingLine": 1697
- }
- },
- {
- "comment": "",
- "key": "Current table: %@ / %@ rows · Total exported: %@",
- "location": {
- "startingColumn": 30,
- "startingLine": 1715
+ "startingColumn": 22,
+ "startingLine": 1462
}
},
{
@@ -575,7 +335,327 @@
"key": "Close",
"location": {
"startingColumn": 24,
- "startingLine": 1729
+ "startingLine": 1474
+ }
+ },
+ {
+ "comment": "",
+ "key": "Filter results",
+ "location": {
+ "startingColumn": 27,
+ "startingLine": 1500
+ }
+ },
+ {
+ "comment": "",
+ "key": "Auto-refresh",
+ "location": {
+ "startingColumn": 20,
+ "startingLine": 1505
+ }
+ },
+ {
+ "comment": "",
+ "key": "Refresh every five seconds",
+ "location": {
+ "startingColumn": 23,
+ "startingLine": 1507
+ }
+ },
+ {
+ "comment": "",
+ "key": "Refresh",
+ "location": {
+ "startingColumn": 23,
+ "startingLine": 1512
+ }
+ },
+ {
+ "comment": "",
+ "key": "SQL Editor",
+ "location": {
+ "startingColumn": 23,
+ "startingLine": 1519
+ }
+ },
+ {
+ "comment": "",
+ "key": "Not loaded",
+ "location": {
+ "startingColumn": 22,
+ "startingLine": 1597
+ }
+ },
+ {
+ "comment": "",
+ "key": "Updated %@",
+ "location": {
+ "startingColumn": 21,
+ "startingLine": 1594
+ }
+ },
+ {
+ "comment": "",
+ "key": "%lld rows",
+ "location": {
+ "startingColumn": 18,
+ "startingLine": 1602
+ }
+ },
+ {
+ "comment": "",
+ "key": "Import SQL into %@?",
+ "location": {
+ "startingColumn": 13,
+ "startingLine": 1904
+ }
+ },
+ {
+ "comment": "",
+ "key": "Operation",
+ "location": {
+ "startingColumn": 20,
+ "startingLine": 1707
+ }
+ },
+ {
+ "comment": "",
+ "key": "Data Export",
+ "location": {
+ "startingColumn": 22,
+ "startingLine": 1708
+ }
+ },
+ {
+ "comment": "",
+ "key": "Data Import / Restore",
+ "location": {
+ "startingColumn": 22,
+ "startingLine": 1709
+ }
+ },
+ {
+ "comment": "",
+ "key": "MySQL Connection",
+ "location": {
+ "startingColumn": 26,
+ "startingLine": 1716
+ }
+ },
+ {
+ "comment": "",
+ "key": "Export Options",
+ "location": {
+ "startingColumn": 30,
+ "startingLine": 1740
+ }
+ },
+ {
+ "comment": "",
+ "key": "Import Options",
+ "location": {
+ "startingColumn": 30,
+ "startingLine": 1796
+ }
+ },
+ {
+ "comment": "",
+ "key": "Progress",
+ "location": {
+ "startingColumn": 26,
+ "startingLine": 1808
+ }
+ },
+ {
+ "comment": "",
+ "key": "Connection",
+ "location": {
+ "startingColumn": 36,
+ "startingLine": 1718
+ }
+ },
+ {
+ "comment": "",
+ "key": "Database",
+ "location": {
+ "startingColumn": 28,
+ "startingLine": 1722
+ }
+ },
+ {
+ "comment": "",
+ "key": "Select Database",
+ "location": {
+ "startingColumn": 30,
+ "startingLine": 1723
+ }
+ },
+ {
+ "comment": "",
+ "key": "Refresh Databases",
+ "location": {
+ "startingColumn": 32,
+ "startingLine": 1731
+ }
+ },
+ {
+ "comment": "",
+ "key": "No tables found. Select a database or refresh the list.",
+ "location": {
+ "startingColumn": 34,
+ "startingLine": 1762
+ }
+ },
+ {
+ "comment": "",
+ "key": "InnoDB data is exported using a consistent snapshot and a single streamed query per table. Tables without unique indexes are supported.",
+ "location": {
+ "startingColumn": 30,
+ "startingLine": 1791
+ }
+ },
+ {
+ "comment": "",
+ "key": "Table structure",
+ "location": {
+ "startingColumn": 32,
+ "startingLine": 1742
+ }
+ },
+ {
+ "comment": "",
+ "key": "Table data",
+ "location": {
+ "startingColumn": 32,
+ "startingLine": 1743
+ }
+ },
+ {
+ "comment": "",
+ "key": "Add DROP TABLE IF EXISTS",
+ "location": {
+ "startingColumn": 32,
+ "startingLine": 1744
+ }
+ },
+ {
+ "comment": "",
+ "key": "Include views (definitions)",
+ "location": {
+ "startingColumn": 32,
+ "startingLine": 1746
+ }
+ },
+ {
+ "comment": "",
+ "key": "Include triggers",
+ "location": {
+ "startingColumn": 32,
+ "startingLine": 1748
+ }
+ },
+ {
+ "comment": "",
+ "key": "Include stored procedures and functions",
+ "location": {
+ "startingColumn": 32,
+ "startingLine": 1750
+ }
+ },
+ {
+ "comment": "",
+ "key": "Loading tables…",
+ "location": {
+ "startingColumn": 57,
+ "startingLine": 1760
+ }
+ },
+ {
+ "comment": "",
+ "key": "Tables (%lld selected)",
+ "location": {
+ "startingColumn": 34,
+ "startingLine": 1753
+ }
+ },
+ {
+ "comment": "",
+ "key": "All",
+ "location": {
+ "startingColumn": 36,
+ "startingLine": 1755
+ }
+ },
+ {
+ "comment": "",
+ "key": "None",
+ "location": {
+ "startingColumn": 36,
+ "startingLine": 1756
+ }
+ },
+ {
+ "comment": "",
+ "key": "Refresh",
+ "location": {
+ "startingColumn": 36,
+ "startingLine": 1757
+ }
+ },
+ {
+ "comment": "",
+ "key": "Views (%lld selected)",
+ "location": {
+ "startingColumn": 38,
+ "startingLine": 1776
+ }
+ },
+ {
+ "comment": "",
+ "key": "All",
+ "location": {
+ "startingColumn": 40,
+ "startingLine": 1778
+ }
+ },
+ {
+ "comment": "",
+ "key": "None",
+ "location": {
+ "startingColumn": 40,
+ "startingLine": 1779
+ }
+ },
+ {
+ "comment": "",
+ "key": "Import SQL statements into the selected database.",
+ "location": {
+ "startingColumn": 30,
+ "startingLine": 1798
+ }
+ },
+ {
+ "comment": "",
+ "key": "Supports MySQL DELIMITER directives, triggers and stored routines. Import is not transactional; use a verified backup before restoring.",
+ "location": {
+ "startingColumn": 30,
+ "startingLine": 1801
+ }
+ },
+ {
+ "comment": "",
+ "key": "Current table: %@ / %@ rows · Total exported: %@",
+ "location": {
+ "startingColumn": 30,
+ "startingLine": 1825
+ }
+ },
+ {
+ "comment": "",
+ "key": "Close",
+ "location": {
+ "startingColumn": 24,
+ "startingLine": 1839
}
},
{
@@ -583,7 +663,7 @@
"key": "Verify Backup…",
"location": {
"startingColumn": 28,
- "startingLine": 1737
+ "startingLine": 1847
}
},
{
@@ -591,7 +671,23 @@
"key": "Verify an SQL file against its SHA-256 checksum sidecar",
"location": {
"startingColumn": 27,
- "startingLine": 1740
+ "startingLine": 1850
+ }
+ },
+ {
+ "comment": "",
+ "key": "Verify Restored Database…",
+ "location": {
+ "startingColumn": 28,
+ "startingLine": 1851
+ }
+ },
+ {
+ "comment": "",
+ "key": "Compare restored table row counts and object names with the export manifest",
+ "location": {
+ "startingColumn": 27,
+ "startingLine": 1855
}
},
{
@@ -599,7 +695,7 @@
"key": "Cancel",
"location": {
"startingColumn": 28,
- "startingLine": 1744
+ "startingLine": 1859
}
},
{
@@ -607,7 +703,7 @@
"key": "Export SQL…",
"location": {
"startingColumn": 31,
- "startingLine": 1751
+ "startingLine": 1866
}
},
{
@@ -615,7 +711,7 @@
"key": "Import SQL…",
"location": {
"startingColumn": 31,
- "startingLine": 1752
+ "startingLine": 1867
}
},
{
@@ -623,7 +719,7 @@
"key": "Import SQL",
"location": {
"startingColumn": 20,
- "startingLine": 1792
+ "startingLine": 1907
}
},
{
@@ -631,7 +727,7 @@
"key": "Cancel",
"location": {
"startingColumn": 20,
- "startingLine": 1800
+ "startingLine": 1915
}
},
{
@@ -639,7 +735,7 @@
"key": "SQL files can modify or delete existing database objects and data. Ensure you have a backup before continuing.",
"location": {
"startingColumn": 17,
- "startingLine": 1805
+ "startingLine": 1920
}
},
{
@@ -647,7 +743,7 @@
"key": "Database Import / Export",
"location": {
"startingColumn": 22,
- "startingLine": 1817
+ "startingLine": 1932
}
},
{
@@ -655,7 +751,7 @@
"key": "Built-in native MySQL database tools",
"location": {
"startingColumn": 22,
- "startingLine": 1820
+ "startingLine": 1935
}
}
]
diff --git a/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/MainView.swiftdeps b/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/MainView.swiftdeps
index cbe97ba..85e65e9 100644
Binary files a/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/MainView.swiftdeps and b/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/MainView.swiftdeps differ
diff --git a/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/WorkbenchReplacement-primary.priors b/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/WorkbenchReplacement-primary.priors
index a7b8cc3..c61370f 100644
Binary files a/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/WorkbenchReplacement-primary.priors and b/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/WorkbenchReplacement-primary.priors differ
diff --git a/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/WorkbenchReplacement.swiftmodule b/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/WorkbenchReplacement.swiftmodule
index bf1efd1..f42ccd9 100644
Binary files a/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/WorkbenchReplacement.swiftmodule and b/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/WorkbenchReplacement.swiftmodule differ
diff --git a/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/WorkbenchReplacement.swiftsourceinfo b/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/WorkbenchReplacement.swiftsourceinfo
index 12be0c5..17ea5b7 100644
Binary files a/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/WorkbenchReplacement.swiftsourceinfo and b/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/WorkbenchReplacement.swiftsourceinfo differ
diff --git a/build/Build/Intermediates.noindex/XCBuildData/build.db b/build/Build/Intermediates.noindex/XCBuildData/build.db
index ec587d6..638f39f 100644
Binary files a/build/Build/Intermediates.noindex/XCBuildData/build.db and b/build/Build/Intermediates.noindex/XCBuildData/build.db differ
diff --git a/build/Build/Intermediates.noindex/XCBuildData/registered-launchservices.txt b/build/Build/Intermediates.noindex/XCBuildData/registered-launchservices.txt
index 18c4e25..abb9e11 100644
--- a/build/Build/Intermediates.noindex/XCBuildData/registered-launchservices.txt
+++ b/build/Build/Intermediates.noindex/XCBuildData/registered-launchservices.txt
@@ -17,3 +17,5 @@
/Volumes/Developer/Applications/WorkbenchReplacement/build/Build/Products/Debug/WorkbenchReplacement.app
/Volumes/Developer/Applications/WorkbenchReplacement/build/Build/Products/Debug/WorkbenchReplacement.app
/Volumes/Developer/Applications/WorkbenchReplacement/build/Build/Products/Debug/WorkbenchReplacement.app
+/Volumes/Developer/Applications/WorkbenchReplacement/build/Build/Products/Debug/WorkbenchReplacement.app
+/Volumes/Developer/Applications/WorkbenchReplacement/build/Build/Products/Debug/WorkbenchReplacement.app
diff --git a/build/Build/Products/Debug/WorkbenchReplacement.app/Contents/MacOS/WorkbenchReplacement b/build/Build/Products/Debug/WorkbenchReplacement.app/Contents/MacOS/WorkbenchReplacement
index 40d2b73..1770550 100755
Binary files a/build/Build/Products/Debug/WorkbenchReplacement.app/Contents/MacOS/WorkbenchReplacement and b/build/Build/Products/Debug/WorkbenchReplacement.app/Contents/MacOS/WorkbenchReplacement differ
diff --git a/build/Build/Products/Debug/WorkbenchReplacement.app/Contents/MacOS/WorkbenchReplacement.debug.dylib b/build/Build/Products/Debug/WorkbenchReplacement.app/Contents/MacOS/WorkbenchReplacement.debug.dylib
index 941343f..e33a17e 100755
Binary files a/build/Build/Products/Debug/WorkbenchReplacement.app/Contents/MacOS/WorkbenchReplacement.debug.dylib and b/build/Build/Products/Debug/WorkbenchReplacement.app/Contents/MacOS/WorkbenchReplacement.debug.dylib differ
diff --git a/build/Build/Products/Debug/WorkbenchReplacement.app/Contents/MacOS/__preview.dylib b/build/Build/Products/Debug/WorkbenchReplacement.app/Contents/MacOS/__preview.dylib
index 7ac2697..b0689d1 100755
Binary files a/build/Build/Products/Debug/WorkbenchReplacement.app/Contents/MacOS/__preview.dylib and b/build/Build/Products/Debug/WorkbenchReplacement.app/Contents/MacOS/__preview.dylib differ
diff --git a/build/Build/Products/Debug/WorkbenchReplacement.app/Contents/_CodeSignature/CodeResources b/build/Build/Products/Debug/WorkbenchReplacement.app/Contents/_CodeSignature/CodeResources
index 08ff164..d908999 100644
--- a/build/Build/Products/Debug/WorkbenchReplacement.app/Contents/_CodeSignature/CodeResources
+++ b/build/Build/Products/Debug/WorkbenchReplacement.app/Contents/_CodeSignature/CodeResources
@@ -19,7 +19,7 @@
cdhash
- NSM7hOCoNX+DMsteke6Yge2XHGs=
+ lXsCGsMbs4xf0Myx5xVMRot9mP8=
requirement
identifier "WorkbenchReplacement.debug" and anchor apple generic and certificate leaf[subject.CN] = "Apple Development: Mark Gregory (FLBRJ3BYDD)" and certificate 1[field.1.2.840.113635.100.6.2.1] /* exists */
diff --git a/build/Build/Products/Debug/WorkbenchReplacement.swiftmodule/Project/arm64-apple-macos.swiftsourceinfo b/build/Build/Products/Debug/WorkbenchReplacement.swiftmodule/Project/arm64-apple-macos.swiftsourceinfo
index ccb2d20..17ea5b7 100644
Binary files a/build/Build/Products/Debug/WorkbenchReplacement.swiftmodule/Project/arm64-apple-macos.swiftsourceinfo and b/build/Build/Products/Debug/WorkbenchReplacement.swiftmodule/Project/arm64-apple-macos.swiftsourceinfo differ
diff --git a/build/Build/Products/Debug/WorkbenchReplacement.swiftmodule/arm64-apple-macos.swiftmodule b/build/Build/Products/Debug/WorkbenchReplacement.swiftmodule/arm64-apple-macos.swiftmodule
index a23de6c..f42ccd9 100644
Binary files a/build/Build/Products/Debug/WorkbenchReplacement.swiftmodule/arm64-apple-macos.swiftmodule and b/build/Build/Products/Debug/WorkbenchReplacement.swiftmodule/arm64-apple-macos.swiftmodule differ
diff --git a/build/Index.noindex/DataStore/v5/units/MainView.o-CNVK7PE7JUX3 b/build/Index.noindex/DataStore/v5/units/MainView.o-CNVK7PE7JUX3
index 2578630..cd2dd08 100644
Binary files a/build/Index.noindex/DataStore/v5/units/MainView.o-CNVK7PE7JUX3 and b/build/Index.noindex/DataStore/v5/units/MainView.o-CNVK7PE7JUX3 differ
diff --git a/build/Logs/Build/LogStoreManifest.plist b/build/Logs/Build/LogStoreManifest.plist
index 021c10a..dfe04c7 100644
--- a/build/Logs/Build/LogStoreManifest.plist
+++ b/build/Logs/Build/LogStoreManifest.plist
@@ -90,6 +90,48 @@
uniqueIdentifier
B2C949DC-0503-4157-BC15-F74641625B50
+ B8940B11-E198-4118-908A-6DCC06A473A1
+
+ className
+ IDECommandLineBuildLog
+ documentTypeString
+ <nil>
+ domainType
+ Xcode.IDEActivityLogDomainType.BuildLog
+ fileName
+ B8940B11-E198-4118-908A-6DCC06A473A1.xcactivitylog
+ hasPrimaryLog
+
+ primaryObservable
+
+ highLevelStatus
+ S
+ totalNumberOfAnalyzerIssues
+ 0
+ totalNumberOfErrors
+ 0
+ totalNumberOfTestFailures
+ 0
+ totalNumberOfWarnings
+ 0
+
+ schemeIdentifier-containerName
+ WorkbenchReplacement project
+ schemeIdentifier-schemeName
+ WorkbenchReplacement
+ schemeIdentifier-sharedScheme
+ 1
+ signature
+ Building project WorkbenchReplacement with scheme WorkbenchReplacement and configuration Debug
+ timeStartedRecording
+ 813878192.18681705
+ timeStoppedRecording
+ 813878206.57349706
+ title
+ Building project WorkbenchReplacement with scheme WorkbenchReplacement and configuration Debug
+ uniqueIdentifier
+ B8940B11-E198-4118-908A-6DCC06A473A1
+
D705A532-F8F7-4B72-94B4-3464B760E3E3
className
@@ -132,48 +174,6 @@
uniqueIdentifier
D705A532-F8F7-4B72-94B4-3464B760E3E3
- EB994874-BDA8-4BAC-BAF2-6EB6F20E2468
-
- className
- IDECommandLineBuildLog
- documentTypeString
- <nil>
- domainType
- Xcode.IDEActivityLogDomainType.BuildLog
- fileName
- EB994874-BDA8-4BAC-BAF2-6EB6F20E2468.xcactivitylog
- hasPrimaryLog
-
- primaryObservable
-
- highLevelStatus
- S
- totalNumberOfAnalyzerIssues
- 0
- totalNumberOfErrors
- 0
- totalNumberOfTestFailures
- 0
- totalNumberOfWarnings
- 0
-
- schemeIdentifier-containerName
- WorkbenchReplacement project
- schemeIdentifier-schemeName
- WorkbenchReplacement
- schemeIdentifier-sharedScheme
- 1
- signature
- Building project WorkbenchReplacement with scheme WorkbenchReplacement and configuration Debug
- timeStartedRecording
- 813877513.105088
- timeStoppedRecording
- 813877526.28998804
- title
- Building project WorkbenchReplacement with scheme WorkbenchReplacement and configuration Debug
- uniqueIdentifier
- EB994874-BDA8-4BAC-BAF2-6EB6F20E2468
-
diff --git a/build/ModuleCache.noindex/Session.modulevalidation b/build/ModuleCache.noindex/Session.modulevalidation
index 98b29e1..36a8e94 100644
--- a/build/ModuleCache.noindex/Session.modulevalidation
+++ b/build/ModuleCache.noindex/Session.modulevalidation
@@ -1 +1 @@
-1792185273.801373: Module build session file for module cache at Path(str: "/Volumes/Developer/Applications/WorkbenchReplacement/build/ModuleCache.noindex")
+1792185392.568994: Module build session file for module cache at Path(str: "/Volumes/Developer/Applications/WorkbenchReplacement/build/ModuleCache.noindex")
diff --git a/build/SDKStatCaches.noindex/macosx27.0-26A425-e829b21a6f8c9b70876ba0858053c0447231f6df4def33e022ae2eb8f782df1a.sdkstatcache b/build/SDKStatCaches.noindex/macosx27.0-26A425-e829b21a6f8c9b70876ba0858053c0447231f6df4def33e022ae2eb8f782df1a.sdkstatcache
index 5542a21..9a6b86a 100644
Binary files a/build/SDKStatCaches.noindex/macosx27.0-26A425-e829b21a6f8c9b70876ba0858053c0447231f6df4def33e022ae2eb8f782df1a.sdkstatcache and b/build/SDKStatCaches.noindex/macosx27.0-26A425-e829b21a6f8c9b70876ba0858053c0447231f6df4def33e022ae2eb8f782df1a.sdkstatcache differ
diff --git a/build/info.plist b/build/info.plist
index 7e44b95..a61a9ed 100644
--- a/build/info.plist
+++ b/build/info.plist
@@ -3,7 +3,7 @@
LastAccessedDate
- 2026-10-16T21:14:33Z
+ 2026-10-16T21:16:32Z
WorkspacePath
/Volumes/Developer/Applications/WorkbenchReplacement/WorkbenchReplacement.xcodeproj