Skip to content
Merged
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Changed

- 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)

### Fixed

Expand Down
15 changes: 7 additions & 8 deletions TablePro/Views/Main/MainContentCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -863,16 +863,15 @@ final class MainContentCoordinator {
}
}

var aiInsertReusesSelectedQueryTab: Bool {
guard let (tab, _) = tabManager.selectedTabAndIndex, tab.tabType == .query else { return false }
return tab.content.query.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty
}

func insertQueryFromAI(_ query: String) {
if let (tab, tabIndex) = tabManager.selectedTabAndIndex,
tab.tabType == .query {
let existingQuery = tab.content.query
if aiInsertReusesSelectedQueryTab, let (_, tabIndex) = tabManager.selectedTabAndIndex {
tabManager.mutate(at: tabIndex) { mutTab in
if existingQuery.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
mutTab.content.query = query
} else {
mutTab.content.query = existingQuery + "\n\n" + query
}
mutTab.content.query = query
mutTab.hasUserInteraction = true
}
} else if tabManager.tabs.isEmpty {
Expand Down
80 changes: 80 additions & 0 deletions TableProTests/Views/Main/AIChatInsertQueryTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import Foundation
import TableProPluginKit
import Testing

@testable import TablePro

@Suite("AIChatInsertQuery")
struct AIChatInsertQueryTests {
@Test("Reuses the selected query tab only when it is empty")
@MainActor
func reusesSelectedQueryTabWhenEmpty() {
let coordinator = Self.makeCoordinator()
defer { coordinator.teardown() }

coordinator.tabManager.addTab(databaseName: "db")

#expect(coordinator.aiInsertReusesSelectedQueryTab == true)
}

@Test("Does not reuse a query tab that already has content")
@MainActor
func doesNotReuseQueryTabWithContent() {
let coordinator = Self.makeCoordinator()
defer { coordinator.teardown() }

coordinator.tabManager.addTab(initialQuery: "SELECT 1", databaseName: "db")

#expect(coordinator.aiInsertReusesSelectedQueryTab == false)
}

@Test("Does not reuse a table tab")
@MainActor
func doesNotReuseTableTab() throws {
let coordinator = Self.makeCoordinator()
defer { coordinator.teardown() }

try coordinator.tabManager.addTableTab(tableName: "users", databaseType: .mysql, databaseName: "db")

#expect(coordinator.aiInsertReusesSelectedQueryTab == false)
}

@Test("Insert fills an empty query tab in place")
@MainActor
func insertFillsEmptyQueryTabInPlace() {
let coordinator = Self.makeCoordinator()
defer { coordinator.teardown() }

coordinator.tabManager.addTab(databaseName: "db")

coordinator.insertQueryFromAI("SELECT * FROM users")

#expect(coordinator.tabManager.tabs.count == 1)
#expect(coordinator.tabManager.selectedTab?.content.query == "SELECT * FROM users")
}

@Test("Insert with no open tabs creates a query tab with the SQL")
@MainActor
func insertWithNoTabsCreatesQueryTab() {
let coordinator = Self.makeCoordinator()
defer { coordinator.teardown() }

#expect(coordinator.tabManager.tabs.isEmpty)

coordinator.insertQueryFromAI("SELECT * FROM orders")

#expect(coordinator.tabManager.tabs.count == 1)
#expect(coordinator.tabManager.selectedTab?.tabType == .query)
#expect(coordinator.tabManager.selectedTab?.content.query == "SELECT * FROM orders")
}

@MainActor
private static func makeCoordinator() -> MainContentCoordinator {
MainContentCoordinator(
connection: TestFixtures.makeConnection(database: "db"),
tabManager: QueryTabManager(),
changeManager: DataChangeManager(),
toolbarState: ConnectionToolbarState()
)
}
}
2 changes: 1 addition & 1 deletion docs/features/ai-assistant.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ Press `Cmd+Shift+L`, click the inspector toggle and pick **AI Chat**, or use **V
/>
</Frame>

Type a question and press Return. Code blocks have **Copy** and **Insert to Editor** buttons. Token counts show below each response.
Type a question and press Return. Code blocks have **Copy** and **Insert** buttons. Insert opens the SQL in a new query tab, or fills the current editor if it's empty. Token counts show below each response.

<Frame caption="Code block actions">
<img
Expand Down
Loading