Skip to content

Commit faedd71

Browse files
authored
Merge pull request #188 from vapor/data-types
data type improvements
2 parents ceca190 + bec6ea6 commit faedd71

28 files changed

+882
-499
lines changed

Sources/MySQL/Codable/MySQLDataDecoder.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ struct MySQLDataDecoder {
4040
case .binary(let binary):
4141
switch binary.storage {
4242
case .string(let data): json = data
43-
default: throw MySQLError(identifier: "json", reason: "Could not decode JSON.", source: .capture())
43+
default: throw MySQLError(identifier: "json", reason: "Could not decode JSON.")
4444
}
4545
case .text(let data): json = data ?? Data()
4646
}

Sources/MySQL/Connection/MySQLConnection+Query.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ extension MySQLConnection {
3333
case .ok, .eof:
3434
// ignore ok and eof
3535
return false
36-
default: throw MySQLError(identifier: "query", reason: "Unsupported message encountered during prepared query: \(message).", source: .capture())
36+
default: throw MySQLError(identifier: "query", reason: "Unsupported message encountered during prepared query: \(message).")
3737
}
3838
}.flatMap {
3939
let ok = ok!
@@ -43,7 +43,7 @@ extension MySQLConnection {
4343
values: params.map { data in
4444
switch data.storage {
4545
case .binary(let binary): return binary
46-
case .text: throw MySQLError(identifier: "binaryData", reason: "Binary data required.", source: .capture())
46+
case .text: throw MySQLError(identifier: "binaryData", reason: "Binary data required.")
4747
}
4848
}
4949
)
@@ -65,7 +65,7 @@ extension MySQLConnection {
6565
case .ok, .eof:
6666
// rows are done
6767
return true
68-
default: throw MySQLError(identifier: "query", reason: "Unsupported message encountered during prepared query: \(message).", source: .capture())
68+
default: throw MySQLError(identifier: "query", reason: "Unsupported message encountered during prepared query: \(message).")
6969
}
7070
}
7171
}

Sources/MySQL/Connection/MySQLConnection+SimpleQuery.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ extension MySQLConnection {
4949
}
5050
return false
5151
case .ok, .eof: return true
52-
default: throw MySQLError(identifier: "simpleQuery", reason: "Unsupported message encountered during simple query: \(message).", source: .capture())
52+
default: throw MySQLError(identifier: "simpleQuery", reason: "Unsupported message encountered during simple query: \(message).")
5353
}
5454
}
5555
}

Sources/MySQL/Connection/MySQLConnection.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ public final class MySQLConnection: BasicWorker, DatabaseConnection, DatabaseQue
9292
handler.state = .callback(promise) { packet in
9393
switch packet {
9494
case .ok(let ok): self.lastMetadata = .init(ok)
95-
case .err(let err): throw err.makeError(source: .capture())
95+
case .err(let err): throw err.makeError()
9696
default: break
9797
}
9898
return try onResponse(packet)
@@ -134,4 +134,4 @@ public final class MySQLConnection: BasicWorker, DatabaseConnection, DatabaseQue
134134
}
135135

136136
/// Error to throw if the connection has closed.
137-
private let closeError = MySQLError(identifier: "closed", reason: "Connection is closed.", source: .capture())
137+
private let closeError = MySQLError(identifier: "closed", reason: "Connection is closed.")

Sources/MySQL/Connection/MySQLConnectionHandler.swift

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ final class MySQLConnectionHandler: ChannelInboundHandler {
3434
// MARK: Private
3535

3636
private func handlePacket(ctx: ChannelHandlerContext, packet: MySQLPacket) throws {
37-
// print("✅ \(packet) \(state)")
37+
print("\(packet) \(state)")
3838
switch state {
3939
case .nascent:
4040
switch packet {
@@ -49,7 +49,21 @@ final class MySQLConnectionHandler: ChannelInboundHandler {
4949
self.readyForQuery = nil
5050
case .fullAuthenticationRequest:
5151
guard config.transport.isTLS else {
52-
throw MySQLError(identifier: "fullAuthRequired", reason: "Full authentication not supported over insecure connections.", source: .capture())
52+
throw MySQLError(
53+
identifier: "fullAuthRequired",
54+
reason: "Full authentication not supported over insecure connections.",
55+
possibleCauses: [
56+
"Using 'caching_sha2_password' auth plugin (default in MySQL >= 8.0.4) over an insecure (no SSL) connection."
57+
],
58+
suggestedFixes: [
59+
"Use a secure MySQLTransportConfig option in your MySQLDatabaseConfig.",
60+
"Use a MySQL auth plugin that does not require full authentication (like 'mysql_native_password').",
61+
"Use MySQL < 8.0.4."
62+
],
63+
documentationLinks: [
64+
"https://mysqlserverteam.com/mysql-8-0-4-new-default-authentication-plugin-caching_sha2_password/"
65+
]
66+
)
5367
}
5468
let packet: MySQLPacket = .plaintextPassword(config.password!)
5569
// if auth write fail, we need to fail the rfq promise
@@ -60,7 +74,7 @@ final class MySQLConnectionHandler: ChannelInboundHandler {
6074
}
6175
ctx.writeAndFlush(wrapOutboundOut(packet), promise: writePromise)
6276
case .err(let err):
63-
let error = err.makeError(source: .capture())
77+
let error = err.makeError()
6478
readyForQuery?.fail(error: error)
6579
self.readyForQuery = nil
6680
default: fatalError("Unsupported packet during connect: \(packet)")
@@ -91,13 +105,13 @@ final class MySQLConnectionHandler: ChannelInboundHandler {
91105
switch authPlugin {
92106
case "mysql_native_password":
93107
guard handshake.capabilities.contains(.CLIENT_SECURE_CONNECTION) else {
94-
throw MySQLError(identifier: "authproto", reason: "Pre-4.1 auth protocol is not supported or safe.", source: .capture())
108+
throw MySQLError(identifier: "authproto", reason: "Pre-4.1 auth protocol is not supported or safe.")
95109
}
96110
guard let password = config.password else {
97-
throw MySQLError(identifier: "password", reason: "Password required for auth plugin.", source: .capture())
111+
throw MySQLError(identifier: "password", reason: "Password required for auth plugin.")
98112
}
99113
guard handshake.authPluginData.count >= 20 else {
100-
throw MySQLError(identifier: "salt", reason: "Server-supplied salt too short.", source: .capture())
114+
throw MySQLError(identifier: "salt", reason: "Server-supplied salt too short.")
101115
}
102116
let salt = Data(handshake.authPluginData[..<20])
103117
let passwordHash = try SHA1.hash(password)
@@ -109,7 +123,7 @@ final class MySQLConnectionHandler: ChannelInboundHandler {
109123
authResponse = hash
110124
case "caching_sha2_password":
111125
guard let password = config.password else {
112-
throw MySQLError(identifier: "password", reason: "Password required for auth plugin.", source: .capture())
126+
throw MySQLError(identifier: "password", reason: "Password required for auth plugin.")
113127
}
114128

115129
// XOR(SHA256(PASSWORD), SHA256(SHA256(SHA256(PASSWORD)), seed_bytes))
@@ -128,7 +142,7 @@ final class MySQLConnectionHandler: ChannelInboundHandler {
128142
let hash2xsalt = try SHA256.hash(hash2x + handshake.authPluginData)
129143
hash.xor(hash2xsalt)
130144
authResponse = hash
131-
default: throw MySQLError(identifier: "authPlugin", reason: "Unsupported auth plugin: '\(authPlugin)'.", source: .capture())
145+
default: throw MySQLError(identifier: "authPlugin", reason: "Unsupported auth plugin: '\(authPlugin)'.")
132146
}
133147
let response = MySQLPacket.HandshakeResponse41(
134148
capabilities: config.capabilities,

Sources/MySQL/Connection/MySQLData.swift

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -186,11 +186,11 @@ public struct MySQLData: Equatable, Encodable {
186186
case .binary(let binary):
187187
func safeCast<J>(_ j: J) throws -> I where J: FixedWidthInteger {
188188
guard j >= I.min else {
189-
throw MySQLError(identifier: "intMin", reason: "Value \(j) too small for \(I.self).", source: .capture())
189+
throw MySQLError(identifier: "intMin", reason: "Value \(j) too small for \(I.self).")
190190
}
191191

192192
guard j <= I.max else {
193-
throw MySQLError(identifier: "intMax", reason: "Value \(j) too big for \(I.self).", source: .capture())
193+
throw MySQLError(identifier: "intMax", reason: "Value \(j) too big for \(I.self).")
194194
}
195195

196196
return I(j)
@@ -395,7 +395,7 @@ extension String: MySQLDataConvertible {
395395
/// See `MySQLDataConvertible.convertFromMySQLData()`
396396
public static func convertFromMySQLData(_ mysqlData: MySQLData) throws -> String {
397397
guard let string = mysqlData.string() else {
398-
throw MySQLError(identifier: "string", reason: "Cannot decode String from MySQLData: \(mysqlData).", source: .capture())
398+
throw MySQLError(identifier: "string", reason: "Cannot decode String from MySQLData: \(mysqlData).")
399399
}
400400
return string
401401
}
@@ -410,10 +410,10 @@ extension Decimal: MySQLDataConvertible {
410410
/// See `MySQLDataConvertible.convertFromMySQLData()`
411411
public static func convertFromMySQLData(_ mysqlData: MySQLData) throws -> Decimal {
412412
guard let string = mysqlData.string() else {
413-
throw MySQLError(identifier: "decimal", reason: "Cannot decode String from MySQLData: \(mysqlData).", source: .capture())
413+
throw MySQLError(identifier: "decimal", reason: "Cannot decode String from MySQLData: \(mysqlData).")
414414
}
415415
guard let decimal = Decimal(string: string) else {
416-
throw MySQLError(identifier: "decimal", reason: "Cannot decode Decimal from String: \(string).", source: .capture())
416+
throw MySQLError(identifier: "decimal", reason: "Cannot decode Decimal from String: \(string).")
417417
}
418418
return decimal
419419
}
@@ -428,7 +428,7 @@ extension FixedWidthInteger {
428428
/// See `MySQLDataConvertible.convertFromMySQLData()`
429429
public static func convertFromMySQLData(_ mysqlData: MySQLData) throws -> Self {
430430
guard let int = try mysqlData.integer(Self.self) else {
431-
throw MySQLError(identifier: "int", reason: "Cannot decode Int from MySQLData: \(mysqlData).", source: .capture())
431+
throw MySQLError(identifier: "int", reason: "Cannot decode Int from MySQLData: \(mysqlData).")
432432
}
433433

434434
return int
@@ -466,7 +466,7 @@ extension OptionalType {
466466
return makeOptionalType(nil)
467467
} else {
468468
guard let convertibleType = WrappedType.self as? MySQLDataConvertible.Type else {
469-
throw MySQLError(identifier: "wrapped", reason: "Could not convert \(WrappedType.self) to MySQLData", source: .capture())
469+
throw MySQLError(identifier: "wrapped", reason: "Could not convert \(WrappedType.self) to MySQLData")
470470
}
471471
let wrapped = try convertibleType.convertFromMySQLData(mysqlData) as! WrappedType
472472
return makeOptionalType(wrapped)
@@ -486,13 +486,13 @@ extension Bool: MySQLDataConvertible {
486486
/// See `MySQLDataConvertible.convertFromMySQLData()`
487487
public static func convertFromMySQLData(_ mysqlData: MySQLData) throws -> Bool {
488488
guard let int = try mysqlData.integer(UInt8.self) else {
489-
throw MySQLError(identifier: "bool", reason: "Could not parse bool from: \(mysqlData)", source: .capture())
489+
throw MySQLError(identifier: "bool", reason: "Could not parse bool from: \(mysqlData)")
490490
}
491491

492492
switch int {
493493
case 1: return true
494494
case 0: return false
495-
default: throw MySQLError(identifier: "bool", reason: "Invalid bool: \(int)", source: .capture())
495+
default: throw MySQLError(identifier: "bool", reason: "Invalid bool: \(int)")
496496
}
497497
}
498498
}
@@ -506,7 +506,7 @@ extension BinaryFloatingPoint {
506506
/// See `MySQLDataConvertible.convertFromMySQLData()`
507507
public static func convertFromMySQLData(_ mysqlData: MySQLData) throws -> Self {
508508
guard let int = mysqlData.float(Self.self) else {
509-
throw MySQLError(identifier: "float", reason: "Cannot decode Float from MySQLData: \(mysqlData).", source: .capture())
509+
throw MySQLError(identifier: "float", reason: "Cannot decode Float from MySQLData: \(mysqlData).")
510510
}
511511

512512
return int
@@ -528,7 +528,7 @@ extension UUID: MySQLDataConvertible {
528528
/// See `MySQLDataConvertible.convertFromMySQLData()`
529529
public static func convertFromMySQLData(_ mysqlData: MySQLData) throws -> UUID {
530530
guard let data = mysqlData.data() else {
531-
throw MySQLError(identifier: "uuid", reason: "Could not parse UUID from: \(mysqlData)", source: .capture())
531+
throw MySQLError(identifier: "uuid", reason: "Could not parse UUID from: \(mysqlData)")
532532
}
533533
return .convertFromData(data)
534534
}
@@ -617,7 +617,7 @@ extension Date {
617617
yearForWeekOfYear: nil
618618
)
619619
guard let date = comps.date else {
620-
throw MySQLError(identifier: "date", reason: "Could not parse Date from: \(time)", source: .capture())
620+
throw MySQLError(identifier: "date", reason: "Could not parse Date from: \(time)")
621621
}
622622

623623
/// For some reason comps.nanosecond is `nil` on linux :(
@@ -668,9 +668,9 @@ extension Date: MySQLDataConvertible {
668668
case .binary(let binary):
669669
switch binary.storage {
670670
case .time(let _time): time = _time
671-
default: throw MySQLError(identifier: "timeBinary", reason: "Parsing MySQLTime from \(binary) is not supported.", source: .capture())
671+
default: throw MySQLError(identifier: "timeBinary", reason: "Parsing MySQLTime from \(binary) is not supported.")
672672
}
673-
case .text: throw MySQLError(identifier: "timeText", reason: "Parsing MySQLTime from text is not supported.", source: .capture())
673+
case .text: throw MySQLError(identifier: "timeText", reason: "Parsing MySQLTime from text is not supported.")
674674
}
675675

676676
return try .convertFromMySQLTime(time)

Sources/MySQL/Database/OldMySQLRowDecoder.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
//
4242
// func require(key: CodingKey) throws -> MySQLData {
4343
// guard let data = self.data[key.stringValue] else {
44-
// throw MySQLError(identifier: "decode", reason: "No value found at key: \(key)", source: .capture())
44+
// throw MySQLError(identifier: "decode", reason: "No value found at key: \(key)")
4545
// }
4646
// return data
4747
// }
@@ -55,7 +55,7 @@
5555
// suggestedFixes: [
5656
// "You can conform nested types to `MySQLJSONType`. (Nested types must be `MySQLDataConvertible`.)"
5757
// ],
58-
// source: .capture()
58+
//
5959
// )
6060
//}
6161
//
@@ -96,7 +96,7 @@
9696
// suggestedFixes: [
9797
// "Conform \(type) to MySQLDataConvertible"
9898
// ],
99-
// source: .capture()
99+
//
100100
// )
101101
// }
102102
// return try convertible.convertFromMySQLData(decoder.require(key: key)) as! T

Sources/MySQL/Database/OldMySQLRowEncoder.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@
9090
// suggestedFixes: [
9191
// "Conform \(type) to `MySQLDataConvertible`"
9292
// ],
93-
// source: .capture()
93+
//
9494
// )
9595
// }
9696
// encoder.data[key.stringValue] = try convertible.convertToMySQLData()

0 commit comments

Comments
 (0)