Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ Thumbs.db
*.p12
*.mobileprovision
Secrets.xcconfig
Local.xcconfig

# Debug
*.log
Expand Down Expand Up @@ -154,3 +155,5 @@ fix-1322-plugin-abi-and-registry-overhaul.diff

# Issue analysis blueprints (local only)
.analysis/
.docs/
Local.xcconfig
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added

- BigQuery: the sidebar now shows every dataset as an expandable node, with each dataset's tables loading when you open it, instead of showing one dataset at a time behind a picker.
- Mark a table as a favorite by clicking the star button at the end of its sidebar row. Favorites are pinned to the top of their section, appear in a dedicated Tables group in the Favorites tab, and sync through iCloud.
- A plus button next to the sidebar filter creates a new table without right-clicking. The button is disabled while safe mode blocks writes.
- Recent section at the top of the Tables sidebar tracks the last 10 tables you opened per connection and database, in-memory for the session. (#1352)
- OpenCode Zen as an AI provider. Add it from the provider list and paste an OpenCode key, or leave the key blank to use the free models; the model list loads automatically, covering the Claude, GPT, Gemini, and open models Zen serves. (#1400)
- Oracle Database 11g (11.1 and 11.2) now connects. Previously only 12c and later worked, so 11g servers failed with a "Server Version Not Supported" error. (#1425)
- Oracle connections can now use a SID instead of a service name. Set Connection Type to SID in the connection form and enter the SID. (#1425)
Expand All @@ -21,6 +24,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Clearing a query with the trash button now also clears its results, and a new Clear Results item on the results right-click menu clears results on their own. (#1256)
- Inserting SQL from AI Chat opens it in a new query tab instead of appending to the current query. An empty editor is filled in place. (#1257)

### Changed

- The Maintenance submenu in the sidebar context menu is hidden when no maintenance operations are available or the target is read-only, instead of showing an empty disabled menu.
- The window minimum width now adjusts to the visible panes, so opening the inspector on a small window no longer pushes content off-screen.

### Removed

- "Create New Table…" from the sidebar right-click menu. Use the plus button next to the sidebar filter instead.
- "View ER Diagram" from the sidebar right-click menu. Access it from the Favorites tab context menu instead.

### Fixed

- Pasting copied rows no longer misplaces values when a cell contains a comma (such as a user agent string); each value stays in its own column, and a real NULL is kept distinct from the literal text "NULL".
Expand Down
1 change: 1 addition & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ Missing a case produces a wrong "{Language} Query" title on the first frame.
| Tab state | JSON persistence | `TabPersistenceService` / `TabStateStorage` |
| Filter presets | UserDefaults | `FilterSettingsStorage` |
| Per-table filters | UserDefaults | `FilterSettingsStorage` (saves `appliedFilters` only) |
| Favorite tables | UserDefaults | `FavoriteTablesStorage` (global, by table name) |

### Logging & Debugging

Expand Down
118 changes: 118 additions & 0 deletions TablePro.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,13 @@
remoteGlobalIDString = 5A1091C62EF17EDC0055EA7C;
remoteInfo = TablePro;
};
5AF00A112FB9000000000001 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 5A1091BF2EF17EDC0055EA7C /* Project object */;
proxyType = 1;
remoteGlobalIDString = 5A1091C62EF17EDC0055EA7C;
remoteInfo = TablePro;
};
5ABQR00000000000000000C0 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 5A1091BF2EF17EDC0055EA7C /* Project object */;
Expand Down Expand Up @@ -297,6 +304,7 @@
5A87A000100000000 /* CassandraDriver.tableplugin */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CassandraDriver.tableplugin; sourceTree = BUILT_PRODUCTS_DIR; };
5ABBED792FB55E1400A78382 /* CSVInspectorPlugin.tableplugin */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CSVInspectorPlugin.tableplugin; sourceTree = BUILT_PRODUCTS_DIR; };
5ABCC5A72F43856700EAF3FC /* TableProTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = TableProTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
5AF00A102FB9000000000001 /* TableProUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = TableProUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
5ABQR00200000000000000A1 /* BigQueryAuth.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BigQueryAuth.swift; sourceTree = "<group>"; };
5ABQR00200000000000000A2 /* BigQueryConnection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BigQueryConnection.swift; sourceTree = "<group>"; };
5ABQR00200000000000000A3 /* BigQueryPlugin.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BigQueryPlugin.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -677,6 +685,11 @@
path = TableProTests;
sourceTree = "<group>";
};
5AF00A122FB9000000000001 /* TableProUITests */ = {
isa = PBXFileSystemSynchronizedRootGroup;
path = TableProUITests;
sourceTree = "<group>";
};
5AE4F4812F6BC0640097AC5B /* Plugins/CloudflareD1DriverPlugin */ = {
isa = PBXFileSystemSynchronizedRootGroup;
exceptions = (
Expand Down Expand Up @@ -708,6 +721,13 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
5AF00A132FB9000000000001 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
5A3BE6F52F97DA8100611C1F /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
Expand Down Expand Up @@ -939,6 +959,7 @@
5A86E000500000000 /* Plugins/MQLExportPlugin */,
5A86F000500000000 /* Plugins/SQLImportPlugin */,
5ABCC5A82F43856700EAF3FC /* TableProTests */,
5AF00A122FB9000000000001 /* TableProUITests */,
5A32BC012F9D5F1300BAEB5F /* mcp-server */,
5A1091C82EF17EDC0055EA7C /* Products */,
5A05FBC72F3EDF7500819CD7 /* Recovered References */,
Expand Down Expand Up @@ -968,6 +989,7 @@
5A86E000100000000 /* MQLExport.tableplugin */,
5A86F000100000000 /* SQLImport.tableplugin */,
5ABCC5A72F43856700EAF3FC /* TableProTests.xctest */,
5AF00A102FB9000000000001 /* TableProUITests.xctest */,
5AEA8B2A2F6808270040461A /* EtcdDriverPlugin.tableplugin */,
5ADDB00300000000000000A0 /* DynamoDBDriverPlugin.tableplugin */,
5ABQR00300000000000000A0 /* BigQueryDriverPlugin.tableplugin */,
Expand Down Expand Up @@ -1524,6 +1546,27 @@
productReference = 5ABCC5A72F43856700EAF3FC /* TableProTests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
5AF00A142FB9000000000001 /* TableProUITests */ = {
isa = PBXNativeTarget;
buildConfigurationList = 5AF00A192FB9000000000001 /* Build configuration list for PBXNativeTarget "TableProUITests" */;
buildPhases = (
5AF00A152FB9000000000001 /* Sources */,
5AF00A132FB9000000000001 /* Frameworks */,
5AF00A162FB9000000000001 /* Resources */,
);
buildRules = (
);
dependencies = (
5AF00A172FB9000000000001 /* PBXTargetDependency */,
);
fileSystemSynchronizedGroups = (
5AF00A122FB9000000000001 /* TableProUITests */,
);
name = TableProUITests;
productName = TableProUITests;
productReference = 5AF00A102FB9000000000001 /* TableProUITests.xctest */;
productType = "com.apple.product-type.bundle.ui-testing";
};
5ABQR00600000000000000B0 /* BigQueryDriverPlugin */ = {
isa = PBXNativeTarget;
buildConfigurationList = 5ABQR00800000000000000B0 /* Build configuration list for PBXNativeTarget "BigQueryDriverPlugin" */;
Expand Down Expand Up @@ -1671,6 +1714,10 @@
CreatedOnToolsVersion = 26.2;
TestTargetID = 5A1091C62EF17EDC0055EA7C;
};
5AF00A142FB9000000000001 = {
CreatedOnToolsVersion = 26.5;
TestTargetID = 5A1091C62EF17EDC0055EA7C;
};
5AE4F4732F6BC0640097AC5B = {
CreatedOnToolsVersion = 26.3;
LastSwiftMigration = 2630;
Expand Down Expand Up @@ -1725,6 +1772,7 @@
5A86E000000000000 /* MQLExport */,
5A86F000000000000 /* SQLImport */,
5ABCC5A62F43856700EAF3FC /* TableProTests */,
5AF00A142FB9000000000001 /* TableProUITests */,
5AEA8B292F6808270040461A /* EtcdDriverPlugin */,
5AE4F4732F6BC0640097AC5B /* CloudflareD1DriverPlugin */,
5ADDB00600000000000000B0 /* DynamoDBDriverPlugin */,
Expand All @@ -1744,6 +1792,13 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
5AF00A162FB9000000000001 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
5A3BE6F62F97DA8100611C1F /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
Expand Down Expand Up @@ -1929,6 +1984,13 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
5AF00A152FB9000000000001 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
5A3BE6F42F97DA8100611C1F /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
Expand Down Expand Up @@ -2212,6 +2274,11 @@
target = 5A1091C62EF17EDC0055EA7C /* TablePro */;
targetProxy = 5ABCC5AB2F43856700EAF3FC /* PBXContainerItemProxy */;
};
5AF00A172FB9000000000001 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 5A1091C62EF17EDC0055EA7C /* TablePro */;
targetProxy = 5AF00A112FB9000000000001 /* PBXContainerItemProxy */;
};
5ABQR00000000000000000C1 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 5ABQR00600000000000000B0 /* BigQueryDriverPlugin */;
Expand Down Expand Up @@ -3713,6 +3780,48 @@
};
name = Release;
};
5AF00A182FB9000000000001 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = "";
GENERATE_INFOPLIST_FILE = YES;
MACOSX_DEPLOYMENT_TARGET = 14.0;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.TablePro.TableProUITests;
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = macosx;
STRING_CATALOG_GENERATE_SYMBOLS = NO;
SWIFT_APPROACHABLE_CONCURRENCY = YES;
SWIFT_EMIT_LOC_STRINGS = NO;
SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES;
SWIFT_VERSION = 5.9;
TEST_TARGET_NAME = TablePro;
};
name = Debug;
};
5AF00A1A2FB9000000000001 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = "";
GENERATE_INFOPLIST_FILE = YES;
MACOSX_DEPLOYMENT_TARGET = 14.0;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.TablePro.TableProUITests;
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = macosx;
STRING_CATALOG_GENERATE_SYMBOLS = NO;
SWIFT_APPROACHABLE_CONCURRENCY = YES;
SWIFT_EMIT_LOC_STRINGS = NO;
SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES;
SWIFT_VERSION = 5.9;
TEST_TARGET_NAME = TablePro;
};
name = Release;
};
5ABQR00700000000000000B1 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
Expand Down Expand Up @@ -4116,6 +4225,15 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
5AF00A192FB9000000000001 /* Build configuration list for PBXNativeTarget "TableProUITests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
5AF00A182FB9000000000001 /* Debug */,
5AF00A1A2FB9000000000001 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
5ABQR00800000000000000B0 /* Build configuration list for PBXNativeTarget "BigQueryDriverPlugin" */ = {
isa = XCConfigurationList;
buildConfigurations = (
Expand Down
11 changes: 11 additions & 0 deletions TablePro.xcodeproj/xcshareddata/xcschemes/TablePro.xcscheme
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,17 @@
ReferencedContainer = "container:TablePro.xcodeproj">
</BuildableReference>
</TestableReference>
<TestableReference
skipped = "NO"
parallelizable = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "5AF00A142FB9000000000001"
BuildableName = "TableProUITests.xctest"
BlueprintName = "TableProUITests"
ReferencedContainer = "container:TablePro.xcodeproj">
</BuildableReference>
</TestableReference>
</Testables>
</TestAction>
<LaunchAction
Expand Down
2 changes: 2 additions & 0 deletions TablePro/Core/Services/AppServices.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ struct AppServices {
let schemaService: SchemaService
let schemaProviderRegistry: SchemaProviderRegistry
let sqlFavoriteManager: SQLFavoriteManager
let favoriteTablesStorage: FavoriteTablesStorage
let aiChatStorage: AIChatStorage
let aiKeyStorage: AIKeyStorage
let groupStorage: GroupStorage
Expand Down Expand Up @@ -43,6 +44,7 @@ struct AppServices {
schemaService: .shared,
schemaProviderRegistry: .shared,
sqlFavoriteManager: .shared,
favoriteTablesStorage: .shared,
aiChatStorage: .shared,
aiKeyStorage: .shared,
groupStorage: .shared,
Expand Down
Loading
Loading