@@ -202,7 +202,7 @@ public struct SwiftLanguage: Language {
202202
203203 return DeclSyntax ( variable)
204204 }
205-
205+
206206 /// Generates the expression to initialize the query.
207207 ///
208208 /// ```swift
@@ -416,7 +416,7 @@ public struct SwiftLanguage: Language {
416416 """
417417 }
418418 }
419-
419+
420420 private static func declaration(
421421 for model: GeneratedModel ,
422422 isOutput: Bool ,
@@ -435,7 +435,20 @@ public struct SwiftLanguage: Language {
435435 }
436436 }
437437
438+ let dynamicLookupTables = model. fields. values. compactMap { value -> ( String , GeneratedModel ) ? in
439+ guard case let . model( model) = value. type else { return nil }
440+ return ( value. name, model)
441+ }
442+
443+ let addDynamicLookup = isOutput && !dynamicLookupTables. isEmpty && model. fields. count > 1
444+
438445 let strct = StructDeclSyntax (
446+ attributes: AttributeListSyntax {
447+ if addDynamicLookup {
448+ let attr : AttributeSyntax = " @dynamicMemberLookup "
449+ attr. with ( \. trailingTrivia, . newline)
450+ }
451+ } ,
439452 name: TokenSyntax . identifier ( model. name) ,
440453 inheritanceClause: inheretance
441454 ) {
@@ -447,11 +460,54 @@ public struct SwiftLanguage: Language {
447460 rowDecodableInit ( for: model)
448461 memberwiseInit ( for: model)
449462 }
463+
464+ if addDynamicLookup {
465+ for (fieldName, table) in dynamicLookupTables {
466+ dynamicMemberLookup ( fieldName: fieldName, typeName: table. name)
467+ }
468+ }
450469 }
451470
452471 return DeclSyntax ( strct)
453472 }
454473
474+ private static func dynamicMemberLookup(
475+ fieldName: String ,
476+ typeName: String
477+ ) -> SubscriptDeclSyntax {
478+ return SubscriptDeclSyntax (
479+ subscriptKeyword: TokenSyntax . keyword ( . subscript)
480+ . with ( \. trailingTrivia, . spaces( 0 ) ) ,
481+ genericParameterClause: GenericParameterClauseSyntax {
482+ GenericParameterSyntax ( name: " Value " )
483+ } ,
484+ parameterClause: FunctionParameterClauseSyntax (
485+ parameters: [
486+ FunctionParameterSyntax (
487+ firstName: " dynamicMember " ,
488+ secondName: " dynamicMember " ,
489+ type: IdentifierTypeSyntax ( name: " KeyPath< \( raw: typeName) , Value> " ) ,
490+ trailingComma: nil
491+ )
492+ ]
493+ ) ,
494+ returnClause: ReturnClauseSyntax ( type: IdentifierTypeSyntax ( name: " Value " ) ) ,
495+ accessorBlock: AccessorBlockSyntax ( accessors: . getter( CodeBlockItemListSyntax {
496+ SubscriptCallExprSyntax (
497+ calledExpression: DeclReferenceExprSyntax ( baseName: TokenSyntax . identifier ( fieldName) ) ,
498+ arguments: LabeledExprListSyntax {
499+ LabeledExprSyntax (
500+ label: " keyPath " ,
501+ colon: TokenSyntax . colonToken ( ) ,
502+ expression: DeclReferenceExprSyntax ( baseName: " dynamicMember " ) ,
503+ trailingComma: nil
504+ )
505+ }
506+ )
507+ } ) )
508+ )
509+ }
510+
455511 private static func rowDecodableInit(
456512 for model: GeneratedModel
457513 ) -> InitializerDeclSyntax {
0 commit comments