Skip to content
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

Fix multiple array type mapping mistakes and add missing date and time array types #463

Merged
merged 4 commits into from
Mar 8, 2024
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
30 changes: 23 additions & 7 deletions Sources/PostgresNIO/Data/PostgresDataType.swift
Original file line number Diff line number Diff line change
Expand Up @@ -113,12 +113,14 @@ public struct PostgresDataType: RawRepresentable, Sendable, Hashable, CustomStri
/// `774`
public static let macaddr8 = PostgresDataType(774)
/// `775`
public static let macaddr8Aray = PostgresDataType(775)
@available(*, deprecated, renamed: "macaddr8Array")
public static let macaddr8Aray = Self.macaddr8Array
public static let macaddr8Array = PostgresDataType(775)
/// `790`
public static let money = PostgresDataType(790)
/// `791`
@available(*, deprecated, renamed: "moneyArray")
public static let _money = PostgresDataType(791)
public static let _money = Self.moneyArray
public static let moneyArray = PostgresDataType(791)
/// `829`
public static let macaddr = PostgresDataType(829)
Expand Down Expand Up @@ -192,6 +194,10 @@ public struct PostgresDataType: RawRepresentable, Sendable, Hashable, CustomStri
public static let timestamp = PostgresDataType(1114)
/// `1115` _timestamp
public static let timestampArray = PostgresDataType(1115)
/// `1182`
public static let dateArray = PostgresDataType(1182)
/// `1183`
public static let timeArray = PostgresDataType(1183)
/// `1184`
public static let timestamptz = PostgresDataType(1184)
/// `1185`
Expand Down Expand Up @@ -446,7 +452,7 @@ public struct PostgresDataType: RawRepresentable, Sendable, Hashable, CustomStri
case .circle: return "CIRCLE"
case .circleArray: return "CIRCLE[]"
case .macaddr8: return "MACADDR8"
case .macaddr8Aray: return "MACADDR8[]"
case .macaddr8Array: return "MACADDR8[]"
case .money: return "MONEY"
case .moneyArray: return "MONEY[]"
case .macaddr: return "MACADDR"
Expand Down Expand Up @@ -485,6 +491,8 @@ public struct PostgresDataType: RawRepresentable, Sendable, Hashable, CustomStri
case .time: return "TIME"
case .timestamp: return "TIMESTAMP"
case .timestampArray: return "TIMESTAMP[]"
case .dateArray: return "DATE[]"
case .timeArray: return "TIME[]"
case .timestamptz: return "TIMESTAMPTZ"
case .timestamptzArray: return "TIMESTAMPTZ[]"
case .interval: return "INTERVAL"
Expand Down Expand Up @@ -596,7 +604,7 @@ public struct PostgresDataType: RawRepresentable, Sendable, Hashable, CustomStri
case .line: return .lineArray
case .cidr: return .cidrArray
case .circle: return .circleArray
case .macaddr8Aray: return .macaddr8
case .macaddr8: return .macaddr8Array
case .money: return .moneyArray
case .int2vector: return .int2vectorArray
case .regproc: return .regprocArray
Expand All @@ -613,6 +621,9 @@ public struct PostgresDataType: RawRepresentable, Sendable, Hashable, CustomStri
case .aclitem: return .aclitemArray
case .macaddr: return .macaddrArray
case .inet: return .inetArray
case .timestamp: return .timestampArray
case .date: return .dateArray
case .time: return .timeArray
case .timestamptz: return .timestamptzArray
case .interval: return .intervalArray
case .numeric: return .numericArray
Expand All @@ -635,6 +646,7 @@ public struct PostgresDataType: RawRepresentable, Sendable, Hashable, CustomStri
case .regdictionary: return .regdictionaryArray
case .numrange: return .numrangeArray
case .tsrange: return .tsrangeArray
case .tstzrange: return .tstzrangeArray
case .daterange: return .daterangeArray
case .jsonpath: return .jsonpathArray
case .regnamespace: return .regnamespaceArray
Expand All @@ -643,7 +655,7 @@ public struct PostgresDataType: RawRepresentable, Sendable, Hashable, CustomStri
case .int4multirange: return .int4multirangeArray
case .tsmultirange: return .tsmultirangeArray
case .tstzmultirange: return .tstzmultirangeArray
case .datemultirange: return .datemultirange
case .datemultirange: return .datemultirangeArray
case .int8multirange: return .int8multirangeArray
case .bool: return .boolArray
case .bytea: return .byteaArray
Expand Down Expand Up @@ -677,7 +689,7 @@ public struct PostgresDataType: RawRepresentable, Sendable, Hashable, CustomStri
case .lineArray: return .line
case .cidrArray: return .cidr
case .circleArray: return .circle
case .macaddr8: return .macaddr8Aray
case .macaddr8Array: return .macaddr8
case .moneyArray: return .money
case .int2vectorArray: return .int2vector
case .regprocArray: return .regproc
Expand All @@ -694,6 +706,9 @@ public struct PostgresDataType: RawRepresentable, Sendable, Hashable, CustomStri
case .aclitemArray: return .aclitem
case .macaddrArray: return .macaddr
case .inetArray: return .inet
case .timestampArray: return .timestamp
case .dateArray: return .date
case .timeArray: return .time
case .timestamptzArray: return .timestamptz
case .intervalArray: return .interval
case .numericArray: return .numeric
Expand All @@ -716,6 +731,7 @@ public struct PostgresDataType: RawRepresentable, Sendable, Hashable, CustomStri
case .regdictionaryArray: return .regdictionary
case .numrangeArray: return .numrange
case .tsrangeArray: return .tsrange
case .tstzrangeArray: return .tstzrange
case .daterangeArray: return .daterange
case .jsonpathArray: return .jsonpath
case .regnamespaceArray: return .regnamespace
Expand All @@ -724,7 +740,7 @@ public struct PostgresDataType: RawRepresentable, Sendable, Hashable, CustomStri
case .int4multirangeArray: return .int4multirange
case .tsmultirangeArray: return .tsmultirange
case .tstzmultirangeArray: return .tstzmultirange
case .datemultirange: return .datemultirange
case .datemultirangeArray: return .datemultirange
case .int8multirangeArray: return .int8multirange
case .boolArray: return .bool
case .byteaArray: return .bytea
Expand Down
7 changes: 7 additions & 0 deletions Sources/PostgresNIO/New/Data/Array+PostgresCodable.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import NIOCore
import struct Foundation.Date
import struct Foundation.UUID

// MARK: Protocols
Expand Down Expand Up @@ -85,6 +86,12 @@ extension UUID: PostgresArrayEncodable {
public static var psqlArrayType: PostgresDataType { .uuidArray }
}

extension Date: PostgresArrayDecodable {}

extension Date: PostgresArrayEncodable {
public static var psqlArrayType: PostgresDataType { .timestamptzArray }
}

extension Range: PostgresArrayDecodable where Bound: PostgresRangeArrayDecodable {}

extension Range: PostgresArrayEncodable where Bound: PostgresRangeArrayEncodable {
Expand Down
38 changes: 38 additions & 0 deletions Tests/IntegrationTests/PostgresNIOTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -783,6 +783,44 @@ final class PostgresNIOTests: XCTestCase {
XCTAssertEqual(row?[data: "array"].array(of: Int64?.self), [1, nil, 3])
}

@available(*, deprecated, message: "Testing deprecated functionality")
func testDateArraySerialize() {
var conn: PostgresConnection?
XCTAssertNoThrow(conn = try PostgresConnection.test(on: eventLoop).wait())
defer { XCTAssertNoThrow( try conn?.close().wait() ) }
let date1 = Date(timeIntervalSince1970: 1704088800),
date2 = Date(timeIntervalSince1970: 1706767200),
date3 = Date(timeIntervalSince1970: 1709272800)
var rows: PostgresQueryResult?
XCTAssertNoThrow(rows = try conn?.query("""
select
$1::timestamptz[] as array
""", [
PostgresData(array: [date1, date2, date3])
]).wait())
let row = rows?.first?.makeRandomAccess()
XCTAssertEqual(row?[data: "array"].array(of: Date.self), [date1, date2, date3])
}

@available(*, deprecated, message: "Testing deprecated functionality")
func testDateArraySerializeAsPostgresDate() {
var conn: PostgresConnection?
XCTAssertNoThrow(conn = try PostgresConnection.test(on: eventLoop).wait())
defer { XCTAssertNoThrow(try conn?.close().wait()) }
let date1 = Date(timeIntervalSince1970: 1704088800),//8766
date2 = Date(timeIntervalSince1970: 1706767200),//8797
date3 = Date(timeIntervalSince1970: 1709272800) //8826
var data = PostgresData(array: [date1, date2, date3].map { Int32(($0.timeIntervalSince1970 - 946_684_800) / 86_400).postgresData }, elementType: .date)
data.type = .dateArray // N.B.: `.date` format is an Int32 count of days since psqlStartDate
var rows: PostgresQueryResult?
XCTAssertNoThrow(rows = try conn?.query("select $1::date[] as array", [data]).wait())
let row = rows?.first?.makeRandomAccess()
XCTAssertEqual(
row?[data: "array"].array(of: Date.self)?.map { Int32((($0.timeIntervalSince1970 - 946_684_800) / 86_400).rounded(.toNearestOrAwayFromZero)) },
[date1, date2, date3].map { Int32((($0.timeIntervalSince1970 - 946_684_800) / 86_400).rounded(.toNearestOrAwayFromZero)) }
)
}

// https://github.com/vapor/postgres-nio/issues/143
func testEmptyStringFromNonNullColumn() {
var conn: PostgresConnection?
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ class Array_PSQLCodableTests: XCTestCase {
XCTAssertEqual(UUID.psqlType, .uuid)
XCTAssertEqual([UUID].psqlType, .uuidArray)

XCTAssertEqual(Date.psqlArrayType, .timestamptzArray)
XCTAssertEqual(Date.psqlType, .timestamptz)
XCTAssertEqual([Date].psqlType, .timestamptzArray)

XCTAssertEqual(Range<Int32>.psqlArrayType, .int4RangeArray)
XCTAssertEqual(Range<Int32>.psqlType, .int4Range)
XCTAssertEqual([Range<Int32>].psqlType, .int4RangeArray)
Expand Down
Loading