Skip to content

Commit 4265268

Browse files
authored
FluentKit Beta 5 (#139)
* field key * fix id key * config updates * nested field * updates * updates * schema * schema * beta.5 tag * fix hostname
1 parent 9244cb2 commit 4265268

File tree

7 files changed

+227
-264
lines changed

7 files changed

+227
-264
lines changed

.github/workflows/test.yml

+4
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ jobs:
1818
steps:
1919
- uses: actions/checkout@v1
2020
- run: swift test --enable-test-discovery --sanitize=thread
21+
env:
22+
POSTGRES_HOSTNAME: psql
2123
bionic:
2224
container:
2325
image: vapor/swift:5.2-bionic
@@ -34,3 +36,5 @@ jobs:
3436
steps:
3537
- uses: actions/checkout@v1
3638
- run: swift test --enable-test-discovery --sanitize=thread
39+
env:
40+
POSTGRES_HOSTNAME: psql

Package.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ let package = Package(
1010
.library(name: "FluentPostgresDriver", targets: ["FluentPostgresDriver"]),
1111
],
1212
dependencies: [
13-
.package(url: "https://github.com/vapor/fluent-kit.git", from: "1.0.0-beta.2"),
13+
.package(url: "https://github.com/vapor/fluent-kit.git", from: "1.0.0-beta.5"),
1414
.package(url: "https://github.com/vapor/postgres-kit.git", from: "2.0.0-beta.2"),
1515
],
1616
targets: [

Sources/FluentPostgresDriver/FluentPostgresDatabase.swift

+37-6
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,24 @@ struct _FluentPostgresDatabase {
99
}
1010

1111
extension _FluentPostgresDatabase: Database {
12-
func execute(query: DatabaseQuery, onRow: @escaping (DatabaseRow) -> ()) -> EventLoopFuture<Void> {
12+
func execute(
13+
query: DatabaseQuery,
14+
onOutput: @escaping (DatabaseOutput) -> ()
15+
) -> EventLoopFuture<Void> {
1316
var expression = SQLQueryConverter(delegate: PostgresConverterDelegate())
1417
.convert(query)
1518
switch query.action {
1619
case .create:
17-
expression = PostgresReturningKey(key: query.idKey, base: expression)
20+
expression = PostgresReturningID(
21+
base: expression,
22+
idKey: query.customIDKey ?? .id
23+
)
1824
default: break
1925
}
2026
let (sql, binds) = self.serialize(expression)
2127
do {
2228
return try self.query(sql, binds.map { try self.encoder.encode($0) }) {
23-
onRow($0.databaseRow(using: self.decoder))
29+
onOutput($0.databaseOutput(using: self.decoder))
2430
}
2531
} catch {
2632
return self.eventLoop.makeFailedFuture(error)
@@ -40,6 +46,31 @@ extension _FluentPostgresDatabase: Database {
4046
}
4147
}
4248

49+
func execute(enum e: DatabaseEnum) -> EventLoopFuture<Void> {
50+
switch e.action {
51+
case .create:
52+
let builder = self.sql().create(enum: e.name)
53+
for c in e.createCases {
54+
_ = builder.value(c)
55+
}
56+
return builder.run()
57+
case .update:
58+
if !e.deleteCases.isEmpty {
59+
self.logger.error("PostgreSQL does not support deleting enum cases.")
60+
}
61+
guard !e.createCases.isEmpty else {
62+
return self.eventLoop.makeSucceededFuture(())
63+
}
64+
let builder = self.sql().alter(enum: e.name)
65+
for create in e.createCases {
66+
_ = builder.add(value: create)
67+
}
68+
return builder.run()
69+
case .delete:
70+
return self.sql().drop(enum: e.name).run()
71+
}
72+
}
73+
4374
func transaction<T>(_ closure: @escaping (Database) -> EventLoopFuture<T>) -> EventLoopFuture<T> {
4475
self.database.withConnection { conn in
4576
conn.simpleQuery("BEGIN").flatMap { _ in
@@ -92,15 +123,15 @@ extension _FluentPostgresDatabase: PostgresDatabase {
92123
}
93124
}
94125

95-
private struct PostgresReturningKey: SQLExpression {
96-
let key: String
126+
private struct PostgresReturningID: SQLExpression {
97127
let base: SQLExpression
128+
let idKey: FieldKey
98129

99130
func serialize(to serializer: inout SQLSerializer) {
100131
serializer.statement {
101132
$0.append(self.base)
102133
$0.append("RETURNING")
103-
$0.append(SQLIdentifier(self.key))
134+
$0.append(SQLIdentifier(self.idKey.description))
104135
}
105136
}
106137
}

Sources/FluentPostgresDriver/FluentPostgresDriver.swift

+29-13
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
extension DatabaseDriverFactory {
1+
extension DatabaseConfigurationFactory {
22
public static func postgres(
33
url: URL,
44
maxConnectionsPerEventLoop: Int = 1
5-
) throws -> DatabaseDriverFactory {
5+
) throws -> DatabaseConfigurationFactory {
66
guard let configuration = PostgresConfiguration(url: url) else {
77
throw FluentPostgresError.invalidURL(url)
88
}
@@ -20,7 +20,7 @@ extension DatabaseDriverFactory {
2020
database: String? = nil,
2121
tlsConfiguration: TLSConfiguration? = nil,
2222
maxConnectionsPerEventLoop: Int = 1
23-
) -> DatabaseDriverFactory {
23+
) -> DatabaseConfigurationFactory {
2424
return .postgres(
2525
configuration: .init(
2626
hostname: hostname,
@@ -37,21 +37,37 @@ extension DatabaseDriverFactory {
3737
public static func postgres(
3838
configuration: PostgresConfiguration,
3939
maxConnectionsPerEventLoop: Int = 1
40-
) -> DatabaseDriverFactory {
41-
return DatabaseDriverFactory { databases in
42-
let db = PostgresConnectionSource(
43-
configuration: configuration
40+
) -> DatabaseConfigurationFactory {
41+
return DatabaseConfigurationFactory {
42+
FluentPostgresConfiguration(
43+
middleware: [],
44+
configuration: configuration,
45+
maxConnectionsPerEventLoop: maxConnectionsPerEventLoop
4446
)
45-
let pool = EventLoopGroupConnectionPool(
46-
source: db,
47-
maxConnectionsPerEventLoop: maxConnectionsPerEventLoop,
48-
on: databases.eventLoopGroup
49-
)
50-
return _FluentPostgresDriver(pool: pool)
5147
}
5248
}
5349
}
5450

51+
struct FluentPostgresConfiguration: DatabaseConfiguration {
52+
var middleware: [AnyModelMiddleware]
53+
let configuration: PostgresConfiguration
54+
let maxConnectionsPerEventLoop: Int
55+
56+
func makeDriver(for databases: Databases) -> DatabaseDriver {
57+
let db = PostgresConnectionSource(
58+
configuration: configuration
59+
)
60+
let pool = EventLoopGroupConnectionPool(
61+
source: db,
62+
maxConnectionsPerEventLoop: maxConnectionsPerEventLoop,
63+
on: databases.eventLoopGroup
64+
)
65+
return _FluentPostgresDriver(pool: pool)
66+
}
67+
68+
69+
}
70+
5571
enum FluentPostgresError: Error {
5672
case invalidURL(URL)
5773
}

Sources/FluentPostgresDriver/PostgresConverterDelegate.swift

+11-1
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,22 @@ struct PostgresConverterDelegate: SQLConverterDelegate {
1717
return SQLRaw("DOUBLE PRECISION")
1818
case .json:
1919
return SQLRaw("JSONB")
20+
case .enum(let value):
21+
return SQLIdentifier(value.name)
2022
default:
2123
return nil
2224
}
2325
}
2426

2527
func nestedFieldExpression(_ column: String, _ path: [String]) -> SQLExpression {
26-
return SQLRaw("\(column)->>'\(path[0])'")
28+
switch path.count {
29+
case 1:
30+
return SQLRaw("\(column)->>'\(path[0])'")
31+
case 2...:
32+
let inner = path[0..<path.count - 1].map { "'\($0)'" }.joined(separator: "->")
33+
return SQLRaw("\(column)->\(inner)->>'\(path.last!)'")
34+
default:
35+
fatalError()
36+
}
2737
}
2838
}
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,49 @@
11
import class Foundation.JSONDecoder
22

33
extension PostgresRow {
4-
internal func databaseRow(using decoder: PostgresDataDecoder) -> DatabaseRow {
5-
return _PostgresDatabaseRow(row: self, decoder: decoder)
4+
internal func databaseOutput(using decoder: PostgresDataDecoder) -> DatabaseOutput {
5+
_PostgresDatabaseOutput(
6+
row: self,
7+
decoder: decoder,
8+
schema: nil
9+
)
610
}
711
}
812

9-
private struct _PostgresDatabaseRow: DatabaseRow {
13+
private struct _PostgresDatabaseOutput: DatabaseOutput {
1014
let row: PostgresRow
1115
let decoder: PostgresDataDecoder
16+
let schema: String?
1217

13-
var description: String { self.row.description }
18+
var description: String {
19+
self.row.description
20+
}
21+
22+
func contains(_ field: FieldKey) -> Bool {
23+
return self.row.column(self.column(field)) != nil
24+
}
1425

15-
func contains(field: String) -> Bool {
16-
return self.row.column(field) != nil
26+
func schema(_ schema: String) -> DatabaseOutput {
27+
_PostgresDatabaseOutput(
28+
row: self.row,
29+
decoder: self.decoder,
30+
schema: schema
31+
)
1732
}
1833

1934
func decode<T>(
20-
field: String,
21-
as type: T.Type,
22-
for database: Database
35+
_ field: FieldKey,
36+
as type: T.Type
2337
) throws -> T where T : Decodable {
24-
return try self.row.sql(decoder: self.decoder).decode(column: field, as: T.self)
38+
try self.row.sql(decoder: self.decoder)
39+
.decode(column: self.column(field), as: T.self)
40+
}
41+
42+
private func column(_ field: FieldKey) -> String {
43+
if let schema = self.schema {
44+
return schema + "_" + field.description
45+
} else {
46+
return field.description
47+
}
2548
}
2649
}

0 commit comments

Comments
 (0)