@@ -129,7 +129,11 @@ cdef numeric_encode_binary(CodecContext settings, WriteBuffer buf, obj):
129
129
# For this reason the below code is pure overhead and is ~25% slower
130
130
# than the simple text decoder above. That said, we need the binary
131
131
# decoder to support binary COPY with numeric values.
132
- cdef numeric_decode_binary(CodecContext settings, FRBuffer * buf):
132
+ cdef numeric_decode_binary_ex(
133
+ CodecContext settings,
134
+ FRBuffer * buf,
135
+ bint trail_fract_zero,
136
+ ):
133
137
cdef:
134
138
uint16_t num_pgdigits = < uint16_t> hton.unpack_int16(frb_read(buf, 2 ))
135
139
int16_t weight = hton.unpack_int16(frb_read(buf, 2 ))
@@ -140,6 +144,7 @@ cdef numeric_decode_binary(CodecContext settings, FRBuffer *buf):
140
144
int16_t pgdigit
141
145
object pydigits
142
146
ssize_t num_pydigits
147
+ ssize_t actual_num_pydigits
143
148
ssize_t buf_size
144
149
int64_t exponent
145
150
int64_t abs_exponent
@@ -183,6 +188,7 @@ cdef numeric_decode_binary(CodecContext settings, FRBuffer *buf):
183
188
1 + # leading zero
184
189
1 + # decimal dot
185
190
num_pydigits + # digits
191
+ 1 + # possible trailing zero padding
186
192
2 + # exponent indicator (E-,E+)
187
193
exponent_chars + # exponent
188
194
1 # null terminator char
@@ -231,6 +237,18 @@ cdef numeric_decode_binary(CodecContext settings, FRBuffer *buf):
231
237
# trailing zeros.
232
238
bufptr += dscale_left
233
239
240
+ if trail_fract_zero:
241
+ # Check if the number of rendered digits matches the exponent,
242
+ # and if so, add another trailing zero, so the result always
243
+ # appears with a decimal point.
244
+ actual_num_pydigits = bufptr - charbuf - 2
245
+ if sign == NUMERIC_NEG:
246
+ actual_num_pydigits -= 1
247
+
248
+ if actual_num_pydigits == abs_exponent:
249
+ bufptr[0 ] = < char > b' 0'
250
+ bufptr += 1
251
+
234
252
if exponent != 0 :
235
253
bufptr[0 ] = b' E'
236
254
if exponent < 0 :
@@ -253,6 +271,10 @@ cdef numeric_decode_binary(CodecContext settings, FRBuffer *buf):
253
271
cpython.PyMem_Free(charbuf)
254
272
255
273
274
+ cdef numeric_decode_binary(CodecContext settings, FRBuffer * buf):
275
+ return numeric_decode_binary_ex(settings, buf, False )
276
+
277
+
256
278
cdef inline char * _unpack_digit_stripping_lzeros(char * buf, int64_t pgdigit):
257
279
cdef:
258
280
int64_t d
0 commit comments