0001    // Query.swift
0002    //
0003    // The MIT License (MIT)
0004    //
0005    // Copyright (c) 2015 Formbound
0006    //
0007    // Permission is hereby granted, free of charge, to any person obtaining a copy
0008    // of this software and associated documentation files (the "Software"), to deal
0009    // in the Software without restriction, including without limitation the rights
0010    // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
0011    // copies of the Software, and to permit persons to whom the Software is
0012    // furnished to do so, subject to the following conditions:
0013    //
0014    // The above copyright notice and this permission notice shall be included in all
0015    // copies or substantial portions of the Software.
0016    //
0017    // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0018    // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0019    // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
0020    // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
0021    // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
0022    // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
0023    // SOFTWARE.
0024    
0025    
0026    public protocol Query
Query.swift:30
public extension Query {
Query.swift:36
public protocol ModelQuery: Query {
: StatementConvertible { 0027 0028 } 0029 0030 public extension Query { 0031 public func execute<T: Connection>(connection: T) throws -> T.ResultType { 0032 return try connection.execute(self) 0033 } 0034 } 0035 0036 public protocol ModelQuery
Query.swift:85
public struct Delete<M: Model>: ModelQuery, FilteredQuery {
Query.swift:105
public struct Insert<M: Model>: ModelQuery {
Query.swift:143
public struct Select<M: Model>: ModelQuery, FilteredQuery {
: Query { 0037 associatedtype ModelType: Model 0038 } 0039 0040 internal protocol FilteredQuery
Query.swift:85
public struct Delete<M: Model>: ModelQuery, FilteredQuery {
Query.swift:143
public struct Select<M: Model>: ModelQuery, FilteredQuery {
{ 0041 var condition: Condition? { get } 0042 } 0043 0044 public struct JoinKey
Model.swift:115
public func == <L: ModelFieldset, R: ModelFieldset>(lhs: L, rhs: R) -> JoinKey<L, R> {
Model.swift:116
    return JoinKey(left: lhs, right: rhs)
Query.swift:78
    internal init<L: ModelFieldset, R: Model>(type: JoinType<R>, key: JoinKey<L, R.Field>) {
Query.swift:161
    public func join<T: Model>(type: JoinType<T>, on key: JoinKey<M.Field, T.Field>) -> Select {
<L
Query.swift:45
    let left: L
: ModelFieldset, R
Query.swift:46
    let right: R
: ModelFieldset> { 0045 let left
Query.swift:80
        self.leftKey = key.left.qualifiedName
: L 0046 let right
Query.swift:81
        self.rightKey = key.right.qualifiedName
: R 0047 } 0048 0049 public enum JoinType
Query.swift:78
    internal init<L: ModelFieldset, R: Model>(type: JoinType<R>, key: JoinKey<L, R.Field>) {
Query.swift:161
    public func join<T: Model>(type: JoinType<T>, on key: JoinKey<M.Field, T.Field>) -> Select {
<T
Query.swift:50
    case Inner(T.Type)
Query.swift:51
    case Outer(T.Type)
Query.swift:52
    case Left(T.Type)
Query.swift:53
    case Right(T.Type)
Query.swift:58
            return "LEFT JOIN \(T.Field.tableName)"
Query.swift:60
            return "RIGHT JOIN \(T.Field.tableName)"
Query.swift:62
            return "INNER JOIN \(T.Field.tableName)"
Query.swift:64
            return "OUTER JOIN \(T.Field.tableName)"
: Model>: CustomStringConvertible { 0050 case Inner
Query.swift:61
        case .Inner:
(T.Type) 0051 case Outer
Query.swift:63
        case .Outer:
(T.Type) 0052 case Left
Query.swift:57
        case .Left:
(T.Type) 0053 case Right
Query.swift:59
        case .Right:
(T.Type) 0054 0055 public var description
Query.swift:79
        self.type = type.description
: String { 0056 switch self { 0057 case .Left: 0058 return "LEFT JOIN \(T.Field.tableName)" 0059 case .Right: 0060 return "RIGHT JOIN \(T.Field.tableName)" 0061 case .Inner: 0062 return "INNER JOIN \(T.Field.tableName)" 0063 case .Outer: 0064 return "OUTER JOIN \(T.Field.tableName)" 0065 } 0066 } 0067 } 0068 0069 internal struct Join
Query.swift:159
    var joins: [Join] = []
Query.swift:163
        new.joins.append(Join(type: type, key: key))
: StatementConvertible { 0070 internal let type
Query.swift:75
        return Statement(components: [type, "ON", leftKey, "=" ,rightKey])
Query.swift:79
        self.type = type.description
: String 0071 internal let leftKey
Query.swift:75
        return Statement(components: [type, "ON", leftKey, "=" ,rightKey])
Query.swift:80
        self.leftKey = key.left.qualifiedName
: String 0072 internal let rightKey
Query.swift:75
        return Statement(components: [type, "ON", leftKey, "=" ,rightKey])
Query.swift:81
        self.rightKey = key.right.qualifiedName
: String 0073 0074 internal func statementWithParameterOffset
Query.swift:254
            statement.merge(join.statementWithParameterOffset(&parameterOffset))
(inout parameterOffset: Int) -> Statement { 0075 return Statement(components: [type, "ON", leftKey, "=" ,rightKey]) 0076 } 0077 0078 internal init
Query.swift:163
        new.joins.append(Join(type: type, key: key))
<L: ModelFieldset, R: Model>(type: JoinType<R>, key: JoinKey<L, R.Field>) { 0079 self.type = type.description 0080 self.leftKey = key.left.qualifiedName 0081 self.rightKey = key.right.qualifiedName 0082 } 0083 } 0084 0085 public struct Delete
Query.swift:91
extension Delete: StatementConvertible {
<M
Query.swift:86
    public typealias ModelType = M
: Model>: ModelQuery, FilteredQuery { 0086 public typealias ModelType
Query.swift:94
        var statement = Statement(components: ["DELETE", "FROM", ModelType.Field.tableName])
= M 0087 0088 internal var condition
Query.swift:96
        if let condition = condition {
: Condition? 0089 } 0090 0091 extension Delete: StatementConvertible { 0092 public func statementWithParameterOffset(inout parameterOffset: Int) -> Statement { 0093 0094 var statement = Statement(components: ["DELETE", "FROM", ModelType.Field.tableName]) 0095 0096 if let condition = condition { 0097 statement.appendComponent("WHERE") 0098 statement.merge(condition.statementWithParameterOffset(&parameterOffset)) 0099 } 0100 0101 return statement 0102 } 0103 } 0104 0105 public struct Insert
Model.swift:130
    public static func insert(valuesByFieldName: [Field: ValueConvertible?]) -> Insert<Self> {
Model.swift:131
        return Insert(valuesByFieldName)
Query.swift:110
    public func set(field: M.Field, value: ValueConvertible?) -> Insert {
Query.swift:121
extension Insert: StatementConvertible {
<M
Query.swift:106
    public typealias ModelType = M
Query.swift:108
    internal var valuesByFieldName: [M.Field: ValueConvertible?] = [:]
Query.swift:110
    public func set(field: M.Field, value: ValueConvertible?) -> Insert {
Query.swift:116
    public init(_ valuesByFieldName: [M.Field: ValueConvertible?]) {
: Model>: ModelQuery { 0106 public typealias ModelType = M 0107 0108 internal var valuesByFieldName
Query.swift:112
        new.valuesByFieldName[field] = value
Query.swift:117
        self.valuesByFieldName = valuesByFieldName
Query.swift:123
        var statement = Statement(components: ["INSERT INTO", M.Field.tableName], parameters: Array(valuesByFieldName.values))
Query.swift:126
            "(\(valuesByFieldName.keys.map { $0.unqualifiedName }.joinWithSeparator(", ")))"
Query.swift:131
        let parameterString = (parameterOffset..<parameterOffset + valuesByFieldName.count).map {
: [M.Field: ValueConvertible?] = [:] 0109 0110 public func set(field: M.Field, value: ValueConvertible?) -> Insert { 0111 var new = self 0112 new.valuesByFieldName[field] = value 0113 return new 0114 } 0115 0116 public init
Model.swift:131
        return Insert(valuesByFieldName)
(_ valuesByFieldName: [M.Field: ValueConvertible?]) { 0117 self.valuesByFieldName = valuesByFieldName 0118 } 0119 } 0120 0121 extension Insert: StatementConvertible { 0122 public func statementWithParameterOffset(inout parameterOffset: Int) -> Statement { 0123 var statement = Statement(components: ["INSERT INTO", M.Field.tableName], parameters: Array(valuesByFieldName.values)) 0124 0125 statement.appendComponent( 0126 "(\(valuesByFieldName.keys.map { $0.unqualifiedName }.joinWithSeparator(", ")))" 0127 ) 0128 0129 statement.appendComponent("VALUES") 0130 0131 let parameterString = (parameterOffset..<parameterOffset + valuesByFieldName.count).map { 0132 return "$\($0)" 0133 }.joinWithSeparator(",") 0134 0135 0136 statement.appendComponent("(\(parameterString))") 0137 0138 return statement 0139 } 0140 } 0141 0142 0143 public struct Select
Model.swift:126
    public static func select(fields: ModelFieldset...) -> Select<Self> {
Model.swift:127
        return Select(fields: fields)
Query.swift:161
    public func join<T: Model>(type: JoinType<T>, on key: JoinKey<M.Field, T.Field>) -> Select {
Query.swift:200
    public func offset(value: UInt?) -> Select {
Query.swift:206
    public func limit(value: UInt?) -> Select {
Query.swift:212
    public func page(value: UInt?) -> Select {
Query.swift:218
    public func filter(condition: Condition) -> Select {
Query.swift:245
extension Select: StatementConvertible {
<M
Query.swift:144
    public typealias ModelType = M
Query.swift:161
    public func join<T: Model>(type: JoinType<T>, on key: JoinKey<M.Field, T.Field>) -> Select {
: Model>: ModelQuery, FilteredQuery { 0144 public typealias ModelType
Query.swift:233
    public func fetch<T: Connection where T.ResultType.Generator.Element == Row>(connection: T) throws -> [ModelType] {
Query.swift:234
        return try connection.execute(self).map { try ModelType(row: $0) }
Query.swift:237
    public func first<T: Connection where T.ResultType.Generator.Element == Row>(connection: T) throws -> ModelType? {
Query.swift:241
        return try connection.execute(new).map { try ModelType(row: $0) }.first
Query.swift:250
        var statement = Statement(components: ["SELECT", fieldString, "FROM", ModelType.Field.tableName])
= M 0145 public let fields
Query.swift:189
        self.fields = fields
Query.swift:248
        let fieldString = fields.isEmpty ? "*" : fields.map { "\($0.qualifiedName) AS \($0.alias)" }.joinWithSeparator(", ")
Query.swift:248
        let fieldString = fields.isEmpty ? "*" : fields.map { "\($0.qualifiedName) AS \($0.alias)" }.joinWithSeparator(", ")
: [ModelFieldset] 0146 0147 public var offset
Query.swift:177
            guard let offset = offset, limit = limit else {
Query.swift:170
                offset = nil
Query.swift:173
            offset = value * limit
Query.swift:202
        new.offset = value
Query.swift:239
        new.offset = 0
Query.swift:267
        if let offset = offset {
: UInt? 0148 public var limit
Query.swift:152
            return limit
Query.swift:155
            limit = newValue
Query.swift:177
            guard let offset = offset, limit = limit else {
Query.swift:169
            guard let value = newValue, limit = limit else {
Query.swift:208
        new.limit = value
Query.swift:240
        new.limit = 1
Query.swift:263
        if let limit = limit {
: UInt? 0149 0150 public var pageSize: UInt? { 0151 get { 0152 return limit 0153 } 0154 set { 0155 limit = newValue 0156 } 0157 } 0158 0159 var joins
Query.swift:163
        new.joins.append(Join(type: type, key: key))
Query.swift:253
        for join in joins {
: [Join] = [] 0160 0161 public func join<T: Model>(type: JoinType<T>, on key: JoinKey<M.Field, T.Field>) -> Select { 0162 var new = self 0163 new.joins.append(Join(type: type, key: key)) 0164 return new 0165 } 0166 0167 public var page
Query.swift:214
        new.page = value
: UInt? { 0168 set { 0169 guard let value = newValue, limit = limit else { 0170 offset = nil 0171 return 0172 } 0173 offset = value * limit 0174 } 0175 0176 get { 0177 guard let offset = offset, limit = limit else { 0178 return nil 0179 } 0180 0181 return offset / limit 0182 } 0183 } 0184 0185 internal var condition
Query.swift:220
        if let existing = self.condition {
Query.swift:228
        new.condition = newCondition
Query.swift:257
        if let condition = condition {
: Condition? 0186 0187 0188 public init
Model.swift:127
        return Select(fields: fields)
Query.swift:193
        self.init(fields: fields)
Query.swift:197
        self.init(fields: [])
(fields: [ModelFieldset]) { 0189 self.fields = fields 0190 } 0191 0192 public init(_ fields: ModelFieldset...) { 0193 self.init(fields: fields) 0194 } 0195 0196 public init() { 0197 self.init(fields: []) 0198 } 0199 0200 public func offset(value: UInt?) -> Select { 0201 var new = self 0202 new.offset = value 0203 return new 0204 } 0205 0206 public func limit(value: UInt?) -> Select { 0207 var new = self 0208 new.limit = value 0209 return new 0210 } 0211 0212 public func page(value: UInt?) -> Select { 0213 var new = self 0214 new.page = value 0215 return new 0216 } 0217 0218 public func filter(condition: Condition) -> Select { 0219 let newCondition: Condition 0220 if let existing = self.condition { 0221 newCondition = .And([existing, condition]) 0222 } 0223 else { 0224 newCondition = condition 0225 } 0226 0227 var new = self 0228 new.condition = newCondition 0229 0230 return new 0231 } 0232 0233 public func fetch<T: Connection where T.ResultType.Generator.Element == Row>(connection: T) throws -> [ModelType] { 0234 return try connection.execute(self).map { try ModelType(row: $0) } 0235 } 0236 0237 public func first<T: Connection where T.ResultType.Generator.Element == Row>(connection: T) throws -> ModelType? { 0238 var new = self 0239 new.offset = 0 0240 new.limit = 1 0241 return try connection.execute(new).map { try ModelType(row: $0) }.first 0242 } 0243 } 0244 0245 extension Select: StatementConvertible { 0246 public func statementWithParameterOffset(inout parameterOffset: Int) -> Statement { 0247 0248 let fieldString = fields.isEmpty ? "*" : fields.map { "\($0.qualifiedName) AS \($0.alias)" }.joinWithSeparator(", ") 0249 0250 var statement = Statement(components: ["SELECT", fieldString, "FROM", ModelType.Field.tableName]) 0251 0252 0253 for join in joins { 0254 statement.merge(join.statementWithParameterOffset(&parameterOffset)) 0255 } 0256 0257 if let condition = condition { 0258 statement.appendComponent("WHERE") 0259 0260 statement.merge(condition.statementWithParameterOffset(&parameterOffset)) 0261 } 0262 0263 if let limit = limit { 0264 statement.appendComponent("LIMIT \(limit)") 0265 } 0266 0267 if let offset = offset { 0268 statement.appendComponent("OFFSET \(offset)") 0269 } 0270 0271 return statement 0272 } 0273 } 0274