Monday, June 30, 2008

[pgsql-es-ayuda] SRF en lenguaje C.... Jerarquia

Que tal lista

tengo una relación jerárquica en una tabla implementada con
nested-interval utilizando secuencias de farey. Utilice la
implementación que tiene a modo de ejemplo en la documentación de
postgres para los números racionales; para obtener la ascendencia
directa de un nodo utilizo un algoritmo que esta implementado en la
siguiente SRF en lenguaje C

Datum
obtAscendencia(PG_FUNCTION_ARGS)
{
FuncCallContext *funcctx;

intervaloFarey *intF; //intervalo de Farey que subexiste
durente
//la gneracion de lo jerarqui
Racional *r = NULL;//el resultado de obtPadre

Racional *pi; //padre inicial

TupleDesc tupdesc;
AttInMetadata *attinmeta;

/* stuff done only on the first call of the function */
if (SRF_IS_FIRSTCALL())
{
MemoryContext oldcontext;

intF = (intervaloFarey *)
palloc(sizeof(intervaloFarey));//fjmb

//guardamos el padre
pi = (Racional *) PG_GETARG_POINTER(0);
intF->izq.num = pi->num;
intF->izq.den = pi->den;

pi = (Racional *) PG_GETARG_POINTER(1);
intF->der.num = pi->num;
intF->der.den = pi->den;


/* create a function context for cross-call persistence */
funcctx = SRF_FIRSTCALL_INIT();

//memeoria fija durante la generacion de la descendencia directa
funcctx->user_fctx = intF;

/* switch to memory context appropriate for multiple function
calls */
oldcontext =
MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);


/* Build a tuple descriptor for our result type */
if (get_call_result_type(fcinfo, NULL, &tupdesc) !=
TYPEFUNC_COMPOSITE)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("function returning record called in context
"
"that cannot accept type record")));

/*
* generate attribute metadata needed later to produce tuples
from raw
* C strings
*/
attinmeta = TupleDescGetAttInMetadata(tupdesc);
funcctx->attinmeta = attinmeta;

MemoryContextSwitchTo(oldcontext);
}

/* stuff done on every call of the function */
funcctx = SRF_PERCALL_SETUP();

intF = funcctx->user_fctx;//fjmb

attinmeta = funcctx->attinmeta;

r = obtPadre( &intF->izq, &intF->der );

if ( ( r->num != 1 ) &&
( r->den != 2 ) )
{
char **strRel;
HeapTuple tuple;
Datum result;

/* elog(INFO, "Enviando izq: %d,%d der: %d,%d ",
intF->izq.num,
intF->izq.den,
intF->der.num,
intF->der.den
);*/


//actualizamos la memoria fija durante
//el retorno de los nodos generado
//(ver documentacion de funciones SRF)
intF->der.num = intF->izq.num;
intF->der.den = intF->izq.den;
intF->izq.num = r->num;
intF->izq.den = r->den;


strRel = (char **) palloc(1 * sizeof(char *));
strRel[0] = (char *) palloc( 100 );

snprintf(strRel[0], 100, "(%d,%d)", r->num, r->den);

tuple = BuildTupleFromCStrings(attinmeta, strRel );

/* make the tuple into a datum */
result = HeapTupleGetDatum(tuple);

/* clean up (this is not really necessary) */
pfree(strRel[0]);
pfree(strRel);

SRF_RETURN_NEXT(funcctx, result);
}
else /* do when there is no more left */
{
SRF_RETURN_DONE(funcctx);
}
}

la declaración de esta función es la siguiente:


CREATE TYPE reg_racional AS ( izq Racional );

CREATE OR REPLACE FUNCTION obtAscendencia( racional, racional )
RETURNS SETOF reg_racional
AS '/usr/lib/postgresql/farey', 'obtAscendencia'
LANGUAGE C IMMUTABLE STRICT;


Todo funciona correctamente con la siguiente sentencia en psql

pba=# select obtascendencia ('(11099,15685)','(6808,9621)');

obtascendencia
------------------
("(4291, 6064)")
("(1774, 2507)")
("(1031, 1457)")
("(288, 407)")
("(121, 171)")
("(75, 106)")
("(29, 41)")
("(12, 17)")
("(7, 10)")
("(2, 3)")


pero si ejecuto:

pba=# select * from obtascendencia ('(11099,15685)','(6808,9621)');

se queda colgada la consulta ... (tengo que matar el proceso desde otra
terminal) ... ¿cómo puede resolver este problema?

Estoy investigando ... si alguien puede orientarme se los agradeceré


Saludos cordiales

PD. si a alguien le interesa el código completo con gusto se los envío

--
TIP 4: No hagas 'kill -9' a postmaster

No comments: