@@ -95,6 +95,20 @@ extension PostgresQuery {
9595 }
9696}
9797
98+ extension PostgresQuery : CustomStringConvertible {
99+ /// See ``Swift/CustomStringConvertible/description``.
100+ public var description : String {
101+ " \( self . sql) \( self . binds) "
102+ }
103+ }
104+
105+ extension PostgresQuery : CustomDebugStringConvertible {
106+ /// See ``Swift/CustomDebugStringConvertible/debugDescription``.
107+ public var debugDescription : String {
108+ " PostgresQuery(sql: \( String ( describing: self . sql) ) , binds: \( String ( reflecting: self . binds) ) ) "
109+ }
110+ }
111+
98112struct PSQLExecuteStatement {
99113 /// The statements name
100114 var name : String
@@ -111,16 +125,19 @@ public struct PostgresBindings: Sendable, Hashable {
111125 var dataType : PostgresDataType
112126 @usableFromInline
113127 var format : PostgresFormat
128+ @usableFromInline
129+ var protected : Bool
114130
115131 @inlinable
116- init ( dataType: PostgresDataType , format: PostgresFormat ) {
132+ init ( dataType: PostgresDataType , format: PostgresFormat , protected : Bool ) {
117133 self . dataType = dataType
118134 self . format = format
135+ self . protected = protected
119136 }
120137
121138 @inlinable
122- init < Value: PostgresEncodable > ( value: Value ) {
123- self . init ( dataType: Value . psqlType, format: Value . psqlFormat)
139+ init < Value: PostgresEncodable > ( value: Value , protected : Bool ) {
140+ self . init ( dataType: Value . psqlType, format: Value . psqlFormat, protected : protected )
124141 }
125142 }
126143
@@ -147,7 +164,7 @@ public struct PostgresBindings: Sendable, Hashable {
147164
148165 public mutating func appendNull( ) {
149166 self . bytes. writeInteger ( - 1 , as: Int32 . self)
150- self . metadata. append ( . init( dataType: . null, format: . binary) )
167+ self . metadata. append ( . init( dataType: . null, format: . binary, protected : true ) )
151168 }
152169
153170 @inlinable
@@ -156,7 +173,7 @@ public struct PostgresBindings: Sendable, Hashable {
156173 context: PostgresEncodingContext < JSONEncoder >
157174 ) throws {
158175 try value. encodeRaw ( into: & self . bytes, context: context)
159- self . metadata. append ( . init( value: value) )
176+ self . metadata. append ( . init( value: value, protected : true ) )
160177 }
161178
162179 @inlinable
@@ -165,7 +182,25 @@ public struct PostgresBindings: Sendable, Hashable {
165182 context: PostgresEncodingContext < JSONEncoder >
166183 ) {
167184 value. encodeRaw ( into: & self . bytes, context: context)
168- self . metadata. append ( . init( value: value) )
185+ self . metadata. append ( . init( value: value, protected: true ) )
186+ }
187+
188+ @inlinable
189+ mutating func appendUnprotected< Value: PostgresEncodable , JSONEncoder: PostgresJSONEncoder > (
190+ _ value: Value ,
191+ context: PostgresEncodingContext < JSONEncoder >
192+ ) throws {
193+ try value. encodeRaw ( into: & self . bytes, context: context)
194+ self . metadata. append ( . init( value: value, protected: false ) )
195+ }
196+
197+ @inlinable
198+ mutating func appendUnprotected< Value: PostgresNonThrowingEncodable , JSONEncoder: PostgresJSONEncoder > (
199+ _ value: Value ,
200+ context: PostgresEncodingContext < JSONEncoder >
201+ ) {
202+ value. encodeRaw ( into: & self . bytes, context: context)
203+ self . metadata. append ( . init( value: value, protected: false ) )
169204 }
170205
171206 public mutating func append( _ postgresData: PostgresData ) {
@@ -176,6 +211,93 @@ public struct PostgresBindings: Sendable, Hashable {
176211 self . bytes. writeInteger ( Int32 ( input. readableBytes) )
177212 self . bytes. writeBuffer ( & input)
178213 }
179- self . metadata. append ( . init( dataType: postgresData. type, format: . binary) )
214+ self . metadata. append ( . init( dataType: postgresData. type, format: . binary, protected: true ) )
215+ }
216+ }
217+
218+ extension PostgresBindings : CustomStringConvertible , CustomDebugStringConvertible {
219+ /// See ``Swift/CustomStringConvertible/description``.
220+ public var description : String {
221+ """
222+ [ \( zip ( self . metadata, BindingsReader ( buffer: self . bytes) )
223+ . lazy. map ( { Self . makeBindingPrintable ( protected: $0. protected, type: $0. dataType, format: $0. format, buffer: $1) } )
224+ . joined ( separator: " , " ) ) ]
225+ """
226+ }
227+
228+ /// See ``Swift/CustomDebugStringConvertible/description``.
229+ public var debugDescription : String {
230+ """
231+ [ \( zip ( self . metadata, BindingsReader ( buffer: self . bytes) )
232+ . lazy. map ( { Self . makeDebugDescription ( protected: $0. protected, type: $0. dataType, format: $0. format, buffer: $1) } )
233+ . joined ( separator: " , " ) ) ]
234+ """
235+ }
236+
237+ private static func makeDebugDescription( protected: Bool , type: PostgresDataType , format: PostgresFormat , buffer: ByteBuffer ? ) -> String {
238+ " ( \( Self . makeBindingPrintable ( protected: protected, type: type, format: format, buffer: buffer) ) ; \( type) ; format: \( format) ) "
239+ }
240+
241+ private static func makeBindingPrintable( protected: Bool , type: PostgresDataType , format: PostgresFormat , buffer: ByteBuffer ? ) -> String {
242+ if protected {
243+ return " **** "
244+ }
245+
246+ guard var buffer = buffer else {
247+ return " null "
248+ }
249+
250+ do {
251+ switch ( type, format) {
252+ case ( . int4, _) , ( . int2, _) , ( . int8, _) :
253+ let number = try Int64 . init ( from: & buffer, type: type, format: format, context: . default)
254+ return String ( describing: number)
255+
256+ case ( . bool, _) :
257+ let bool = try Bool . init ( from: & buffer, type: type, format: format, context: . default)
258+ return String ( describing: bool)
259+
260+ case ( . varchar, _) , ( . bpchar, _) , ( . text, _) , ( . name, _) :
261+ let value = try String . init ( from: & buffer, type: type, format: format, context: . default)
262+ return String ( reflecting: value) // adds quotes
263+
264+ default :
265+ return " \( buffer. readableBytes) bytes "
266+ }
267+ } catch {
268+ return " \( buffer. readableBytes) bytes "
269+ }
270+ }
271+ }
272+
273+ /// A small helper to inspect encoded bindings
274+ private struct BindingsReader : Sequence {
275+ typealias Element = Optional < ByteBuffer >
276+
277+ var buffer : ByteBuffer
278+
279+ struct Iterator : IteratorProtocol {
280+ typealias Element = Optional < ByteBuffer >
281+ private var buffer : ByteBuffer
282+
283+ init ( buffer: ByteBuffer ) {
284+ self . buffer = buffer
285+ }
286+
287+ mutating func next( ) -> Optional < Optional < ByteBuffer > > {
288+ guard let length = self . buffer. readInteger ( as: Int32 . self) else {
289+ return . none
290+ }
291+
292+ if length < 0 {
293+ return . some( . none)
294+ }
295+
296+ return . some( self . buffer. readSlice ( length: Int ( length) ) !)
297+ }
298+ }
299+
300+ func makeIterator( ) -> Iterator {
301+ Iterator ( buffer: self . buffer)
180302 }
181303}
0 commit comments