*** ./src/backend/utils/adt/arrayfuncs.c.orig 2013-10-03 20:54:36.725985694 +0200 --- ./src/backend/utils/adt/arrayfuncs.c 2013-10-03 20:53:50.700605494 +0200 *************** *** 1841,1846 **** --- 1841,1935 ---- } + char * + array_ref_ref(ArrayType *array, + int nSubscripts, + int *indx, + int arraytyplen, + int elmlen, + bool elmbyval, + char elmalign, + bool *isNull) + { + int i, + ndim, + *dim, + *lb, + offset, + fixedDim[1], + fixedLb[1]; + char *arraydataptr, + *retptr; + bits8 *arraynullsptr; + + if (arraytyplen > 0) + { + /* + * fixed-length arrays -- these are assumed to be 1-d, 0-based + */ + ndim = 1; + fixedDim[0] = arraytyplen / elmlen; + fixedLb[0] = 0; + dim = fixedDim; + lb = fixedLb; + arraydataptr = (char *) array; + arraynullsptr = NULL; + } + else + { + /* detoast input array if necessary */ + array = DatumGetArrayTypeP(PointerGetDatum(array)); + + ndim = ARR_NDIM(array); + dim = ARR_DIMS(array); + lb = ARR_LBOUND(array); + arraydataptr = ARR_DATA_PTR(array); + arraynullsptr = ARR_NULLBITMAP(array); + } + + /* + * Return NULL for invalid subscript + */ + if (ndim != nSubscripts || ndim <= 0 || ndim > MAXDIM) + { + *isNull = true; + return (Datum) 0; + } + for (i = 0; i < ndim; i++) + { + if (indx[i] < lb[i] || indx[i] >= (dim[i] + lb[i])) + { + *isNull = true; + return (Datum) 0; + } + } + + /* + * Calculate the element number + */ + offset = ArrayGetOffset(nSubscripts, dim, lb, indx); + + /* + * Check for NULL array element + */ + if (array_get_isnull(arraynullsptr, offset)) + { + *isNull = true; + return (Datum) 0; + } + + /* + * OK, get the element + */ + *isNull = false; + retptr = array_seek(arraydataptr, 0, arraynullsptr, offset, + elmlen, elmbyval, elmalign); + + return retptr; + } + + + /* * array_get_slice : * This routine takes an array and a range of indices (upperIndex and *** ./src/pl/plpgsql/src/pl_exec.c.orig 2013-04-01 20:20:36.000000000 +0200 --- ./src/pl/plpgsql/src/pl_exec.c 2013-10-03 21:49:09.932043358 +0200 *************** *** 3992,3997 **** --- 3992,4000 ---- SPITupleTable *save_eval_tuptable; MemoryContext oldcontext; + char *refptr; + bool fast_update = false; + /* * We need to do subscript evaluation, which might require * evaluating general expressions; and the caller might have *************** *** 4139,4153 **** /* * Build the modified array value. */ ! newarrayval = array_set(oldarrayval, nsubscripts, subscriptvals, - coerced_value, - *isNull, arrayelem->arraytyplen, arrayelem->elemtyplen, arrayelem->elemtypbyval, ! arrayelem->elemtypalign); MemoryContextSwitchTo(oldcontext); --- 4142,4180 ---- /* * Build the modified array value. */ ! ! /* only for fixed length types and types referenced by val */ ! if (arrayelem->elemtyplen > 0 ! && target->dtype == PLPGSQL_DTYPE_VAR && ((PLpgSQL_var *)target)->freeval ! && !*isNull) ! { ! refptr = array_ref_ref(oldarrayval, nsubscripts, subscriptvals, arrayelem->arraytyplen, arrayelem->elemtyplen, arrayelem->elemtypbyval, ! arrayelem->elemtypalign, ! isNull); ! if (!*isNull) ! { ! //elog(NOTICE, "try to fast update"); ! fast_update = true; ! memcpy(refptr, &coerced_value, arrayelem->elemtyplen); ! break; ! } ! } ! ! if (!fast_update) ! newarrayval = array_set(oldarrayval, ! nsubscripts, ! subscriptvals, ! coerced_value, ! *isNull, ! arrayelem->arraytyplen, ! arrayelem->elemtyplen, ! arrayelem->elemtypbyval, ! arrayelem->elemtypalign); MemoryContextSwitchTo(oldcontext);