/// A type that represents a column in a database table. /// /// ## Topics /// /// ### Standard Columns /// /// - ``rowID`` /// /// ### Deriving SQL Expressions /// /// - ``detached`` /// - ``match(_:)-727nk`` /// - ``match(_:)-1vvo8`` /// /// ### Creating Column Assignments /// /// - ``noOverwrite`` /// - ``set(to:)`` public protocol ColumnExpression: SQLSpecificExpressible { /// The column name. /// /// The column name is never qualified with a table name. /// /// For example, the name of a column can be `"score"`, but /// not `"player.score"`. var name: String { get } } extension ColumnExpression { /// Returns an SQL column. public var sqlExpression: SQLExpression { .column(name) } /// An SQL expression that refers to an aliased column /// (`expression AS alias`). /// /// Once detached, a column is never qualified with any table name in the /// SQL generated by the query interface. /// /// For example, see how `Column("total").detached` makes it possible to /// sort this query, when a raw `Column("total")` could not: /// /// ```swift /// // SELECT player.*, /// // (player.score + player.bonus) AS total, /// // team.* /// // FROM player /// // JOIN team ON team.id = player.teamID /// // ORDER BY total, player.name /// // ~~~~~ /// let request = Player /// .annotated(with: (Column("score") + Column("bonus")).forKey("total")) /// .including(required: Player.team) /// .order(Column("total").detached, Column("name")) /// ``` public var detached: SQLExpression { SQL(sql: name.quotedDatabaseIdentifier).sqlExpression } } extension ColumnExpression where Self == Column { /// The hidden rowID column. public static var rowID: Self { Column.rowID } } /// A column in a database table. /// /// For example: /// /// ```swift /// struct Player: TableRecord { /// var score: Int /// } /// /// let maximumScore = try dbQueue.read { db in /// // SELECT MAX(score) FROM player /// try Player /// .select(max(Column("score")), as: Int.self) /// .fetchOne(db) /// } /// ``` /// /// ## Topics /// /// ### Standard Columns /// /// - ``rowID-3bn70`` /// - ``rank`` /// /// ### Creating A Column /// /// - ``init(_:)-5grmu`` /// - ``init(_:)-7xc4z`` public struct Column: Sendable { /// The hidden rowID column. public static let rowID = Column("rowid") public var name: String /// Creates a `Column` given its name. /// /// The name should be unqualified, such as `"score"`. Qualified name such /// as `"player.score"` are unsupported. public init(_ name: String) { self.name = name } /// Creates a `Column` given a `CodingKey`. public init(_ codingKey: some CodingKey) { self.name = codingKey.stringValue } } extension Column: ColumnExpression { } /// Support for column enums: /// /// struct Player { /// enum Columns: String, ColumnExpression { /// case id, name, score /// } /// } extension ColumnExpression where Self: RawRepresentable, Self.RawValue == String { public var name: String { rawValue } }