Skip to content

Commit f60cb33

Browse files
Fix decoding of negative numeric values, add tests
1 parent ca015a8 commit f60cb33

File tree

2 files changed

+38
-2
lines changed

2 files changed

+38
-2
lines changed

Sources/PostgreSQL/Data/PostgreSQLData+String.swift

+7-2
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ extension String: PostgreSQLDataConvertible {
1414
var ndigits: Int16
1515
/// How many of the digits are before the decimal point (always add 1)
1616
var weight: Int16
17-
/// If 1, this number is negative. Otherwise, positive.
17+
/// If 0x4000, this number is negative. See NUMERIC_NEG in
18+
/// https://github.com/postgres/postgres/blob/master/src/backend/utils/adt/numeric.c
1819
var sign: Int16
1920
/// The number of sig digits after the decimal place (get rid of trailing 0s)
2021
var dscale: Int16
@@ -62,6 +63,10 @@ extension String: PostgreSQLDataConvertible {
6263
fractional += String(repeating: "0", count: 4 - string.count) + string
6364
}
6465
}
66+
67+
if integer.count == 0 {
68+
integer = "0"
69+
}
6570

6671
if fractional.count > metadata.dscale.bigEndian {
6772
/// use the dscale to remove extraneous zeroes at the end of the fractional part
@@ -78,7 +83,7 @@ extension String: PostgreSQLDataConvertible {
7883
}
7984

8085
/// use sign to determine adding a leading `-`
81-
if metadata.sign.bigEndian == 1 {
86+
if (metadata.sign.bigEndian & 0x4000) != 0 {
8287
return "-" + numeric
8388
} else {
8489
return numeric

Tests/PostgreSQLTests/PostgreSQLConnectionTests.swift

+31
Original file line numberDiff line numberDiff line change
@@ -559,6 +559,36 @@ class PostgreSQLConnectionTests: XCTestCase {
559559
}
560560
}
561561

562+
// https://github.com/vapor/postgresql/pull/111
563+
func testNumericDecode() throws {
564+
let conn = try PostgreSQLConnection.makeTest()
565+
566+
let sum = { (value: String) -> PostgreSQLSelectExpression in
567+
.expression(.function(.function("SUM", [.expression(.literal(.numeric(value)))])), alias: .identifier("value"))
568+
}
569+
570+
var testValues = ["0.543201203", "1000.1", "10000.1", "42.0001", "42.00001", "10234.543201", "102340567.8"]
571+
testValues += testValues.map { "-\($0)" }
572+
573+
struct NumericString: PostgreSQLTable {
574+
let value: String
575+
}
576+
577+
for value in testValues {
578+
let result = try conn.select().column(sum(value)).first(decoding: NumericString.self).wait()?.value
579+
XCTAssert(result == value)
580+
}
581+
582+
struct NumericDouble: PostgreSQLTable {
583+
let value: Double
584+
}
585+
586+
for value in testValues {
587+
let result = try conn.select().column(sum(value)).first(decoding: NumericDouble.self).wait()?.value
588+
XCTAssert(result == Double(value))
589+
}
590+
}
591+
562592
static var allTests = [
563593
("testBenchmark", testBenchmark),
564594
("testVersion", testVersion),
@@ -579,6 +609,7 @@ class PostgreSQLConnectionTests: XCTestCase {
579609
("testInvalidDate", testInvalidDate),
580610
("testEmptyArray", testEmptyArray),
581611
("testZeroNumeric", testZeroNumeric),
612+
("testNumericDecode", testNumericDecode),
582613
]
583614
}
584615

0 commit comments

Comments
 (0)