Skip to content

Commit b5cca72

Browse files
authored
PostgresData: Fix en- and decoding of NULL values in arrays (#324)
1 parent 3a16650 commit b5cca72

File tree

2 files changed

+35
-6
lines changed

2 files changed

+35
-6
lines changed

Sources/PostgresNIO/Data/PostgresData+Array.swift

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ extension PostgresData {
1313
var buffer = ByteBufferAllocator().buffer(capacity: 0)
1414
// 0 if empty, 1 if not
1515
buffer.writeInteger(array.isEmpty ? 0 : 1, as: UInt32.self)
16-
// b
16+
// b - this gets ignored by psql
1717
buffer.writeInteger(0, as: UInt32.self)
1818
// array element type
1919
buffer.writeInteger(elementType.rawValue)
@@ -30,7 +30,7 @@ extension PostgresData {
3030
buffer.writeInteger(numericCast(value.readableBytes), as: UInt32.self)
3131
buffer.writeBuffer(&value)
3232
} else {
33-
buffer.writeInteger(0, as: UInt32.self)
33+
buffer.writeInteger(-1, as: Int32.self)
3434
}
3535
}
3636
}
@@ -77,10 +77,10 @@ extension PostgresData {
7777
guard let isNotEmpty = value.readInteger(as: UInt32.self) else {
7878
return nil
7979
}
80-
guard let b = value.readInteger(as: UInt32.self) else {
80+
// b
81+
guard let _ = value.readInteger(as: UInt32.self) else {
8182
return nil
8283
}
83-
assert(b == 0, "Array b field did not equal zero")
8484
guard let type = value.readInteger(as: PostgresDataType.self) else {
8585
return nil
8686
}
@@ -99,9 +99,9 @@ extension PostgresData {
9999

100100
var array: [PostgresData] = []
101101
while
102-
let itemLength = value.readInteger(as: UInt32.self),
103-
let itemValue = value.readSlice(length: numericCast(itemLength))
102+
let itemLength = value.readInteger(as: Int32.self)
104103
{
104+
let itemValue = itemLength == -1 ? nil : value.readSlice(length: numericCast(itemLength))
105105
let data = PostgresData(
106106
type: type,
107107
typeModifier: nil,

Tests/IntegrationTests/PostgresNIOTests.swift

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -555,6 +555,19 @@ final class PostgresNIOTests: XCTestCase {
555555
let row = rows?.first?.makeRandomAccess()
556556
XCTAssertEqual(row?[data: "array"].array(of: Int.self), [])
557557
}
558+
559+
func testOptionalIntegerArrayParse() {
560+
var conn: PostgresConnection?
561+
XCTAssertNoThrow(conn = try PostgresConnection.test(on: eventLoop).wait())
562+
defer { XCTAssertNoThrow( try conn?.close().wait() ) }
563+
var rows: PostgresQueryResult?
564+
XCTAssertNoThrow(rows = try conn?.query("""
565+
select
566+
'{1, 2, NULL, 4}'::int8[] as array
567+
""").wait())
568+
let row = rows?.first?.makeRandomAccess()
569+
XCTAssertEqual(row?[data: "array"].array(of: Int?.self), [1, 2, nil, 4])
570+
}
558571

559572
func testNullIntegerArrayParse() {
560573
var conn: PostgresConnection?
@@ -599,6 +612,22 @@ final class PostgresNIOTests: XCTestCase {
599612
XCTAssertEqual(row?[data: "array"].array(of: Int.self), [])
600613
}
601614

615+
func testOptionalIntegerArraySerialize() {
616+
var conn: PostgresConnection?
617+
XCTAssertNoThrow(conn = try PostgresConnection.test(on: eventLoop).wait())
618+
defer { XCTAssertNoThrow( try conn?.close().wait() ) }
619+
var rows: PostgresQueryResult?
620+
XCTAssertNoThrow(rows = try conn?.query("""
621+
select
622+
$1::int8[] as array
623+
""", [
624+
PostgresData(array: [1, nil, 3] as [Int64?])
625+
]).wait())
626+
XCTAssertEqual(rows?.count, 1)
627+
let row = rows?.first?.makeRandomAccess()
628+
XCTAssertEqual(row?[data: "array"].array(of: Int64?.self), [1, nil, 3])
629+
}
630+
602631
// https://github.com/vapor/postgres-nio/issues/143
603632
func testEmptyStringFromNonNullColumn() {
604633
var conn: PostgresConnection?

0 commit comments

Comments
 (0)