diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2018-04-04 11:28:33 -0400 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2018-04-04 11:28:40 -0400 |
commit | 331b2369c0ad1e51d5e50bf5dd75232e0160553a (patch) | |
tree | c4664e95d32549da837b34db0b1305773618c7c9 /contrib/jsonb_plperl/jsonb_plperl.c | |
parent | 3a5e0a91bb324ad2b2b1a0623a3f2e37772b43fc (diff) | |
download | postgresql-331b2369c0ad1e51d5e50bf5dd75232e0160553a.tar.gz |
Fix platform and Perl-version dependencies in new jsonb_plperl code.
Testing SvTYPE() directly is more fraught with problems than one might
think, because depending on context Perl might be storing a scalar value
in one of several forms, eg both numeric and string values. This resulted
in Perl-version-dependent buildfarm test failures. Instead use the SvTYPE
test only to distinguish non-scalar cases (AV, HV, NULL). Disambiguate
scalars by testing SvIOK, SvNOK, then SvPOK. This creates a preference
order for how we will resolve cases where the value is available in more
than one form, which seems fine to me.
Furthermore, because we're now dealing directly with a "double" value
in the SvNOK case, we can get rid of an inadequate and unportable
string-comparison test for infinities, and use isinf() instead.
(We do need some additional #include and "-lm" infrastructure to use
that in a contrib module, per prior experiences.)
In passing, prevent the regression test results from depending on DROP
CASCADE order; I've not seen that malfunction, but it's trouble waiting
to happen.
Discussion: https://postgr.es/m/E1f3MMJ-0006bf-B0@gemulon.postgresql.org
Diffstat (limited to 'contrib/jsonb_plperl/jsonb_plperl.c')
-rw-r--r-- | contrib/jsonb_plperl/jsonb_plperl.c | 76 |
1 files changed, 42 insertions, 34 deletions
diff --git a/contrib/jsonb_plperl/jsonb_plperl.c b/contrib/jsonb_plperl/jsonb_plperl.c index ad9e65516f..837bae2ab5 100644 --- a/contrib/jsonb_plperl/jsonb_plperl.c +++ b/contrib/jsonb_plperl/jsonb_plperl.c @@ -1,11 +1,14 @@ #include "postgres.h" +#include <float.h> +#include <math.h> + +/* Defined by Perl */ #undef _ #include "fmgr.h" #include "plperl.h" #include "plperl_helpers.h" - #include "utils/jsonb.h" #include "utils/fmgrprotos.h" @@ -188,46 +191,51 @@ SV_to_JsonbValue(SV *in, JsonbParseState **jsonb_state, bool is_elem) case SVt_PVHV: return HV_to_JsonbValue((HV *) in, jsonb_state); - case SVt_NV: - case SVt_IV: + case SVt_NULL: + out.type = jbvNull; + break; + + default: + if (SvIOK(in)) { - char *str = sv2cstr(in); + IV ival = SvIV(in); - /* - * Use case-insensitive comparison because infinity - * representation varies across Perl versions. - */ - if (pg_strcasecmp(str, "inf") == 0) + out.type = jbvNumeric; + out.val.numeric = + DatumGetNumeric(DirectFunctionCall1(int8_numeric, + Int64GetDatum((int64) ival))); + } + else if (SvNOK(in)) + { + double nval = SvNV(in); + + if (isinf(nval)) ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), (errmsg("cannot convert infinite value to jsonb")))); out.type = jbvNumeric; - out.val.numeric = DatumGetNumeric(DirectFunctionCall3(numeric_in, - CStringGetDatum(str), 0, -1)); + out.val.numeric = + DatumGetNumeric(DirectFunctionCall1(float8_numeric, + Float8GetDatum(nval))); + } + else if (SvPOK(in)) + { + out.type = jbvString; + out.val.string.val = sv2cstr(in); + out.val.string.len = strlen(out.val.string.val); + } + else + { + /* + * XXX It might be nice if we could include the Perl type in + * the error message. + */ + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + (errmsg("cannot transform this Perl type to jsonb")))); + return NULL; } - break; - - case SVt_NULL: - out.type = jbvNull; - break; - - case SVt_PV: /* string */ - out.type = jbvString; - out.val.string.val = sv2cstr(in); - out.val.string.len = strlen(out.val.string.val); - break; - - default: - - /* - * XXX It might be nice if we could include the Perl type in the - * error message. - */ - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - (errmsg("cannot transform this Perl type to jsonb")))); - return NULL; } /* Push result into 'jsonb_state' unless it is a raw scalar. */ |