2011/9/23 Robert Haas <[email protected]>:
> On Fri, Sep 23, 2011 at 12:26 AM, Pavel Stehule <[email protected]>
> wrote:
>> I fixed crash that described Tom. Do you know about other?
>
> No, I just don't see a new version of the patch.
>
sorry - my mistake - I sent it only to Tom
Regards
Pavel
> --
> Robert Haas
> EnterpriseDB: http://www.enterprisedb.com
> The Enterprise PostgreSQL Company
>
*** ./src/pl/plpgsql/src/gram.y.orig 2011-09-19 10:25:28.000000000 +0200
--- ./src/pl/plpgsql/src/gram.y 2011-09-22 22:02:11.000000000 +0200
***************
*** 998,1003 ****
--- 998,1004 ----
new->dtype = PLPGSQL_DTYPE_ARRAYELEM;
new->subscript = $3;
new->arrayparentno = $1;
+ new->arraytypoid = InvalidOid;
plpgsql_adddatum((PLpgSQL_datum *) new);
*** ./src/pl/plpgsql/src/pl_exec.c.orig 2011-09-19 10:25:28.000000000 +0200
--- ./src/pl/plpgsql/src/pl_exec.c 2011-09-22 22:14:46.000000000 +0200
***************
*** 3991,4008 ****
PLpgSQL_expr *subscripts[MAXDIM];
int subscriptvals[MAXDIM];
bool oldarrayisnull;
! Oid arraytypeid,
! arrayelemtypeid;
int32 arraytypmod;
- int16 arraytyplen,
- elemtyplen;
- bool elemtypbyval;
- char elemtypalign;
Datum oldarraydatum,
coerced_value;
ArrayType *oldarrayval;
ArrayType *newarrayval;
SPITupleTable *save_eval_tuptable;
/*
* We need to do subscript evaluation, which might require
--- 3991,4004 ----
PLpgSQL_expr *subscripts[MAXDIM];
int subscriptvals[MAXDIM];
bool oldarrayisnull;
! Oid arraytypoid;
int32 arraytypmod;
Datum oldarraydatum,
coerced_value;
ArrayType *oldarrayval;
ArrayType *newarrayval;
SPITupleTable *save_eval_tuptable;
+ PLpgSQL_arrayelem *base_arrayelem;
/*
* We need to do subscript evaluation, which might require
***************
*** 4027,4032 ****
--- 4023,4030 ----
{
PLpgSQL_arrayelem *arrayelem = (PLpgSQL_arrayelem *) target;
+ base_arrayelem = arrayelem;
+
if (nsubscripts >= MAXDIM)
ereport(ERROR,
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
***************
*** 4038,4061 ****
/* Fetch current value of array datum */
exec_eval_datum(estate, target,
! &arraytypeid, &arraytypmod,
&oldarraydatum, &oldarrayisnull);
! /* If target is domain over array, reduce to base type */
! arraytypeid = getBaseTypeAndTypmod(arraytypeid, &arraytypmod);
! /* ... and identify the element type */
! arrayelemtypeid = get_element_type(arraytypeid);
! if (!OidIsValid(arrayelemtypeid))
! ereport(ERROR,
! (errcode(ERRCODE_DATATYPE_MISMATCH),
! errmsg("subscripted object is not an array")));
! get_typlenbyvalalign(arrayelemtypeid,
! &elemtyplen,
! &elemtypbyval,
! &elemtypalign);
! arraytyplen = get_typlen(arraytypeid);
/*
* Evaluate the subscripts, switch into left-to-right order.
--- 4036,4067 ----
/* Fetch current value of array datum */
exec_eval_datum(estate, target,
! &arraytypoid, &arraytypmod,
&oldarraydatum, &oldarrayisnull);
! /* If base_arrayelem has initialized metadata, then use it */
! if (base_arrayelem->arraytypoid != arraytypoid ||
! base_arrayelem->arraytypmod != arraytypmod)
! {
! /* If target is domain over array, reduce to base type */
! arraytypoid = getBaseTypeAndTypmod(arraytypoid, &arraytypmod);
! base_arrayelem->arraytypoid = arraytypoid;
! base_arrayelem->arraytypmod = arraytypmod;
! /* ... and identify the element type */
! base_arrayelem->arrayelemtypoid = get_element_type(arraytypoid);
! if (!OidIsValid(base_arrayelem->arrayelemtypoid))
! ereport(ERROR,
! (errcode(ERRCODE_DATATYPE_MISMATCH),
! errmsg("subscripted object is not an array")));
!
! get_typlenbyvalalign(base_arrayelem->arrayelemtypoid,
! &(base_arrayelem->elemtyplen),
! &(base_arrayelem->elemtypbyval),
! &(base_arrayelem->elemtypalign));
! base_arrayelem->arraytyplen = get_typlen(arraytypoid);
! }
/*
* Evaluate the subscripts, switch into left-to-right order.
***************
*** 4093,4099 ****
/* Coerce source value to match array element type. */
coerced_value = exec_simple_cast_value(value,
valtype,
! arrayelemtypeid,
arraytypmod,
*isNull);
--- 4099,4105 ----
/* Coerce source value to match array element type. */
coerced_value = exec_simple_cast_value(value,
valtype,
! base_arrayelem->arrayelemtypoid,
arraytypmod,
*isNull);
***************
*** 4107,4118 ****
* array, either, so that's a no-op too. This is all ugly but
* corresponds to the current behavior of ExecEvalArrayRef().
*/
! if (arraytyplen > 0 && /* fixed-length array? */
(oldarrayisnull || *isNull))
return;
if (oldarrayisnull)
! oldarrayval = construct_empty_array(arrayelemtypeid);
else
oldarrayval = (ArrayType *) DatumGetPointer(oldarraydatum);
--- 4113,4124 ----
* array, either, so that's a no-op too. This is all ugly but
* corresponds to the current behavior of ExecEvalArrayRef().
*/
! if (base_arrayelem->arraytyplen > 0 && /* fixed-length array? */
(oldarrayisnull || *isNull))
return;
if (oldarrayisnull)
! oldarrayval = construct_empty_array(base_arrayelem->arrayelemtypoid);
else
oldarrayval = (ArrayType *) DatumGetPointer(oldarraydatum);
***************
*** 4124,4139 ****
subscriptvals,
coerced_value,
*isNull,
! arraytyplen,
! elemtyplen,
! elemtypbyval,
! elemtypalign);
/*
* Avoid leaking the result of exec_simple_cast_value, if it
* performed a conversion to a pass-by-ref type.
*/
! if (!*isNull && coerced_value != value && !elemtypbyval)
pfree(DatumGetPointer(coerced_value));
/*
--- 4130,4145 ----
subscriptvals,
coerced_value,
*isNull,
! base_arrayelem->arraytyplen,
! base_arrayelem->elemtyplen,
! base_arrayelem->elemtypbyval,
! base_arrayelem->elemtypalign);
/*
* Avoid leaking the result of exec_simple_cast_value, if it
* performed a conversion to a pass-by-ref type.
*/
! if (!*isNull && coerced_value != value && !base_arrayelem->elemtypbyval)
pfree(DatumGetPointer(coerced_value));
/*
***************
*** 4145,4151 ****
*isNull = false;
exec_assign_value(estate, target,
PointerGetDatum(newarrayval),
! arraytypeid, isNull);
/*
* Avoid leaking the modified array value, too.
--- 4151,4157 ----
*isNull = false;
exec_assign_value(estate, target,
PointerGetDatum(newarrayval),
! arraytypoid, isNull);
/*
* Avoid leaking the modified array value, too.
*** ./src/pl/plpgsql/src/plpgsql.h.orig 2011-09-19 10:25:28.000000000 +0200
--- ./src/pl/plpgsql/src/plpgsql.h 2011-09-22 22:11:10.000000000 +0200
***************
*** 299,304 ****
--- 299,311 ----
int dno;
PLpgSQL_expr *subscript;
int arrayparentno; /* dno of parent array variable */
+ Oid arraytypoid; /* oid of arraytype */
+ int32 arraytypmod; /* tymod of arraytype */
+ int16 arraytyplen; /* typlen of arraytype */
+ Oid arrayelemtypoid; /* oid of element type */
+ bool elemtypbyval; /* true when elementtype use byval copy */
+ int16 elemtyplen; /* size of element value */
+ char elemtypalign; /* align of element type */
} PLpgSQL_arrayelem;
*** ./src/test/regress/expected/plpgsql.out.orig 2011-09-19 10:25:28.000000000 +0200
--- ./src/test/regress/expected/plpgsql.out 2011-09-22 23:04:39.000000000 +0200
***************
*** 4509,4511 ****
--- 4509,4528 ----
drop function foreach_test(anyarray);
drop type xy_tuple;
+ create table rtype (id int, ar text[]);
+ create or replace function foo() returns text[] language plpgsql as $$
+ declare
+ r record;
+ begin
+ r := row(12, '{foo,bar,baz}')::rtype;
+ r.ar[2] := 'replace';
+ return r.ar;
+ end$$;
+ select foo();
+ foo
+ -------------------
+ {foo,replace,baz}
+ (1 row)
+
+ drop function foo();
+ drop table rtype;
*** ./src/test/regress/sql/plpgsql.sql.orig 2011-09-22 23:02:16.442135414 +0200
--- ./src/test/regress/sql/plpgsql.sql 2011-09-22 23:04:11.733364057 +0200
***************
*** 3559,3561 ****
--- 3559,3577 ----
drop function foreach_test(anyarray);
drop type xy_tuple;
+
+ create table rtype (id int, ar text[]);
+
+ create or replace function foo() returns text[] language plpgsql as $$
+ declare
+ r record;
+ begin
+ r := row(12, '{foo,bar,baz}')::rtype;
+ r.ar[2] := 'replace';
+ return r.ar;
+ end$$;
+
+ select foo();
+
+ drop function foo();
+ drop table rtype;
--
Sent via pgsql-hackers mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers