Acessando PostgreSQL com C - Cursores

Veremos neste artigo como trabalhar com cursores através da libpq, utilizando a linguagem C.

[ Hits: 42.803 ]

Por: Poleto em 27/04/2006


Retornando uma linha por vez



Antes de darmos os próximos passos com cursores, vamos alterar nosso código para ficar um pouco mais legível, uma vez que para retornar uma linha de cada vez teremos que fazer a verificação do retorno da função PQexec cada vez que ela for chamada (ou seja, uma vez por linha!), o que resultaria em um código cheio de switch, o que ficaria "feio", mas dizer assim. Criaremos uma função que ficará assim:

int ExecutaComando(const char *comando, PGresult **ptr_resultado)
{
   int codigo_retorno = 1;
   const char *str_resultado;
  
   PGresult *resultado_local;
  
   printf(" Executando comando: %s ", comando);
      
   /*executa o comando e armazena localmente*/
   resultado_local = PQexec(conn, comando);
  
   /*passa o resultado local para o segundo parâmetro da função, para que seja acessível dentro de MAIN*/
   *ptr_resultado = resultado_local;
  
   /*Verifica se o comando foi bem sucedido*/
   if(!resultado_local)
   {
      /*Se falhou, imprime mensagem na tela e seta o código de retorno da função como 0 (erro)*/
      printf("O comando falhou. ");
      codigo_retorno = 0;
   }
   else
   {
      /*Se foi sucedido, chamamos PQresultStatus para verificar qual o código de retorno*/
      switch(PQresultStatus(resultado_local))
      {
         case PGRES_COMMAND_OK:
            printf("Comando ok, %s linhas afetadas. ", PQcmdTuples(resultado_local));
            break;
         case PGRES_TUPLES_OK:
            printf("A query retornou %d linhas. ", PQntuples(resultado_local));
            break;
         default:
            printf("Error in query: %s ", PQresultErrorMessage(resultado_local));
            PQclear(resultado_local);
            codigo_retorno = 0;
            break;
      }
   }
  
   /*retorna código de retorno*/
   return codigo_retorno;
}

Esta função não tem nenhum mistério, tudo aqui já foi visto, apenas colocamos a execução de um comando e a verificação de retorno dentro da função.

Agora que nosso código vai ficar mais legível, vamos continuar com o básico. Vamos no código abaixo retornar apenas uma linha por vez. Não há mistério nisso, lembra que na declaração do FETCH podemos dizer quantos dados queremos retornar? Nosso código vai ficar assim (lembrando que estamos omitindo a parte aonde abrimos e fechamos a conexão com o banco):

    comando_ok = ExecutaComando("BEGIN WORK", &result);
    
    if(comando_ok)
    {
       PQclear(result);
      
       /*Executa o comando*/
       comando_ok = ExecutaComando("DECLARE curr CURSOR FOR SELECT * FROM contatos", &result);
      
       if(comando_ok)
       {
          PQclear(result);
          comando_ok = ExecutaComando("FETCH 1 IN curr", &result);
          
          while(comando_ok && PQntuples(result) > 0)
          {
             PQclear(result);
             ExecutaComando("FETCH NEXT IN curr", &result);
          }
       }
      comando_ok = ExecutaComando("COMMIT WORK", &result);
    }

    if(comando_ok)
       PQclear(result);

A saída do programa será algo assim (no meu caso, a minha tabela tem 5 linhas):

Executando comando: BEGIN WORK
Comando ok, linhas afetadas.

Executando comando: DECLARE curr CURSOR FOR SELECT * FROM contatos
Comando ok, linhas afetadas.

Executando comando: FETCH 1 IN curr
A query retornou 1 linhas.

Executando comando: FETCH NEXT IN curr
A query retornou 1 linhas.

Executando comando: FETCH NEXT IN curr
A query retornou 1 linhas.

Executando comando: FETCH NEXT IN curr
A query retornou 1 linhas.

Executando comando: FETCH NEXT IN curr
A query retornou 1 linhas.

Executando comando: FETCH NEXT IN curr
A query retornou 0 linhas.

Executando comando: COMMIT WORK
Comando ok, linhas afetadas.

Note que quando o cursor atinge o final do conjunto de dados, o comando FETCH NEXT irá retornar zero.

Página anterior     Próxima página

Páginas do artigo
   1. Introdução
   2. Uma breve explicação sobre cursores
   3. Declaração de cursores
   4. Retornando uma linha por vez
   5. Informações sobre colunas
   6. Acessando os dados recuperados
Outros artigos deste autor

PostgreSQL - Embutindo comandos SQL no seu código C

Acessando PostgreSQL com C

Instalando o CMS Drupal 4.7

Leitura recomendada

Ensaio acerca de bibliotecas de código aberto para abstração de acesso a banco de dados em linguagem C++

Acessando PostgreSQL com C

Embutindo um banco de dados SQLite em sua aplicação C++

PostgreSQL - Embutindo comandos SQL no seu código C

Usando MySQL na linguagem C

  
Comentários
[1] Comentário enviado por jragomes em 28/04/2006 - 14:02h

Parabéns pelo artigo, muito bem escrito e detalhado.

[2] Comentário enviado por madsonbraz em 02/05/2006 - 08:53h

Me tire uma duvida, é possivel criar um cluster com o postgresql?

[3] Comentário enviado por poleto em 02/05/2006 - 14:54h

madsonbraz,

E possivel sim, mas eu particularmente nao sei como.

[]'s
Poleto

[4] Comentário enviado por rjesus em 13/03/2007 - 11:20h

Olá, sou novo no linux, utilizoo o SUSE versão 10.1, tentei executar o exemplo que foi passado acima e obtive o seguinte resultado :
suse:/usr/include/pgsql # gcc $(pkg-config --libs --cflags gtk+-2.0) -g teste1.c
/tmp/ccc0dzwL.o: In function `main':
/usr/include/pgsql/teste1.c:13: undefined reference to `PQconnectdb'
/usr/include/pgsql/teste1.c:15: undefined reference to `PQstatus'
/usr/include/pgsql/teste1.c:28: undefined reference to `PQexec'
/usr/include/pgsql/teste1.c:21: undefined reference to `PQerrorMessage'
/usr/include/pgsql/teste1.c:22: undefined reference to `PQfinish'
/usr/include/pgsql/teste1.c:36: undefined reference to `PQresultStatus'
/usr/include/pgsql/teste1.c:42: undefined reference to `PQresultErrorMessage'
/usr/include/pgsql/teste1.c:45: undefined reference to `PQcmdTuples'
/usr/include/pgsql/teste1.c:53: undefined reference to `PQclear'
/usr/include/pgsql/teste1.c:59: undefined reference to `PQfinish'
collect2: ld returned 1 exit status
Alguêm poderia me ajudar ???
Obigado!

[5] Comentário enviado por poleto em 13/03/2007 - 15:04h

Fala rjesus,

Parece que você esqueceu alguns parâmetros para o gcc na hora de executar.
Dá uma olhada neste artigo que tem os detalhes necessários para compilar programas com suporte ao PostgreSQL:

http://www.vivaolinux.com.br/artigos/verArtigo.php?codigo=4169

Qualquer coisa grita.
[]'s
Poleto

[6] Comentário enviado por evaldobarbosa em 04/12/2008 - 15:36h

Eu resolvi o problema criando um arquivo que já automatiza esse negócio pra mim, saca só:

#!/bin/bash

rm cursores

g++ -o arquivo -I/usr/include/postgresql/ arquivo.cpp -lpq
#clear
echo ###### executando #####
if [ -x cursores ] ; then
./cursores
fi

exit 0


Contribuir com comentário




Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts