/*
	Autor: Daniel Matte Freitas.
	Site: http://www.danielmatte.com
	E-mail: danielmatte at gmail.com

	Descrição: Código exemplificando a utilização de Cursores do PostgreSQL em C.
*/
#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
		PGresult *result;

		// Iniciando a transação
		result = PQexec(bancoDeDados, "BEGIN");
		if (!result || PQresultStatus(result) != PGRES_COMMAND_OK)
		{
			// Em caso de falha exibir a mensagem
			retval = -1;
		}
		else
		{
			PQclear(result);

			// Declarando o cursor
			result = PQexec(bancoDeDados, "DECLARE cursor1 NO SCROLL CURSOR FOR select * from tabela_daniel;");
			if (!result || PQresultStatus(result) != PGRES_COMMAND_OK)
			{
				// Em caso de falha exibir a mensagem
				retval = -1;
			}
			else
			{
				while ( 1 )
				{
					PQclear(result);
					// Percorrendo o cursor
					result = PQexec(bancoDeDados, "FETCH FORWARD 1 in cursor1;");
					if (	! result || \
						(	PQresultStatus(result) != PGRES_COMMAND_OK && \
							PQresultStatus(result) != PGRES_TUPLES_OK ) )
					{
						retval = -1;
					}
					else if (PQresultStatus(result) == PGRES_TUPLES_OK && \
								PQntuples(result) > 0)
					{
						// Exibindo o resultado
						int i;
						for ( i = 0 ; i < PQnfields(result) ; i ++ )
						{
							printf("%-20s", PQgetvalue(result, 0, i));
						}
						printf("\n");
						continue;
					}
					break;
				}
				if ( retval != -1 )
				{
					PQclear(result);

					// Fechando o cursor
					result = PQexec(bancoDeDados, "CLOSE cursor1");
					if ( !result || PQresultStatus(result) != PGRES_COMMAND_OK )
					{
						retval = -1;
					}
					else
					{
						PQclear(result);

						// Finalizando a transação
						result = PQexec(bancoDeDados, "COMMIT");
						if ( !result || PQresultStatus(result) != PGRES_COMMAND_OK )
						{
							retval = -1;
						}
					}
				}
			}
		}
		// Em caso de falha, exibir a mensagem
		if ( retval == -1 && result != NULL)
		{
			char *retString;
			retString = PQresultErrorMessage(result);
			printf("Falha executando sql.\n%s", retString);
		}
		if ( result ) PQclear(result);
		PQfinish(bancoDeDados);
	}
	return retval;
}

