Skip to content

Commit c542692

Browse files
committed
add tablenamecache
1 parent 2814c62 commit c542692

File tree

7 files changed

+76
-37
lines changed

7 files changed

+76
-37
lines changed

Package.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,13 @@ let package = Package(
99
],
1010
dependencies: [
1111
// 🌎 Utility package containing tools for byte manipulation, Codable, OS APIs, and debugging.
12-
.package(url: "https://github.com/vapor/core.git", .branch("nio")),
12+
.package(url: "https://github.com/vapor/core.git", .branch("master")),
1313

1414
// Swift ORM framework (queries, models, and relations) for building NoSQL and SQL database integrations.
15-
.package(url: "https://github.com/vapor/fluent.git", .branch("nio")),
15+
.package(url: "https://github.com/vapor/fluent.git", .branch("master")),
1616

1717
// 🐘 Non-blocking, event-driven Swift client for PostgreSQL.
18-
.package(url: "https://github.com/vapor/postgresql.git", .branch("nio")),
18+
.package(url: "https://github.com/vapor/postgresql.git", .branch("master")),
1919
],
2020
targets: [
2121
.target(name: "FluentPostgreSQL", dependencies: ["Async", "CodableKit", "Fluent", "FluentSQL", "PostgreSQL"]),

Sources/FluentPostgreSQL/FluentPostgreSQLProvider.swift

Lines changed: 12 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import Async
12
import Service
23

34
/// Adds Fluent PostgreSQL's services to your project.
@@ -17,29 +18,14 @@ public final class FluentPostgreSQLProvider: Provider {
1718

1819
/// See `Provider.register(_:)`
1920
public func register(_ services: inout Services) throws {
20-
try services.register(PostgreSQLVersionCheckProvider())
2121
try services.register(FluentProvider())
2222
try services.register(PostgreSQLProvider())
2323
}
2424

2525
/// See `Provider.boot(_:)`
26-
public func boot(_ worker: Container) throws { }
27-
}
28-
29-
/// check server version and override _globalEnableIdentityColumns
30-
/// dirty workaround for missing pre migration hook
31-
public final class PostgreSQLVersionCheckProvider: Provider {
32-
/// See `Provider.repositoryName`
33-
public static let repositoryName = "fluent-postgresql"
34-
35-
public init() {}
36-
/// See `Provider.register(_:)`
37-
public func register(_ services: inout Services) throws {}
38-
39-
/// See `Provider.boot(_:)`
40-
public func boot(_ worker: Container) throws {
41-
try worker.withConnection(to: .psql) { conn in
42-
conn.simpleQuery("SELECT current_setting('server_version') as version").map(to: Void.self) { rows in
26+
public func willBoot(_ worker: Container) throws -> Future<Void> {
27+
return worker.withConnection(to: .psql) { conn in
28+
return conn.simpleQuery("SELECT current_setting('server_version') as version").map(to: Void.self) { rows in
4329
_serverVersion = try rows[0].firstValue(forColumn: "version")!.decode(String.self)
4430
if let versionString = _serverVersion {
4531
let pointIndex = versionString.index(of: ".") ?? versionString.endIndex
@@ -49,12 +35,16 @@ public final class PostgreSQLVersionCheckProvider: Provider {
4935
}
5036
}
5137
}
52-
}.wait()
38+
}
5339
}
5440

55-
// get current server version
56-
public static func getServerVersion() -> String {
57-
return _serverVersion ?? "N/A"
41+
/// See `Provider.boot(_:)`
42+
public func didBoot(_ worker: Container) throws -> Future<Void> {
43+
return worker.withConnection(to: .psql) { conn in
44+
return conn.simpleQuery("select * from pg_class").map(to: Void.self) { rows in
45+
print(rows)
46+
}
47+
}
5848
}
5949
}
6050

Sources/FluentPostgreSQL/PostgreSQLDatabase+QuerySupporting.swift

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ extension PostgreSQLDatabase: QuerySupporting, CustomSQLSupporting {
1111
into handler: @escaping ([QueryField: PostgreSQLData], PostgreSQLConnection) throws -> (),
1212
on connection: PostgreSQLConnection
1313
) -> EventLoopFuture<Void> {
14-
return Future<Void>.flatMap(on: connection) {
14+
/// wait for the table name cache before continuing
15+
return PostgreSQLTableNameCache.get(for: connection).flatMap(to: Void.self) { tableNameCache in
1516
// Convert Fluent `DatabaseQuery` to generic FluentSQL `DataQuery`
1617
var (sqlQuery, bindValues) = query.makeDataQuery()
1718

@@ -47,7 +48,7 @@ extension PostgreSQLDatabase: QuerySupporting, CustomSQLSupporting {
4748
return try connection.query(sqlString, parameters) { row in
4849
var res: [QueryField: PostgreSQLData] = [:]
4950
for (col, data) in row {
50-
let field = QueryField(entity: col.table, name: col.name)
51+
let field = QueryField(entity: tableNameCache.storage[col.tableOID], name: col.name)
5152
res[field] = data
5253
}
5354
try handler(res, connection)
@@ -109,6 +110,9 @@ extension PostgreSQLDatabase: QuerySupporting, CustomSQLSupporting {
109110
return PostgreSQLData(type: convertibleType.postgreSQLDataType, format: .binary, data: nil)
110111
}
111112
}
113+
114+
/// See `QuerySupporting.QueryFilter`
115+
public typealias QueryFilter = DataPredicateComparison
112116
}
113117

114118
extension PostgreSQLData: FluentData {}

Sources/FluentPostgreSQL/PostgreSQLDatabase+SchemaSupporting.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@ extension PostgreSQLDatabase: SchemaSupporting, IndexSupporting {
5757

5858
/// See `SchemaSupporting.execute`
5959
public static func execute(schema: DatabaseSchema<PostgreSQLDatabase>, on connection: PostgreSQLConnection) -> Future<Void> {
60+
/// schema is changing, invalidate the table name cache
61+
PostgreSQLTableNameCache.invalidate(for: connection)
62+
6063
return Future.flatMap(on: connection) {
6164
var schemaQuery = schema.makeSchemaQuery(dataTypeFactory: dataType)
6265
schema.applyReferences(to: &schemaQuery)
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import Async
2+
3+
/// Caches table OID to string name associations.
4+
final class PostgreSQLTableNameCache {
5+
/// The internal cache.
6+
var storage: [Int32: String]
7+
8+
/// Static shared cache, stored by connections.
9+
private static var shared: [ObjectIdentifier: PostgreSQLTableNameCache] = [:]
10+
11+
/// Creates a new cache.
12+
private init(cache: [Int32: String]) {
13+
self.storage = cache
14+
}
15+
16+
/// Invalidates the cache for the supplied connection.
17+
static func invalidate(for connection: PostgreSQLConnection) {
18+
shared[ObjectIdentifier(connection)] = nil
19+
}
20+
21+
/// Generates a cache for the supplied connection.
22+
static func get(for connection: PostgreSQLConnection) -> Future<PostgreSQLTableNameCache> {
23+
if let existing = shared[ObjectIdentifier(connection)] {
24+
return Future.map(on: connection) { existing }
25+
} else {
26+
return connection.simpleQuery("select oid, relname from pg_class").map(to: PostgreSQLTableNameCache.self) { rows in
27+
var cache: [Int32: String] = [:]
28+
29+
for row in rows {
30+
let oid = try row.firstValue(forColumn: "oid")!.decode(Int32.self)
31+
let name = try row.firstValue(forColumn: "relname")!.decode(String.self)
32+
cache[oid] = name
33+
}
34+
35+
let new = PostgreSQLTableNameCache(cache: cache)
36+
shared[ObjectIdentifier(connection)] = new
37+
return new
38+
}
39+
}
40+
}
41+
}

Tests/FluentPostgreSQLTests/FluentPostgreSQLTests.swift

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import Async
2+
import Core
23
import XCTest
34
import FluentBenchmark
45
import FluentPostgreSQL
@@ -9,15 +10,16 @@ class FluentPostgreSQLTests: XCTestCase {
910
var database: PostgreSQLDatabase!
1011

1112
override func setUp() {
12-
let eventLoop = MultiThreadedEventLoopGroup(numThreads: 1)
1313
let config = PostgreSQLDatabaseConfig(
14-
hostname: ProcessInfo.processInfo.environment["PSQL_HOSTNAME"] ?? "localhost",
14+
hostname: (try? Process.execute("docker-machine", "ip")) ?? "192.168.99.100",
1515
port: 5432,
1616
username: "vapor_username",
1717
database: "vapor_database",
1818
password: nil
1919
)
20-
database = PostgreSQLDatabase(config: config)
20+
let main = MultiThreadedEventLoopGroup(numThreads: 1)
21+
database = PostgreSQLDatabase(config: config, on: main)
22+
let eventLoop = MultiThreadedEventLoopGroup(numThreads: 1)
2123
benchmarker = Benchmarker(database, on: eventLoop, onFail: XCTFail)
2224
}
2325

@@ -197,6 +199,10 @@ class FluentPostgreSQLTests: XCTestCase {
197199
XCTAssertEqual(123.456, fetched.date!.value!.timeIntervalSinceReferenceDate, accuracy: 1e-6)
198200
}
199201

202+
func testContains() throws {
203+
try benchmarker.benchmarkContains_withSchema()
204+
}
205+
200206
static let allTests = [
201207
("testSchema", testSchema),
202208
("testModels", testModels),
@@ -214,6 +220,7 @@ class FluentPostgreSQLTests: XCTestCase {
214220
("testGH24", testGH24),
215221
("testGH21", testGH21),
216222
("testPersistsDateMillisecondPart", testPersistsDateMillisecondPart),
223+
("testContains", testContains),
217224
]
218225
}
219226

circle.yml

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,12 @@ jobs:
1010
- run: swift test
1111
linux:
1212
docker:
13-
- image: norionomura/swift:swift-4.1-branch
13+
- image: codevapor/swift:4.1
1414
- image: circleci/postgres:latest
1515
environment:
1616
POSTGRES_USER: vapor_username
1717
POSTGRES_DB: vapor_database
1818
steps:
19-
- run:
20-
name: Update APT
21-
command: apt-get update
22-
- run:
23-
name: Install Swift NIO dependencies
24-
command: apt-get install -yq pkg-config libssl-dev
2519
- checkout
2620
- run:
2721
name: Compile code

0 commit comments

Comments
 (0)