Skip to content

Commit fdf0ee4

Browse files
committed
add databasekit
1 parent e2d2f86 commit fdf0ee4

13 files changed

+161
-20
lines changed

Package.swift

+7-1
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,17 @@ let package = Package(
1313
// Core extensions, type-aliases, and functions that facilitate common tasks.
1414
.package(url: "https://github.com/vapor/core.git", .branch("beta")),
1515

16+
// Core services for creating database integrations.
17+
.package(url: "https://github.com/vapor/database-kit.git", .branch("beta")),
18+
1619
// Non-blocking networking for Swift (HTTP and WebSockets).
1720
.package(url: "https://github.com/vapor/engine.git", .branch("beta")),
21+
22+
// Service container and configuration system.
23+
.package(url: "https://github.com/vapor/service.git", .branch("beta")),
1824
],
1925
targets: [
20-
.target(name: "PostgreSQL", dependencies: ["Async", "Bits", "TCP"]),
26+
.target(name: "PostgreSQL", dependencies: ["Async", "Bits", "DatabaseKit", "Service", "TCP"]),
2127
.testTarget(name: "PostgreSQLTests", dependencies: ["PostgreSQL"]),
2228
]
2329
)

Sources/PostgreSQL/Client/PostgreSQLClient+Authenticate.swift renamed to Sources/PostgreSQL/Connection/PostgreSQLConnection+Authenticate.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import Async
22

3-
extension PostgreSQLClient {
3+
extension PostgreSQLConnection {
44
/// Authenticates the `PostgreSQLClient` using a username with no password.
55
public func authenticate(username: String) -> Future<Void> {
66
let startup = PostgreSQLStartupMessage.versionThree(parameters: ["user": username])

Sources/PostgreSQL/Client/PostgreSQLClient+Query.swift renamed to Sources/PostgreSQL/Connection/PostgreSQLConnection+Query.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import Async
22

3-
extension PostgreSQLClient {
3+
extension PostgreSQLConnection {
44
/// Sends a parameterized PostgreSQL query command, collecting the parsed results.
55
public func query(
66
_ string: String,
@@ -77,7 +77,7 @@ extension PostgreSQLClient {
7777

7878
/// MARK: Codable
7979

80-
extension PostgreSQLClient {
80+
extension PostgreSQLConnection {
8181
/// Sends a parameterized PostgreSQL query command, collecting the parsed results.
8282
public func query(
8383
_ string: String,

Sources/PostgreSQL/Client/PostgreSQLClient+SimpleQuery.swift renamed to Sources/PostgreSQL/Connection/PostgreSQLConnection+SimpleQuery.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import Async
22

3-
extension PostgreSQLClient {
3+
extension PostgreSQLConnection {
44
/// Sends a simple PostgreSQL query command, collecting the parsed results.
55
public func simpleQuery(_ string: String) -> Future<[[String: PostgreSQLData]]> {
66
var rows: [[String: PostgreSQLData]] = []
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
import Async
22
import TCP
33

4-
extension PostgreSQLClient {
4+
extension PostgreSQLConnection {
55
/// Connects to a Redis server using a TCP socket.
66
public static func connect(
77
hostname: String = "localhost",
88
port: UInt16 = 5432,
99
on worker: Worker
10-
) throws -> PostgreSQLClient {
10+
) throws -> PostgreSQLConnection {
1111
let socket = try TCPSocket(isNonBlocking: true)
1212
let client = try TCPClient(socket: socket)
1313
try client.connect(hostname: hostname, port: port)
14-
return PostgreSQLClient(stream: socket.stream(on: worker), on: worker)
14+
return PostgreSQLConnection(stream: socket.stream(on: worker), on: worker)
1515
}
1616
}

Sources/PostgreSQL/Client/PostgreSQLClient.swift renamed to Sources/PostgreSQL/Connection/PostgreSQLConnection.swift

+6-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import Async
22

33
/// A PostgreSQL frontend client.
4-
public final class PostgreSQLClient {
4+
public final class PostgreSQLConnection {
55
/// Handles enqueued redis commands and responses.
66
private let queueStream: AsymmetricQueueStream<PostgreSQLMessage, PostgreSQLMessage>
77

@@ -45,6 +45,11 @@ public final class PostgreSQLClient {
4545
return responses
4646
}
4747
}
48+
49+
/// Closes this client.
50+
public func close() {
51+
queueStream.close()
52+
}
4853
}
4954

5055
/// Enqueues a single input and waits for multiple output.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
/// Config options for a `PostgreSQLConnection`
2+
public struct PostgreSQLConnectionConfig {
3+
/// Creates a `PostgreSQLConnectionConfig` with default settings.
4+
public static func `default`() -> PostgreSQLConnectionConfig {
5+
return .init()
6+
}
7+
8+
/// Creates a new `PostgreSQLConnectionConfig`.
9+
public init() {}
10+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import Async
2+
3+
/// Creates connections to an identified PostgreSQL database.
4+
public final class PostgreSQLDatabase: Database {
5+
/// This database's configuration.
6+
public let config: PostgreSQLDatabaseConfig
7+
8+
/// Creates a new `PostgreSQLDatabase`.
9+
public init(config: PostgreSQLDatabaseConfig) {
10+
self.config = config
11+
}
12+
13+
/// See `Database.makeConnection()`
14+
public func makeConnection(using connectionConfig: PostgreSQLConnectionConfig, on worker: Worker) -> Future<PostgreSQLConnection> {
15+
do {
16+
let client = try PostgreSQLConnection.connect(hostname: config.hostname, port: config.port, on: worker)
17+
return client.authenticate(username: config.username).transform(to: client)
18+
} catch {
19+
return Future(error: error)
20+
}
21+
}
22+
}
23+
24+
/// A connection created by a `PostgreSQLDatabase`.
25+
extension PostgreSQLConnection: DatabaseConnection {
26+
/// See `DatabaseConnection.Config`
27+
public typealias Config = PostgreSQLConnectionConfig
28+
}
29+
30+
extension DatabaseIdentifier {
31+
/// Default identifier for `PostgreSQLDatabase`.
32+
public static var psql: DatabaseIdentifier<PostgreSQLDatabase> {
33+
return .init("psql")
34+
}
35+
}
36+
37+
/// MARK: HACK
38+
39+
import Service
40+
41+
extension DatabaseConnection {
42+
/// See `DatabaseConnectable.connect(to:)`
43+
public func connect<D>(to database: DatabaseIdentifier<D>?) -> Future<D.Connection> {
44+
assert(database == nil)
45+
return Future(self as! D.Connection)
46+
}
47+
}
48+
49+
extension ServiceType {
50+
public static var serviceSupports: [Any.Type] {
51+
return []
52+
}
53+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/// Config options for a `PostgreSQLConnection`
2+
public struct PostgreSQLDatabaseConfig {
3+
/// Creates a `PostgreSQLDatabaseConfig` with default settings.
4+
public static func `default`() -> PostgreSQLDatabaseConfig {
5+
return .init(hostname: "localhost", port: 5432, username: "postgres")
6+
}
7+
8+
/// Destination hostname.
9+
public let hostname: String
10+
11+
/// Destination port.
12+
public let port: UInt16
13+
14+
/// Username to authenticate.
15+
public let username: String
16+
17+
/// Creates a new `PostgreSQLDatabaseConfig`.
18+
public init(hostname: String, port: UInt16, username: String) {
19+
self.hostname = hostname
20+
self.port = port
21+
self.username = username
22+
}
23+
}

Sources/PostgreSQL/Exports.swift

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
@_exported import DatabaseKit
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import Service
2+
3+
/// Provides base `PostgreSQL` services such as database and connection.
4+
public final class PostgreSQLProvider: Provider {
5+
/// See `Provider.repositoryName`
6+
public static let repositoryName = "fluent-postgresql"
7+
8+
/// See `Provider.register`
9+
public func register(_ services: inout Services) throws {
10+
try services.register(DatabaseKitProvider())
11+
services.register(PostgreSQLConnectionConfig.self)
12+
services.register(PostgreSQLDatabaseConfig.self)
13+
services.register(PostgreSQLDatabase.self)
14+
var databases = DatabaseConfig()
15+
databases.add(database: PostgreSQLDatabase.self, as: .psql)
16+
services.register(databases)
17+
}
18+
19+
/// See `Provider.boot`
20+
public func boot(_ worker: Container) throws { }
21+
}
22+
23+
/// MARK: Services
24+
25+
extension PostgreSQLConnectionConfig: ServiceType {
26+
/// See `ServiceType.makeService(for:)`
27+
public static func makeService(for worker: Container) throws -> PostgreSQLConnectionConfig {
28+
return .default()
29+
}
30+
}
31+
32+
extension PostgreSQLDatabaseConfig: ServiceType {
33+
/// See `ServiceType.makeService(for:)`
34+
public static func makeService(for worker: Container) throws -> PostgreSQLDatabaseConfig {
35+
return .default()
36+
}
37+
}
38+
extension PostgreSQLDatabase: ServiceType {
39+
/// See `ServiceType.makeService(for:)`
40+
public static func makeService(for worker: Container) throws -> PostgreSQLDatabase {
41+
return try .init(config: worker.make(for: PostgreSQLDatabase.self))
42+
}
43+
}

Tests/LinuxMain.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import XCTest
22
@testable import PostgreSQLTests
33

44
XCTMain([
5-
testCase(PostgreSQLClientTests.allTests),
5+
testCase(PostgreSQLConnectionTests.allTests),
66
testCase(PostgreSQLMessageTests.allTests),
77
testCase(PostgreSQLDataTests.allTests),
88
])

Tests/PostgreSQLTests/PostgreSQLClientTests.swift renamed to Tests/PostgreSQLTests/PostgreSQLConnectionTests.swift

+10-10
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,21 @@ import XCTest
44
import PostgreSQL
55
import TCP
66

7-
class PostgreSQLClientTests: XCTestCase {
7+
class PostgreSQLConnectionTests: XCTestCase {
88
func testVersion() throws {
9-
let (client, eventLoop) = try PostgreSQLClient.makeTest()
9+
let (client, eventLoop) = try PostgreSQLConnection.makeTest()
1010
let results = try client.simpleQuery("SELECT version();").await(on: eventLoop)
1111
XCTAssert(results[0]["version"]?.string?.contains("10.1") == true)
1212
}
1313

1414
func testSelectTypes() throws {
15-
let (client, eventLoop) = try PostgreSQLClient.makeTest()
15+
let (client, eventLoop) = try PostgreSQLConnection.makeTest()
1616
let results = try client.query("select * from pg_type;").await(on: eventLoop)
1717
XCTAssert(results.count > 350)
1818
}
1919

2020
func testParse() throws {
21-
let (client, eventLoop) = try PostgreSQLClient.makeTest()
21+
let (client, eventLoop) = try PostgreSQLConnection.makeTest()
2222
let query = """
2323
select * from "pg_type" where "typlen" = $1 or "typlen" = $2
2424
"""
@@ -33,7 +33,7 @@ class PostgreSQLClientTests: XCTestCase {
3333
}
3434

3535
func testTypes() throws {
36-
let (client, eventLoop) = try PostgreSQLClient.makeTest()
36+
let (client, eventLoop) = try PostgreSQLConnection.makeTest()
3737
let createQuery = """
3838
create table kitchen_sink (
3939
"smallint" smallint,
@@ -123,7 +123,7 @@ class PostgreSQLClientTests: XCTestCase {
123123
}
124124

125125
func testParameterizedTypes() throws {
126-
let (client, eventLoop) = try PostgreSQLClient.makeTest()
126+
let (client, eventLoop) = try PostgreSQLConnection.makeTest()
127127
let createQuery = """
128128
create table kitchen_sink (
129129
"smallint" smallint,
@@ -231,7 +231,7 @@ class PostgreSQLClientTests: XCTestCase {
231231
}
232232

233233
func testParameterizedEncodable() throws {
234-
let (client, eventLoop) = try PostgreSQLClient.makeTest()
234+
let (client, eventLoop) = try PostgreSQLConnection.makeTest()
235235
_ = try client.query("drop table if exists foo;").await(on: eventLoop)
236236
let createResult = try client.query("create table foo (fooid integer);").await(on: eventLoop)
237237
XCTAssertEqual(createResult.count, 0)
@@ -256,11 +256,11 @@ class PostgreSQLClientTests: XCTestCase {
256256
]
257257
}
258258

259-
extension PostgreSQLClient {
259+
extension PostgreSQLConnection {
260260
/// Creates a test event loop and psql client.
261-
static func makeTest() throws -> (PostgreSQLClient, EventLoop) {
261+
static func makeTest() throws -> (PostgreSQLConnection, EventLoop) {
262262
let eventLoop = try DefaultEventLoop(label: "codes.vapor.postgresql.client.test")
263-
let client = try PostgreSQLClient.connect(on: eventLoop)
263+
let client = try PostgreSQLConnection.connect(on: eventLoop)
264264
_ = try client.authenticate(username: "postgres").await(on: eventLoop)
265265
return (client, eventLoop)
266266
}

0 commit comments

Comments
 (0)