PostgreSQL e C

December 26th, 2007 Posted in C, PostgreSQL

Este documento visa introduzir algumas funções da libpq, utilizada para fazer conexões em banco de dados postgresql através da linguagem de programação C.
A versão do postgreSQL utilizado neste documento é 8.2.3. As funções que serão descritas aqui são: PQconnectdb, PQstatus, PQerrorMessage, PQexec, PQprint, PQresultStatus, PQresultErrorMessage, PQclear e PQfinish.

PQconnectdb

PGconn *PQconnectdb(const char *conninfo);

Esta função cria uma conexão com o SGBD apartir da string(conninfo) recebida como parâmetro, contendo palavras chave que são utilizadas para efetuar a conexão. Neste caso serão utilizadas as seguintes palavras chave:

1) host: Nome do host ao qual será feita a conexão.
2) port: Porta do SGBD que será utilizada para efetuar a conexão.
3) dbname: Nome da base de dados a ser manipulada.
4) user: Usuário utilizado para efetuar a conexão.
5) password: Senha utilizada para efetuar a conexão.
6) connect_timeout: Tempo máximo para esperar que a conexão seja estabelecida, em segundos.* Existem outras palavras chave, porém neste caso apenas estas já satisfazem.

O seu retorno é um ponteiro que representa a conexão,utilizado para manipulá-la.

PQstatus

ConnStatusType PQstatus(PGconn *conn);

Esta função recebe como parâmetro o ponteiro que representa a conexão, retornando o seu status (podendo ser CONNECTION_OK ou CONNECTION_BAD).

PQerrorMessage

char *PQerrorMessage(PGconn* conn);

Esta função recebe como parâmetro o ponteiro que representa a conexão e retorna um outro ponteiro(string) que contém a última mensagem de erro gerada pela conexão.

PQexec

PGresult *PQexec(PGconn *conn, const char *command);

Envia um comando ao servidor e aguarda o resultado (função síncrona). Recebe como parâmetro o ponteiro que representa a conexão e uma string que contém o comando a ser executado.

Seu retorno pode ser um ponteiro nulo (NULL) ou um ponteiro do tipo PGresult - estrutura que armazena as informações sobre a query. No caso de um ponteiro NULL ser retornado, pode ser considerado como PGRES_FATAL_ERROR e para detalhar o erro é utilziada a função PQresultErrorMessage (descrita neste documento).

PQprint

void PQprint(FILE *fout, const PGresult *res, const PQprintOpt *po);

Função que imprime o resultado de uma consulta. Recebe como parâmetro um output stream, PGresult (referente a consulta) e uma estrutura de opções (PQprintOpt).

A estrutura recebida como parâmetro é composta pelos seguintes campos:

typedef struct _PQprintOpt
{
  pqbool  header;  /* print output field headings and row count */
  pqbool  align;  /* fill align the fields */
  pqbool  standard;  /* old brain dead format */
  pqbool  html3;  /* output html tables */
  pqbool  expanded;  /* expand tables */
  pqbool  pager;  /* use pager for output if needed */
  char  *fieldSep;  /* field separator */
  char  *tableOpt;  /* insert to HTML table … */
  char  *caption;  /* HTML caption */
  char  **fieldName;  /* null terminated array of repalcement field names */
} PQprintOpt;

PQresultStatus

ExecStatusType PQresultStatus(const PGresult *res);

Recebe como parâmetro um ponteiro do tipo PGresult e retorna o status do resultado de uma query.

Retorno da função:

PGRES_EMPTY_QUERY (string enviada para o servidor vazia)
PGRES_COMMAND_OK (comando executado com sucesso, sem dados de retorno)
PGRES_TUPLES_OK (comando executado com sucesso, dados retornados)
PGRES_COPY_OUT
PGRES_COPY_IN
PGRES_BAD_RESPONSE (resposta inesperada recebida)
PGRES_NONFATAL_ERROR
PGRES_FATAL_ERROR (ocorreu um erro fatal)

PQresultErrorMessage

char *PQresultErrorMessage(const PGresult *res);

Recebe como parâmetro o ponteiro que representa a conexão e retorna um ponteiro(string) que descreve o erro ocorrido.

PQclear

void PQclear(PGresult *res);

Recebe como parâmetro um ponteiro para um resultado (PGresult) e libera a memória associada a ele.

PQfinish

void PQfinish(PGconn *conn);

Recebe como parâmetro um ponteiro que representa uma conexão com o SGBD e fecha a mesma.

Código

Abaixo segue o código fonte de uma aplicação que fiz para exemplificar as funções expostas aqui.
Para compilar utilize: gcc -Wall -o artigo artigo.c -lpq

#include <postgresql/libpq-fe.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

// String de configuração para efetuar a conexão
#define DB_CONNECT_STRING "host=192.168.1.201 port=5432 dbname=dbdaniel user=postgres connect_timeout=8"

int main(void)
{
  // Ponteiro utilizado para minha conexão
  PGconn *bancoDeDados = NULL;
  // Variavel para verificar o status da conexão
  ConnStatusType retConn;

  // Variavel de retorno do aplicativo
  int retval = 0;

  // Efetua a conexão
  bancoDeDados = PQconnectdb( DB_CONNECT_STRING );

  // Verifica o status da conexão
  retConn = PQstatus(bancoDeDados);
  if ( retConn != CONNECTION_OK )
  {
    // Em caso de falha, obter o erro
    char *retString;
    retString = PQerrorMessage(bancoDeDados);
    printf("Falha efetuando a conexão.\n%s", retString);
    free(retString);
    retval = -1;
  }
  else
  {
    // Conexão efetuada com sucesso, efetuar consulta : D
    PGresult *result;
    result = PQexec(bancoDeDados, "select * from tabela_daniel");
    if (!result || PQresultStatus(result) != PGRES_TUPLES_OK)
    {
      // Em caso de falha exibir a mensagem
      char *retString;
      retString = PQresultErrorMessage(result);
      printf("Falha executando sql.\n%s", retString);
      retval = -1;
    }
    else
    {
      // Comando executado com sucesso, mostrando o conteúdo
      PQprintOpt pq;
      char *fieldSep = "\t-\t";
      memset(&pq, 0, sizeof(pq));
      pq.fieldSep = fieldSep;
      pq.header = 1;
      pq.standard = 1;
      PQprint(stdout, result, &pq);
    }
    PQclear(result);
    PQfinish(bancoDeDados);
  }
  return retval;
}

Para quem deseja estudar mais sobre o assunto, segue o link para a documentação da libpq (Enviada por Euler Taveira):

http://www.postgresql.org/docs/8.3/static/libpq.html

  1. 8 Responses to “PostgreSQL e C”

  2. By Fernando F. on Dec 27, 2007

    Muito legal seu artigo cara, a libpq é muito poderosa, vale a pena se aprofundar na sua utilização.

  3. By Fernando F. on Dec 27, 2007

    PS: Postei um link no meu site para este artigo.

  4. By Euler Taveira on Dec 27, 2007

    Algumas correções:
    (i) o arquivo a ser incluído em uma aplicação cliente é o ‘libpq-fe.h’ e não o ‘postgresql.h’
    (ii) Nas linhas do memset() e do PQPrint() apareceram um & ao invés de &.
    (iii) era interessante citar o manual para aqueles que queiram se aprofundar no uso da libpq [1]

    [1] http://www.postgresql.org/docs/8.3/static/libpq.html

  5. By Daniel on Dec 27, 2007

    Euler, obrigado pelas observações. Estes erros (i e ii) aconteceram devido à minha inexperiência com a utilização de blog. Na minha aplicação estou utilizando “<postgresql/libpq-fe.h>” e não sei porque apareceu assim, vou corrigir!

    Vou adicionar a referência também!

    Valeu!

  6. By Alexsander on Dec 27, 2007

    Tem um outro artigo de 2005 que trata do mesmo assunto, não custa nada citar:
    http://www.vivaolinux.com.br/artigos/verArtigo.php?codigo=4169&pagina=6

    Tenho usado a libpq em aplicações comerciais há alguns anos, especialmente em softwares em C para coletores de dados. Ela é excelente.

  7. By Daniel on Dec 27, 2007

    Alexsander, muito bom o artigo que você fez referência, inclusive eu estava querendo falar sobre cursores em um próximo momento. Olhando os artigos deste autor notei que ele possui publicado um sobre cursores (http://www.vivaolinux.com.br/artigos/verArtigo.php?codigo=4482)
    que por sinal é bem interessante.

    Conheço poucas pessoas que trabalham com a libpq, nenhuma fora da empresa que trabalho.

    Valeu pela dica!

  8. By Jean on Sep 4, 2008

    Ola galera to condificuldade de rodar esse exemplo q vcs fizeram ! ele da erro no menset()
    e no PQPrint() vcs tem o codigo ai funcionando perfeitamente to precisando urgentissimo! valeu galera!

  9. By Jean on Sep 4, 2008

    Gostei muito !! se poderem mandar mais coisas relacionadas a o postgres e C e CGI fico gratto! to fazendo um projeto utilizando essas duas tecnologias ! preciso de ajuda se alguem poder ajudar! valeu!”

Post a Comment