Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 3680cd0

Browse files
author
Nikita Glukhov
committed
Optimize numeric conversions in jsonb_plpython
1 parent ceb3a38 commit 3680cd0

File tree

3 files changed

+49
-2
lines changed

3 files changed

+49
-2
lines changed

contrib/jsonb_plpython/jsonb_plpython.c

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,13 @@ PLyObject_FromJsonbValue(JsonbValue *jsonbValue)
126126
{
127127
Datum num;
128128
char *str;
129+
int64 intval;
130+
131+
if (numeric_to_exact_int64(jsonbValue->val.numeric, &intval))
132+
#ifndef HAVE_LONG_INT_64
133+
if ((long) intval == intval)
134+
#endif
135+
return PyInt_FromLong((long) intval);
129136

130137
num = NumericGetDatum(jsonbValue->val.numeric);
131138
str = DatumGetCString(DirectFunctionCall1(numeric_out, num));
@@ -409,7 +416,26 @@ static JsonbValue *
409416
PLyNumber_ToJsonbValue(PyObject *obj, JsonbValue *jbvNum)
410417
{
411418
Numeric num;
412-
char *str = PLyObject_AsString(obj);
419+
char *str;
420+
421+
jbvNum->type = jbvNumeric;
422+
423+
if (PyInt_Check(obj))
424+
{
425+
long val = PyInt_AsLong(obj);
426+
427+
if (val != -1 || !PyErr_Occurred())
428+
{
429+
jbvNum->val.numeric =
430+
DatumGetNumeric(DirectFunctionCall1(int8_numeric,
431+
Int64GetDatum((int64) val)));
432+
return jbvNum;
433+
}
434+
435+
PyErr_Clear();
436+
}
437+
438+
str = PLyObject_AsString(obj);
413439

414440
PG_TRY();
415441
{
@@ -441,7 +467,6 @@ PLyNumber_ToJsonbValue(PyObject *obj, JsonbValue *jbvNum)
441467
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
442468
(errmsg("cannot convert NaN to jsonb"))));
443469

444-
jbvNum->type = jbvNumeric;
445470
jbvNum->val.numeric = num;
446471

447472
return jbvNum;

src/backend/utils/adt/numeric.c

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3349,6 +3349,27 @@ numeric_float4(PG_FUNCTION_ARGS)
33493349
PG_RETURN_DATUM(result);
33503350
}
33513351

3352+
/*
3353+
* numeric_get_int64() -
3354+
*
3355+
* Try to convert numeric to int64 if it is an exact integer (i.e. it does
3356+
* not have digits after the decimal point). Return true if okay.
3357+
*/
3358+
bool
3359+
numeric_to_exact_int64(Numeric num, int64 *result)
3360+
{
3361+
NumericVar var;
3362+
3363+
if (NUMERIC_IS_NAN(num))
3364+
return false;
3365+
3366+
if (NUMERIC_DSCALE(num) != 0)
3367+
return false; /* digits after the decimal point are not allowed */
3368+
3369+
init_var_from_num(num, &var);
3370+
3371+
return numericvar_to_int64(&var, result);
3372+
}
33523373

33533374
/* ----------------------------------------------------------------------
33543375
*

src/include/utils/numeric.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,5 +60,6 @@ extern bool numeric_is_nan(Numeric num);
6060
int32 numeric_maximum_size(int32 typmod);
6161
extern char *numeric_out_sci(Numeric num, int scale);
6262
extern char *numeric_normalize(Numeric num);
63+
extern bool numeric_to_exact_int64(Numeric value, int64 *out);
6364

6465
#endif /* _PG_NUMERIC_H_ */

0 commit comments

Comments
 (0)