út 30. 1. 2024 v 17:46 odesílatel Dagfinn Ilmari Mannsåker <
ilm...@ilmari.org> napsal:

> Pavel Stehule <pavel.steh...@gmail.com> writes:
>
> > út 30. 1. 2024 v 17:18 odesílatel Dagfinn Ilmari Mannsåker <
> > ilm...@ilmari.org> napsal:
> >
> >> Pavel Stehule <pavel.steh...@gmail.com> writes:
> >>
> >> > út 30. 1. 2024 v 16:43 odesílatel Dagfinn Ilmari Mannsåker <
> >> > ilm...@ilmari.org> napsal:
> >> >
> >> >> Pavel Stehule <pavel.steh...@gmail.com> writes:
> >> >>
> >> >> > I inserted perl reference support - hstore_plperl and json_plperl
> does
> >> >> it.
> >> >> >
> >> >> > +<->/* Dereference references recursively. */
> >> >> > +<->while (SvROK(in))
> >> >> > +<-><-->in = SvRV(in);
> >> >>
> >> >> That code in hstore_plperl and json_plperl is only relevant because
> they
> >> >> deal with non-scalar values (hashes for hstore, and also arrays for
> >> >> json) which must be passed as references.  The recursive nature of
> the
> >> >> dereferencing is questionable, and masked the bug fixed by commit
> >> >> 1731e3741cbbf8e0b4481665d7d523bc55117f63.
> >> >>
> >> >> bytea_plperl only deals with scalars (specifically strings), so
> should
> >> >> not concern itself with references.  In fact, this code breaks
> returning
> >> >> objects with overloaded stringification, for example:
> >> >>
> >> >> CREATE FUNCTION plperlu_overload() RETURNS bytea LANGUAGE plperlu
> >> >>   TRANSFORM FOR TYPE bytea
> >> >>   AS $$
> >> >>     package StringOverload { use overload '""' => sub { "stuff" }; }
> >> >>     return bless {}, "StringOverload";
> >> >>   $$;
> >> >>
> >> >> This makes the server crash with an assertion failure from Perl
> because
> >> >> SvPVbyte() was passed a non-scalar value:
> >> >>
> >> >> postgres: ilmari regression_bytea_plperl [local] SELECT: sv.c:2865:
> >> >> Perl_sv_2pv_flags:
> >> >> Assertion `SvTYPE(sv) != SVt_PVAV && SvTYPE(sv) != SVt_PVHV &&
> >> SvTYPE(sv)
> >> >> != SVt_PVFM' failed.
> >> >>
> >> >> If I remove the dereferincing loop it succeeds:
> >> >>
> >> >> SELECT encode(plperlu_overload(), 'escape') AS string;
> >> >>  string
> >> >> --------
> >> >>  stuff
> >> >> (1 row)
> >> >>
> >> >> Attached is a v2 patch which removes the dereferencing and includes
> the
> >> >> above example as a test.
> >> >>
> >> >
> >> > But without dereference it returns bad value.
> >>
> >> Where exactly does it return a bad value?  The existing tests pass, and
> >> the one I included shows that it does the right thing in that case too.
> >> If you pass it an unblessed reference it returns the stringified version
> >> of that, as expected.
> >>
> >
> > ugly test code
> >
> > (2024-01-30 13:44:28) postgres=# CREATE or replace FUNCTION
> > perl_inverse_bytes(bytea) RETURNS bytea
> > TRANSFORM FOR TYPE bytea
> > AS $$ my $bytes =  pack 'H*', '0123'; my $ref = \$bytes;
>
> You are returning a reference, not a string.
>

I know, but for this case, should not be raised an error?


>
> > return $ref;
> > $$ LANGUAGE plperlu;
> > CREATE FUNCTION
> > (2024-01-30 13:44:33) postgres=# select perl_inverse_bytes(''), '
> '::bytea;
> > ┌──────────────────────────────────────┬───────┐
> > │          perl_inverse_bytes          │ bytea │
> > ╞══════════════════════════════════════╪═══════╡
> > │ \x5343414c41522830783130656134333829 │ \x20  │
> > └──────────────────────────────────────┴───────┘
> > (1 row)
>
> ~=# select encode('\x5343414c41522830783130656134333829', 'escape');
> ┌───────────────────┐
> │      encode       │
> ├───────────────────┤
> │ SCALAR(0x10ea438) │
> └───────────────────┘
>
> This is how Perl stringifies references in the absence of overloading.
> Return the byte string directly from your function and it will do the
> right thing:
>
> CREATE FUNCTION plperlu_bytes() RETURNS bytea LANGUAGE plperlu
>  TRANSFORM FOR TYPE bytea
>  AS $$ return pack  'H*', '0123'; $$;
>
> SELECT plperlu_bytes();
>  plperlu_bytes
> ---------------
>  \x0123
> (1 row)
>
>
> - ilmari
>

Reply via email to