@@ -86,12 +86,22 @@ extension QueryType {
86
86
/// - Returns: An `INSERT` statement for the encodable objects
87
87
public func insertMany( _ encodables: [ Encodable ] , userInfo: [ CodingUserInfoKey : Any ] = [ : ] ,
88
88
otherSetters: [ Setter ] = [ ] ) throws -> Insert {
89
- let combinedSetters = try encodables. map { encodable -> [ Setter ] in
90
- let encoder = SQLiteEncoder ( userInfo: userInfo)
89
+ let combinedSettersWithoutNils = try encodables. map { encodable -> [ Setter ] in
90
+ let encoder = SQLiteEncoder ( userInfo: userInfo, forcingNilValueSetters : false )
91
91
try encodable. encode ( to: encoder)
92
92
return encoder. setters + otherSetters
93
93
}
94
- return self . insertMany ( combinedSetters)
94
+ // requires the same number of setters per encodable
95
+ guard Set ( combinedSettersWithoutNils. map ( \. count) ) . count == 1 else {
96
+ // asymmetric sets of value insertions (some nil, some not), requires NULL value to satisfy INSERT query
97
+ let combinedSymmetricSetters = try encodables. map { encodable -> [ Setter ] in
98
+ let encoder = SQLiteEncoder ( userInfo: userInfo, forcingNilValueSetters: true )
99
+ try encodable. encode ( to: encoder)
100
+ return encoder. setters + otherSetters
101
+ }
102
+ return self . insertMany ( combinedSymmetricSetters)
103
+ }
104
+ return self . insertMany ( combinedSettersWithoutNils)
95
105
}
96
106
97
107
/// Creates an `INSERT ON CONFLICT DO UPDATE` statement, aka upsert, by encoding the given object
@@ -165,9 +175,11 @@ private class SQLiteEncoder: Encoder {
165
175
166
176
let encoder : SQLiteEncoder
167
177
let codingPath : [ CodingKey ] = [ ]
178
+ let forcingNilValueSetters : Bool
168
179
169
- init ( encoder: SQLiteEncoder ) {
180
+ init ( encoder: SQLiteEncoder , forcingNilValueSetters : Bool = false ) {
170
181
self . encoder = encoder
182
+ self . forcingNilValueSetters = forcingNilValueSetters
171
183
}
172
184
173
185
func superEncoder( ) -> Swift . Encoder {
@@ -202,6 +214,46 @@ private class SQLiteEncoder: Encoder {
202
214
encoder. setters. append ( Expression ( key. stringValue) <- value)
203
215
}
204
216
217
+ func encodeIfPresent( _ value: Int ? , forKey key: SQLiteEncoder . SQLiteKeyedEncodingContainer < Key > . Key ) throws {
218
+ if let value = value {
219
+ encoder. setters. append ( Expression ( key. stringValue) <- value)
220
+ } else if forcingNilValueSetters {
221
+ encoder. setters. append ( Expression < Int ? > ( key. stringValue) <- nil )
222
+ }
223
+ }
224
+
225
+ func encodeIfPresent( _ value: Bool ? , forKey key: Key ) throws {
226
+ if let value = value {
227
+ encoder. setters. append ( Expression ( key. stringValue) <- value)
228
+ } else if forcingNilValueSetters {
229
+ encoder. setters. append ( Expression < Bool ? > ( key. stringValue) <- nil )
230
+ }
231
+ }
232
+
233
+ func encodeIfPresent( _ value: Float ? , forKey key: Key ) throws {
234
+ if let value = value {
235
+ encoder. setters. append ( Expression ( key. stringValue) <- Double ( value) )
236
+ } else if forcingNilValueSetters{
237
+ encoder. setters. append ( Expression < Double ? > ( key. stringValue) <- nil )
238
+ }
239
+ }
240
+
241
+ func encodeIfPresent( _ value: Double ? , forKey key: Key ) throws {
242
+ if let value = value {
243
+ encoder. setters. append ( Expression ( key. stringValue) <- value)
244
+ } else if forcingNilValueSetters {
245
+ encoder. setters. append ( Expression < Double ? > ( key. stringValue) <- nil )
246
+ }
247
+ }
248
+
249
+ func encodeIfPresent( _ value: String ? , forKey key: MyKey ) throws {
250
+ if let value = value {
251
+ encoder. setters. append ( Expression ( key. stringValue) <- value)
252
+ } else if forcingNilValueSetters {
253
+ encoder. setters. append ( Expression < String ? > ( key. stringValue) <- nil )
254
+ }
255
+ }
256
+
205
257
func encode< T> ( _ value: T , forKey key: Key ) throws where T: Swift . Encodable {
206
258
switch value {
207
259
case let data as Data :
@@ -217,6 +269,28 @@ private class SQLiteEncoder: Encoder {
217
269
}
218
270
}
219
271
272
+ func encodeIfPresent< T> ( _ value: T ? , forKey key: Key ) throws where T: Swift . Encodable {
273
+ guard let value = value else {
274
+ guard forcingNilValueSetters else {
275
+ return
276
+ }
277
+ encoder. setters. append ( Expression < String ? > ( key. stringValue) <- nil )
278
+ return
279
+ }
280
+ switch value {
281
+ case let data as Data :
282
+ encoder. setters. append ( Expression ( key. stringValue) <- data)
283
+ case let date as Date :
284
+ encoder. setters. append ( Expression ( key. stringValue) <- date. datatypeValue)
285
+ case let uuid as UUID :
286
+ encoder. setters. append ( Expression ( key. stringValue) <- uuid. datatypeValue)
287
+ default :
288
+ let encoded = try JSONEncoder ( ) . encode ( value)
289
+ let string = String ( data: encoded, encoding: . utf8)
290
+ encoder. setters. append ( Expression ( key. stringValue) <- string)
291
+ }
292
+ }
293
+
220
294
func encode( _ value: Int8 , forKey key: Key ) throws {
221
295
throw EncodingError . invalidValue ( value, EncodingError . Context ( codingPath: codingPath,
222
296
debugDescription: " encoding an Int8 is not supported " ) )
@@ -274,9 +348,11 @@ private class SQLiteEncoder: Encoder {
274
348
fileprivate var setters : [ Setter ] = [ ]
275
349
let codingPath : [ CodingKey ] = [ ]
276
350
let userInfo : [ CodingUserInfoKey : Any ]
351
+ let forcingNilValueSetters : Bool
277
352
278
- init ( userInfo: [ CodingUserInfoKey : Any ] ) {
353
+ init ( userInfo: [ CodingUserInfoKey : Any ] , forcingNilValueSetters : Bool = false ) {
279
354
self . userInfo = userInfo
355
+ self . forcingNilValueSetters = forcingNilValueSetters
280
356
}
281
357
282
358
func singleValueContainer( ) -> SingleValueEncodingContainer {
@@ -288,7 +364,7 @@ private class SQLiteEncoder: Encoder {
288
364
}
289
365
290
366
func container< Key> ( keyedBy type: Key . Type ) -> KeyedEncodingContainer < Key > where Key: CodingKey {
291
- KeyedEncodingContainer ( SQLiteKeyedEncodingContainer ( encoder: self ) )
367
+ KeyedEncodingContainer ( SQLiteKeyedEncodingContainer ( encoder: self , forcingNilValueSetters : forcingNilValueSetters ) )
292
368
}
293
369
}
294
370
0 commit comments