@@ -77,7 +77,7 @@ class AssociationHasManyFirstSQLTests: GRDBTestCase {
77
77
}
78
78
}
79
79
80
- func testHasManyFirstWithDeeperAssociation ( ) throws {
80
+ func testHasManyFirstWithOneDeeperAssociation ( ) throws {
81
81
struct Toy : TableRecord { }
82
82
struct Child : TableRecord { }
83
83
struct Parent : TableRecord , EncodableRecord {
@@ -266,6 +266,149 @@ class AssociationHasManyFirstSQLTests: GRDBTestCase {
266
266
}
267
267
}
268
268
}
269
+
270
+ func testHasManyFirstWithTwoDeeperAssociations( ) throws {
271
+ struct Vendor : TableRecord { }
272
+ struct Toy : TableRecord { }
273
+ struct Child : TableRecord { }
274
+ struct Parent : TableRecord , EncodableRecord {
275
+ func encode( to container: inout PersistenceContainer ) {
276
+ container [ " id " ] = 1
277
+ container [ " rowid " ] = 2
278
+ }
279
+ }
280
+
281
+ let dbQueue = try makeDatabaseQueue ( )
282
+ try dbQueue. inDatabase { db in
283
+ try db. create ( table: " parent " ) { t in
284
+ t. autoIncrementedPrimaryKey ( " id " )
285
+ }
286
+ try db. create ( table: " vendor " ) { t in
287
+ t. autoIncrementedPrimaryKey ( " id " )
288
+ }
289
+ try db. create ( table: " child " ) { t in
290
+ t. autoIncrementedPrimaryKey ( " id " )
291
+ t. column ( " parentId " , . integer) . references ( " parent " )
292
+ }
293
+ try db. create ( table: " toy " ) { t in
294
+ t. autoIncrementedPrimaryKey ( " id " )
295
+ t. column ( " childId " , . integer) . references ( " child " )
296
+ t. column ( " vendorId " , . integer) . references ( " vendor " )
297
+ }
298
+
299
+ do {
300
+ let association = Parent
301
+ . hasMany ( Child . self)
302
+ . orderByPrimaryKey ( )
303
+ . first
304
+ . joining ( required: Child . hasOne ( Toy . self) . including ( optional: Toy . belongsTo ( Vendor . self) ) )
305
+ XCTFail ( " TODO: fix SQL " )
306
+ // TODO: vendor is included and should be present in the selection
307
+ try assertMatchSQL ( db, Parent . all ( ) . including ( required: association) , """
308
+ SELECT " parent " .*, " child " .*
309
+ FROM " parent "
310
+ JOIN " child " ON " child " . " id " = (
311
+ SELECT " child " . " id "
312
+ FROM " child "
313
+ JOIN " toy " ON " toy " . " childId " = " child " . " id "
314
+ LEFT JOIN " vendor " ON " vendor " . " id " = " toy " . " vendorId "
315
+ WHERE " child " . " parentId " = " parent " . " id "
316
+ ORDER BY " child " . " id "
317
+ LIMIT 1)
318
+ """ )
319
+ try assertMatchSQL ( db, Parent . all ( ) . including ( optional: association) , """
320
+ SELECT " parent " .*, " child " .*
321
+ FROM " parent "
322
+ LEFT JOIN " child " ON " child " . " id " = (
323
+ SELECT " child " . " id "
324
+ FROM " child "
325
+ JOIN " toy " ON " toy " . " childId " = " child " . " id "
326
+ LEFT JOIN " vendor " ON " vendor " . " id " = " toy " . " vendorId "
327
+ WHERE " child " . " parentId " = " parent " . " id "
328
+ ORDER BY " child " . " id " LIMIT 1)
329
+ """ )
330
+ try assertMatchSQL ( db, Parent . all ( ) . joining ( required: association) , """
331
+ SELECT " parent " .*
332
+ FROM " parent "
333
+ JOIN " child " ON " child " . " id " = (
334
+ SELECT " child " . " id "
335
+ FROM " child "
336
+ JOIN " toy " ON " toy " . " childId " = " child " . " id "
337
+ LEFT JOIN " vendor " ON " vendor " . " id " = " toy " . " vendorId "
338
+ WHERE " child " . " parentId " = " parent " . " id "
339
+ ORDER BY " child " . " id "
340
+ LIMIT 1)
341
+ """ )
342
+ try assertMatchSQL ( db, Parent . all ( ) . joining ( optional: association) , """
343
+ SELECT " parent " .*
344
+ FROM " parent "
345
+ LEFT JOIN " child " ON " child " . " id " = (
346
+ SELECT " child " . " id "
347
+ FROM " child "
348
+ JOIN " toy " ON " toy " . " childId " = " child " . " id "
349
+ LEFT JOIN " vendor " ON " vendor " . " id " = " toy " . " vendorId "
350
+ WHERE " child " . " parentId " = " parent " . " id "
351
+ ORDER BY " child " . " id "
352
+ LIMIT 1)
353
+ """ )
354
+ try assertMatchSQL ( db, Parent ( ) . request ( for: association) , """
355
+ SELECT " child " .*, " vendor " .*
356
+ FROM " child "
357
+ JOIN " toy " ON " toy " . " childId " = " child " . " id "
358
+ LEFT JOIN " vendor " ON " vendor " . " id " = " toy " . " vendorId "
359
+ WHERE " child " . " parentId " = 1
360
+ ORDER BY " child " . " id "
361
+ LIMIT 1
362
+ """ )
363
+ }
364
+
365
+ do {
366
+ let association = Parent
367
+ . hasMany ( Child . self)
368
+ . orderByPrimaryKey ( )
369
+ . first
370
+ . including ( required: Child . hasOne ( Toy . self) . including ( optional: Toy . belongsTo ( Vendor . self) ) )
371
+ XCTFail ( " TODO: check SQL " )
372
+ try assertMatchSQL ( db, Parent . all ( ) . including ( required: association) , """
373
+ SELECT " parent " .*, " child " .*, " toy " .*, " vendor " .*
374
+ FROM " parent "
375
+ JOIN " child " ON " child " . " id " = (
376
+ SELECT " child " . " id "
377
+ FROM " child "
378
+ JOIN " toy " ON " toy " . " childId " = " child " . " id "
379
+ LEFT JOIN " vendor " ON " vendor " . " id " = " toy " . " vendorId "
380
+ WHERE " child " . " parentId " = " parent " . " id "
381
+ ORDER BY " child " . " id "
382
+ LIMIT 1)
383
+ JOIN " toy " ON " toy " . " childId " = " child " . " id "
384
+ LEFT JOIN " vendor " ON " vendor " . " id " = " toy " . " vendorId "
385
+ """ )
386
+ try assertMatchSQL ( db, Parent . all ( ) . joining ( required: association) , """
387
+ SELECT " parent " .*, " toy " .*, " vendor " .*
388
+ FROM " parent "
389
+ JOIN " child " ON " child " . " id " = (
390
+ SELECT " child " . " id "
391
+ FROM " child "
392
+ JOIN " toy " ON " toy " . " childId " = " child " . " id "
393
+ LEFT JOIN " vendor " ON " vendor " . " id " = " toy " . " vendorId "
394
+ WHERE " child " . " parentId " = " parent " . " id "
395
+ ORDER BY " child " . " id "
396
+ LIMIT 1)
397
+ JOIN " toy " ON " toy " . " childId " = " child " . " id "
398
+ LEFT JOIN " vendor " ON " vendor " . " id " = " toy " . " vendorId "
399
+ """ )
400
+ try assertMatchSQL ( db, Parent ( ) . request ( for: association) , """
401
+ SELECT " child " .*, " toy " .*, " vendor " .*
402
+ FROM " child "
403
+ JOIN " toy " ON " toy " . " childId " = " child " . " id "
404
+ LEFT JOIN " vendor " ON " vendor " . " id " = " toy " . " vendorId "
405
+ WHERE " child " . " parentId " = 1
406
+ ORDER BY " child " . " id "
407
+ LIMIT 1
408
+ """ )
409
+ }
410
+ }
411
+ }
269
412
270
413
func testHasManyLast( ) throws {
271
414
struct Child : TableRecord { }
0 commit comments