PostgreSQL La base de donnees la plus sophistiquee au monde.

Forums PostgreSQL.fr

Le forum officiel de la communauté francophone de PostgreSQL

Vous n'êtes pas identifié(e).

#1 Re : C et C++ » Afficher résultat fonction avec libpq » 15/02/2012 17:39:16

Yes ! Merci pour votre aide.
En fait mon erreur si situait lors du parcours du résulat.
Je mets le code que j'ai utilisé et qui marche en espérant que ça servira pour autre personne.

/* Etablir la connecxion à base de données */
PGconn *ConnectDB(const char* conninfo)
{
	PGconn *conn = NULL;

	// Etablir la connecxion à base de données
	conn = PQconnectdb(conninfo);

	if (PQstatus(conn) != CONNECTION_OK)
    {
        printf("Connecxion à la base de données non établie !");
        CloseConn(conn);
    }

	printf("Connecxion à la base réussie - OK\n");

	return conn;
}
/* Récupérer les résultats de l'exécution de la procédure*/
void fetchResults(PGconn *conn, char query[])
{
	// Pour contenir le nombre des champs retournés
	int nFields;

	// Commencer une transaction
	PGresult *res  = PQexec(conn, "begin");

    if (PQresultStatus(res) != PGRES_COMMAND_OK)
    {
		printf("BEGIN command failed : %s", PQerrorMessage(conn));
        PQclear(res);
        CloseConn(conn);
    }

	printf("Transaction démarrée.....");

	// Initialiser le resultat
    PQclear(res);

    // récupérer le nom du curseur automatique (portal) contenant les résulats
    res = PQexec(conn, query);
    if (PQresultStatus(res) != PGRES_TUPLES_OK)
    {
		printf("Echec récupération nom curseur : %d - %s", PQerrorMessage(conn), PQresultStatus(res));
        PQclear(res);
        CloseConn(conn);
    }

	// récupérer nom curseur retourné
	char* cursorName = NULL;

	// récupérer le nombre des champs
    nFields = PQnfields(res);

	// Préparer l'entête avec le nom des colonnes
	printf("\Affichage nom du cuseur :");
	printf("\n********************************************************************\n");
    for (int i = 0; i < nFields; i++)
        printf("%-30s", PQfname(res, i));
    printf("\n********************************************************************\n");

    // afficher les enregistrements retournés
    for (int i = 0; i < PQntuples(res); i++)
    {
        for (int j = 0; j < nFields; j++)
		{
			cursorName = PQgetvalue(res, i, j);
            printf("%-30s", PQgetvalue(res, i, j));
		}
        printf("\n");
    }

	// récupérer les résultat contenus dans le curseur
	sprintf(query,"FETCH ALL IN \"%s\"", cursorName);
    res = PQexec(conn, query);

    if (PQresultStatus(res) != PGRES_TUPLES_OK)
    {
		printf("FETCH ALL failed : %s", PQerrorMessage(conn));
        PQclear(res);
        CloseConn(conn);
    }

    // récupérer le nombre des champs
    nFields = PQnfields(res);

	// Préparer l'entête avec le nom des colonnes
	printf("\nAffichage contenu du curseur :");
	printf("\n********************************************************************\n");
    for (int i = 0; i < nFields; i++)
        printf("%-30s", PQfname(res, i));
    printf("\n********************************************************************\n");

    // afficher les enregistrements retournés
    for (int i = 0; i < PQntuples(res); i++)
    {
        for (int j = 0; j < nFields; j++)
            printf("%-30s", PQgetvalue(res, i, j));
        printf("\n");
    }
  
    PQclear(res);

    // fermer le curseur
	sprintf(query,"CLOSE \"%s\"", cursorName);
    res = PQexec(conn, query);
    PQclear(res);

    // Fermer la transaction
    res = PQexec(conn, "END");

	// Effecer le resultat
    PQclear(res);

}
int main(int argc, char **argv)
{
	// déclaration et initialisation des variables
	PGconn *pgsqlConn = NULL;
    const char *conninfo = "host = '127.0.0.1' port = 5432 dbname = 'mabase' user = 'postgres' password = '*******'"; 
	
	// paramétrer la requete selon la procédure stockée et ses arguments
	char query[150] = "select theriaque.get_the_result(13183)";
	
	// connexion à la base de données
	pgsqlConn = ConnectDB(conninfo);
	
	// afficher les données
	fetchResults(pgsqlConn, query);

	// quitter
	printf("\nPress ENTER to remove all records & table.....\n");
	CloseConn(pgsqlConn);

	return 0;
}

Encorde merci pour aide et collaboration
Cordialement

#2 Re : C et C++ » Afficher résultat fonction avec libpq » 15/02/2012 13:39:36

En fait, le résultat que j'ai récupéré ne provient d'une requete lancée dans le programme C mais plutot depuis un éditeur Postgres.
D'ailleur, depuis l'éditeur j'ai réussi à exécuter les commandes et afficher les données.
Par contre, lorsque j'exécute la requete "select get_the_result" depuis le programme C, aucune erreur n'est retourné et le PQresultStatus(res) est égal à 2.

#3 Re : C et C++ » Afficher résultat fonction avec libpq » 15/02/2012 12:40:10

Merci de votre réponse. J'ai vraiment essayé mais toujours il y a un problème.
Voici le code que j'utilise :

// connexion à la base de données
pgsqlConn = ConnectDB(conninfo);

// Commencer une transaction
PGresult *res  = PQexec(conn, "BEGIN");

if (PQresultStatus(res) != PGRES_COMMAND_OK)
{
	printf("Echec création transaction : %s", PQerrorMessage(conn));
        PQclear(res);
        CloseConn(conn);
}

// Initialiser le resultat
PQclear(res);

// récupérer nom curseur 
res = PQexec(conn, "SELECT get_the_results ('13183')");
if (PQresultStatus(res) != PGRES_COMMAND_OK)
 {
        printf("Echec récupération nom curseur : %s", PQerrorMessage(conn));
        PQclear(res);
        CloseConn(conn);
    }

	// récupérer nom curseur retourné
	char* curName = PQgetvalue(res, 0, 0);

// Clear result
    PQclear(res);

	// parcourir le curseur
	query = "";
	sprintf(query,"FETCH ALL IN \"%s\"", curName);
    res = PQexec(conn, query);

    if (PQresultStatus(res) != PGRES_TUPLES_OK)
    {
		printf("FETCH ALL failed : %s", PQerrorMessage(conn));
        PQclear(res);
        CloseConn(conn);
    }

    // récupérer le nombre des champs
    nFields = PQnfields(res);

	// Préparer l'entête avec le nom des colonnes
	printf("\nFetch employee record:");
	printf("\n********************************************************************\n");
    for (int i = 0; i < nFields; i++)
        printf("%-30s", PQfname(res, i));
    printf("\n********************************************************************\n");

    // afficher les enregistrements retournés
    for (int i = 0; i < PQntuples(res); i++)
    {
        for (int j = 0; j < nFields; j++)
            printf("%-30s", PQgetvalue(res, i, j));
        printf("\n");
    }
  
    PQclear(res);

    // fermer le curseur
    res = PQexec(conn, "CLOSE emprec");
    PQclear(res);

    // Fermer la transaction
    res = PQexec(conn, "END");

  // Effecer le resultat
    PQclear(res);

Le problème que la 1ère requete qui va me retourner le nom du curseur retourne une erreur mais qui n'est pas affichée.
Merci de voir ce bout de code et de me corriger.
Cordialement.

#4 Re : C et C++ » Afficher résultat fonction avec libpq » 15/02/2012 12:03:17

Bonjour,
Merci pour vos réponses.
En fait, il serait difficile pour moi maintenant de changer le type de retour de la fonction.  Je dois afficher les résultat depuis le refCursor retourné.

Le programme C++ doit récupérer ce nom comme résultat de la fonction et le mettre dans la commande FETCH ALL FROM "mettre le nom ici".

Si j'ai bien compris, je dois récupérer le nom du portal retourné et ensuite exécuter la requete "FETCH ALL FROM "nom_portal_récupéré".
Par la suite, je pourrais afficher les résultat contenus dans ce "portal".

Merci de votre aide.
Cordialement.

#5 Re : C et C++ » Afficher résultat fonction avec libpq » 14/02/2012 19:13:11

Effectivement, la fonction ne fait que du "Select".
Dans ce cas, je n'ai pas besoin de retourner quelque chose ?
Est ce que le type TABLE suffit ?

Merci encore.
Cordialement.

#6 Re : C et C++ » Afficher résultat fonction avec libpq » 14/02/2012 18:37:13

Merci pour votre réponse.
En fait, j'ai effectué une migration de la procédure depuis SQL Server et l'outil que j'ai utilisé m'a généré cette fonction.

Je ne pense pas qu'un refcursor soit utilisable comme ça.

1. Est ce que je dois obligatoirement modifier le type de retour de la fonction ?
2. Si je change le type de retour, est ce que ça donne le résultat escompté ?

Cela dit, il est encore plus simple de créer une vue que ce genre de fonction, si le but est de simplifier les requêtes coté c++.

En fait, le but c'est d'appeler des fonctions PostgreSQL à l'aide de la librairie libpq.

Merci encore.
Cordialement.

#7 PL/pgSQL » script pour afficher résultat d'une fonction » 14/02/2012 18:29:29

mourad
Réponses : 1

Bonjour tout le monde,
j'ai crée la fonction suivante :

CREATE OR REPLACE FUNCTION "mabase"."get_the_results" (varchar) RETURNS "pg_catalog"."refcursor" AS
$body$
DECLARE
  CodeId ALIAS FOR $1;
  curRet REFCURSOR;
  SQL_QUERY varchar;
BEGIN
      SQL_QUERY := 'SELECT sp_code_sq_pk    ,      
             sp_gsp_code_fk   ,     
             A.CDF_NOM        AS STATUT_LABO ,          
             B.CDF_NOM        AS SP_LISTE    ,         
             sp_catc_code_fk  ,    
             sp_ceph_code_fk  ,   
             sp_cge_code_fk   ,     
             sp_pr_code_fk    ,      
             sp_type_spe      ,        
             sp_gref_fk       ,         
             sp_nom           ,           
             sp_nomcomp       ,         
             sp_ph            ,           
             sp_cipucd        ,         
             sp_datecr        ,        
             sp_datemj        ,          
             sp_nl            ,             
             sp_aphp          ,            
             sp_origine_gene  ,    
             sp_nomlong		  ,
             SP_CIPUCD13	  ,
		     SP_MONO_VIRTUELLE AS MONO_VIR      
      FROM   theriaque.SP_SPECIALITE,
             theriaque.CDF_CODIF A, 
             theriaque.CDF_CODIF B
      WHERE  SP_CDF_SLAB_CODE_FK = A.CDF_CODE_PK 
      AND    SP_CDF_LI_CODE_FK   = B.CDF_CODE_PK
      AND    A.CDF_NUMERO_PK     = ''15'' 
      AND    B.CDF_NUMERO_PK     = ''08''
      AND    SP_CODE_SQ_PK = CAST('||CodeId||' AS NUMERIC)';
open curRet FOR execute SQL_QUERY;
RETURN curRet;
end;

et je désire écrire un script qui affiche les résultats retournés par cette fonction. J'ai essayé avec ces lignes

declare resCur CURSOR for select * from get_the_specialite('13183',1,0); 
FETECH ALL in resCur;

mais aucun résultat n'est affiché. Si j'exécute la 1ère ligne seulement j'ai comme résultat le nom de la procédure comme libellé et <unnamed dropal X> comme valeur.
Est ce que quelqu'un pourrait m'éclaircir ce problème et m'aider à le résoudre.
Merci d'avance pour votre aide.
Cordialement.

#8 C et C++ » Afficher résultat fonction avec libpq » 14/02/2012 18:09:17

mourad
Réponses : 14

Bonjour tout le monde,
j'ai crée une fonction

CREATE OR REPLACE FUNCTION "mabase"."get_the_results" (varchar) RETURNS "pg_catalog"."refcursor" AS
$body$
DECLARE
  CodeId ALIAS FOR $1;
  curRet REFCURSOR;
  SQL_QUERY varchar;
BEGIN
      SQL_QUERY := 'SELECT sp_code_sq_pk    ,      
             sp_gsp_code_fk   ,     
             A.CDF_NOM        AS STATUT_LABO ,          
             B.CDF_NOM        AS SP_LISTE    ,         
             sp_catc_code_fk  ,    
             sp_ceph_code_fk  ,   
             sp_cge_code_fk   ,     
             sp_pr_code_fk    ,      
             sp_type_spe      ,        
             sp_gref_fk       ,         
             sp_nom           ,           
             sp_nomcomp       ,         
             sp_ph            ,           
             sp_cipucd        ,         
             sp_datecr        ,        
             sp_datemj        ,          
             sp_nl            ,             
             sp_aphp          ,            
             sp_origine_gene  ,    
             sp_nomlong		  ,
             SP_CIPUCD13	  ,
		     SP_MONO_VIRTUELLE AS MONO_VIR      
      FROM   theriaque.SP_SPECIALITE,
             theriaque.CDF_CODIF A, 
             theriaque.CDF_CODIF B
      WHERE  SP_CDF_SLAB_CODE_FK = A.CDF_CODE_PK 
      AND    SP_CDF_LI_CODE_FK   = B.CDF_CODE_PK
      AND    A.CDF_NUMERO_PK     = ''15'' 
      AND    B.CDF_NUMERO_PK     = ''08''
      AND    SP_CODE_SQ_PK = CAST('||CodeId||' AS NUMERIC)';
open curRet FOR execute SQL_QUERY;
RETURN curRet;
end;

J'ai voulu afficher les résultats renvoyée par cette procédure depuis une petite application C++.
J'ai utilisé la librairie libpq, mais je n'arrive pas à afficher les résultats vu que lorsque je récupère les enregistrements renvoyés dans un CURSOR et puis j'essai de faire le parcours de ce curseur j'ai toujours le nom de la procédure qui est affiché avec comme valeur "unnamed portal".
Est ce que quelqu'un a une idée où se trouve mon problème et qu'est ce que je dois faire pour corriger ce problème ?
Merci d'avance pour votre aide.
Cordialement.

#10 Re : Général » Appel d'une fonction retournant un curseur » 24/03/2009 11:57:33

En fait je suis au tout début avec PostgreSQL. Et comment faire pour envoyer directement les donnée de la requête du curseur. Est ce que je dois changer les paramètres de sortie et retourner les noms des colonnes et leur type au lieu d'un curseur ?
Merci pour votre collaboration.

#11 Re : Général » Appel d'une fonction retournant un curseur » 17/03/2009 09:38:41

J'ai essayé cela mais j'ai comme sortie "unnamed portal 1". Je ne sais pas c'est du à quoi?

#12 Général » Appel d'une fonction retournant un curseur » 16/03/2009 14:26:25

mourad
Réponses : 6

Bjr tout le monde, voici la fonction que j'ai crée
<Code>

CREATE OR REPLACE FUNCTION "theriaque"."get_the_infos" (varchar) RETURNS "pg_catalog"."refcursor" AS
$body$
DECLARE
  NA ALIAS FOR $1;
  curRet REFCURSOR;
BEGIN
    OPEN curRet FOR
    SELECT DEXTR_VER_THER_PK AS VERS, DEXTR_DATE_EXTR_PK AS DATE_EXT FROM DEXTR_DATE_EXTRACTION;
  RETURN curRet;
END;
$body$
LANGUAGE 'plpgsql'
VOLATILE
CALLED ON NULL INPUT
SECURITY INVOKER
COST 100;
</Code>

Elle marche convenablement et je peux l'exécuter avec l'outil que j'utilise SQL Manager 2007 Lite for PostgreSQL.
Mais lorsque je veux l'exécuter autrement avec l'éditeur de commande en suivant le lien http://postgresql.developpez.com/faq...kees#appelproc, j'ai utilisé
<Code> SELECT * FROM GET_THE_INFOS('') AS (VERS varchar(10), DATE_EXTR date); </Code>

mais j'ai toujours l'erreur suivante : ERROR: a column definition list is only allowed for functions returning "record".
Est ce que quelqu'un pourrait m'orienter pour trouver mon erreur.
Merci d'avance.
Cordialement

Pied de page des forums

Propulsé par FluxBB