@@ -95,6 +95,20 @@ extension PostgresQuery {
95
95
}
96
96
}
97
97
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
+
98
112
struct PSQLExecuteStatement {
99
113
/// The statements name
100
114
var name : String
@@ -111,16 +125,19 @@ public struct PostgresBindings: Sendable, Hashable {
111
125
var dataType : PostgresDataType
112
126
@usableFromInline
113
127
var format : PostgresFormat
128
+ @usableFromInline
129
+ var protected : Bool
114
130
115
131
@inlinable
116
- init ( dataType: PostgresDataType , format: PostgresFormat ) {
132
+ init ( dataType: PostgresDataType , format: PostgresFormat , protected : Bool ) {
117
133
self . dataType = dataType
118
134
self . format = format
135
+ self . protected = protected
119
136
}
120
137
121
138
@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 )
124
141
}
125
142
}
126
143
@@ -147,7 +164,7 @@ public struct PostgresBindings: Sendable, Hashable {
147
164
148
165
public mutating func appendNull( ) {
149
166
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 ) )
151
168
}
152
169
153
170
@inlinable
@@ -156,7 +173,7 @@ public struct PostgresBindings: Sendable, Hashable {
156
173
context: PostgresEncodingContext < JSONEncoder >
157
174
) throws {
158
175
try value. encodeRaw ( into: & self . bytes, context: context)
159
- self . metadata. append ( . init( value: value) )
176
+ self . metadata. append ( . init( value: value, protected : true ) )
160
177
}
161
178
162
179
@inlinable
@@ -165,7 +182,25 @@ public struct PostgresBindings: Sendable, Hashable {
165
182
context: PostgresEncodingContext < JSONEncoder >
166
183
) {
167
184
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 ) )
169
204
}
170
205
171
206
public mutating func append( _ postgresData: PostgresData ) {
@@ -176,6 +211,93 @@ public struct PostgresBindings: Sendable, Hashable {
176
211
self . bytes. writeInteger ( Int32 ( input. readableBytes) )
177
212
self . bytes. writeBuffer ( & input)
178
213
}
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)
180
302
}
181
303
}
0 commit comments