------=_Part_7970_28385420.1204228431243
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: 7bit
Content-Disposition: inline
I have written a PostgreSQL 8.3beta2 server side function named
array_times_scalar (source included below). It works, but I haven't found
sufficient examples to be certain that I am not leaking memory. I was
wondering if someone can either point me to examples or take a look at the
code below.
I am, however, getting incorrect values if I select a particular array
index
out of the result of this function. That is, "select
(array_times_scalar('{344,52,25}'::smallint[],0.001::double
precision))[1];"
is not the same as the first element of "select
array_times_scalar('{344,52,25}'::smallint[],0.001::double precision);". I
was hoping if someone could shed a light on why that may be.
As a side-note: I've written similar function in plpgsql, which produces
correct results when I extract any element of the returned array. However,
I
need the speed of a C-function since this function may be run on millions
of
records at a time.
Thanks.
create or replace function array_times_scalar(smallint[], double
precision)
returns real[]
as '/var/lib/pgsql/test_func','array_times_scalar' language C immutable
strict;
Datum array_times_scalar(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1(array_times_scalar);
/**
** Returns the input array with every element multiplied
** by the specified scale.
**/
Datum
array_times_scalar(PG_FUNCTION_ARGS){
ArrayType *input;
Datum *i_data;
bool *nulls;
float8 scale = 0;
ArrayType *result;
Datum *result_data;
int ndims, *dims, *lbs;
Oid i_eltype, s_eltype, o_eltype;
int16 i_typlen, o_typlen;
bool i_typbyval, o_typbyval;
char i_typalign, o_typalign;
int i, n;
/* return null on null input */
if (PG_ARGISNULL(0) || PG_ARGISNULL(1)){
PG_RETURN_NULL();
}
/* get input args */
input = PG_GETARG_ARRAYTYPE_P(0);
/* get input array element type */
i_eltype = ARR_ELEMTYPE(input);
get_typlenbyvalalign(i_eltype, &i_typlen, &i_typbyval,
&i_typalign);
/* validate input data type */
switch(i_eltype){
case INT2OID:
case INT4OID:
case FLOAT4OID:
case FLOAT8OID:
break;
default:
elog(ERROR, "Invalid input data type");
break;
}
/* get scale data type */
s_eltype = get_fn_expr_argtype(fcinfo->flinfo, 1);
/* validate the scale data type */
switch(s_eltype){
case INT2OID: scale = PG_GETARG_INT16(1); break;
case INT4OID: scale = PG_GETARG_INT32(1); break;
case FLOAT4OID: scale = PG_GETARG_FLOAT4(1); break;
case FLOAT8OID: scale = PG_GETARG_FLOAT8(1); break;
default:
elog(ERROR, "Invalid scale type");
break;
}
/* get output array element type */
if (i_eltype == FLOAT8OID || s_eltype == FLOAT8OID){
o_eltype = FLOAT8OID;
}
else if (i_eltype == FLOAT4OID || s_eltype == FLOAT4OID){
o_eltype = FLOAT4OID;
}
else {
o_eltype = INT4OID;
}
get_typlenbyvalalign(o_eltype, &o_typlen, &o_typbyval,
&o_typalign);
/* get various pieces of data from the input array */
ndims = ARR_NDIM(input);
dims = ARR_DIMS(input);
lbs = ARR_LBOUND(input);
/* get src data */
deconstruct_array(input, i_eltype, i_typlen, i_typbyval,
i_typalign,
&i_data, &nulls, &n);
/* construct result array */
result_data = (Datum *)palloc(n * sizeof(Datum));
/* apply scale */
for(i=0; i<n; i++){
if (nulls[i]){
result_data[i] = PointerGetDatum(NULL);
}
else {
double v = 0;
switch(i_eltype){
case INT2OID: v = DatumGetInt16(i_data[i]);
break;
case INT4OID: v = DatumGetInt32(i_data[i]);
break;
case FLOAT4OID: v = DatumGetFloat4(i_data[i]);
break;
case FLOAT8OID: v = DatumGetFloat8(i_data[i]);
break;
}
v *= scale;
switch(o_eltype){
case INT4OID: result_data[i] =
Int32GetDatum((int32)v); break;
case FLOAT4OID: result_data[i] =
Float4GetDatum((float4)v); break;
case FLOAT8OID: result_data[i] =
Float8GetDatum((float8)v); break;
}
}
}
result = construct_md_array((void *)result_data, nulls, ndims,
dims,
lbs, o_eltype, o_typlen, o_typbyval, o_typalign);
pfree(i_data);
pfree(result_data);
pfree(nulls);
PG_RETURN_ARRAYTYPE_P(result);
}
------=_Part_7970_28385420.1204228431243
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: 7bit
Content-Disposition: inline
I
have written a PostgreSQL 8.3beta2 server side function named
array_times_scalar (source included below). It works, but I haven't
found sufficient examples to be certain that I am not leaking memory. I
was wondering if someone can either point me to examples or take a
look at the code below.<br><br>I am, however, getting incorrect values if
I select a particular
array index out of the result of this function. That is, "select
(array_times_scalar('{344,52,25}'::smallint[],0.001::double
precision))[1];"
is not the same as the first element of "select
array_times_scalar('{344,52,25}'::smallint[],0.001::double
precision);". I was hoping if someone could shed a light on
why that may be.<br><br>As a side-note: I've written similar function
in plpgsql, which produces correct results when I extract any element of
the returned array. However, I need the speed of a C-function since this
function may be run on millions of records at a time.<br>
<br>Thanks.<br><br><br>create or replace function
array_times_scalar(smallint[], double precision) returns real[] <br>as
'/var/lib/pgsql/test_func',<div>'array_times_scalar'
language C immutable strict;<br>
<br>Datum array_times_scalar(PG_FUNCTION_ARGS);<br>
PG_FUNCTION_INFO_V1(array_times_scalar);<br><br>/**<br> ** Returns
the input array with every element multiplied<br> ** by the specified
scale.<br> **/<br>Datum<br>array_times_scalar(PG_FUNCTION_ARGS){<br>
ArrayType *input;<br>
Datum
*i_data;<br>
bool
*nulls;<br>
float8 scale =
0;<br> ArrayType
*result;<br>
Datum
*result_data;<br>
int ndims, *dims,
*lbs;<br>
Oid i_eltype, s_eltype,
o_eltype;<br>
int16 i_typlen,
o_typlen;<br>
bool i_typbyval,
o_typbyval;<br>
char i_typalign,
o_typalign;<br>
int i,
n;<br><br> /* return null on
null input */<br> if
(PG_ARGISNULL(0) || PG_ARGISNULL(1)){<br>
PG_RETURN_NULL();<br>
}<br><br> /* get input args
*/<br> input =
PG_GETARG_ARRAYTYPE_P(0);<br><br>
/* get input array element type
*/<br> i_eltype =
ARR_ELEMTYPE(input);<br>
get_typlenbyvalalign(i_eltype,
&i_typlen, &i_typbyval,
&i_typalign);<br><br> /*
validate input data type */<br>
switch(i_eltype){<br> case
INT2OID:<br> case
INT4OID:<br> case FLOAT4OID:<br>
case
FLOAT8OID:<br>
break;<br>
default:<br>
elog(ERROR, "Invalid input data
type");<br>
break;<br>
}<br><br> /* get scale data type
*/<br>
s_eltype =
get_fn_expr_argtype(fcinfo->flinfo,
1);<br><br> /* validate the
scale data type */<br>
switch(s_eltype){<br> case
INT2OID: scale = PG_GETARG_INT16(1);
break;<br> case
INT4OID: scale = PG_GETARG_INT32(1); break;<br>
case FLOAT4OID: scale =
PG_GETARG_FLOAT4(1); break;<br>
case FLOAT8OID: scale = PG_GETARG_FLOAT8(1);
break;<br>
default:<br>
elog(ERROR, "Invalid scale
type");<br>
break;<br>
}<br><br> /* get output array
element type */<br> if (i_eltype
== FLOAT8OID || s_eltype ==
FLOAT8OID){<br>
o_eltype = FLOAT8OID;<br>
}<br> else if (i_eltype ==
FLOAT4OID || s_eltype == FLOAT4OID){<br>
o_eltype = FLOAT4OID;<br>
}<br> else
{<br>
o_eltype = INT4OID;<br>
}<br>
get_typlenbyvalalign(o_eltype, &o_typlen, &o_typbyval,
&o_typalign);<br><br>
/* get various pieces of data
from the input array */<br>
ndims =
ARR_NDIM(input);<br> dims =
ARR_DIMS(input);<br> lbs =
ARR_LBOUND(input);<br><br> /*
get src data */<br>
deconstruct_array(input, i_eltype, i_typlen, i_typbyval, i_typalign,
&i_data, &nulls, &n);<br>
<br> /* construct result array
*/<br> result_data = (Datum
*)palloc(n *
sizeof(Datum));<br><br> /* apply
scale */<br> for(i=0; i<n;
i++){<br>
if
(nulls[i]){<br>
result_data[i] = PointerGetDatum(NULL);<br>
}<br>
else
{<br>
double v =
0;<br><br>
switch(i_eltype){<br>
case INT2OID: v = DatumGetInt16(i_data[i]);
break;<br>
case INT4OID: v = DatumGetInt32(i_data[i]); break;<br>
case FLOAT4OID: v = DatumGetFloat4(i_data[i]);
break;<br>
case FLOAT8OID: v = DatumGetFloat8(i_data[i]);
break;<br>
}<br><br>
v *= scale;<br>
<br>
switch(o_eltype){<br>
case INT4OID: result_data[i] = Int32GetDatum((int32)v);
break;<br>
case FLOAT4OID: result_data[i] = Float4GetDatum((float4)v); break;<br>
case FLOAT8OID: result_data[i] = Float8GetDatum((float8)v);
break;<br>
}<br>
}<br>
}<br><br> result =
construct_md_array((void *)result_data, nulls, ndims, dims, lbs, o_eltype,
o_typlen, o_typbyval, o_typalign);<br>
<br>
pfree(i_data);<br>
pfree(result_data);<br>
pfree(nulls);<br><br>
PG_RETURN_ARRAYTYPE_P(result);<br>}</div>
------=_Part_7970_28385420.1204228431243--


|