@@ -484,47 +484,7 @@ private struct SQLQualifiedRelation {
484
484
485
485
// Qualify all joins, selection, filter, and ordering, so that all
486
486
// identifiers can be correctly disambiguated and qualified.
487
- joins = relation. children. compactMapValues { child -> SQLQualifiedJoin ? in
488
- let kind : SQLQualifiedJoin . Kind
489
- switch child. kind {
490
- case . oneRequired:
491
- kind = . innerJoin
492
- case . oneOptional:
493
- kind = . leftJoin
494
- case . allPrefetched, . allNotPrefetched:
495
- // This relation child is not fetched with an SQL join.
496
- return nil
497
- }
498
-
499
- if child. relation. firstOnly {
500
- // Filters and order are handled in a subquery (see target below).
501
- // We only keep children that need to be exposed in the outer
502
- // query (those with a non-empty selection).
503
- #warning("TODO outerRelation 1")
504
- // TODO: we may have a problem if we remove children used for
505
- // ordering or filtering with aliases.
506
- #warning("TODO outerRelation 2")
507
- // TODO: keep children that have children with selection
508
- #warning("TODO target")
509
- // TODO: in the target remove to-many children
510
- let outerRelation = child. relation
511
- . with ( \. firstOnly, false )
512
- . unfiltered ( )
513
- . unordered ( )
514
- . filteringChildren { $0. relation. selection. isEmpty == false }
515
- return SQLQualifiedJoin (
516
- kind: kind,
517
- condition: child. condition,
518
- relation: SQLQualifiedRelation ( outerRelation) ,
519
- target: . firstOnly( child. relation) )
520
- } else {
521
- return SQLQualifiedJoin (
522
- kind: kind,
523
- condition: child. condition,
524
- relation: SQLQualifiedRelation ( child. relation) ,
525
- target: . all)
526
- }
527
- }
487
+ joins = relation. children. compactMapValues { SQLQualifiedJoin ( $0) }
528
488
sourceSelection = relation. selection. map { $0. qualifiedSelectable ( with: sourceAlias) }
529
489
filtersPromise = relation. filtersPromise. map { $0. map { $0. qualifiedExpression ( with: sourceAlias) } }
530
490
sourceOrdering = relation. ordering. qualified ( with: sourceAlias)
@@ -655,14 +615,54 @@ private struct SQLQualifiedJoin: Refinable {
655
615
656
616
enum Target {
657
617
case all
658
- case firstOnly ( SQLRelation )
618
+ case subRelation ( SQLRelation )
659
619
}
660
620
661
621
var kind : Kind
662
622
var condition : SQLAssociationCondition
663
623
var relation : SQLQualifiedRelation
664
624
var target : Target
665
625
626
+ init ? ( _ child: SQLRelation . Child ) {
627
+ switch child. kind {
628
+ case . oneRequired:
629
+ kind = . innerJoin
630
+ case . oneOptional:
631
+ kind = . leftJoin
632
+ case . allPrefetched, . allNotPrefetched:
633
+ // This relation child is not fetched with an SQL join.
634
+ return nil
635
+ }
636
+
637
+ condition = child. condition
638
+
639
+ if child. relation. firstOnly {
640
+ // Filters and order are handled in a subRelation.
641
+ // We only keep children that need to be exposed in the outer
642
+ // query (those with a non-empty selection).
643
+ #warning("TODO outerRelation 1")
644
+ // TODO: we may have a problem if we remove children used for
645
+ // ordering or filtering with aliases.
646
+ #warning("TODO outerRelation 2")
647
+ // TODO: keep children that have children with selection
648
+ #warning("TODO target")
649
+ // TODO: in the target remove to-many children
650
+ let outerRelation = child. relation
651
+ . with ( \. firstOnly, false )
652
+ . unfiltered ( )
653
+ . unordered ( )
654
+ . filteringChildren { $0. relation. selection. isEmpty == false }
655
+
656
+ let subRelation = child. relation
657
+
658
+ relation = SQLQualifiedRelation ( outerRelation)
659
+ target = . subRelation( subRelation)
660
+ } else {
661
+ relation = SQLQualifiedRelation ( child. relation)
662
+ target = . all
663
+ }
664
+ }
665
+
666
666
func sql( _ db: Database , _ context: inout SQLGenerationContext , leftAlias: TableAlias ) throws -> String {
667
667
try sql ( db, & context, leftAlias: leftAlias, allowingInnerJoin: true )
668
668
}
@@ -705,7 +705,7 @@ private struct SQLQualifiedJoin: Refinable {
705
705
if filters. isEmpty == false {
706
706
sql += " ON \( filters. joined ( operator: . and) . expressionSQL ( & context, wrappedInParenthesis: false ) ) "
707
707
}
708
- case let . firstOnly ( subRelation) :
708
+ case let . subRelation ( subRelation) :
709
709
guard let primaryKey = try subRelation. primaryKeyExpression ( db) else {
710
710
fatalError ( " Not implemented " )
711
711
}
0 commit comments