Hello

this patch significantly reduce a ccache searching. On my test - bubble sort

postgres=# \sf buble
CREATE OR REPLACE FUNCTION public.buble(integer[])
 RETURNS integer[]
 LANGUAGE plpgsql
AS $function$
declare
  unsorted bool := true;
  aux int;
begin
  while unsorted
  loop
    unsorted := false;
    for i in array_lower($1,1) .. array_upper($1,1) - 1
    loop
      if $1[i] > $1[i+1] then
        aux := $1[i];
        $1[i] := $1[i+1]; $1[i+1] := aux;
        unsorted := true;
      end if;
    end loop;
  end loop;
  return $1;
end;
$function$ immutable

it decrease evaluation time about 15%.

Regards

Pavel Stehule

p.s. I know so bubble sort is not effective for large arrays. This
algorithm was used because a array is intensive modified.
*** ./pl_exec.c.orig	2011-06-20 08:55:37.000000000 +0200
--- ./pl_exec.c	2011-06-20 11:38:55.988650907 +0200
***************
*** 153,158 ****
--- 153,170 ----
  static void exec_assign_value(PLpgSQL_execstate *estate,
  				  PLpgSQL_datum *target,
  				  Datum value, Oid valtype, bool *isNull);
+ static void
+ exec_eval_array_datum(PLpgSQL_execstate *estate,
+ 				PLpgSQL_datum *datum,
+ 				Oid *arraytypoid,
+ 				int32 *arraytypmod,
+ 				int16 *arraytyplen,
+ 				Oid *elemtypeid,
+ 				int16 *elemtyplen,
+ 				bool *elemtybyval,
+ 				char *elemtypalign,
+ 				Datum *value,
+ 				bool *isnull);
  static void exec_eval_datum(PLpgSQL_execstate *estate,
  				PLpgSQL_datum *datum,
  				Oid *typeid,
***************
*** 3981,4001 ****
  								&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.
--- 3993,4009 ----
  								&arraytypeid, &arraytypmod,
  								&oldarraydatum, &oldarrayisnull);
  
! 				/* Fetch current value of array datum and metadata */
! 				exec_eval_array_datum(estate, target,
! 								&arraytypeid,
! 								&arraytypmod,
! 								&arraytyplen,
! 										 &arrayelemtypeid,
! 										 &elemtyplen,
! 										 &elemtypbyval,
! 										 &elemtypalign,
! 												&oldarraydatum,
! 												&oldarrayisnull);
  
  				/*
  				 * Evaluate the subscripts, switch into left-to-right order.
***************
*** 4099,4104 ****
--- 4107,4178 ----
  	}
  }
  
+ 
+ /*
+  * exec_eval_array_datum			Get current value of PLpgSQL_datum
+  *
+  * The type oid, typmod, value in Datum format, and null flag are returned.
+  * The arraytyplen, elemtyplen, elemtypbyval, elemtypalign are returned.
+  *
+  * This routine is is used for array type variables - returns additional info
+  * about array elements - removes useless search inside ccache.
+  */ 
+ static void
+ exec_eval_array_datum(PLpgSQL_execstate *estate,
+ 				PLpgSQL_datum *datum,
+ 				Oid *arraytypoid,
+ 				int32 *arraytypmod,
+ 				int16 *arraytyplen,
+ 				Oid *elemtypeid,
+ 				int16 *elemtyplen,
+ 				bool *elemtybyval,
+ 				char *elemtypalign,
+ 				Datum *value,
+ 				bool *isnull)
+ {
+ 	PLpgSQL_var *var = (PLpgSQL_var *) datum;
+ 
+ 	Assert(datum->dtype == PLPGSQL_DTYPE_VAR);
+ 
+ 	if (var->array_desc == NULL)
+ 	{
+ 		PLpgSQL_array_desc *array_desc = (PLpgSQL_array_desc *) palloc(sizeof(PLpgSQL_array_desc));
+ 
+ 		array_desc->arraytypoid = var->datatype->typoid;
+ 		array_desc->arraytypmod = var->datatype->atttypmod;
+ 
+ 		/* If target is domain over array, reduce to base type */
+ 		array_desc->arraytypoid = getBaseTypeAndTypmod(array_desc->arraytypoid, 
+ 									    &array_desc->arraytypmod);
+ 
+ 		array_desc->elemtypoid = get_element_type(array_desc->arraytypoid);
+ 		if (!OidIsValid(array_desc->elemtypoid))
+ 			ereport(ERROR,
+ 					(errcode(ERRCODE_DATATYPE_MISMATCH),
+ 					 errmsg("subscripted object is not an array")));
+ 
+ 		get_typlenbyvalalign(array_desc->elemtypoid,
+ 							 &array_desc->elemtyplen,
+ 							 &array_desc->elemtypbyval,
+ 							 &array_desc->elemtypalign);
+ 		array_desc->arraytyplen = get_typlen(array_desc->arraytypoid);
+ 
+ 		var->array_desc = array_desc;
+ 	}
+ 
+ 	*arraytypoid = var->array_desc->arraytypoid;
+ 	*arraytypmod = var->array_desc->arraytypmod;
+ 	*arraytyplen = var->array_desc->arraytyplen;
+ 
+ 	*elemtypeid = var->array_desc->elemtypoid;
+ 	*elemtyplen = var->array_desc->elemtyplen;
+ 	*elemtybyval = var->array_desc->elemtypbyval;
+ 	*elemtypalign = var->array_desc->elemtypalign;
+ 
+ 	*value = var->value;
+ 	*isnull = var->isnull;
+ }
+ 
  /*
   * exec_eval_datum				Get current value of a PLpgSQL_datum
   *
*** ./plpgsql.h.orig	2011-06-20 08:55:37.000000000 +0200
--- ./plpgsql.h	2011-06-20 11:17:10.943993153 +0200
***************
*** 172,177 ****
--- 172,191 ----
  	int32		atttypmod;		/* typmod (taken from someplace else) */
  } PLpgSQL_type;
  
+ /*
+  * PLpgSQL_array_desc holds a metadata about array and array's element stored
+  * in some variable.
+  */
+ typedef struct
+ {
+ 	Oid		arraytypoid;
+ 	int32		arraytypmod;
+ 	int16		arraytyplen;
+ 	Oid			elemtypoid;
+ 	bool			elemtypbyval;
+ 	int16			elemtyplen;
+ 	char			elemtypalign;
+ } PLpgSQL_array_desc;
  
  /*
   * PLpgSQL_datum is the common supertype for PLpgSQL_expr, PLpgSQL_var,
***************
*** 234,239 ****
--- 248,254 ----
  	int			lineno;
  
  	PLpgSQL_type *datatype;
+ 	PLpgSQL_array_desc *array_desc;
  	int			isconst;
  	int			notnull;
  	PLpgSQL_expr *default_val;
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to