Skip site navigation (1) Skip section navigation (2)

SRF en lenguaje C.... Jerarquia

From: Felipe de Jesús Molina Bravo <felipe(dot)molina(at)inegi(dot)gob(dot)mx>
To: pgsql-es-ayuda(at)postgresql(dot)org
Subject: SRF en lenguaje C.... Jerarquia
Date: 2008-06-30 19:58:06
Message-ID: 1214855886.4728.45.camel@fjmb (view raw or flat)
Thread:
Lists: pgsql-es-ayuda
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




pgsql-es-ayuda by date

Next:From: Carlos MendezDate: 2008-06-30 23:12:33
Subject: Re: conectar php pgsql en fedora ?
Previous:From: Danner Marante JacasDate: 2008-06-30 18:59:48
Subject: RE: [OT] Cubanos en la lista

Privacy Policy | About PostgreSQL
Copyright © 1996-2014 The PostgreSQL Global Development Group