@@ -83,6 +83,97 @@ extension MutablePersistableRecordEncodableTests {
8383 XCTAssertEqual ( string, " foo (MutablePersistableRecord) " )
8484 }
8585 }
86+
87+ // Regression test for <https://github.com/groue/GRDB.swift/issues/1565>
88+ func testSingleValueContainer( ) throws {
89+ struct Struct : Encodable {
90+ let value : String
91+ }
92+
93+ struct Wrapper < Model: Encodable > : MutablePersistableRecord , Encodable {
94+ static var databaseTableName : String { " t1 " }
95+ var model : Model
96+ var otherValue : String
97+
98+ enum CodingKeys : String , CodingKey {
99+ case otherValue
100+ }
101+
102+ func encode( to encoder: any Encoder ) throws {
103+ var modelContainer = encoder. singleValueContainer ( )
104+ try modelContainer. encode ( model)
105+
106+ var container = encoder. container ( keyedBy: CodingKeys . self)
107+ try container. encode ( otherValue, forKey: . otherValue)
108+ }
109+ }
110+
111+ let dbQueue = try makeDatabaseQueue ( )
112+ try dbQueue. inDatabase { db in
113+ try db. create ( table: " t1 " ) { t in
114+ t. column ( " value " , . text)
115+ t. column ( " otherValue " , . text)
116+ }
117+
118+ var value = Wrapper ( model: Struct ( value: " foo " ) , otherValue: " bar " )
119+ try assert ( value, isEncodedIn: [ " value " : " foo " , " otherValue " : " bar " ] )
120+
121+ try value. insert ( db)
122+ let row = try Row . fetchOne ( db, sql: " SELECT value, otherValue FROM t1 " ) !
123+ XCTAssertEqual ( row [ 0 ] , " foo " )
124+ XCTAssertEqual ( row [ 1 ] , " bar " )
125+ }
126+ }
127+
128+ // Regression test for <https://github.com/groue/GRDB.swift/issues/1565>
129+ // Here we test that `EncodableRecord` takes precedence over `Encodable`
130+ // when a record is encoded with a `SingleValueEncodingContainer`.
131+ func testSingleValueContainerWithEncodableRecord( ) throws {
132+ struct Struct : Encodable , EncodableRecord {
133+ let value : String
134+
135+ func encode( to container: inout PersistenceContainer ) throws {
136+ container [ " column1 " ] = " test "
137+ container [ " column2 " ] = 12
138+ }
139+ }
140+
141+ struct Wrapper < Model: Encodable > : MutablePersistableRecord , Encodable {
142+ static var databaseTableName : String { " t1 " }
143+ var model : Model
144+ var otherValue : String
145+
146+ enum CodingKeys : String , CodingKey {
147+ case otherValue
148+ }
149+
150+ func encode( to encoder: any Encoder ) throws {
151+ var modelContainer = encoder. singleValueContainer ( )
152+ try modelContainer. encode ( model)
153+
154+ var container = encoder. container ( keyedBy: CodingKeys . self)
155+ try container. encode ( otherValue, forKey: . otherValue)
156+ }
157+ }
158+
159+ let dbQueue = try makeDatabaseQueue ( )
160+ try dbQueue. inDatabase { db in
161+ try db. create ( table: " t1 " ) { t in
162+ t. column ( " column1 " , . text)
163+ t. column ( " column2 " , . integer)
164+ t. column ( " otherValue " , . text)
165+ }
166+
167+ var value = Wrapper ( model: Struct ( value: " foo " ) , otherValue: " bar " )
168+ try assert ( value, isEncodedIn: [ " column1 " : " test " , " column2 " : 12 , " otherValue " : " bar " ] )
169+
170+ try value. insert ( db)
171+ let row = try Row . fetchOne ( db, sql: " SELECT column1, column2, otherValue FROM t1 " ) !
172+ XCTAssertEqual ( row [ 0 ] , " test " )
173+ XCTAssertEqual ( row [ 1 ] , 12 )
174+ XCTAssertEqual ( row [ 2 ] , " bar " )
175+ }
176+ }
86177}
87178
88179// MARK: - Different kinds of single-value properties
0 commit comments