agora inbox for [email protected]  
help / color / mirror / Atom feed
From: Dagfinn Ilmari Mannsåker <[email protected]>
To: Pavel Stehule <[email protected]>
Cc: vignesh C <[email protected]>
Cc: Ivan Panchenko <[email protected]>
Cc: Tom Lane <[email protected]>
Cc: Peter Eisentraut <[email protected]>
Cc: [email protected]
Cc: Greg Sabino Mullane <[email protected]>
Subject: Re: Bytea PL/Perl transform
Date: Tue, 30 Jan 2024 16:46:10 +0000
Message-ID: <[email protected]> (raw)
In-Reply-To: <CAFj8pRAWUEDXHtMj3aNKxunTEeQtweQ_wE5wad469d_B2-3TOQ@mail.gmail.com>
References: <[email protected]>
	<[email protected]>
	<[email protected]>
	<[email protected]>
	<CALDaNm0GWMdDPtJq6XN3vurE2=YcBkOKGpTWbRrpm9T21A5+rA@mail.gmail.com>
	<CAFj8pRB24y1VPNbB3Ej5UK+3-Qp7-TxYtFKdJj6dwqZVAim7=A@mail.gmail.com>
	<[email protected]>
	<CAFj8pRAC-+ce7b4RPOYOcO+NfBO8hH-cZbOjS8cPsPgu49vAgg@mail.gmail.com>
	<[email protected]>
	<CAFj8pRAWUEDXHtMj3aNKxunTEeQtweQ_wE5wad469d_B2-3TOQ@mail.gmail.com>

Pavel Stehule <[email protected]> writes:

> út 30. 1. 2024 v 17:18 odesílatel Dagfinn Ilmari Mannsåker <
> [email protected]> napsal:
>
>> Pavel Stehule <[email protected]> writes:
>>
>> > út 30. 1. 2024 v 16:43 odesílatel Dagfinn Ilmari Mannsåker <
>> > [email protected]> napsal:
>> >
>> >> Pavel Stehule <[email protected]> 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.

> 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





view thread (15+ messages)  latest in thread

reply

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Reply to all the recipients using the --to and --cc options:
  reply via email

  To: [email protected]
  Cc: [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected]
  Subject: Re: Bytea PL/Perl transform
  In-Reply-To: <[email protected]>

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox