2011/9/23 Robert Haas <robertmh...@gmail.com>: > On Fri, Sep 23, 2011 at 12:26 AM, Pavel Stehule <pavel.steh...@gmail.com> > 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 (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers