Skip to content

Commit a339dda

Browse files
committed
fix: address code review issues in Cassandra plugin driver
1 parent 9222702 commit a339dda

1 file changed

Lines changed: 31 additions & 12 deletions

File tree

Plugins/CassandraDriverPlugin/CassandraPlugin.swift

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,12 @@ final class CassandraPlugin: NSObject, TableProPlugin, DriverPlugin {
3838
private actor CassandraConnectionActor {
3939
private static let logger = Logger(subsystem: "com.TablePro.CassandraDriver", category: "Connection")
4040

41+
nonisolated(unsafe) private static let isoFormatter: ISO8601DateFormatter = {
42+
let f = ISO8601DateFormatter()
43+
f.formatOptions = [.withInternetDateTime, .withFractionalSeconds]
44+
return f
45+
}()
46+
4147
private var cluster: OpaquePointer? // CassCluster*
4248
private var session: OpaquePointer? // CassSession*
4349
private var currentKeyspace: String?
@@ -69,15 +75,23 @@ private actor CassandraConnectionActor {
6975

7076
// SSL/TLS
7177
if sslMode != "Disabled" {
72-
let ssl = cass_ssl_new()
78+
guard let ssl = cass_ssl_new() else {
79+
cass_cluster_free(cluster)
80+
self.cluster = nil
81+
throw CassandraPluginError.connectionFailed("Failed to create SSL context")
82+
}
7383

7484
if sslMode == "Verify CA" || sslMode == "Verify Identity" {
7585
cass_ssl_set_verify_flags(ssl, Int32(CASS_SSL_VERIFY_PEER_CERT.rawValue))
7686

7787
if let caCertPath = sslCaCertPath, !caCertPath.isEmpty,
7888
let certData = FileManager.default.contents(atPath: caCertPath),
7989
let certString = String(data: certData, encoding: .utf8) {
80-
cass_ssl_add_trusted_cert(ssl, certString)
90+
let rc = cass_ssl_add_trusted_cert(ssl, certString)
91+
if rc != CASS_OK {
92+
Self.logger.warning("Failed to add CA certificate, proceeding without verification")
93+
cass_ssl_set_verify_flags(ssl, Int32(CASS_SSL_VERIFY_NONE.rawValue))
94+
}
8195
}
8296
} else {
8397
// "Preferred" / "Required" — encrypt but skip cert verification
@@ -437,9 +451,7 @@ private actor CassandraConnectionActor {
437451
var timestamp: Int64 = 0
438452
if cass_value_get_int64(value, &timestamp) == CASS_OK {
439453
let date = Date(timeIntervalSince1970: Double(timestamp) / 1000.0)
440-
let formatter = ISO8601DateFormatter()
441-
formatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds]
442-
return formatter.string(from: date)
454+
return isoFormatter.string(from: date)
443455
}
444456
return nil
445457

@@ -650,7 +662,12 @@ final class CassandraPluginDriver: PluginDatabaseDriver, @unchecked Sendable {
650662

651663
func disconnect() {
652664
let actor = connectionActor
653-
Task { await actor.close() }
665+
let semaphore = DispatchSemaphore(value: 0)
666+
Task {
667+
await actor.close()
668+
semaphore.signal()
669+
}
670+
semaphore.wait()
654671
stateLock.lock()
655672
_currentKeyspace = nil
656673
_cachedVersion = nil
@@ -696,15 +713,17 @@ final class CassandraPluginDriver: PluginDatabaseDriver, @unchecked Sendable {
696713
// MARK: - Pagination
697714

698715
func fetchRowCount(query: String) async throws -> Int {
699-
let countQuery = "SELECT COUNT(*) FROM (\(stripTrailingSemicolon(query)))"
700-
let result = try await execute(query: countQuery)
701-
guard let firstRow = result.rows.first, let countStr = firstRow.first else { return 0 }
702-
return Int(countStr ?? "0") ?? 0
716+
// CQL does not support subqueries, so we can't wrap an arbitrary query in SELECT COUNT(*) FROM (...).
717+
// Return -1 to signal unknown count; the UI will hide the total page count.
718+
-1
703719
}
704720

705721
func fetchRows(query: String, offset: Int, limit: Int) async throws -> PluginQueryResult {
706-
// Cassandra doesn't support OFFSET natively.
707-
// For paginated browsing, we use LIMIT and let the default protocol handle paging.
722+
// CQL does not support OFFSET. Only the first page (offset=0) can be fetched via simple LIMIT.
723+
// For offset>0, throw so the caller knows pagination is unsupported for arbitrary queries.
724+
if offset > 0 {
725+
throw CassandraPluginError.unsupportedOperation
726+
}
708727
let baseQuery = stripTrailingSemicolon(query)
709728
let paginatedQuery = "\(baseQuery) LIMIT \(limit)"
710729
return try await execute(query: paginatedQuery)

0 commit comments

Comments
 (0)