642 lines
26 KiB
Swift
642 lines
26 KiB
Swift
// QueryInterfaceRequest is the type of requests generated by TableRecord:
|
|
//
|
|
// struct Player: TableRecord { ... }
|
|
// let playerRequest = Player.all() // QueryInterfaceRequest<Player>
|
|
//
|
|
// It wraps an SQLSelectQuery, and has an attached type.
|
|
//
|
|
// The attached type helps decoding raw database values:
|
|
//
|
|
// try dbQueue.read { db in
|
|
// try playerRequest.fetchAll(db) // [Player]
|
|
// }
|
|
//
|
|
// The attached type also helps the compiler validate associated requests:
|
|
//
|
|
// playerRequest.including(required: Player.team) // OK
|
|
// fruitRequest.including(required: Player.team) // Does not compile
|
|
|
|
/// QueryInterfaceRequest is a request that generates SQL for you.
|
|
///
|
|
/// For example:
|
|
///
|
|
/// try dbQueue.read { db in
|
|
/// let request = Player
|
|
/// .filter(Column("score") > 1000)
|
|
/// .order(Column("name"))
|
|
/// let players = try request.fetchAll(db) // [Player]
|
|
/// }
|
|
///
|
|
/// See https://github.com/groue/GRDB.swift#the-query-interface
|
|
public struct QueryInterfaceRequest<T> {
|
|
var query: SQLSelectQuery
|
|
}
|
|
|
|
extension QueryInterfaceRequest : FetchRequest {
|
|
public typealias RowDecoder = T
|
|
|
|
/// Returns a tuple that contains a prepared statement that is ready to be
|
|
/// executed, and an eventual row adapter.
|
|
///
|
|
/// - parameter db: A database connection.
|
|
/// - returns: A prepared statement and an eventual row adapter.
|
|
/// :nodoc:
|
|
public func prepare(_ db: Database) throws -> (SelectStatement, RowAdapter?) {
|
|
return try SQLSelectQueryGenerator(query).prepare(db)
|
|
}
|
|
|
|
/// Returns the number of rows fetched by the request.
|
|
///
|
|
/// - parameter db: A database connection.
|
|
/// :nodoc:
|
|
public func fetchCount(_ db: Database) throws -> Int {
|
|
return try query.fetchCount(db)
|
|
}
|
|
|
|
/// Returns the database region that the request looks into.
|
|
///
|
|
/// - parameter db: A database connection.
|
|
/// :nodoc:
|
|
public func databaseRegion(_ db: Database) throws -> DatabaseRegion {
|
|
return try SQLSelectQueryGenerator(query).databaseRegion(db)
|
|
}
|
|
}
|
|
|
|
extension QueryInterfaceRequest : DerivableRequest, AggregatingRequest {
|
|
|
|
// MARK: Request Derivation
|
|
|
|
/// Creates a request which selects *selection*.
|
|
///
|
|
/// // SELECT id, email FROM player
|
|
/// var request = Player.all()
|
|
/// request = request.select([Column("id"), Column("email")])
|
|
///
|
|
/// Any previous selection is replaced:
|
|
///
|
|
/// // SELECT email FROM player
|
|
/// request
|
|
/// .select([Column("id")])
|
|
/// .select([Column("email")])
|
|
public func select(_ selection: [SQLSelectable]) -> QueryInterfaceRequest {
|
|
return mapQuery { $0.select(selection) }
|
|
}
|
|
|
|
/// Creates a request which selects *selection*, and fetches values of
|
|
/// type *type*.
|
|
///
|
|
/// try dbQueue.read { db in
|
|
/// // SELECT max(score) FROM player
|
|
/// let request = Player.all().select([max(Column("score"))], as: Int.self)
|
|
/// let maxScore: Int? = try request.fetchOne(db)
|
|
/// }
|
|
public func select<RowDecoder>(_ selection: [SQLSelectable], as type: RowDecoder.Type) -> QueryInterfaceRequest<RowDecoder> {
|
|
return mapQuery { $0.select(selection) }.asRequest(of: RowDecoder.self)
|
|
}
|
|
|
|
/// Creates a request which selects *selection*, and fetches values of
|
|
/// type *type*.
|
|
///
|
|
/// try dbQueue.read { db in
|
|
/// // SELECT max(score) FROM player
|
|
/// let request = Player.all().select(max(Column("score")), as: Int.self)
|
|
/// let maxScore: Int? = try request.fetchOne(db)
|
|
/// }
|
|
public func select<RowDecoder>(_ selection: SQLSelectable..., as type: RowDecoder.Type) -> QueryInterfaceRequest<RowDecoder> {
|
|
return select(selection, as: type)
|
|
}
|
|
|
|
/// Creates a request which selects *sql*, and fetches values of
|
|
/// type *type*.
|
|
///
|
|
/// try dbQueue.read { db in
|
|
/// // SELECT max(score) FROM player
|
|
/// let request = Player.all().select(sql: "max(score)", as: Int.self)
|
|
/// let maxScore: Int? = try request.fetchOne(db)
|
|
/// }
|
|
public func select<RowDecoder>(sql: String, arguments: StatementArguments = StatementArguments(), as type: RowDecoder.Type) -> QueryInterfaceRequest<RowDecoder> {
|
|
return select(literal: SQLLiteral(sql: sql, arguments: arguments), as: type)
|
|
}
|
|
|
|
/// Creates a request which selects an SQL *literal*, and fetches values of
|
|
/// type *type*.
|
|
///
|
|
/// try dbQueue.read { db in
|
|
/// // SELECT IFNULL(name, 'Anonymous') FROM player WHERE id = 42
|
|
/// let request = Player.
|
|
/// .filter(primaryKey: 42)
|
|
/// .select(
|
|
/// SQLLiteral(
|
|
/// sql: "IFNULL(name, ?)",
|
|
/// arguments: ["Anonymous"]),
|
|
/// as: String.self)
|
|
/// let name: String? = try request.fetchOne(db)
|
|
/// }
|
|
///
|
|
/// With Swift 5, you can safely embed raw values in your SQL queries,
|
|
/// without any risk of syntax errors or SQL injection:
|
|
///
|
|
/// try dbQueue.read { db in
|
|
/// // SELECT IFNULL(name, 'Anonymous') FROM player WHERE id = 42
|
|
/// let request = Player.
|
|
/// .filter(primaryKey: 42)
|
|
/// .select(
|
|
/// literal: "IFNULL(name, \("Anonymous"))",
|
|
/// as: String.self)
|
|
/// let name: String? = try request.fetchOne(db)
|
|
/// }
|
|
public func select<RowDecoder>(literal sqlLiteral: SQLLiteral, as type: RowDecoder.Type) -> QueryInterfaceRequest<RowDecoder> {
|
|
return select(SQLSelectionLiteral(literal: sqlLiteral), as: type)
|
|
}
|
|
|
|
/// Creates a request which appends *selection*.
|
|
///
|
|
/// // SELECT id, email, name FROM player
|
|
/// var request = Player.all()
|
|
/// request = request
|
|
/// .select([Column("id"), Column("email")])
|
|
/// .annotated(with: [Column("name")])
|
|
public func annotated(with selection: [SQLSelectable]) -> QueryInterfaceRequest {
|
|
return mapQuery { $0.annotated(with: selection) }
|
|
}
|
|
|
|
/// Creates a request which returns distinct rows.
|
|
///
|
|
/// // SELECT DISTINCT * FROM player
|
|
/// var request = Player.all()
|
|
/// request = request.distinct()
|
|
///
|
|
/// // SELECT DISTINCT name FROM player
|
|
/// var request = Player.select(Column("name"))
|
|
/// request = request.distinct()
|
|
public func distinct() -> QueryInterfaceRequest {
|
|
return mapQuery { $0.distinct() }
|
|
}
|
|
|
|
/// Creates a request with the provided *predicate promise* added to the
|
|
/// eventual set of already applied predicates.
|
|
///
|
|
/// // SELECT * FROM player WHERE 1
|
|
/// var request = Player.all()
|
|
/// request = request.filter { db in true }
|
|
public func filter(_ predicate: @escaping (Database) throws -> SQLExpressible) -> QueryInterfaceRequest {
|
|
return mapQuery { $0.filter(predicate) }
|
|
}
|
|
|
|
/// Creates a request grouped according to *expressions promise*.
|
|
public func group(_ expressions: @escaping (Database) throws -> [SQLExpressible]) -> QueryInterfaceRequest {
|
|
return mapQuery { $0.group(expressions) }
|
|
}
|
|
|
|
/// Creates a request with the provided *predicate* added to the
|
|
/// eventual set of already applied predicates.
|
|
public func having(_ predicate: SQLExpressible) -> QueryInterfaceRequest {
|
|
return mapQuery { $0.having(predicate) }
|
|
}
|
|
|
|
/// Creates a request with the provided *orderings promise*.
|
|
///
|
|
/// // SELECT * FROM player ORDER BY name
|
|
/// var request = Player.all()
|
|
/// request = request.order { _ in [Column("name")] }
|
|
///
|
|
/// Any previous ordering is replaced:
|
|
///
|
|
/// // SELECT * FROM player ORDER BY name
|
|
/// request
|
|
/// .order{ _ in [Column("email")] }
|
|
/// .reversed()
|
|
/// .order{ _ in [Column("name")] }
|
|
public func order(_ orderings: @escaping (Database) throws -> [SQLOrderingTerm]) -> QueryInterfaceRequest {
|
|
return mapQuery { $0.order(orderings) }
|
|
}
|
|
|
|
/// Creates a request that reverses applied orderings.
|
|
///
|
|
/// // SELECT * FROM player ORDER BY name DESC
|
|
/// var request = Player.all().order(Column("name"))
|
|
/// request = request.reversed()
|
|
///
|
|
/// If no ordering was applied, the returned request is identical.
|
|
///
|
|
/// // SELECT * FROM player
|
|
/// var request = Player.all()
|
|
/// request = request.reversed()
|
|
public func reversed() -> QueryInterfaceRequest {
|
|
return mapQuery { $0.reversed() }
|
|
}
|
|
|
|
/// Creates a request which fetches *limit* rows, starting at *offset*.
|
|
///
|
|
/// // SELECT * FROM player LIMIT 1
|
|
/// var request = Player.all()
|
|
/// request = request.limit(1)
|
|
///
|
|
/// Any previous limit is replaced.
|
|
public func limit(_ limit: Int, offset: Int? = nil) -> QueryInterfaceRequest {
|
|
return mapQuery { $0.limit(limit, offset: offset) }
|
|
}
|
|
|
|
/// Creates a request that allows you to define expressions that target
|
|
/// a specific database table.
|
|
///
|
|
/// In the example below, the "team.avgScore < player.score" condition in
|
|
/// the ON clause could be not achieved without table aliases.
|
|
///
|
|
/// struct Player: TableRecord {
|
|
/// static let team = belongsTo(Team.self)
|
|
/// }
|
|
///
|
|
/// // SELECT player.*, team.*
|
|
/// // JOIN team ON ... AND team.avgScore < player.score
|
|
/// let playerAlias = TableAlias()
|
|
/// let request = Player
|
|
/// .all()
|
|
/// .aliased(playerAlias)
|
|
/// .including(required: Player.team.filter(Column("avgScore") < playerAlias[Column("score")])
|
|
public func aliased(_ alias: TableAlias) -> QueryInterfaceRequest {
|
|
return mapQuery { $0.qualified(with: alias) }
|
|
}
|
|
|
|
/// Creates a request bound to type Target.
|
|
///
|
|
/// The returned request can fetch if the type Target is fetchable (Row,
|
|
/// value, record).
|
|
///
|
|
/// // Int?
|
|
/// let maxScore = try Player
|
|
/// .select(max(scoreColumn))
|
|
/// .asRequest(of: Int.self) // <--
|
|
/// .fetchOne(db)
|
|
///
|
|
/// - parameter type: The fetched type Target
|
|
/// - returns: A typed request bound to type Target.
|
|
public func asRequest<RowDecoder>(of type: RowDecoder.Type) -> QueryInterfaceRequest<RowDecoder> {
|
|
return QueryInterfaceRequest<RowDecoder>(query: query)
|
|
}
|
|
|
|
/// Returns a request whose query is transformed by the given closure.
|
|
func mapQuery(_ transform: (SQLSelectQuery) -> SQLSelectQuery) -> QueryInterfaceRequest {
|
|
var request = self
|
|
request.query = transform(query)
|
|
return request
|
|
}
|
|
}
|
|
|
|
extension QueryInterfaceRequest {
|
|
/// Turns a request into a SQLRelation.
|
|
///
|
|
/// This method helps initializing associations:
|
|
///
|
|
/// struct Book: TableRecord {
|
|
/// // invokes Author.all().relation
|
|
/// static let author = belongsTo(Author.self)
|
|
/// }
|
|
var relation: SQLRelation {
|
|
let query = self.query
|
|
|
|
// Prevent information loss
|
|
GRDBPrecondition(!query.isDistinct, "Not implemented: join distinct queries")
|
|
GRDBPrecondition(query.groupPromise == nil, "Can't join aggregated queries")
|
|
GRDBPrecondition(query.havingExpression == nil, "Can't join aggregated queries")
|
|
GRDBPrecondition(query.limit == nil, "Can't join limited queries")
|
|
|
|
return query.relation
|
|
}
|
|
}
|
|
|
|
/// Conditional conformance to TableRequest when RowDecoder conforms
|
|
/// to TableRecord:
|
|
///
|
|
/// let request = Player.all()
|
|
/// request.filter(key: ...)
|
|
/// request.filter(keys: ...)
|
|
extension QueryInterfaceRequest: TableRequest where RowDecoder: TableRecord {
|
|
/// :nodoc:
|
|
public var databaseTableName: String {
|
|
return RowDecoder.databaseTableName
|
|
}
|
|
}
|
|
|
|
extension QueryInterfaceRequest where T: MutablePersistableRecord {
|
|
|
|
// MARK: Deleting
|
|
|
|
/// Deletes matching rows; returns the number of deleted rows.
|
|
///
|
|
/// - parameter db: A database connection.
|
|
/// - returns: The number of deleted rows
|
|
/// - throws: A DatabaseError is thrown whenever an SQLite error occurs.
|
|
@discardableResult
|
|
public func deleteAll(_ db: Database) throws -> Int {
|
|
try SQLSelectQueryGenerator(query).makeDeleteStatement(db).execute()
|
|
return db.changesCount
|
|
}
|
|
}
|
|
|
|
extension TableRecord {
|
|
|
|
// MARK: Request Derivation
|
|
|
|
/// Creates a request which fetches all records.
|
|
///
|
|
/// // SELECT * FROM player
|
|
/// let request = Player.all()
|
|
///
|
|
/// The selection defaults to all columns. This default can be changed for
|
|
/// all requests by the `TableRecord.databaseSelection` property, or
|
|
/// for individual requests with the `TableRecord.select` method.
|
|
public static func all() -> QueryInterfaceRequest<Self> {
|
|
let relation = SQLRelation(
|
|
source: .table(tableName: databaseTableName, alias: nil),
|
|
selection: databaseSelection)
|
|
let query = SQLSelectQuery(relation: relation)
|
|
return QueryInterfaceRequest(query: query)
|
|
}
|
|
|
|
/// Creates a request which fetches no record.
|
|
public static func none() -> QueryInterfaceRequest<Self> {
|
|
return all().none() // don't laugh
|
|
}
|
|
|
|
/// Creates a request which selects *selection*.
|
|
///
|
|
/// // SELECT id, email FROM player
|
|
/// let request = Player.select(Column("id"), Column("email"))
|
|
public static func select(_ selection: SQLSelectable...) -> QueryInterfaceRequest<Self> {
|
|
return all().select(selection)
|
|
}
|
|
|
|
/// Creates a request which selects *selection*.
|
|
///
|
|
/// // SELECT id, email FROM player
|
|
/// let request = Player.select([Column("id"), Column("email")])
|
|
public static func select(_ selection: [SQLSelectable]) -> QueryInterfaceRequest<Self> {
|
|
return all().select(selection)
|
|
}
|
|
|
|
/// Creates a request which selects *sql*.
|
|
///
|
|
/// // SELECT id, email FROM player
|
|
/// let request = Player.select(sql: "id, email")
|
|
public static func select(sql: String, arguments: StatementArguments = StatementArguments()) -> QueryInterfaceRequest<Self> {
|
|
return select(literal: SQLLiteral(sql: sql, arguments: arguments))
|
|
}
|
|
|
|
/// Creates a request which selects an SQL *literal*.
|
|
///
|
|
/// // SELECT id, email FROM player
|
|
/// let request = Player.select(literal: SQLLiteral(sql: "id, email"))
|
|
public static func select(literal sqlLiteral: SQLLiteral) -> QueryInterfaceRequest<Self> {
|
|
return all().select(literal: sqlLiteral)
|
|
}
|
|
|
|
/// Creates a request which selects *selection*, and fetches values of
|
|
/// type *type*.
|
|
///
|
|
/// try dbQueue.read { db in
|
|
/// // SELECT max(score) FROM player
|
|
/// let request = Player.select([max(Column("score"))], as: Int.self)
|
|
/// let maxScore: Int? = try request.fetchOne(db)
|
|
/// }
|
|
public static func select<RowDecoder>(_ selection: [SQLSelectable], as type: RowDecoder.Type) -> QueryInterfaceRequest<RowDecoder> {
|
|
return all().select(selection, as: type)
|
|
}
|
|
|
|
/// Creates a request which selects *selection*, and fetches values of
|
|
/// type *type*.
|
|
///
|
|
/// try dbQueue.read { db in
|
|
/// // SELECT max(score) FROM player
|
|
/// let request = Player.select(max(Column("score")), as: Int.self)
|
|
/// let maxScore: Int? = try request.fetchOne(db)
|
|
/// }
|
|
public static func select<RowDecoder>(_ selection: SQLSelectable..., as type: RowDecoder.Type) -> QueryInterfaceRequest<RowDecoder> {
|
|
return all().select(selection, as: type)
|
|
}
|
|
|
|
/// Creates a request which selects *sql*, and fetches values of
|
|
/// type *type*.
|
|
///
|
|
/// try dbQueue.read { db in
|
|
/// // SELECT max(score) FROM player
|
|
/// let request = Player.select(sql: "max(score)", as: Int.self)
|
|
/// let maxScore: Int? = try request.fetchOne(db)
|
|
/// }
|
|
public static func select<RowDecoder>(sql: String, arguments: StatementArguments = StatementArguments(), as type: RowDecoder.Type) -> QueryInterfaceRequest<RowDecoder> {
|
|
return all().select(literal: SQLLiteral(sql: sql, arguments: arguments), as: type)
|
|
}
|
|
|
|
/// Creates a request which selects an SQL *literal*, and fetches values of
|
|
/// type *type*.
|
|
///
|
|
/// try dbQueue.read { db in
|
|
/// // SELECT max(score) FROM player
|
|
/// let request = Player.select(literal: SQLLiteral(sql: "max(score)"), as: Int.self)
|
|
/// let maxScore: Int? = try request.fetchOne(db)
|
|
/// }
|
|
public static func select<RowDecoder>(literal sqlLiteral: SQLLiteral, as type: RowDecoder.Type) -> QueryInterfaceRequest<RowDecoder> {
|
|
return all().select(literal: sqlLiteral, as: type)
|
|
}
|
|
|
|
/// Creates a request with the provided *predicate*.
|
|
///
|
|
/// // SELECT * FROM player WHERE email = 'arthur@example.com'
|
|
/// let request = Player.filter(Column("email") == "arthur@example.com")
|
|
///
|
|
/// The selection defaults to all columns. This default can be changed for
|
|
/// all requests by the `TableRecord.databaseSelection` property, or
|
|
/// for individual requests with the `TableRecord.select` method.
|
|
public static func filter(_ predicate: SQLExpressible) -> QueryInterfaceRequest<Self> {
|
|
return all().filter(predicate)
|
|
}
|
|
|
|
/// Creates a request with the provided primary key *predicate*.
|
|
///
|
|
/// // SELECT * FROM player WHERE id = 1
|
|
/// let request = Player.filter(key: 1)
|
|
///
|
|
/// The selection defaults to all columns. This default can be changed for
|
|
/// all requests by the `TableRecord.databaseSelection` property, or
|
|
/// for individual requests with the `TableRecord.select` method.
|
|
public static func filter<PrimaryKeyType: DatabaseValueConvertible>(key: PrimaryKeyType?) -> QueryInterfaceRequest<Self> {
|
|
return all().filter(key: key)
|
|
}
|
|
|
|
/// Creates a request with the provided primary key *predicate*.
|
|
///
|
|
/// // SELECT * FROM player WHERE id IN (1, 2, 3)
|
|
/// let request = Player.filter(keys: [1, 2, 3])
|
|
///
|
|
/// The selection defaults to all columns. This default can be changed for
|
|
/// all requests by the `TableRecord.databaseSelection` property, or
|
|
/// for individual requests with the `TableRecord.select` method.
|
|
public static func filter<Sequence: Swift.Sequence>(keys: Sequence) -> QueryInterfaceRequest<Self> where Sequence.Element: DatabaseValueConvertible {
|
|
return all().filter(keys: keys)
|
|
}
|
|
|
|
/// Creates a request with the provided primary key *predicate*.
|
|
///
|
|
/// // SELECT * FROM passport WHERE personId = 1 AND countryCode = 'FR'
|
|
/// let request = Passport.filter(key: ["personId": 1, "countryCode": "FR"])
|
|
///
|
|
/// When executed, this request raises a fatal error if there is no unique
|
|
/// index on the key columns.
|
|
///
|
|
/// The selection defaults to all columns. This default can be changed for
|
|
/// all requests by the `TableRecord.databaseSelection` property, or
|
|
/// for individual requests with the `TableRecord.select` method.
|
|
public static func filter(key: [String: DatabaseValueConvertible?]?) -> QueryInterfaceRequest<Self> {
|
|
return all().filter(key: key)
|
|
}
|
|
|
|
/// Creates a request with the provided primary key *predicate*.
|
|
///
|
|
/// // SELECT * FROM passport WHERE (personId = 1 AND countryCode = 'FR') OR ...
|
|
/// let request = Passport.filter(keys: [["personId": 1, "countryCode": "FR"], ...])
|
|
///
|
|
/// When executed, this request raises a fatal error if there is no unique
|
|
/// index on the key columns.
|
|
///
|
|
/// The selection defaults to all columns. This default can be changed for
|
|
/// all requests by the `TableRecord.databaseSelection` property, or
|
|
/// for individual requests with the `TableRecord.select` method.
|
|
public static func filter(keys: [[String: DatabaseValueConvertible?]]) -> QueryInterfaceRequest<Self> {
|
|
return all().filter(keys: keys)
|
|
}
|
|
|
|
/// Creates a request with the provided *predicate*.
|
|
///
|
|
/// // SELECT * FROM player WHERE email = 'arthur@example.com'
|
|
/// let request = Player.filter(sql: "email = ?", arguments: ["arthur@example.com"])
|
|
///
|
|
/// The selection defaults to all columns. This default can be changed for
|
|
/// all requests by the `TableRecord.databaseSelection` property, or
|
|
/// for individual requests with the `TableRecord.select` method.
|
|
public static func filter(sql: String, arguments: StatementArguments = StatementArguments()) -> QueryInterfaceRequest<Self> {
|
|
return filter(literal: SQLLiteral(sql: sql, arguments: arguments))
|
|
}
|
|
|
|
/// Creates a request with the provided *predicate*.
|
|
///
|
|
/// // SELECT * FROM player WHERE email = 'arthur@example.com'
|
|
/// let request = Player.filter(literal: SQLLiteral(sql: "email = ?", arguments: ["arthur@example.com"]))
|
|
///
|
|
/// With Swift 5, you can safely embed raw values in your SQL queries,
|
|
/// without any risk of syntax errors or SQL injection:
|
|
///
|
|
/// let request = Player.filter(literal: "name = \("O'Brien"))
|
|
///
|
|
/// The selection defaults to all columns. This default can be changed for
|
|
/// all requests by the `TableRecord.databaseSelection` property, or
|
|
/// for individual requests with the `TableRecord.select` method.
|
|
public static func filter(literal sqlLiteral: SQLLiteral) -> QueryInterfaceRequest<Self> {
|
|
// NOT TESTED
|
|
return all().filter(literal: sqlLiteral)
|
|
}
|
|
|
|
/// Creates a request sorted according to the
|
|
/// provided *orderings*.
|
|
///
|
|
/// // SELECT * FROM player ORDER BY name
|
|
/// let request = Player.order(Column("name"))
|
|
///
|
|
/// The selection defaults to all columns. This default can be changed for
|
|
/// all requests by the `TableRecord.databaseSelection` property, or
|
|
/// for individual requests with the `TableRecord.select` method.
|
|
public static func order(_ orderings: SQLOrderingTerm...) -> QueryInterfaceRequest<Self> {
|
|
return all().order(orderings)
|
|
}
|
|
|
|
/// Creates a request sorted according to the
|
|
/// provided *orderings*.
|
|
///
|
|
/// // SELECT * FROM player ORDER BY name
|
|
/// let request = Player.order([Column("name")])
|
|
///
|
|
/// The selection defaults to all columns. This default can be changed for
|
|
/// all requests by the `TableRecord.databaseSelection` property, or
|
|
/// for individual requests with the `TableRecord.select` method.
|
|
public static func order(_ orderings: [SQLOrderingTerm]) -> QueryInterfaceRequest<Self> {
|
|
return all().order(orderings)
|
|
}
|
|
|
|
/// Creates a request sorted by primary key.
|
|
///
|
|
/// // SELECT * FROM player ORDER BY id
|
|
/// let request = Player.orderByPrimaryKey()
|
|
///
|
|
/// // SELECT * FROM country ORDER BY code
|
|
/// let request = Country.orderByPrimaryKey()
|
|
///
|
|
/// The selection defaults to all columns. This default can be changed for
|
|
/// all requests by the `TableRecord.databaseSelection` property, or
|
|
/// for individual requests with the `TableRecord.select` method.
|
|
public static func orderByPrimaryKey() -> QueryInterfaceRequest<Self> {
|
|
return all().orderByPrimaryKey()
|
|
}
|
|
|
|
/// Creates a request sorted according to *sql*.
|
|
///
|
|
/// // SELECT * FROM player ORDER BY name
|
|
/// let request = Player.order(sql: "name")
|
|
///
|
|
/// The selection defaults to all columns. This default can be changed for
|
|
/// all requests by the `TableRecord.databaseSelection` property, or
|
|
/// for individual requests with the `TableRecord.select` method.
|
|
public static func order(sql: String, arguments: StatementArguments = StatementArguments()) -> QueryInterfaceRequest<Self> {
|
|
return all().order(literal: SQLLiteral(sql: sql, arguments: arguments))
|
|
}
|
|
|
|
/// Creates a request sorted according to an SQL *literal*.
|
|
///
|
|
/// // SELECT * FROM player ORDER BY name
|
|
/// let request = Player.order(literal: SQLLiteral(sql: "name"))
|
|
///
|
|
/// With Swift 5, you can safely embed raw values in your SQL queries,
|
|
/// without any risk of syntax errors or SQL injection:
|
|
///
|
|
/// // SELECT * FROM player ORDER BY name
|
|
/// let request = Player.order(literal: "name"))
|
|
///
|
|
/// The selection defaults to all columns. This default can be changed for
|
|
/// all requests by the `TableRecord.databaseSelection` property, or
|
|
/// for individual requests with the `TableRecord.select` method.
|
|
public static func order(literal sqlLiteral: SQLLiteral) -> QueryInterfaceRequest<Self> {
|
|
return all().order(literal: sqlLiteral)
|
|
}
|
|
|
|
/// Creates a request which fetches *limit* rows, starting at
|
|
/// *offset*.
|
|
///
|
|
/// // SELECT * FROM player LIMIT 1
|
|
/// let request = Player.limit(1)
|
|
///
|
|
/// The selection defaults to all columns. This default can be changed for
|
|
/// all requests by the `TableRecord.databaseSelection` property, or
|
|
/// for individual requests with the `TableRecord.select` method.
|
|
public static func limit(_ limit: Int, offset: Int? = nil) -> QueryInterfaceRequest<Self> {
|
|
return all().limit(limit, offset: offset)
|
|
}
|
|
|
|
/// Creates a request that allows you to define expressions that target
|
|
/// a specific database table.
|
|
///
|
|
/// In the example below, the "team.avgScore < player.score" condition in
|
|
/// the ON clause could be not achieved without table aliases.
|
|
///
|
|
/// struct Player: TableRecord {
|
|
/// static let team = belongsTo(Team.self)
|
|
/// }
|
|
///
|
|
/// // SELECT player.*, team.*
|
|
/// // JOIN team ON ... AND team.avgScore < player.score
|
|
/// let playerAlias = TableAlias()
|
|
/// let request = Player
|
|
/// .aliased(playerAlias)
|
|
/// .including(required: Player.team.filter(Column("avgScore") < playerAlias[Column("score")])
|
|
public static func aliased(_ alias: TableAlias) -> QueryInterfaceRequest<Self> {
|
|
return all().aliased(alias)
|
|
}
|
|
}
|