@@ -307,17 +307,18 @@ public final class PostgresConnection: SQLDatabase, @unchecked Sendable {
307307 var allSets : [ [ SQLRow ] ] = [ ]
308308 var current : [ SQLRow ] = [ ]
309309 var columns : [ PGColumnDesc ] = [ ]
310+ var sqlCols : [ SQLColumn ] = [ ] // computed once per RowDescription
310311 var pendingError : ( any Error ) ?
311312
312313 loop: while true {
313314 let m = try await receiveMessage ( )
314315 switch m {
315316 case . rowDescription( let cols) :
316317 columns = cols
318+ sqlCols = cols. map { SQLColumn ( name: $0. name, dataTypeID: $0. typeOID) }
317319 current = [ ]
318320 case . dataRow( let rawValues) :
319321 if pendingError == nil {
320- let sqlCols = columns. map { SQLColumn ( name: $0. name, dataTypeID: $0. typeOID) }
321322 let values = zip ( columns, rawValues) . map { col, raw -> SQLValue in
322323 guard var buf = raw else { return . null }
323324 return pgDecode ( typeOID: col. typeOID, buffer: & buf)
@@ -329,6 +330,7 @@ public final class PostgresConnection: SQLDatabase, @unchecked Sendable {
329330 allSets. append ( current)
330331 current = [ ]
331332 columns = [ ]
333+ sqlCols = [ ]
332334 }
333335 case . readyForQuery:
334336 break loop
@@ -399,6 +401,7 @@ public final class PostgresConnection: SQLDatabase, @unchecked Sendable {
399401
400402 private func collectResults( ) async throws -> [ SQLRow ] {
401403 var columns : [ PGColumnDesc ] = [ ]
404+ var sqlCols : [ SQLColumn ] = [ ] // computed once per RowDescription, shared across rows
402405 var rows : [ SQLRow ] = [ ]
403406 var pendingError : ( any Error ) ?
404407
@@ -407,11 +410,9 @@ public final class PostgresConnection: SQLDatabase, @unchecked Sendable {
407410 switch msg {
408411 case . rowDescription( let cols) :
409412 columns = cols
413+ sqlCols = cols. map { SQLColumn ( name: $0. name, dataTypeID: $0. typeOID) }
410414 case . dataRow( let rawValues) :
411415 if pendingError == nil {
412- let sqlCols = columns. map {
413- SQLColumn ( name: $0. name, dataTypeID: $0. typeOID)
414- }
415416 let values = zip ( columns, rawValues) . map { col, raw -> SQLValue in
416417 guard var buf = raw else { return . null }
417418 return pgDecode ( typeOID: col. typeOID, buffer: & buf)
@@ -463,6 +464,24 @@ public final class PostgresConnection: SQLDatabase, @unchecked Sendable {
463464
464465// MARK: - PostgreSQL text decoder
465466
467+ // Static formatters — DateFormatter/ISO8601DateFormatter are expensive to construct;
468+ // allocating one per cell (old behaviour) added measurable overhead on date-heavy result sets.
469+ private nonisolated ( unsafe) let _pgDateFmt: DateFormatter = {
470+ let f = DateFormatter ( ) ; f. locale = Locale ( identifier: " en_US_POSIX " )
471+ f. dateFormat = " yyyy-MM-dd " ; return f
472+ } ( )
473+ private nonisolated ( unsafe) let _pgTsFmt: ISO8601DateFormatter = {
474+ let f = ISO8601DateFormatter ( )
475+ f. formatOptions = [ . withInternetDateTime, . withFractionalSeconds]
476+ return f
477+ } ( )
478+ private nonisolated ( unsafe) let _pgTsFmt2 : ISO8601DateFormatter = {
479+ // Postgres may omit fractional seconds
480+ let f = ISO8601DateFormatter ( )
481+ f. formatOptions = [ . withInternetDateTime]
482+ return f
483+ } ( )
484+
466485func pgDecode( typeOID: UInt32 , buffer: inout ByteBuffer ) -> SQLValue {
467486 let text = buffer. readString ( length: buffer. readableBytes) ?? " "
468487 switch typeOID {
@@ -481,18 +500,22 @@ func pgDecode(typeOID: UInt32, buffer: inout ByteBuffer) -> SQLValue {
481500 case 2950 : // uuid
482501 return UUID ( uuidString: text) . map { . uuid( $0) } ?? . string( text)
483502 case 1082 : // date
484- let fmt = DateFormatter ( ) ; fmt. dateFormat = " yyyy-MM-dd "
485- return fmt. date ( from: text) . map { . date( $0) } ?? . string( text)
503+ return _pgDateFmt. date ( from: text) . map { . date( $0) } ?? . string( text)
486504 case 1114 , 1184 : // timestamp, timestamptz
487- let fmt = ISO8601DateFormatter ( )
488- return fmt. date ( from: text) . map { . date( $0) } ?? . string( text)
505+ return ( _pgTsFmt. date ( from: text) ?? _pgTsFmt2. date ( from: text) ) . map { . date( $0) } ?? . string( text)
489506 default :
490507 return . string( text)
491508 }
492509}
493510
494511// MARK: - SQLValue → PostgreSQL literal
495512
513+ private nonisolated ( unsafe) let _pgLiteralFmt: ISO8601DateFormatter = {
514+ let f = ISO8601DateFormatter ( )
515+ f. formatOptions = [ . withInternetDateTime, . withFractionalSeconds]
516+ return f
517+ } ( )
518+
496519private extension SQLValue {
497520 var pgLiteral : String {
498521 switch self {
@@ -509,9 +532,7 @@ private extension SQLValue {
509532 case . string( let v) : return " ' \( v. replacingOccurrences ( of: " ' " , with: " '' " ) ) ' "
510533 case . bytes( let v) : return " E' \\ \\ x " + v. map { String ( format: " %02x " , $0) } . joined ( ) + " ' "
511534 case . uuid( let v) : return " ' \( v. uuidString) ' "
512- case . date( let v) :
513- let fmt = ISO8601DateFormatter ( )
514- return " ' \( fmt. string ( from: v) ) ' "
535+ case . date( let v) : return " ' \( _pgLiteralFmt. string ( from: v) ) ' "
515536 }
516537 }
517538}
0 commit comments