@@ -150,9 +150,8 @@ cdef numeric_decode_binary_ex(
150150 int64_t abs_exponent
151151 ssize_t exponent_chars
152152 ssize_t front_padding = 0
153- ssize_t trailing_padding = 0
154153 ssize_t num_fract_digits
155- ssize_t dscale_left
154+ ssize_t trailing_fract_zeros_adj
156155 char smallbuf[_NUMERIC_DECODER_SMALLBUF_SIZE]
157156 char * charbuf
158157 char * bufptr
@@ -175,14 +174,34 @@ cdef numeric_decode_binary_ex(
175174 elif pgdigit0 < 1000 :
176175 front_padding = 1
177176
177+ # The number of fractional decimal digits actually encoded in
178+ # base-DEC_DEIGITS digits sent by Postgres.
179+ num_fract_digits = (num_pgdigits - weight - 1 ) * DEC_DIGITS
180+
181+ # The trailing zero adjustment necessary to obtain exactly
182+ # dscale number of fractional digits in output. May be negative,
183+ # which indicates that trailing zeros in the last input digit
184+ # should be discarded.
185+ trailing_fract_zeros_adj = dscale - num_fract_digits
186+
178187 # Maximum possible number of decimal digits in base 10.
179- num_pydigits = num_pgdigits * DEC_DIGITS + dscale
188+ # The actual number might be up to 3 digits smaller due to
189+ # leading zeros in first input digit.
190+ num_pydigits = num_pgdigits * DEC_DIGITS
191+ if trailing_fract_zeros_adj > 0 :
192+ num_pydigits += trailing_fract_zeros_adj
193+
180194 # Exponent.
181195 exponent = (weight + 1 ) * DEC_DIGITS - front_padding
182196 abs_exponent = abs (exponent)
183- # Number of characters required to render absolute exponent value.
184- exponent_chars = < ssize_t> log10(< double > abs_exponent) + 1
197+ if abs_exponent != 0 :
198+ # Number of characters required to render absolute exponent value
199+ # in decimal.
200+ exponent_chars = < ssize_t> log10(< double > abs_exponent) + 1
201+ else :
202+ exponent_chars = 0
185203
204+ # Output buffer size.
186205 buf_size = (
187206 1 + # sign
188207 1 + # leading zero
@@ -221,21 +240,14 @@ cdef numeric_decode_binary_ex(
221240 bufptr = _unpack_digit(bufptr, pgdigit)
222241
223242 if dscale:
224- if weight >= 0 :
225- num_fract_digits = num_pgdigits - weight - 1
226- else :
227- num_fract_digits = num_pgdigits
228-
229- # Check how much dscale is left to render (trailing zeros).
230- dscale_left = dscale - num_fract_digits * DEC_DIGITS
231- if dscale_left > 0 :
232- for i in range (dscale_left):
243+ if trailing_fract_zeros_adj > 0 :
244+ for i in range (trailing_fract_zeros_adj):
233245 bufptr[i] = < char > b' 0'
234246
235247 # If display scale is _less_ than the number of rendered digits,
236- # dscale_left will be negative and this will strip the excess
237- # trailing zeros.
238- bufptr += dscale_left
248+ # trailing_fract_zeros_adj will be negative and this will strip
249+ # the excess trailing zeros.
250+ bufptr += trailing_fract_zeros_adj
239251
240252 if trail_fract_zero:
241253 # Check if the number of rendered digits matches the exponent,
0 commit comments