Skip to content

Commit 6080505

Browse files
committed
organization updates
1 parent 1a0855e commit 6080505

19 files changed

+156
-45
lines changed

Sources/PostgreSQL/Connection/PostgreSQLConnection+Query.swift

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@ extension PostgreSQLConnection {
44
/// Sends a parameterized PostgreSQL query command, collecting the parsed results.
55
public func query(
66
_ string: String,
7-
_ parameters: [PostgreSQLDataCustomConvertible] = []
8-
) throws -> Future<[[String: PostgreSQLData]]> {
9-
var rows: [[String: PostgreSQLData]] = []
7+
_ parameters: [PostgreSQLDataConvertible] = []
8+
) throws -> Future<[[PostgreSQLColumn: PostgreSQLData]]> {
9+
var rows: [[PostgreSQLColumn: PostgreSQLData]] = []
1010
return try query(string, parameters) { row in
1111
rows.append(row)
12-
}.map(to: [[String: PostgreSQLData]].self) {
12+
}.map(to: [[PostgreSQLColumn: PostgreSQLData]].self) {
1313
return rows
1414
}
1515
}
@@ -18,12 +18,11 @@ extension PostgreSQLConnection {
1818
/// the supplied closure.
1919
public func query(
2020
_ string: String,
21-
_ parameters: [PostgreSQLDataCustomConvertible] = [],
21+
_ parameters: [PostgreSQLDataConvertible] = [],
2222
resultFormat: PostgreSQLResultFormat = .binary(),
23-
onRow: @escaping ([String: PostgreSQLData]) throws -> ()
23+
onRow: @escaping ([PostgreSQLColumn: PostgreSQLData]) throws -> ()
2424
) throws -> Future<Void> {
2525
let parameters = try parameters.map { try $0.convertToPostgreSQLData() }
26-
logger?.log(query: string, parameters: parameters)
2726
let parse = PostgreSQLParseRequest(
2827
statementName: "",
2928
query: string,
@@ -65,7 +64,11 @@ extension PostgreSQLConnection {
6564
guard let row = currentRow else {
6665
throw PostgreSQLError(identifier: "query", reason: "Unexpected PostgreSQLDataRow without preceding PostgreSQLRowDescription.", source: .capture())
6766
}
68-
let parsed = try row.parse(data: data, formatCodes: resultFormats)
67+
let parsed = try row.parse(
68+
data: data,
69+
formatCodes: resultFormats,
70+
tableNameCache: self.tableNameCache!
71+
)
6972
try onRow(parsed)
7073
case .close: break
7174
case .noData: break

Sources/PostgreSQL/Connection/PostgreSQLConnection+SimpleQuery.swift

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,18 @@ import Async
22

33
extension PostgreSQLConnection {
44
/// Sends a simple PostgreSQL query command, collecting the parsed results.
5-
public func simpleQuery(_ string: String) -> Future<[[String: PostgreSQLData]]> {
6-
var rows: [[String: PostgreSQLData]] = []
5+
public func simpleQuery(_ string: String) -> Future<[[PostgreSQLColumn: PostgreSQLData]]> {
6+
var rows: [[PostgreSQLColumn: PostgreSQLData]] = []
77
return simpleQuery(string) { row in
88
rows.append(row)
9-
}.map(to: [[String: PostgreSQLData]].self) {
9+
}.map(to: [[PostgreSQLColumn: PostgreSQLData]].self) {
1010
return rows
1111
}
1212
}
1313

1414
/// Sends a simple PostgreSQL query command, returning the parsed results to
1515
/// the supplied closure.
16-
public func simpleQuery(_ string: String, onRow: @escaping ([String: PostgreSQLData]) -> ()) -> Future<Void> {
16+
public func simpleQuery(_ string: String, onRow: @escaping ([PostgreSQLColumn: PostgreSQLData]) -> ()) -> Future<Void> {
1717
logger?.log(query: string, parameters: [])
1818
var currentRow: PostgreSQLRowDescription?
1919
let query = PostgreSQLQuery(query: string)
@@ -25,7 +25,11 @@ extension PostgreSQLConnection {
2525
guard let row = currentRow else {
2626
throw PostgreSQLError(identifier: "simpleQuery", reason: "Unexpected PostgreSQLDataRow without preceding PostgreSQLRowDescription.", source: .capture())
2727
}
28-
let parsed = try row.parse(data: data, formatCodes: row.fields.map { $0.formatCode })
28+
let parsed = try row.parse(
29+
data: data,
30+
formatCodes: row.fields.map { $0.formatCode },
31+
tableNameCache: self.tableNameCache
32+
)
2933
onRow(parsed)
3034
case .close: break // query over, waiting for `readyForQuery`
3135
default: throw PostgreSQLError(identifier: "simpleQuery", reason: "Unexpected message during PostgreSQLQuery: \(message)", source: .capture())

Sources/PostgreSQL/Connection/PostgreSQLConnection.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ public final class PostgreSQLConnection {
1717
/// If non-nil, will log queries.
1818
public var logger: PostgreSQLLogger?
1919

20+
/// Caches oid -> table name data.
21+
internal var tableNameCache: PostgreSQLTableNameCache?
22+
2023
/// Creates a new Redis client on the provided data source and sink.
2124
init(queue: QueueHandler<PostgreSQLMessage, PostgreSQLMessage>, channel: Channel) {
2225
self.queue = queue

Sources/PostgreSQL/Data/PostgreSQLArrayCustomConvertible.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import Foundation
22

33
/// Representable by a `T[]` column on the PostgreSQL database.
4-
public protocol PostgreSQLArrayCustomConvertible: PostgreSQLDataCustomConvertible {
4+
public protocol PostgreSQLArrayCustomConvertible: PostgreSQLDataConvertible {
55
/// The associated array element type
66
associatedtype PostgreSQLArrayElement // : PostgreSQLDataCustomConvertible
77

@@ -127,15 +127,15 @@ extension Array: PostgreSQLArrayCustomConvertible {
127127
}
128128
}
129129

130-
func requirePostgreSQLDataCustomConvertible<T>(_ type: T.Type) -> PostgreSQLDataCustomConvertible.Type {
131-
guard let custom = T.self as? PostgreSQLDataCustomConvertible.Type else {
130+
func requirePostgreSQLDataCustomConvertible<T>(_ type: T.Type) -> PostgreSQLDataConvertible.Type {
131+
guard let custom = T.self as? PostgreSQLDataConvertible.Type else {
132132
fatalError("`\(T.self)` does not conform to `PostgreSQLDataCustomConvertible`")
133133
}
134134
return custom
135135
}
136136

137-
func requirePostgreSQLDataCustomConvertible<T>(_ type: T) -> PostgreSQLDataCustomConvertible {
138-
guard let custom = type as? PostgreSQLDataCustomConvertible else {
137+
func requirePostgreSQLDataCustomConvertible<T>(_ type: T) -> PostgreSQLDataConvertible {
138+
guard let custom = type as? PostgreSQLDataConvertible else {
139139
fatalError("`\(T.self)` does not conform to `PostgreSQLDataCustomConvertible`")
140140
}
141141
return custom
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
/// Represents a PostgreSQL column.
2+
public struct PostgreSQLColumn: Hashable {
3+
/// See `Hashable.hashValue`
4+
public var hashValue: Int {
5+
return ((table ?? "_") + "." + name).hashValue
6+
}
7+
8+
/// The table this column belongs to.
9+
public var table: String?
10+
11+
/// The column's name.
12+
public var name: String
13+
}
14+
15+
extension PostgreSQLColumn: CustomStringConvertible {
16+
public var description: String {
17+
if let table = table {
18+
return "\(table)(\(name))"
19+
} else {
20+
return "\(name)"
21+
}
22+
}
23+
}
24+
25+
extension Dictionary where Key == PostgreSQLColumn {
26+
/// Accesses the _first_ value from this dictionary with a matching field name.
27+
public func firstValue(forField fieldName: String) -> Value? {
28+
for (field, value) in self {
29+
if field.name == fieldName {
30+
return value
31+
}
32+
}
33+
return nil
34+
}
35+
36+
/// Access a `Value` from this dictionary keyed by `PostgreSQLColumn`s
37+
/// using a field (column) name and entity (table) name.
38+
public func value(forTable table: String, atField field: String) -> Value? {
39+
return self[PostgreSQLColumn(table: table, name: field)]
40+
}
41+
}
42+
43+
import Async
44+
45+
final class PostgreSQLTableNameCache {
46+
var connection: Future<PostgreSQLConnection>
47+
var cache: [Int32: String?]
48+
var working: Bool
49+
50+
init(connection: Future<PostgreSQLConnection>) {
51+
self.connection = connection
52+
self.cache = [:]
53+
self.working = false
54+
}
55+
56+
func tableName(oid: Int32) throws -> String? {
57+
if oid == 0 {
58+
return nil
59+
}
60+
61+
if working {
62+
cache[oid] = "pg_class"
63+
return "pg_class"
64+
}
65+
working = true
66+
defer { working = false }
67+
if let existing = cache[oid] {
68+
return existing
69+
} else {
70+
let res = try connection
71+
.wait()
72+
.simpleQuery("select relname from pg_class where oid = \(oid)")
73+
.wait()
74+
let new: String?
75+
if res.count > 0 {
76+
new = try res[0].firstValue(forField: "relname")!.decode(String.self)
77+
} else {
78+
new = nil
79+
}
80+
cache[oid] = new
81+
return new
82+
}
83+
}
84+
}

Sources/PostgreSQL/Data/PostgreSQLData+BinaryFloatingPoint.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,8 @@ extension BinaryFloatingPoint {
6464
}
6565
}
6666

67-
extension Double: PostgreSQLDataCustomConvertible { }
68-
extension Float: PostgreSQLDataCustomConvertible { }
67+
extension Double: PostgreSQLDataConvertible { }
68+
extension Float: PostgreSQLDataConvertible { }
6969

7070
extension Data {
7171
/// Converts this data to a floating-point number.

Sources/PostgreSQL/Data/PostgreSQLData+Bool.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import Foundation
22

3-
extension Bool: PostgreSQLDataCustomConvertible {
3+
extension Bool: PostgreSQLDataConvertible {
44
/// See `PostgreSQLDataCustomConvertible.postgreSQLDataType`
55
public static var postgreSQLDataType: PostgreSQLDataType { return .bool }
66

Sources/PostgreSQL/Data/PostgreSQLData+Data.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import Foundation
22

3-
extension Data: PostgreSQLDataCustomConvertible {
3+
extension Data: PostgreSQLDataConvertible {
44
/// See `PostgreSQLDataCustomConvertible.postgreSQLDataType`
55
public static var postgreSQLDataType: PostgreSQLDataType { return .bytea }
66

Sources/PostgreSQL/Data/PostgreSQLData+Date.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import Foundation
22

3-
extension Date: PostgreSQLDataCustomConvertible {
3+
extension Date: PostgreSQLDataConvertible {
44
/// See `PostgreSQLDataCustomConvertible.postgreSQLDataType`
55
public static var postgreSQLDataType: PostgreSQLDataType { return .timestamp }
66

Sources/PostgreSQL/Data/PostgreSQLData+FixedWidthInteger.swift

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -71,17 +71,17 @@ extension FixedWidthInteger {
7171
}
7272
}
7373

74-
extension Int: PostgreSQLDataCustomConvertible {}
75-
extension Int8: PostgreSQLDataCustomConvertible {}
76-
extension Int16: PostgreSQLDataCustomConvertible {}
77-
extension Int32: PostgreSQLDataCustomConvertible {}
78-
extension Int64: PostgreSQLDataCustomConvertible {}
74+
extension Int: PostgreSQLDataConvertible {}
75+
extension Int8: PostgreSQLDataConvertible {}
76+
extension Int16: PostgreSQLDataConvertible {}
77+
extension Int32: PostgreSQLDataConvertible {}
78+
extension Int64: PostgreSQLDataConvertible {}
7979

80-
extension UInt: PostgreSQLDataCustomConvertible {}
81-
extension UInt8: PostgreSQLDataCustomConvertible {}
82-
extension UInt16: PostgreSQLDataCustomConvertible {}
83-
extension UInt32: PostgreSQLDataCustomConvertible {}
84-
extension UInt64: PostgreSQLDataCustomConvertible {}
80+
extension UInt: PostgreSQLDataConvertible {}
81+
extension UInt8: PostgreSQLDataConvertible {}
82+
extension UInt16: PostgreSQLDataConvertible {}
83+
extension UInt32: PostgreSQLDataConvertible {}
84+
extension UInt64: PostgreSQLDataConvertible {}
8585

8686
extension Data {
8787
/// Converts this data to a fixed-width integer.

0 commit comments

Comments
 (0)