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 ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers