Skip to content

Ensure ltree works #548

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Apr 25, 2025
Merged
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
9 changes: 8 additions & 1 deletion Sources/PostgresNIO/New/Data/String+PostgresCodable.swift
Original file line number Diff line number Diff line change
@@ -36,13 +36,20 @@ extension String: PostgresDecodable {
// we can force unwrap here, since this method only fails if there are not enough
// bytes available.
self = buffer.readString(length: buffer.readableBytes)!

case (_, .uuid):
guard let uuid = try? UUID(from: &buffer, type: .uuid, format: format, context: context) else {
throw PostgresDecodingError.Code.failure
}
self = uuid.uuidString

default:
throw PostgresDecodingError.Code.typeMismatch
// We should eagerly try to convert any datatype into a String. For example the oid
// for ltree isn't static. For this reason we should just try to convert anything.
guard let string = buffer.readString(length: buffer.readableBytes) else {
throw PostgresDecodingError.Code.typeMismatch
}
self = string
}
}
}
55 changes: 55 additions & 0 deletions Tests/IntegrationTests/PostgresClientTests.swift
Original file line number Diff line number Diff line change
@@ -292,6 +292,61 @@ final class PostgresClientTests: XCTestCase {
XCTFail("Unexpected error: \(String(reflecting: error))")
}
}

func testLTree() async throws {
let tableName = "test_client_ltree"

var mlogger = Logger(label: "test")
mlogger.logLevel = .debug
let logger = mlogger
let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 8)
self.addTeardownBlock {
try await eventLoopGroup.shutdownGracefully()
}

let clientConfig = PostgresClient.Configuration.makeTestConfiguration()
let client = PostgresClient(configuration: clientConfig, eventLoopGroup: eventLoopGroup, backgroundLogger: logger)

try await withThrowingTaskGroup(of: Void.self) { taskGroup in
taskGroup.addTask {
await client.run()
}

try await client.query("CREATE EXTENSION IF NOT EXISTS ltree;")

try await client.query("DROP TABLE IF EXISTS \"\(unescaped: tableName)\";")

try await client.query(
"""
CREATE TABLE IF NOT EXISTS "\(unescaped: tableName)" (
id SERIAL PRIMARY KEY,
label ltree NOT NULL
);
"""
)

try await client.query(
"""
INSERT INTO "\(unescaped: tableName)" (label) VALUES ('foo.bar.baz')
"""
)

let rows = try await client.query(
"""
SELECT id, label FROM "\(unescaped: tableName)" WHERE label ~ 'foo.*'
"""
)

var count = 0
for try await (id, label) in rows.decode((Int, String).self) {
count += 1
}
XCTAssertEqual(count, 1)

taskGroup.cancelAll()
}
}

}

@available(macOS 13.0, iOS 16.0, tvOS 16.0, watchOS 9.0, *)
12 changes: 0 additions & 12 deletions Tests/PostgresNIOTests/New/Data/String+PSQLCodableTests.swift
Original file line number Diff line number Diff line change
@@ -31,18 +31,6 @@ class String_PSQLCodableTests: XCTestCase {
}
}

func testDecodeFailureFromInvalidType() {
let buffer = ByteBuffer()
let dataTypes: [PostgresDataType] = [.bool, .float4Array, .float8Array]

for dataType in dataTypes {
var loopBuffer = buffer
XCTAssertThrowsError(try String(from: &loopBuffer, type: dataType, format: .binary, context: .default)) {
XCTAssertEqual($0 as? PostgresDecodingError.Code, .typeMismatch)
}
}
}

func testDecodeFromUUID() {
let uuid = UUID()
var buffer = ByteBuffer()
8 changes: 4 additions & 4 deletions Tests/PostgresNIOTests/New/PostgresRowTests.swift
Original file line number Diff line number Diff line change
@@ -172,7 +172,7 @@ final class PostgresRowTests: XCTestCase {
name: "name",
tableOID: 1,
columnAttributeNumber: 1,
dataType: .int8,
dataType: .text,
dataTypeSize: 0,
dataTypeModifier: 0,
format: .binary
@@ -185,7 +185,7 @@ final class PostgresRowTests: XCTestCase {
columns: rowDescription
)

XCTAssertThrowsError(try row.decode((UUID?, String).self)) { error in
XCTAssertThrowsError(try row.decode((UUID?, Int).self)) { error in
guard let psqlError = error as? PostgresDecodingError else { return XCTFail("Unexpected error type") }

XCTAssertEqual(psqlError.columnName, "name")
@@ -194,8 +194,8 @@ final class PostgresRowTests: XCTestCase {
XCTAssertEqual(psqlError.file, #fileID)
XCTAssertEqual(psqlError.postgresData, ByteBuffer(integer: 123))
XCTAssertEqual(psqlError.postgresFormat, .binary)
XCTAssertEqual(psqlError.postgresType, .int8)
XCTAssert(psqlError.targetType == String.self)
XCTAssertEqual(psqlError.postgresType, .text)
XCTAssert(psqlError.targetType == Int.self)
}
}
}