Skip to content

Commit 7efd3b1

Browse files
committed
format: format 0E-x where x > 6 like PG does
Officially in the GDA spec, formatting a 0 with any decimal places should be 0. However, this code doesn't do that - it formats the number of 0s up to 6, and then `0E-exponent` afterwards. To make this more "PG" compatible, we fix this by ensuring we display as many 0s as the exponent allows in the `.String()` case.
1 parent 3bce48c commit 7efd3b1

File tree

5 files changed

+52
-6
lines changed

5 files changed

+52
-6
lines changed

.github/workflows/go.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,10 +61,10 @@ jobs:
6161
run: go vet -unsafeptr=false ./...
6262

6363
- name: 'Staticcheck'
64-
# staticcheck requires go1.17.
65-
if: ${{ matrix.arch == 'x64' && matrix.go >= '1.17' }}
64+
# staticcheck requires go1.19.
65+
if: ${{ matrix.arch == 'x64' && matrix.go >= '1.19' }}
6666
run: |
67-
go install honnef.co/go/tools/cmd/staticcheck@latest
67+
go install honnef.co/go/tools/cmd/staticcheck@v0.4.3
6868
staticcheck ./...
6969
7070
- name: 'GCAssert'

decimal_test.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -447,6 +447,12 @@ func TestFormat(t *testing.T) {
447447
f: "000",
448448
g: "0e+2",
449449
},
450+
"0E-9": {
451+
e: "0e-9",
452+
f: "0.000000000",
453+
g: "0.000000000",
454+
G: "0.000000000",
455+
},
450456
}
451457
verbs := []string{"%e", "%E", "%f", "%g", "%G"}
452458

format.go

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,19 @@ func (d *Decimal) Append(buf []byte, fmt byte) []byte {
6565
case 'f':
6666
return fmtF(buf, d, digits)
6767
case 'g', 'G':
68+
// Ensure that we correctly display all 0s like PG does.
69+
// For 0.00000000, the co-efficient is represented as 0
70+
// and hence the digits is incorrectly 0 (for 1.000000, it'd be
71+
// 10000000). Hence, pad the digit length before calculating the
72+
// adjExponentLimit.
73+
// See: https://github.com/cockroachdb/cockroach/issues/102217.
74+
digitLen := len(digits)
75+
if d.Coeff.BitLen() == 0 && d.Exponent < 0 {
76+
digitLen += int(-d.Exponent)
77+
}
6878
// See: http://speleotrove.com/decimal/daconvs.html#reftostr
6979
const adjExponentLimit = -6
70-
adj := int(d.Exponent) + (len(digits) - 1)
80+
adj := int(d.Exponent) + (digitLen - 1)
7181
if d.Exponent <= 0 && adj >= adjExponentLimit {
7282
return fmtF(buf, d, digits)
7383
}

gda_test.go

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -683,8 +683,26 @@ func gdaTest(t *testing.T, path string, tcs []TestCase) {
683683
if strings.HasPrefix(tc.Result, "SNAN") {
684684
tc.Result = "sNaN"
685685
}
686-
if !strings.EqualFold(s, tc.Result) {
687-
t.Fatalf("expected %s, got %s", tc.Result, s)
686+
expected := tc.Result
687+
// Adjust 0E- or -0E- tests to match PG behavior.
688+
// See: https://github.com/cockroachdb/cockroach/issues/102217.
689+
if pos, neg := strings.HasPrefix(expected, "0E-"), strings.HasPrefix(expected, "-0E-"); pos || neg {
690+
startIdx := 3
691+
if neg {
692+
startIdx = 4
693+
}
694+
p, err := strconv.ParseInt(expected[startIdx:], 10, 64)
695+
if err != nil {
696+
t.Fatalf("unexpected error converting int: %v", err)
697+
}
698+
expected = ""
699+
if neg {
700+
expected = "-"
701+
}
702+
expected += "0." + strings.Repeat("0", int(p))
703+
}
704+
if !strings.EqualFold(s, expected) {
705+
t.Fatalf("expected %s, got %s", expected, s)
688706
}
689707
return
690708
}

sql_test.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,4 +75,16 @@ func TestSQL(t *testing.T) {
7575
if nd.Valid {
7676
t.Fatal("expected null")
7777
}
78+
79+
var g Decimal
80+
if err := db.QueryRow("select 0::decimal(19,9)").Scan(&g); err != nil {
81+
t.Fatal(err)
82+
}
83+
zeroD, _, err := NewFromString("0.000000000")
84+
if err != nil {
85+
t.Fatal(err)
86+
}
87+
if g.String() != zeroD.String() {
88+
t.Fatalf("expected 0::decimal(19.9) pg value %s match, found %s", g.String(), zeroD.String())
89+
}
7890
}

0 commit comments

Comments
 (0)