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
6 changes: 0 additions & 6 deletions TablePro/Core/ChangeTracking/SQLStatementGenerator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -259,12 +259,6 @@ struct SQLStatementGenerator {
return ParameterizedStatement(sql: sql, parameters: parameters)
}

/// Marker type for SQL function literals that cannot be parameterized
private struct SQLFunctionLiteral {
let value: String
init(_ value: String) { self.value = value }
}

// MARK: - UPDATE Generation

func generateUpdateSQL(for change: RowChange) -> ParameterizedStatement? {
Expand Down
9 changes: 2 additions & 7 deletions TablePro/Core/Database/DatabaseDriver.swift
Original file line number Diff line number Diff line change
Expand Up @@ -230,16 +230,11 @@ extension DatabaseDriver {
var queryBuildingPluginDriver: (any PluginDatabaseDriver)? { nil }

func quoteIdentifier(_ name: String) -> String {
let q = "\""
let escaped = name.replacingOccurrences(of: q, with: q + q)
return "\(q)\(escaped)\(q)"
SQLEscaping.quoteIdentifier(name)
}

func escapeStringLiteral(_ value: String) -> String {
var result = value
result = result.replacingOccurrences(of: "'", with: "''")
result = result.replacingOccurrences(of: "\0", with: "")
return result
SQLEscaping.escapeStringLiteral(value)
}

func createViewTemplate() -> String? { nil }
Expand Down
7 changes: 7 additions & 0 deletions TablePro/Core/Database/SQLEscaping.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,13 @@ enum SQLEscaping {
return result
}

/// Quote a SQL identifier using ANSI double-quote rules, doubling any embedded quote.
static func quoteIdentifier(_ identifier: String) -> String {
let quote = "\""
let escaped = identifier.replacingOccurrences(of: quote, with: quote + quote)
return "\(quote)\(escaped)\(quote)"
}

/// Known SQL temporal function expressions that should not be quoted/parameterized.
/// Canonical source — used by SQLStatementGenerator and sidebar save logic.
static let temporalFunctionExpressions: Set<String> = [
Expand Down
32 changes: 0 additions & 32 deletions TablePro/Core/LSP/LSPTypes.swift
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,6 @@ struct LSPInlineCompletionParams: Codable, Sendable, Equatable {
let formattingOptions: LSPFormattingOptions
}

struct LSPDidShowCompletionParams: Codable, Sendable {
let textDocument: LSPTextDocumentIdentifier
let items: [LSPInlineCompletionItem]
}

struct LSPClientInfo: Codable, Sendable, Equatable {
let name: String
let version: String
Expand Down Expand Up @@ -149,17 +144,6 @@ struct LSPJSONRPCNotification<P: Encodable>: Encodable {
let params: P?
}

struct LSPJSONRPCResponse<R: Decodable>: Decodable {
let id: Int?
let result: R?
let error: LSPJSONRPCError?
}

struct LSPJSONRPCError: Decodable, Sendable {
let code: Int
let message: String
}

// MARK: - Copilot Conversation Types

struct CopilotConversationTurn: Codable, Sendable {
Expand Down Expand Up @@ -261,22 +245,6 @@ struct CopilotConversationTurnDeleteParams: Codable, Sendable {
let source: String
}

struct CopilotProgressParams: Codable, Sendable {
let token: String
let value: CopilotProgressValue
}

struct CopilotProgressValue: Codable, Sendable {
let kind: String
let title: String?
let reply: String?
let result: CopilotProgressResult?
}

struct CopilotProgressResult: Codable, Sendable {
let followUp: String?
}

struct CopilotModel: Codable, Sendable {
let id: String
let modelFamily: String?
Expand Down
6 changes: 0 additions & 6 deletions TablePro/Core/MCP/MCPAuditLogStorage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,6 @@ actor MCPAuditLogStorage {
private var dbPath: String?
private let testDatabaseSuffix: String?

enum TimeRange: Equatable {
case lastHours(Int)
case lastDays(Int)
case all
}

init() {
self.testDatabaseSuffix = nil
setupDatabase()
Expand Down
47 changes: 0 additions & 47 deletions TablePro/Core/MCP/TokenPermissionFilter.swift

This file was deleted.

4 changes: 2 additions & 2 deletions TablePro/Core/Plugins/QueryResultExportDataSource.swift
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,14 @@ final class QueryResultExportDataSource: PluginExportDataSource, @unchecked Send
if let driver {
return driver.quoteIdentifier(identifier)
}
return "\"\(identifier.replacingOccurrences(of: "\"", with: "\"\""))\""
return SQLEscaping.quoteIdentifier(identifier)
}

func escapeStringLiteral(_ value: String) -> String {
if let driver {
return driver.escapeStringLiteral(value)
}
return value.replacingOccurrences(of: "'", with: "''")
return SQLEscaping.escapeStringLiteral(value)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve NULs when exporting query results

When exporting cached query results with the SQL export plugin, this data source is constructed without a driver, so this fallback is used for every text cell. SQLEscaping.escapeStringLiteral strips \0, whereas the previous fallback only doubled quotes, so a value like "a\0b" is emitted as 'ab' and reloads as different data. Please keep the old query-result escaping semantics or encode NULs explicitly instead of dropping them.

Useful? React with 👍 / 👎.

}

func fetchTableDDL(table: String, databaseName: String) async throws -> String {
Expand Down
12 changes: 0 additions & 12 deletions TablePro/Models/Connection/ConnectionExport.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,6 @@
import Foundation
import UniformTypeIdentifiers

// MARK: - Sheet Binding Wrappers

struct IdentifiableURL: Identifiable {
let id = UUID()
let url: URL
}

struct IdentifiableConnections: Identifiable {
let id = UUID()
let connections: [DatabaseConnection]
}

// MARK: - UTType

extension UTType {
Expand Down
40 changes: 0 additions & 40 deletions TablePro/Models/Connection/ConnectionToolbarState.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,46 +11,6 @@ import Observation
import SwiftUI
import TableProPluginKit

// MARK: - Connection Environment

/// Represents the connection environment type for visual badges
enum ConnectionEnvironment: String, CaseIterable {
case local = "LOCAL"
case ssh = "SSH"
case production = "PROD"
case staging = "STAGING"

/// SF Symbol for this environment type
var iconName: String {
switch self {
case .local: return "house.fill"
case .ssh: return "lock.fill"
case .production: return "exclamationmark.triangle.fill"
case .staging: return "testtube.2"
}
}

/// Badge background color
var backgroundColor: Color {
switch self {
case .local: return .gray.opacity(0.3)
case .ssh: return .orange.opacity(0.3)
case .production: return .red.opacity(0.3)
case .staging: return .blue.opacity(0.3)
}
}

/// Badge foreground color
var foregroundColor: Color {
switch self {
case .local: return .secondary
case .ssh: return .orange
case .production: return .red
case .staging: return .blue
}
}
}

// MARK: - Connection State

/// Represents the current state of the database connection
Expand Down
17 changes: 17 additions & 0 deletions TableProTests/Core/Database/SQLEscapingTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,23 @@ struct SQLEscapingTests {
#expect(result == "\\''")
}

// MARK: - quoteIdentifier Tests (ANSI SQL)

@Test("Plain identifier wrapped in double quotes")
func testQuoteIdentifierPlain() {
#expect(SQLEscaping.quoteIdentifier("users") == "\"users\"")
}

@Test("Embedded double quote is doubled")
func testQuoteIdentifierEmbeddedQuote() {
#expect(SQLEscaping.quoteIdentifier("we\"ird") == "\"we\"\"ird\"")
}

@Test("Empty identifier yields empty quotes")
func testQuoteIdentifierEmpty() {
#expect(SQLEscaping.quoteIdentifier("") == "\"\"")
}

// MARK: - escapeLikeWildcards Tests

@Test("LIKE plain string unchanged")
Expand Down
Loading