PostgreSQL e C
December 26th, 2007 Posted in C, PostgreSQLEste 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:
{
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 <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
8 Responses to “PostgreSQL e C”
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.
By Fernando F. on Dec 27, 2007
PS: Postei um link no meu site para este artigo.
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
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!
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.
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!
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!
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!”