*** ./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);
  
