Re: pgsql: Transforms for jsonb to PL/Perl - Mailing list pgsql-committers

From Tom Lane
Subject Re: pgsql: Transforms for jsonb to PL/Perl
Date
Msg-id 15089.1522791424@sss.pgh.pa.us
Whole thread Raw
In response to Re: pgsql: Transforms for jsonb to PL/Perl  (Tom Lane <tgl@sss.pgh.pa.us>)
Responses Re: pgsql: Transforms for jsonb to PL/Perl  (Anthony Bykov <a.bykov@postgrespro.ru>)
Re: pgsql: Transforms for jsonb to PL/Perl  (Anthony Bykov <a.bykov@postgrespro.ru>)
List pgsql-committers
I wrote:
> Hm, it fails on my own machine too (RHEL6, perl 5.10.1), with the
> same "cannot transform this Perl type to jsonb" symptoms.  A bit
> of tracing shows that SvTYPE(in) is returning SVt_PVIV in some
> of the failing cases, and SVt_PVNV in others.

I tried to fix this by reducing the amount of knowledge that function
embeds about the possible SvTYPEs.  After the special cases for AV,
HV, and NULL, the attached just tests SvIOK, SvNOK, and SvPOK, and
does the right thing for each case.

This results in one change in the module's test results: the example
that thinks it's returning a regexp match result no longer fails,
but just returns the scalar result (0).  I'm inclined to think that
this is correct/desirable and the existing behavior is an accidental
artifact of not coping with Perl's various augmented representations
of scalar values.

Thoughts?

            regards, tom lane

diff --git a/contrib/jsonb_plperl/expected/jsonb_plperl.out b/contrib/jsonb_plperl/expected/jsonb_plperl.out
index 5bb5677..4af2fbb 100644
*** a/contrib/jsonb_plperl/expected/jsonb_plperl.out
--- b/contrib/jsonb_plperl/expected/jsonb_plperl.out
*************** AS $$
*** 46,53 ****
  return ('1' =~ m(0\t2));
  $$;
  SELECT testRegexpToJsonb();
! ERROR:  cannot transform this Perl type to jsonb
! CONTEXT:  PL/Perl function "testregexptojsonb"
  CREATE FUNCTION roundtrip(val jsonb) RETURNS jsonb
  LANGUAGE plperl
  TRANSFORM FOR TYPE jsonb
--- 46,56 ----
  return ('1' =~ m(0\t2));
  $$;
  SELECT testRegexpToJsonb();
!  testregexptojsonb
! -------------------
!  0
! (1 row)
!
  CREATE FUNCTION roundtrip(val jsonb) RETURNS jsonb
  LANGUAGE plperl
  TRANSFORM FOR TYPE jsonb
diff --git a/contrib/jsonb_plperl/expected/jsonb_plperlu.out b/contrib/jsonb_plperl/expected/jsonb_plperlu.out
index 9527e9e..6fc6c3d 100644
*** a/contrib/jsonb_plperl/expected/jsonb_plperlu.out
--- b/contrib/jsonb_plperl/expected/jsonb_plperlu.out
*************** AS $$
*** 46,53 ****
  return ('1' =~ m(0\t2));
  $$;
  SELECT testRegexpToJsonb();
! ERROR:  cannot transform this Perl type to jsonb
! CONTEXT:  PL/Perl function "testregexptojsonb"
  CREATE FUNCTION roundtrip(val jsonb) RETURNS jsonb
  LANGUAGE plperlu
  TRANSFORM FOR TYPE jsonb
--- 46,56 ----
  return ('1' =~ m(0\t2));
  $$;
  SELECT testRegexpToJsonb();
!  testregexptojsonb
! -------------------
!  0
! (1 row)
!
  CREATE FUNCTION roundtrip(val jsonb) RETURNS jsonb
  LANGUAGE plperlu
  TRANSFORM FOR TYPE jsonb
diff --git a/contrib/jsonb_plperl/jsonb_plperl.c b/contrib/jsonb_plperl/jsonb_plperl.c
index ad9e655..79301d9 100644
*** a/contrib/jsonb_plperl/jsonb_plperl.c
--- b/contrib/jsonb_plperl/jsonb_plperl.c
*************** SV_to_JsonbValue(SV *in, JsonbParseState
*** 188,233 ****
          case SVt_PVHV:
              return HV_to_JsonbValue((HV *) in, jsonb_state);

!         case SVt_NV:
!         case SVt_IV:
              {
!                 char       *str = sv2cstr(in);

!                 /*
!                  * Use case-insensitive comparison because infinity
!                  * representation varies across Perl versions.
!                  */
!                 if (pg_strcasecmp(str, "inf") == 0)
                      ereport(ERROR,
!                             (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                               (errmsg("cannot convert infinite value to jsonb"))));

                  out.type = jbvNumeric;
!                 out.val.numeric = DatumGetNumeric(DirectFunctionCall3(numeric_in,
!                                                                       CStringGetDatum(str), 0, -1));
              }
-             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. */
--- 188,238 ----
          case SVt_PVHV:
              return HV_to_JsonbValue((HV *) in, jsonb_state);

!         case SVt_NULL:
!             out.type = jbvNull;
!             break;
!
!         default:
!             if (SvIOK(in))
              {
!                 IV            ival = SvIV(in);

!                 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_FEATURE_NOT_SUPPORTED),
                               (errmsg("cannot convert infinite value to jsonb"))));

                  out.type = jbvNumeric;
!                 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;
              }
      }

      /* Push result into 'jsonb_state' unless it is a raw scalar. */

pgsql-committers by date:

Previous
From: Andres Freund
Date:
Subject: Re: pgsql: Add Bloom filter implementation.
Next
From: Alvaro Herrera
Date:
Subject: pgsql: Don't clone internal triggers to partitions