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