forked from vapor/postgres-nio
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathPostgresDatabase+Query.swift
92 lines (81 loc) · 2.38 KB
/
PostgresDatabase+Query.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
import NIO
import Logging
extension PostgresDatabase {
public func query(
_ string: String,
_ binds: [PostgresData] = []
) -> EventLoopFuture<PostgresQueryResult> {
var rows: [PostgresRow] = []
var metadata: PostgresQueryMetadata?
return self.query(string, binds, onMetadata: {
metadata = $0
}) {
rows.append($0)
}.map {
.init(metadata: metadata!, rows: rows)
}
}
public func query(
_ string: String,
_ binds: [PostgresData] = [],
onMetadata: @escaping (PostgresQueryMetadata) -> () = { _ in },
onRow: @escaping (PostgresRow) throws -> ()
) -> EventLoopFuture<Void> {
let request = PostgresCommands.query(query: string, binds: binds, onMetadata: onMetadata, onRow: onRow)
return self.send(request, logger: logger)
}
}
public struct PostgresQueryResult {
public let metadata: PostgresQueryMetadata
public let rows: [PostgresRow]
}
extension PostgresQueryResult: Collection {
public typealias Index = Int
public typealias Element = PostgresRow
public var startIndex: Int {
self.rows.startIndex
}
public var endIndex: Int {
self.rows.endIndex
}
public subscript(position: Int) -> PostgresRow {
self.rows[position]
}
public func index(after i: Int) -> Int {
self.rows.index(after: i)
}
}
public struct PostgresQueryMetadata {
public let command: String
public var oid: Int?
public var rows: Int?
init?(string: String) {
let parts = string.split(separator: " ")
guard parts.count >= 1 else {
return nil
}
switch parts[0] {
case "INSERT":
// INSERT oid rows
guard parts.count == 3 else {
return nil
}
self.command = .init(parts[0])
self.oid = Int(parts[1])
self.rows = Int(parts[2])
case "DELETE", "UPDATE", "SELECT", "MOVE", "FETCH", "COPY":
// <cmd> rows
guard parts.count == 2 else {
return nil
}
self.command = .init(parts[0])
self.oid = nil
self.rows = Int(parts[1])
default:
// <cmd>
self.command = string
self.oid = nil
self.rows = nil
}
}
}