diff --git a/.gitignore b/.gitignore index 818f351..79b1600 100644 --- a/.gitignore +++ b/.gitignore @@ -1,33 +1,5 @@ -# Created by https://www.gitignore.io/api/xcode - -### Xcode ### -# Xcode -# -# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore - -## Build generated -.build/ -build/ -DerivedData -Carthage/ -Packages/ - -## Various settings -*.pbxuser -!default.pbxuser -*.mode1v3 -!default.mode1v3 -*.mode2v3 -!default.mode2v3 -*.perspectivev3 -!default.perspectivev3 -xcuserdata - -## Other -*.xccheckout -*.moved-aside -*.xcuserstate -*.xcscmblueprint -XcodeDevelopment/ -*.xcodeproj - +.DS_Store +/.build +/Packages +/*.xcodeproj +Build diff --git a/.swift-version b/.swift-version index d0b9234..9f55b2c 100644 --- a/.swift-version +++ b/.swift-version @@ -1 +1 @@ -DEVELOPMENT-SNAPSHOT-2016-05-09-a +3.0 diff --git a/.travis.yml b/.travis.yml index 6b539d2..4e422d7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,12 +6,10 @@ os: language: generic sudo: required dist: trusty -osx_image: xcode7.3 +osx_image: xcode8 install: - - eval "$(curl -sL https://raw.githubusercontent.com/Zewo/Zewo/5254525d9da56df29346fd76e99529c22034d61d/Scripts/install-swiftenv.sh)" + - eval "$(curl -sL https://raw.githubusercontent.com/Zewo/Zewo/master/Scripts/Travis/install.sh)" script: - - swift build --fetch # clones all dependencies - - rm -rf Packages/*/Tests # deletes dependency's tests until duplicate Package.tests issue can be resolved in SPM. At that point, remove. - - swift build -Xlinker -rpath -Xlinker $(pwd)/.build/debug/ - - swift build --configuration release -Xlinker -rpath -Xlinker $(pwd)/.build/release/ + - swift build + - swift build --configuration release - swift test diff --git a/LICENSE b/LICENSE index f7c62cf..10c82c6 100644 --- a/LICENSE +++ b/LICENSE @@ -1,7 +1,7 @@ The MIT License (MIT) -Copyright (c) 2015 Zewo +Copyright (c) 2016 Zewo Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/Package.swift b/Package.swift index 731575a..6ca7af7 100644 --- a/Package.swift +++ b/Package.swift @@ -3,7 +3,6 @@ import PackageDescription let package = Package( name: "SQL", dependencies: [ - .Package(url: "https://github.com/Zewo/String.git", majorVersion: 0, minor: 7), - .Package(url: "https://github.com/Zewo/URI.git", majorVersion: 0, minor: 8), + .Package(url: "https://github.com/Zewo/Core.git", majorVersion: 0, minor: 13) ] ) diff --git a/README.md b/README.md index 92bd8ee..dd9e678 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ import PackageDescription let package = Package( dependencies: [ - .Package(url: "https://github.com/Zewo/SQL.git", majorVersion: 0, minor: 5), + .Package(url: "https://github.com/Zewo/SQL.git", majorVersion: 0, minor: 13), ] ) ``` @@ -68,7 +68,7 @@ public class Artist: Table { case name = "name" case artistId = "artist_id" } - + static let tableName: String = "artists" } ``` @@ -92,7 +92,7 @@ public final class Artist { let id: Int? let name: String let genre: String - + init(name: String, genre: String) { self.name = name self.genre = genre @@ -106,13 +106,13 @@ extension Artist: Model { case name = "name" case genre = "genre" } - + // Specify a table name static let tableName: String = "artists" - + // Specify which field is primary static var primaryKeyField: Field = .id - + // Provide a getter and setter for the primary key var primaryKey: Int? { get { @@ -122,13 +122,13 @@ extension Artist: Model { id = newValue } } - + // Specify the values to be persisted var serialize: [Field: ValueConvertible?] { return [.name: name, .genre: genre] } - - // Provide an initializer for the model taking a row + + // Provide an initializer for the model taking a row convenience init(row: Row) throws { try self.init( name: row.value(Artist.field(.name)), @@ -169,7 +169,7 @@ This project is released under the MIT license. See [LICENSE](LICENSE) for detai [swift-badge]: https://img.shields.io/badge/Swift-3.0-orange.svg?style=flat [swift-url]: https://swift.org -[zewo-badge]: https://img.shields.io/badge/Zewo-0.5-FF7565.svg?style=flat +[zewo-badge]: https://img.shields.io/badge/Zewo-0.13-FF7565.svg?style=flat [zewo-url]: http://zewo.io [platform-badge]: https://img.shields.io/badge/Platforms-OS%20X%20--%20Linux-lightgray.svg?style=flat [platform-url]: https://swift.org @@ -181,4 +181,4 @@ This project is released under the MIT license. See [LICENSE](LICENSE) for detai [travis-badge]: https://travis-ci.org/Zewo/SQL.svg?branch=master [travis-url]: https://travis-ci.org/Zewo/SQL [codebeat-badge]: https://codebeat.co/badges/13196ddb-e30d-4a6a-bd41-3227cd965b80 -[codebeat-url]: https://codebeat.co/projects/github-com-zewo-sql \ No newline at end of file +[codebeat-url]: https://codebeat.co/projects/github-com-zewo-sql diff --git a/Sources/SQL/Core/ConnectionProtocol.swift b/Sources/SQL/Core/ConnectionProtocol.swift index 36c089f..a0d68c5 100644 --- a/Sources/SQL/Core/ConnectionProtocol.swift +++ b/Sources/SQL/Core/ConnectionProtocol.swift @@ -1,28 +1,4 @@ -// ConnectionProtocol.swift -// -// The MIT License (MIT) -// -// Copyright (c) 2015 Formbound -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -@_exported import URI +import Core /** @@ -35,17 +11,17 @@ public protocol ConnectionInfoProtocol { var databaseName: String { get } var username: String? { get } var password: String? { get } - - init?(uri: URI) + + init?(uri: URL) } public protocol ConnectionProtocol: class { associatedtype InternalStatus associatedtype Result: ResultProtocol - associatedtype Error: ErrorProtocol, CustomStringConvertible + associatedtype ConnectionError: Error, CustomStringConvertible associatedtype ConnectionInfo: ConnectionInfoProtocol associatedtype QueryRenderer: QueryRendererProtocol - + var connectionInfo: ConnectionInfo { get } func open() throws @@ -53,7 +29,8 @@ public protocol ConnectionProtocol: class { func close() var internalStatus: InternalStatus { get } - + + @discardableResult func execute(_ statement: String, parameters: [Value?]?) throws -> Result func begin() throws @@ -69,13 +46,13 @@ public protocol ConnectionProtocol: class { func rollbackToSavePointNamed(_ name: String) throws init(info: ConnectionInfo) - - var mostRecentError: Error? { get } + + var mostRecentError: ConnectionError? { get } } public extension ConnectionProtocol { - - public init?(uri: URI) { + + public init?(uri: URL) { guard let info = ConnectionInfo(uri: uri) else { return nil } @@ -84,7 +61,7 @@ public extension ConnectionProtocol { public func transaction(handler: (Void) throws -> T) throws -> T { try begin() - + do { let result = try handler() try commit() @@ -109,31 +86,35 @@ public extension ConnectionProtocol { throw error } } - + + @discardableResult func execute(_ statement: String) throws -> Result { return try execute(statement, parameters: nil) } - + public func execute(_ query: Select) throws -> Result { return try execute(QueryRenderer.renderStatement(query), parameters: query.sqlParameters) } - + + @discardableResult public func execute(_ query: Update) throws -> Result { return try execute(QueryRenderer.renderStatement(query), parameters: query.sqlParameters) } - + + @discardableResult public func execute(_ query: Insert, returnInsertedRows: Bool = false) throws -> Result { return try execute(QueryRenderer.renderStatement(query, forReturningInsertedRows: returnInsertedRows), parameters: query.sqlParameters) } - + + @discardableResult public func execute(_ query: Delete) throws -> Result { return try execute(QueryRenderer.renderStatement(query), parameters: query.sqlParameters) } - + public func execute(_ statement: String, parameters: [ValueConvertible?]) throws -> Result { return try execute(statement, parameters: parameters.map { $0?.sqlValue }) } - + public func execute(_ statement: String, parameters: ValueConvertible?...) throws -> Result { return try execute(statement, parameters: parameters) } diff --git a/Sources/SQL/Core/FieldInfo.swift b/Sources/SQL/Core/FieldInfo.swift index 9c4b0f6..57dc1e8 100644 --- a/Sources/SQL/Core/FieldInfo.swift +++ b/Sources/SQL/Core/FieldInfo.swift @@ -1,27 +1,3 @@ -// FieldInfo.swift -// -// The MIT License (MIT) -// -// Copyright (c) 2015 Formbound -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - public protocol FieldInfoProtocol: CustomStringConvertible { var name: String { get } var index: Int { get } diff --git a/Sources/SQL/Core/QualifiedField.swift b/Sources/SQL/Core/QualifiedField.swift index 09d3c5b..19c15f6 100644 --- a/Sources/SQL/Core/QualifiedField.swift +++ b/Sources/SQL/Core/QualifiedField.swift @@ -1,33 +1,8 @@ -// QualifiedField.swift -// -// The MIT License (MIT) -// -// Copyright (c) 2016 Formbound -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - - public struct QualifiedField { public let unqualifiedName: String public var tableName: String? public var alias: String? - + public init(_ name: String, alias: String? = nil) { let components = name.split(separator: ".") if components.count == 2, let tableName = components.first, let fieldName = components.last { @@ -38,10 +13,10 @@ public struct QualifiedField { self.unqualifiedName = name self.tableName = nil } - + self.alias = alias } - + func alias(_ alias: String) -> QualifiedField { var new = self new.alias = alias diff --git a/Sources/SQL/Core/ResultProtocol.swift b/Sources/SQL/Core/ResultProtocol.swift index 8efda43..6465b1e 100644 --- a/Sources/SQL/Core/ResultProtocol.swift +++ b/Sources/SQL/Core/ResultProtocol.swift @@ -1,26 +1,4 @@ -// ResultProtocol.swift -// -// The MIT License (MIT) -// -// Copyright (c) 2015 Formbound -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. +import Core public protocol ResultStatus { var successful: Bool { get } @@ -36,21 +14,21 @@ public protocol ResultProtocol: Collection { subscript(index: Int) -> Iterator.Element { get } var count: Int { get } - + func data(atRow rowIndex: Int, forFieldIndex fieldIndex: Int) -> Data? } extension ResultProtocol { - + public var fields: [FieldInfo] { return Array(fieldsByName.values) } - + public func index(ofFieldByName name: String) -> Int? { guard let field = fieldsByName[name] else { return nil } - + return field.index } @@ -61,7 +39,7 @@ extension ResultProtocol { public var endIndex: Int { return count } - + public func index(after: Int) -> Int { return after + 1 } diff --git a/Sources/SQL/Core/RowProtocol.swift b/Sources/SQL/Core/RowProtocol.swift index 30edef5..5de4715 100644 --- a/Sources/SQL/Core/RowProtocol.swift +++ b/Sources/SQL/Core/RowProtocol.swift @@ -1,29 +1,4 @@ -// RowProtocol.swift -// -// The MIT License (MIT) -// -// Copyright (c) 2015 Formbound -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -@_exported import String - +import Core public protocol RowConvertible { init(row: T) throws @@ -31,84 +6,84 @@ public protocol RowConvertible { public protocol RowProtocol { associatedtype Result: ResultProtocol - + var result: Result { get } var index: Int { get } - + func data(_ field: QualifiedField) throws -> Data? } -public enum RowProtocolError: ErrorProtocol { +public enum RowProtocolError: Error { case expectedQualifiedField(QualifiedField) case unexpectedNilValue(QualifiedField) } public extension RowProtocol { - + public func data(_ field: QualifiedField) throws -> Data? { - + let fieldName: String - - + + if let alias = field.alias { fieldName = alias } else { fieldName = field.unqualifiedName } - + guard let fieldIndex = result.index(ofFieldByName: fieldName) else { throw RowProtocolError.expectedQualifiedField(field) } - + return result.data(atRow: index, forFieldIndex: fieldIndex) } - + public func data(_ field: QualifiedField) throws -> Data { guard let data: Data = try data(field) else { throw RowProtocolError.unexpectedNilValue(field) } - + return data } - + public func data(_ field: String) throws -> Data { let field = QualifiedField(field) guard let data: Data = try data(field) else { throw RowProtocolError.unexpectedNilValue(field) } - + return data } - + // MARK: - ValueConvertible - + public func value(_ field: QualifiedField) throws -> T? { guard let data: Data = try data(field) else { return nil } - + return try T(rawSQLData: data) } - + public func value(_ field: QualifiedField) throws -> T { guard let data: Data = try data(field) else { throw RowProtocolError.unexpectedNilValue(field) } - + return try T(rawSQLData: data) } - + // MARK - String support - + public func data(field: String) throws -> Data? { return try data(QualifiedField(field)) } - + public func value(_ field: String) throws -> T? { return try value(QualifiedField(field)) } - + public func value(_ field: String) throws -> T { return try value(QualifiedField(field)) } @@ -128,13 +103,13 @@ public struct TableRow: RowProtocol { public var result: Row.Result public var index: Int private let _data: (QualifiedField) throws -> Data? - + public init(row: Row) { self.result = row.result self.index = row.index self._data = row.data } - + public func data(_ field: QualifiedField) throws -> Data? { return try self._data(field) } @@ -144,7 +119,7 @@ extension TableRow where Table.Field.RawValue == String { public func value(_ field: Table.Field) throws -> T { return try value(field) } - + public func value(_ field: Table.Field) throws -> T? { return try value(field) } diff --git a/Sources/SQL/Core/StatementRepresentable.swift b/Sources/SQL/Core/StatementRepresentable.swift index 150c4a4..d4b94bb 100644 --- a/Sources/SQL/Core/StatementRepresentable.swift +++ b/Sources/SQL/Core/StatementRepresentable.swift @@ -1,27 +1,4 @@ -// StatementRepresentable.swift -// -// The MIT License (MIT) -// -// Copyright (c) 2016 Formbound -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - +import Foundation public protocol StatementStringRepresentable: CustomStringConvertible { var sqlString: String { get } @@ -35,27 +12,27 @@ extension StatementStringRepresentable { public extension String { public func sqlStringWithEscapedPlaceholdersUsingPrefix(_ prefix: String, suffix: String? = nil, transformer: (Int) -> String) -> String { - - var strings = split(byString: "%@") - + + var strings = self.components(separatedBy: "%@") + if strings.count == 1 { return self } - + var newStrings = [String]() - + for i in 0.. String { let string = map { $0.sqlString }.joined(separator: separator ?? "") - + if(isolate) { return "(\(string))" } - + return string } } diff --git a/Sources/SQL/Core/Value.swift b/Sources/SQL/Core/Value.swift index 2443b73..7868b23 100644 --- a/Sources/SQL/Core/Value.swift +++ b/Sources/SQL/Core/Value.swift @@ -1,36 +1,14 @@ -// Value.swift -// -// The MIT License (MIT) -// -// Copyright (c) 2015 Formbound -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. +import Core public enum Value { - public struct Error: ErrorProtocol { - let description: String - } - case string(String) case data(Data) } +public struct ValueError: Error { + let description: String +} + public protocol ValueConvertible: ParameterConvertible { var sqlValue: Value { get } @@ -47,7 +25,7 @@ extension ValueConvertible { extension Int: ValueConvertible { public init(rawSQLData data: Data) throws { guard let value = Int(try String(data: data)) else { - throw Value.Error(description: "Failed to convert data to Int") + throw ValueError(description: "Failed to convert data to Int") } self = value } @@ -60,7 +38,7 @@ extension Int: ValueConvertible { extension UInt: ValueConvertible { public init(rawSQLData data: Data) throws { guard let value = UInt(try String(data: data)) else { - throw Value.Error(description: "Failed to convert data to UInt") + throw ValueError(description: "Failed to convert data to UInt") } self = value } @@ -73,7 +51,7 @@ extension UInt: ValueConvertible { extension Float: ValueConvertible { public init(rawSQLData data: Data) throws { guard let value = Float(try String(data: data)) else { - throw Value.Error(description: "Failed to convert data to Float") + throw ValueError(description: "Failed to convert data to Float") } self = value } @@ -86,7 +64,7 @@ extension Float: ValueConvertible { extension Double: ValueConvertible { public init(rawSQLData data: Data) throws { guard let value = Double(try String(data: data)) else { - throw Value.Error(description: "Failed to convert data to Double") + throw ValueError(description: "Failed to convert data to Double") } self = value } diff --git a/Sources/SQL/Model/Entity.swift b/Sources/SQL/Model/Entity.swift index 9538969..fd2c27f 100644 --- a/Sources/SQL/Model/Entity.swift +++ b/Sources/SQL/Model/Entity.swift @@ -1,27 +1,3 @@ -// Entity.swift -// -// The MIT License (MIT) -// -// Copyright (c) 2016 Formbound -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - public protocol EntityProtocol { associatedtype Model: ModelProtocol @@ -33,7 +9,7 @@ public protocol PersistedEntityProtocol: EntityProtocol, Equatable { } public extension EntityProtocol where Model.Field.RawValue == String { - public static func get(_ pk: Model.PrimaryKey, connection: Connection) throws -> PersistedEntity? { + public static func get (_ pk: Model.PrimaryKey, connection: Connection) throws -> PersistedEntity? where Connection.Result.Iterator.Element: RowProtocol { var select = Model.select(where: Model.Field.primaryKey == pk) select.limit(to: 1) @@ -48,15 +24,15 @@ public extension EntityProtocol where Model.Field.RawValue == String { return PersistedEntity(model: try Model.init(row: tableRow), primaryKey: try tableRow.value(Model.Field.primaryKey)) } - public static func fetchAll(connection: Connection) throws -> [PersistedEntity] { + public static func fetchAll (connection: Connection) throws -> [PersistedEntity] where Connection.Result.Iterator.Element: RowProtocol { return try fetch(where: nil, limit: nil, offset: nil, connection: connection) } - public static func first(where predicate: Predicate? = nil, connection: Connection) throws -> PersistedEntity? { + public static func first (where predicate: Predicate? = nil, connection: Connection) throws -> PersistedEntity? where Connection.Result.Iterator.Element: RowProtocol { return try fetch(where: predicate, limit: 1, offset: 0, connection: connection).first } - public static func fetch(where predicate: Predicate? = nil, limit: Int? = 0, offset: Int? = 0, connection: Connection) throws -> [PersistedEntity] { + public static func fetch (where predicate: Predicate? = nil, limit: Int? = 0, offset: Int? = 0, connection: Connection) throws -> [PersistedEntity] where Connection.Result.Iterator.Element: RowProtocol { var select = Model.select if let predicate = predicate { @@ -80,7 +56,7 @@ public extension EntityProtocol where Model.Field.RawValue == String { } } - public func create(connection: Connection) throws -> PersistedEntity { + public func create (connection: Connection) throws -> PersistedEntity where Connection.Result.Iterator.Element: RowProtocol { return try connection.transaction { try self.model.willSave() try self.model.willCreate() @@ -106,22 +82,22 @@ public extension EntityProtocol where Model.Field.RawValue == String { } } - public func save(connection: Connection) throws -> PersistedEntity { + public func save (connection: Connection) throws -> PersistedEntity where Connection.Result.Iterator.Element: RowProtocol { return try create(connection: connection) } } public extension PersistedEntityProtocol where Model.Field.RawValue == String { - public func delete(connection: Connection) throws -> Entity { + public func delete (connection: Connection) throws -> Entity where Connection.Result.Iterator.Element: RowProtocol { try connection.execute(Model.delete(where: Model.Field.primaryKey == self.primaryKey)) return Entity(model: model) } - public func refresh(connection: Connection) throws -> PersistedEntity { + public func refresh (connection: Connection) throws -> PersistedEntity where Connection.Result.Iterator.Element: RowProtocol { try model.willRefresh() - guard let refreshed = try self.dynamicType.get(primaryKey, connection: connection) else { + guard let refreshed = try type(of: self).get(primaryKey, connection: connection) else { throw EntityError("Failed to re-fetch model with primary key \(primaryKey)") } @@ -130,7 +106,7 @@ public extension PersistedEntityProtocol where Model.Field.RawValue == String { return refreshed } - public func update(connection: Connection) throws -> PersistedEntity { + public func update (connection: Connection) throws -> PersistedEntity where Connection.Result.Iterator.Element: RowProtocol { try model.willSave() try model.willUpdate() @@ -143,12 +119,12 @@ public extension PersistedEntityProtocol where Model.Field.RawValue == String { return new } - public func save(connection: Connection) throws -> PersistedEntity { + public func save (connection: Connection) throws -> PersistedEntity where Connection.Result.Iterator.Element: RowProtocol { return try update(connection: connection) } } -public struct Entity: EntityProtocol { +public struct Entity : EntityProtocol where Model.Field.RawValue == String { public let model: Model public init(model: Model) { @@ -156,7 +132,7 @@ public struct Entity: } } -public struct PersistedEntity: PersistedEntityProtocol { +public struct PersistedEntity : PersistedEntityProtocol where Model.Field.RawValue == String { public let model: Model public let primaryKey: Model.PrimaryKey @@ -166,6 +142,6 @@ public struct PersistedEntity(lhs: Entity, rhs: Entity) -> Bool { +public func == (lhs: Entity, rhs: Entity) -> Bool where Entity.Model == Model { return "\(Model.Field.tableName).\(lhs.primaryKey.hashValue)" == "\(Model.Field.tableName).\(rhs.primaryKey.hashValue)" } diff --git a/Sources/SQL/Model/ModelProtocol.swift b/Sources/SQL/Model/ModelProtocol.swift index 4e1d37a..628b884 100644 --- a/Sources/SQL/Model/ModelProtocol.swift +++ b/Sources/SQL/Model/ModelProtocol.swift @@ -1,28 +1,3 @@ -// ModelProtocol.swift -// -// The MIT License (MIT) -// -// Copyright (c) 2016 Formbound -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - - public protocol ModelField: TableField { static var primaryKey: Self { get } } @@ -30,21 +5,21 @@ public protocol ModelField: TableField { public protocol ModelProtocol: TableProtocol, TableRowConvertible { associatedtype PrimaryKey: Hashable, ValueConvertible associatedtype Field: ModelField - + func serialize() -> [Field: ValueConvertible?] - + func willSave() throws func didSave() - + func willUpdate() throws func didUpdate() - + func willCreate() throws func didCreate() - + func willDelete() throws func didDelete() - + func willRefresh() throws func didRefresh() } @@ -52,23 +27,23 @@ public protocol ModelProtocol: TableProtocol, TableRowConvertible { public extension ModelProtocol { public func willSave() throws {} public func didSave() {} - + public func willUpdate() throws {} public func didUpdate() {} - + public func willCreate() throws {} public func didCreate() {} - + public func willDelete() throws {} public func didDelete() {} - + public func willRefresh() throws {} public func didRefresh() {} } -public struct EntityError: ErrorProtocol, CustomStringConvertible { +public struct EntityError: Error, CustomStringConvertible { public let description: String - + public init(_ description: String) { self.description = description } diff --git a/Sources/SQL/Model/TableProtocol.swift b/Sources/SQL/Model/TableProtocol.swift index 2021d8c..fd2b4dc 100644 --- a/Sources/SQL/Model/TableProtocol.swift +++ b/Sources/SQL/Model/TableProtocol.swift @@ -1,28 +1,3 @@ -// TableProtocol.swift -// -// The MIT License (MIT) -// -// Copyright (c) 2016 Formbound -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - - public protocol TableField: RawRepresentable, Hashable, ParameterConvertible { static var tableName: String { get } } @@ -31,7 +6,7 @@ public extension TableField { public var sqlParameter: Parameter { return .field(qualifiedField) } - + public var qualifiedField: QualifiedField { return QualifiedField("\(Self.tableName).\(self.rawValue)", alias: "\(Self.tableName)__\(self.rawValue)") } @@ -39,50 +14,50 @@ public extension TableField { public protocol TableProtocol { associatedtype Field: TableField - + } public extension TableProtocol where Self.Field.RawValue == String { - + public static func select(_ fields: Field...) -> Select { return Select(fields.map { $0.qualifiedField }, from: [Field.tableName]) } - + public static func select(where predicate: Predicate) -> Select { return select.filtered(predicate) } - + public static var select: Select { return Select("*", from: Field.tableName) } - + public static func update(_ dict: [Field: ValueConvertible?]) -> Update { var translated = [QualifiedField: ValueConvertible?]() - + for (key, value) in dict { translated[key.qualifiedField] = value } - + var update = Update(Field.tableName) update.set(translated) - + return update } - + public static func insert(_ dict: [Field: ValueConvertible?]) -> Insert { var translated = [QualifiedField: ValueConvertible?]() - + for (key, value) in dict { translated[key.qualifiedField] = value } - + return Insert(Field.tableName, values: translated) } - + public static func delete(where predicate: Predicate) -> Delete { return Delete(from: Field.tableName).filtered(predicate) } - + public static var delete: Delete { return Delete(from: Field.tableName) } diff --git a/Sources/SQL/Query/Delete.swift b/Sources/SQL/Query/Delete.swift index c84f4de..f55a98d 100644 --- a/Sources/SQL/Query/Delete.swift +++ b/Sources/SQL/Query/Delete.swift @@ -1,32 +1,8 @@ -// Delete.swift -// -// The MIT License (MIT) -// -// Copyright (c) 2016 Formbound -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - public struct Delete: PredicatedQuery { public var predicate: Predicate? = nil - + public let tableName: String - + public init(from tableName: String) { self.tableName = tableName } @@ -37,7 +13,7 @@ extension Delete: StatementParameterListConvertible { if let predicate = predicate { return predicate.sqlParameters } - + return [] } } diff --git a/Sources/SQL/Query/Function.swift b/Sources/SQL/Query/Function.swift index 5d43795..6c8cf35 100644 --- a/Sources/SQL/Query/Function.swift +++ b/Sources/SQL/Query/Function.swift @@ -1,27 +1,3 @@ -// Function.swift -// -// The MIT License (MIT) -// -// Copyright (c) 2016 Formbound -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - public enum Function { case sum(QualifiedField) } diff --git a/Sources/SQL/Query/Insert.swift b/Sources/SQL/Query/Insert.swift index 9a3134e..fb5051e 100644 --- a/Sources/SQL/Query/Insert.swift +++ b/Sources/SQL/Query/Insert.swift @@ -1,44 +1,20 @@ -// Insert.swift -// -// The MIT License (MIT) -// -// Copyright (c) 2016 Formbound -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - public struct Insert { public let valuesByField: [QualifiedField: Value?] - + public let tableName: String - + public init(_ tableName: String, values: [QualifiedField: Value?]) { self.tableName = tableName self.valuesByField = values } - + public init(_ tableName: String, values: [QualifiedField: ValueConvertible?]) { var transformed = [QualifiedField: Value?]() - + for (key, value) in values { transformed[key] = value?.sqlValue } - + self.init(tableName, values: transformed) } } diff --git a/Sources/SQL/Query/Join.swift b/Sources/SQL/Query/Join.swift index dce74d2..e4c6163 100644 --- a/Sources/SQL/Query/Join.swift +++ b/Sources/SQL/Query/Join.swift @@ -1,37 +1,13 @@ -// Join.swift -// -// The MIT License (MIT) -// -// Copyright (c) 2016 Formbound -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - public struct Join { public enum `Type` { case inner(String) case outer(String) } - + public let leftKey: QualifiedField public let rightKey: QualifiedField public let type: Type - + public init(type: `Type`, leftKey: QualifiedField, rightKey: QualifiedField) { self.type = type self.leftKey = leftKey diff --git a/Sources/SQL/Query/Operator.swift b/Sources/SQL/Query/Operator.swift index a9a2da8..8aeafd4 100644 --- a/Sources/SQL/Query/Operator.swift +++ b/Sources/SQL/Query/Operator.swift @@ -1,33 +1,9 @@ -// Operator.swift -// -// The MIT License (MIT) -// -// Copyright (c) 2016 Formbound -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - public enum Operator { case equal - + case greaterThan case greaterThanOrEqual - + case lessThan case lessThanOrEqual case contains diff --git a/Sources/SQL/Query/Order.swift b/Sources/SQL/Query/Order.swift index 560337f..d302514 100644 --- a/Sources/SQL/Query/Order.swift +++ b/Sources/SQL/Query/Order.swift @@ -1,28 +1,3 @@ -// Order.swift -// -// The MIT License (MIT) -// -// Copyright (c) 2016 Formbound -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - - public enum Order { case asc(StatementStringRepresentable) case desc(StatementStringRepresentable) diff --git a/Sources/SQL/Query/Parameter.swift b/Sources/SQL/Query/Parameter.swift index d747ff4..06b83ed 100644 --- a/Sources/SQL/Query/Parameter.swift +++ b/Sources/SQL/Query/Parameter.swift @@ -1,33 +1,9 @@ -// Parameter.swift -// -// The MIT License (MIT) -// -// Copyright (c) 2016 Formbound -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - public protocol ParameterConvertible { var sqlParameter: Parameter { get } } public enum Parameter { - + case field(QualifiedField) case value(Value?) case values([Value?]) diff --git a/Sources/SQL/Query/Predicate.swift b/Sources/SQL/Query/Predicate.swift index 06f9da5..bf0975a 100644 --- a/Sources/SQL/Query/Predicate.swift +++ b/Sources/SQL/Query/Predicate.swift @@ -1,27 +1,3 @@ -// Predicate.swift -// -// The MIT License (MIT) -// -// Copyright (c) 2016 Formbound -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - public indirect enum Predicate { case expression(left: Parameter, operator: Operator, right: Parameter) case and([Predicate]) @@ -75,15 +51,15 @@ extension ParameterConvertible { public func contains(_ values: [ValueConvertible?]) -> Predicate { return contains(values.map { $0?.sqlValue }) } - + public func contains(_ values: ValueConvertible?...) -> Predicate { return contains(values) } - + public func contains(_ values: [Value?]) -> Predicate { return .expression(left: self.sqlParameter, operator: .contains, right: .values(values)) } - + public func contains(_ values: Value?...) -> Predicate { return contains(values) } @@ -95,23 +71,23 @@ extension ParameterConvertible { public func containedIn(_ values: [ValueConvertible?]) -> Predicate { return containedIn(values.map { $0?.sqlValue }) } - + public func containedIn(_ values: ValueConvertible?...) -> Predicate { return containedIn(values) } - + public func containedIn(_ values: [Value?]) -> Predicate { return .expression(left: self.sqlParameter, operator: .containedIn, right: .values(values)) } - + public func containedIn(_ values: Value?...) -> Predicate { return containedIn(values) } - + public func isNull() -> Predicate { return .expression(left: self.sqlParameter, operator: .equal, right: .null) } - + public func isNotNulll() -> Predicate { return .not(isNull()) } @@ -140,10 +116,10 @@ public extension PredicatedQuery { predicate = value return } - + predicate = .and([existing, value]) } - + public func filtered(_ value: Predicate) -> Self { var new = self new.filter(value) diff --git a/Sources/SQL/Query/QueryRenderer.swift b/Sources/SQL/Query/QueryRenderer.swift index 189eb2f..eb8cd8d 100644 --- a/Sources/SQL/Query/QueryRenderer.swift +++ b/Sources/SQL/Query/QueryRenderer.swift @@ -1,35 +1,11 @@ -// QueryRenderer.swift -// -// The MIT License (MIT) -// -// Copyright (c) 2016 Formbound -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - public protocol QueryRendererProtocol { - + static func renderStatement(_ statement: Select) -> String - + static func renderStatement(_ statement: Update) -> String - + static func renderStatement(_ statement: Insert, forReturningInsertedRows returnInsertedRows: Bool) -> String - + static func renderStatement(_ statement: Delete) -> String } @@ -38,7 +14,7 @@ public extension QueryRendererProtocol { switch predicate { case .expression(let left, let op, let right): var components = [composeParameter(left), op.sqlString] - + switch op { case .containedIn, .contains: components.append("(\(composeParameter(right)))") @@ -46,9 +22,9 @@ public extension QueryRendererProtocol { default: components.append(composeParameter(right)) } - + return components.joined(separator: " ") - + case .and(let predicates): return "(\(predicates.map { composePredicate($0) }.joined(separator: " AND ")))" case .or(let predicates): @@ -57,7 +33,7 @@ public extension QueryRendererProtocol { return "NOT \(composePredicate(predicate))" } } - + static func composeParameter(_ parameter: Parameter) -> String { switch parameter { case .field(let field): diff --git a/Sources/SQL/Query/Select.swift b/Sources/SQL/Query/Select.swift index 4f8e493..4e95e93 100644 --- a/Sources/SQL/Query/Select.swift +++ b/Sources/SQL/Query/Select.swift @@ -1,27 +1,3 @@ -// Select.swift -// -// The MIT License (MIT) -// -// Copyright (c) 2016 Formbound -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - public protocol SelectComponentConvertible { var sqlSelectComponent: Select.Component { get } } @@ -33,52 +9,52 @@ public struct Select: PredicatedQuery { case subquery(Select, alias: String) case function(Function, alias: String) } - + public var order: [Order] = [] - + private(set) public var fields: [Component] public let from: [Component] - + private(set) public var limit: Int? = nil private(set) public var offset: Int? = nil - + public var predicate: Predicate? = nil - + public var joins: [Join] = [] - + public func subquery(as alias: String) -> Component { return .subquery(self, alias: alias) } - + public init(_ fields: [SelectComponentConvertible], from source: [SelectComponentConvertible]) { self.fields = fields.map { $0.sqlSelectComponent } self.from = source.map { $0.sqlSelectComponent } } - + public init(_ fields: SelectComponentConvertible..., from source: SelectComponentConvertible) { self.init(fields, from: [source]) } - + public mutating func extend(_ fields: SelectComponentConvertible...) { self.fields += fields.map { $0.sqlSelectComponent } } - + // MARK: - Order - + public mutating func order(by value: [Order]) { order += value } - + public mutating func order(by value: Order...) { order(by: value) } - + public func ordered(by value: [Order]) -> Select { var new = self new.order(by: value) return new } - + public func ordered(by value: Order...) -> Select { return ordered(by: value) } @@ -86,23 +62,23 @@ public struct Select: PredicatedQuery { public mutating func limit(to value: Int) { limit = value } - + public func limited(to value: Int) -> Select { var new = self new.limit(to: value) return new } - + public mutating func offset(by value: Int) { offset = value } - + public func offsetted(by value: Int) -> Select { var new = self new.offset(by: value) return new } - + public mutating func join(_ joinType: Join.`Type`, on leftKey: QualifiedField, equals rightKey: QualifiedField) { joins.append( Join( @@ -135,15 +111,15 @@ extension Select: ParameterConvertible { } } -extension Select.Component: StringLiteralConvertible { +extension Select.Component: ExpressibleByStringLiteral { public init(stringLiteral value: String) { self = .string(value) } - + public init(extendedGraphemeClusterLiteral value: String) { self = .string(value) } - + public init(unicodeScalarLiteral value: String) { self = .string(value) } @@ -171,14 +147,14 @@ extension String: SelectComponentConvertible { extension Select: StatementParameterListConvertible { public var sqlParameters: [Value?] { var parameters = [Value?]() - + parameters += fields.flatMap { $0.sqlParameters } parameters += from.flatMap { $0.sqlParameters } - + if let predicate = predicate { parameters += predicate.sqlParameters } - + return parameters } } diff --git a/Sources/SQL/Query/Update.swift b/Sources/SQL/Query/Update.swift index bdc121f..3248fe9 100644 --- a/Sources/SQL/Query/Update.swift +++ b/Sources/SQL/Query/Update.swift @@ -1,42 +1,18 @@ -// Update.swift -// -// The MIT License (MIT) -// -// Copyright (c) 2016 Formbound -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - public struct Update: PredicatedQuery { public var predicate: Predicate? = nil - + public private(set) var valuesByField: [QualifiedField: Value?] = [:] - + public let tableName: String - + public init(_ tableName: String) { self.tableName = tableName } - + public mutating func set(_ field: QualifiedField, _ value: T?) { valuesByField[field] = value?.sqlValue } - + public mutating func set(_ dict: [QualifiedField: ValueConvertible?]) { for (key, value) in dict { valuesByField[key] = value?.sqlValue @@ -47,13 +23,13 @@ public struct Update: PredicatedQuery { extension Update: StatementParameterListConvertible { public var sqlParameters: [Value?] { var parameters = [Value?]() - + if let predicate = predicate { parameters += predicate.sqlParameters } - + parameters += valuesByField.values - + return parameters } } diff --git a/Tests/SQLTests/.DS_Store b/Tests/SQLTests/.DS_Store new file mode 100644 index 0000000..5008ddf Binary files /dev/null and b/Tests/SQLTests/.DS_Store differ diff --git a/Tests/SQL/SQLTests.swift b/Tests/SQLTests/SQLTests.swift similarity index 97% rename from Tests/SQL/SQLTests.swift rename to Tests/SQLTests/SQLTests.swift index 1a0568e..45f7d49 100644 --- a/Tests/SQL/SQLTests.swift +++ b/Tests/SQLTests/SQLTests.swift @@ -8,23 +8,23 @@ struct User { extension User: ModelProtocol { typealias PrimaryKey = Int - + enum Field: String, ModelField { case username case password case id - + static let tableName: String = "users" static let primaryKey: Field = .id } - + func serialize() -> [Field : ValueConvertible?] { return [ .username: username, .password: password ] } - + init(row: TableRow) throws { username = try row.value(.username) password = try row.value(.password)