Class
CompositeChildrenProperty
Declares a many-to-one relation between the referenced (“child”) model and the referencing (“parent”) model, where the parent model specifies its ID with
CompositeIDProperty.@propertyWrapper final class CompositeChildrenProperty<From, To> where From : Model, To : Model, From.IDValue : Fields
Overview
CompositeChildrenProperty serves the same purpose for child models with parents which use @CompositeID that ChildrenProperty serves for parent models which use @ID.
Unfortunately, while the type of ID used by the child model makes no difference, limitations of Swift’s generics syntax make it impractical to support both @ID-using and @CompositeID-using models as the parent model with a single property type.
CompositeChildrenProperty cannot reference a ParentProperty or OptionalParentProperty; use ChildrenProperty instead.
Example:
Note
This example is somewhat contrived; in reality, this kind of metadata would have much more complex relationships.
final class TableMetadata: Model {
static let schema = "table_metadata"
final class IDValue: Fields, Hashable {
@Field(key: "table_schema") var schema: String
@Field(key: "table_name") var name: String
init() {}
static func ==(lhs: IDValue, rhs: IDValue) -> Bool { lhs.schema == rhs.schema && lhs.name == rhs.name }
func hash(into hasher: inout Hasher) { hasher.combine(self.schema); hasher.combine(self.name) }
}
@CompositeID var id: IDValue?
@CompositeChildren(for: \.$referencedTable) var referencingForeignKeys: [ForeignKeyMetadata]
@CompositeChildren(for: \.$nextCrossReferencedTable) var indirectReferencingForeignKeys: [ForeignKeyMetadata]
// ...
}
final class ForeignKeyMetadata: Model {
static let schema = "foreign_key_metadata"
@ID(custom: "constraint_name") var id: String?
@CompositeParent(prefix: "referenced") var referencedTable: TableMetadata
@CompositeOptionalParent(prefix: "next_xref") var nextCrossReferencedTable: TableMetadata?
// ...
struct CreateTableMigration: AsyncMigration {
func prepare(on database: Database) async throws {
try await database.schema(ForeignKeyMetadata.schema)
.field("constraint_name", .string, .required, .identifier(auto: false))
.field("referenced_table_schema", .string, .required)
.field("referenced_table_name", .string, .required)
.foreignKey(["referenced_table_schema", "referenced_table_name"], references: TableMetadata.schema, ["table_schema", "table_name"])
.field("next_xref_table_schema", .string)
.field("next_xref_table_name", .string)
.foreignKey(["next_xref_table_schema", "next_xref_table_name"], references: TableMetadata.schema, ["table_schema", "table_name"])
.constraint(.sql(.check(SQLBinaryExpression( // adds a check constraint to ensure that neither field is ever NULL when the other isn't
left: SQLBinaryExpression(left: SQLIdentifier("next_xref_table_schema"), .is, right: SQLLiteral.null),
.equal,
right: SQLBinaryExpression(left: SQLIdentifier("next_xref_table_name"), .is, right: SQLLiteral.null)
))))
// ...
.create()
}
}
}
Topics
Initializers
Instance Properties
Instance Methods
Type Aliases
Default Implementations
Relationships
Conforms To
AnyCodablePropertyAnyDatabasePropertyAnyPropertyEagerLoadablePropertyRelationSwift.CopyableSwift.CustomStringConvertibleSwift.EscapableSwift.SendableSwift.SendableMetatype