Skip to content

Commit

Permalink
Update to Zewo 0.13 (Swift 3) (#14)
Browse files Browse the repository at this point in the history
  • Loading branch information
joernroeder authored and Danappelxx committed Oct 1, 2016
1 parent f26c987 commit 1b912f9
Show file tree
Hide file tree
Showing 7 changed files with 168 additions and 141 deletions.
2 changes: 1 addition & 1 deletion .swift-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
DEVELOPMENT-SNAPSHOT-2016-05-09-a
3.0
17 changes: 17 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
notifications:
slack: zewo:VjyVCCQvTOw9yrbzQysZezD1
os:
- linux
- osx
language: generic
sudo: required
dist: trusty
osx_image: xcode8
install:
- eval "$(curl -sL https://raw.githubusercontent.com/Zewo/Zewo/master/Scripts/Travis/install.sh)"
script:
- swift build
- swift build --configuration release
# tests require a live psql database
# TODO: setup psql on travis
# - swift test
4 changes: 2 additions & 2 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import PackageDescription
let package = Package(
name: "PostgreSQL",
dependencies: [
.Package(url: "https://github.com/Zewo/CLibpq.git", majorVersion: 0, minor: 5),
.Package(url: "https://github.com/Zewo/SQL.git", majorVersion: 0, minor: 0)
.Package(url: "https://github.com/Zewo/CLibpq.git", majorVersion: 0, minor: 13),
.Package(url: "https://github.com/Zewo/SQL.git", majorVersion: 0, minor: 13)
]
)
100 changes: 62 additions & 38 deletions Sources/PostgreSQL/Connection.swift
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
@_exported import SQL
import CLibpq
import Core

public struct ConnectionError: Error, CustomStringConvertible {
public let description: String
}

public final class Connection: ConnectionProtocol {
public typealias QueryRenderer = PostgreSQL.QueryRenderer

public struct Error: ErrorProtocol, CustomStringConvertible {
public let description: String
}

public struct ConnectionInfo: ConnectionInfoProtocol {
public var host: String
public var port: Int
Expand All @@ -17,19 +18,28 @@ public final class Connection: ConnectionProtocol {
public var options: String?
public var tty: String?

public init(_ uri: URI) throws {
public init?(uri: URL) {
do {
try self.init(uri)
} catch {
return nil
}
}

guard let host = uri.host, port = uri.port, databaseName = uri.path?.trim(["/"]) else {
throw Error(description: "Failed to extract host, port, database name from URI")
public init(_ uri: URL) throws {
let databaseName = uri.path.trim(["/"])

guard let host = uri.host, let port = uri.port else {
throw ConnectionError(description: "Failed to extract host, port, database name from URI")
}

self.host = host
self.port = port
self.databaseName = databaseName
self.username = uri.userInfo?.username
self.password = uri.userInfo?.password

self.username = uri.user
self.password = uri.password
}

public init(host: String, port: Int = 5432, databaseName: String, password: String? = nil, options: String? = nil, tty: String? = nil) {
self.host = host
self.port = port
Expand All @@ -40,7 +50,6 @@ public final class Connection: ConnectionProtocol {
}
}


public enum InternalStatus {
case Bad
case Started
Expand Down Expand Up @@ -87,7 +96,6 @@ public final class Connection: ConnectionProtocol {
break
}
}

}

public var logger: Logger?
Expand All @@ -96,7 +104,7 @@ public final class Connection: ConnectionProtocol {

public let connectionInfo: ConnectionInfo

public required init(_ info: ConnectionInfo) {
public required init(info: ConnectionInfo) {
self.connectionInfo = info
}

Expand Down Expand Up @@ -124,12 +132,12 @@ public final class Connection: ConnectionProtocol {
}
}

public var mostRecentError: Error? {
guard let errorString = String(validatingUTF8: PQerrorMessage(connection)) where !errorString.isEmpty else {
public var mostRecentError: ConnectionError? {
guard let errorString = String(validatingUTF8: PQerrorMessage(connection)), !errorString.isEmpty else {
return nil
}

return Error(description: errorString)
return ConnectionError(description: errorString)
}

public func close() {
Expand All @@ -138,17 +146,18 @@ public final class Connection: ConnectionProtocol {
}

public func createSavePointNamed(_ name: String) throws {
try execute("SAVEPOINT \(name)")
try execute("SAVEPOINT \(name)", parameters: nil)
}

public func rollbackToSavePointNamed(_ name: String) throws {
try execute("ROLLBACK TO SAVEPOINT \(name)")
try execute("ROLLBACK TO SAVEPOINT \(name)", parameters: nil)
}

public func releaseSavePointNamed(_ name: String) throws {
try execute("RELEASE SAVEPOINT \(name)")
try execute("RELEASE SAVEPOINT \(name)", parameters: nil)
}

@discardableResult
public func execute(_ statement: String, parameters: [Value?]?) throws -> Result {

var statement = statement.sqlStringWithEscapedPlaceholdersUsingPrefix("$") {
Expand All @@ -159,13 +168,15 @@ public final class Connection: ConnectionProtocol {

guard let parameters = parameters else {
guard let resultPointer = PQexec(connection, statement) else {
throw mostRecentError ?? Error(description: "Empty result")
throw mostRecentError ?? ConnectionError(description: "Empty result")
}

return try Result(resultPointer)
}

var parameterData = [[UInt8]?]()
var parameterData = [UnsafePointer<Int8>?]()
var deallocators = [() -> ()]()
defer { deallocators.forEach { $0() } }

for parameter in parameters {

Expand All @@ -174,28 +185,41 @@ public final class Connection: ConnectionProtocol {
continue
}

let data: AnyCollection<Int8>
switch value {
case .data(let data):
parameterData.append(Array(data))
break
case .data(let value):
data = AnyCollection(value.map { Int8($0) })

case .string(let string):
parameterData.append(Array(string.utf8) + [0])
break
data = AnyCollection(string.utf8CString)
}

let pointer = UnsafeMutablePointer<Int8>.allocate(capacity: Int(data.count))
deallocators.append {
pointer.deallocate(capacity: Int(data.count))
}
}

for (index, byte) in data.enumerated() {
pointer[index] = byte
}

guard let result:OpaquePointer = PQexecParams(
self.connection,
statement,
Int32(parameters.count),
nil,
parameterData.map { UnsafePointer<Int8>($0) },
nil,
nil,
0
) else {
throw mostRecentError ?? Error(description: "Empty result")
parameterData.append(pointer)
}

let result: OpaquePointer = try parameterData.withUnsafeBufferPointer { buffer in
guard let result = PQexecParams(
self.connection,
statement,
Int32(parameters.count),
nil,
buffer.isEmpty ? nil : buffer.baseAddress,
nil,
nil,
0
) else {
throw mostRecentError ?? ConnectionError(description: "Empty result")
}
return result
}

return try Result(result)
Expand Down
22 changes: 12 additions & 10 deletions Sources/PostgreSQL/Result.swift
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import CLibpq
import Core
@_exported import SQL

public class Result: SQL.ResultProtocol {
public enum ResultError: Error {
case badStatus(Result.Status, String)
}

public enum Error: ErrorProtocol {
case BadStatus(Status, String)
}
public class Result: SQL.ResultProtocol {

public enum Status: Int, ResultStatus {
case EmptyQuery
Expand Down Expand Up @@ -67,7 +68,7 @@ public class Result: SQL.ResultProtocol {
self.resultPointer = resultPointer

guard status.successful else {
throw Error.BadStatus(status, String(validatingUTF8: PQresultErrorMessage(resultPointer)) ?? "No error message")
throw ResultError.badStatus(status, String(validatingUTF8: PQresultErrorMessage(resultPointer)) ?? "No error message")
}
}

Expand All @@ -81,12 +82,14 @@ public class Result: SQL.ResultProtocol {

public func data(atRow rowIndex: Int, forFieldIndex fieldIndex: Int) -> Data? {

let start = PQgetvalue(resultPointer, Int32(rowIndex), Int32(fieldIndex))
let count = PQgetlength(resultPointer, Int32(rowIndex), Int32(fieldIndex))
guard count > 0, let start = PQgetvalue(resultPointer, Int32(rowIndex), Int32(fieldIndex)) else {
return Data()
}

let buffer = UnsafeBufferPointer<UInt8>(start: UnsafePointer<UInt8>(start), count: Int(count))

return Data(Array(buffer))
return start.withMemoryRebound(to: UInt8.self, capacity: Int(count)) { start in
return Data(Array(UnsafeBufferPointer(start: start, count: Int(count))))
}
}

public var count: Int {
Expand Down Expand Up @@ -123,6 +126,5 @@ public class Result: SQL.ResultProtocol {
}

return result

}()
}
1 change: 1 addition & 0 deletions Tests/LinuxMain.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ import XCTest
@testable import PostgreSQLTests

XCTMain([
testCase(PostgreSQLTests.allTests),
])
Loading

0 comments on commit 1b912f9

Please sign in to comment.