On Mon, May 23, 2011 at 14:59, Greg Sabino Mullane <[email protected]> wrote:
> I've not been able to duplicate this in a standalone script yet,
> but in the guts of Bucardo is a trigger function called validate_goat()
> that is giving this error on 9.1 HEAD, but not on previous versions:
>
> "Failed to add table "public.pgbench_tellers": DBD::Pg::st execute
> failed: ERROR: Modification of non-creatable hash value attempted,
> subscript "pkey" at line 4."
> ...
> Some Googling suggests it might
> be because we are using &PL_sv_undef instead of a proper
> newSV(0).
Yep. Per
http://search.cpan.org/~jesse/perl-5.14.0/pod/perlguts.pod#AVs,_HVs_and_undefined_values
|...For example, intuition tells you that this XS code:
|
| AV *av = newAV();
| av_store( av, 0, &PL_sv_undef );
|
| is equivalent to this Perl code:
|
| my @av;
| $av[0] = undef;
| Unfortunately, this isn't true. AVs use &PL_sv_undef as a marker for
indicating that an array element has not yet been initialized.
We have a few places that have that pattern :-(.
I was able to reproduce it fairly easily(1) by passing in NULL values
explicitly. Fixed in the attached.
I looked at 9.0 and below and they did this correctly. This code path
was heavily re-factored in 9.1 for better array and composite type
support . As noted in perlguts using &PL_sv_undef follows your
intuition, but its wrong :-(. Classic perl xs I suppose.
Greg, can you confirm the attached fixes it for you?
--
[1]
=> create or replace function td() returns trigger language plperlu as
$bc$
$_TD->{new}{a} = 1;
return 'MODIFY';
$bc$;
CREATE FUNCTION
=> create table trig_test(a int);
CREATE TABLE
=> create trigger test_trig before insert on trig_test for each row
execute procedure td();
CREATE TRIGGER
=> insert into trig_test values (NULL);
CONTEXT: PL/Perl function "td"
ERROR: Modification of non-creatable hash value attempted, subscript
"a" at line 2.
*** a/src/pl/plperl/plperl.c
--- b/src/pl/plperl/plperl.c
***************
*** 1357,1363 **** make_array_ref(plperl_array_info *info, int first, int last)
for (i = first; i < last; i++)
{
if (info->nulls[i])
! av_push(result, &PL_sv_undef);
else
{
Datum itemvalue = info->elements[i];
--- 1357,1366 ----
for (i = first; i < last; i++)
{
if (info->nulls[i])
! {
! /* We cant use &PL_sv_undef here... see perlguts */
! av_push(result, newSV(0));
! }
else
{
Datum itemvalue = info->elements[i];
***************
*** 2639,2646 **** plperl_hash_from_tuple(HeapTuple tuple, TupleDesc tupdesc)
if (isnull)
{
! /* Store (attname => undef) and move on. */
! hv_store_string(hv, attname, &PL_sv_undef);
continue;
}
--- 2642,2652 ----
if (isnull)
{
! /*
! * Store (attname => undef) and move on. Note, we cant use
! * &PL_sv_undef here... see perlguts for more
! */
! hv_store_string(hv, attname, newSV(0));
continue;
}
--
Sent via pgsql-bugs mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-bugs