Skip to content

Commit b726a2d

Browse files
authored
Merge pull request #190 from vapor/decimal-precision
store Decimal using Codable impl
2 parents b190f5d + 940d72c commit b726a2d

File tree

5 files changed

+48
-35
lines changed

5 files changed

+48
-35
lines changed

Sources/MySQL/Connection/MySQLData.swift

Lines changed: 0 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -26,15 +26,6 @@ public struct MySQLData: Equatable, Encodable {
2626
self.storage = .binary(binary)
2727
}
2828

29-
public init(decimal: Decimal) {
30-
let binary = MySQLBinaryData(
31-
type: .MYSQL_TYPE_NEWDECIMAL,
32-
isUnsigned: true,
33-
storage: .string(.init(decimal.description.utf8))
34-
)
35-
self.storage = .binary(binary)
36-
}
37-
3829
/// Creates a new `MySQLData` from `Data`.
3930
public init(data: Data?) {
4031
let binary = MySQLBinaryData(
@@ -401,24 +392,6 @@ extension String: MySQLDataConvertible {
401392
}
402393
}
403394

404-
extension Decimal: MySQLDataConvertible {
405-
/// See `MySQLDataConvertible.convertToMySQLData(format:)`
406-
public func convertToMySQLData() -> MySQLData {
407-
return MySQLData(decimal: self)
408-
}
409-
410-
/// See `MySQLDataConvertible.convertFromMySQLData()`
411-
public static func convertFromMySQLData(_ mysqlData: MySQLData) throws -> Decimal {
412-
guard let string = mysqlData.string() else {
413-
throw MySQLError(identifier: "decimal", reason: "Cannot decode String from MySQLData: \(mysqlData).")
414-
}
415-
guard let decimal = Decimal(string: string) else {
416-
throw MySQLError(identifier: "decimal", reason: "Cannot decode Decimal from String: \(string).")
417-
}
418-
return decimal
419-
}
420-
}
421-
422395
extension FixedWidthInteger {
423396
/// See `MySQLDataConvertible.convertToMySQLData(format:)`
424397
public func convertToMySQLData() -> MySQLData {
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
extension Decimal: MySQLDataTypeStaticRepresentable {
2+
/// See `MySQLDataTypeStaticRepresentable`.
3+
public static var mysqlDataType: MySQLDataType {
4+
/// https://github.com/apple/swift-corelibs-foundation/blob/master/Foundation/Decimal.swift#L567
5+
/// decimal has max string size of 200
6+
return .varchar(200)
7+
}
8+
}
9+
10+
extension Decimal: MySQLDataConvertible {
11+
/// See `MySQLDataConvertible`.
12+
public func convertToMySQLData() -> MySQLData {
13+
return .init(string: self.description)
14+
}
15+
16+
/// See `MySQLDataConvertible`.
17+
public static func convertFromMySQLData(_ mysqlData: MySQLData) throws -> Decimal {
18+
guard let decimal = try Decimal(string: String.convertFromMySQLData(mysqlData)) else {
19+
throw MySQLError(identifier: "decimal", reason: "Could not decode decimal from MySQLData: \(mysqlData).")
20+
}
21+
return decimal
22+
}
23+
}

Sources/MySQL/SQL/MySQLDataType.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ public struct MySQLDataType: SQLDataType, Equatable {
99
/// See `SQLDataType`.
1010
public static func dataType(appropriateFor type: Any.Type) -> MySQLDataType? {
1111
guard let type = type as? MySQLDataTypeStaticRepresentable.Type else {
12-
return nil
12+
return .json
1313
}
1414
return type.mysqlDataType
1515
}

Sources/MySQL/SQL/MySQLDataTypeStaticRepresentable.swift

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,6 @@ extension String: MySQLDataTypeStaticRepresentable {
2525
}
2626
}
2727

28-
extension Decimal: MySQLDataTypeStaticRepresentable {
29-
/// See `MySQLDataTypeStaticRepresentable`.
30-
public static var mysqlDataType: MySQLDataType {
31-
return .decimal
32-
}
33-
}
34-
3528
extension FixedWidthInteger {
3629
/// See `MySQLDataTypeStaticRepresentable`.
3730
public static var mysqlDataType: MySQLDataType {

Tests/MySQLTests/MySQLTests.swift

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,29 @@ class MySQLTests: XCTestCase {
280280
XCTAssertEqual(sql, "ALTER TABLE `Galaxy` ADD COLUMN `name` VARCHAR(255) NOT NULL AFTER `id`")
281281
}
282282

283+
func testDecimalPrecision() throws {
284+
struct DecimalTest: MySQLTable {
285+
var num: Decimal
286+
}
287+
288+
let conn = try MySQLConnection.makeTest()
289+
defer {
290+
try? conn.drop(table: DecimalTest.self).ifExists().run().wait()
291+
}
292+
try conn.create(table: DecimalTest.self)
293+
.column(for: \DecimalTest.num)
294+
.run().wait()
295+
296+
let a = DecimalTest(num: .init(sign: .plus, exponent: 80, significand: 1.0))
297+
try conn.insert(into: DecimalTest.self).value(a)
298+
.run().wait()
299+
300+
let b = try conn.select()
301+
.all().from(DecimalTest.self)
302+
.all(decoding: DecimalTest.self).wait()
303+
XCTAssertEqual(b.first?.num, a.num)
304+
}
305+
283306
static let allTests = [
284307
("testBenchmark", testBenchmark),
285308
("testSimpleQuery", testSimpleQuery),
@@ -295,6 +318,7 @@ class MySQLTests: XCTestCase {
295318
("testInsertMany", testInsertMany),
296319
("testPreparedStatementOverload", testPreparedStatementOverload),
297320
("testColumnAfter", testColumnAfter),
321+
("testDecimalPrecision", testDecimalPrecision),
298322
]
299323
}
300324

0 commit comments

Comments
 (0)