#include <unistd.h>
#include "libpq-fe.h"

char *hostname = "";
char *port     = "55432";
char *dbname   = "alvherre";
char *username = "alvherre";
char *password = "";

/* establece conexión con la BD. */
PGconn *
sql_conn(void)
{
	PGconn     *conn;

	/* conectar */
	conn = PQsetdbLogin(hostname,
			port,
			NULL,  /* options */
			NULL,  /* tty */
			dbname,
			username,
			password);

	/* verificar resultado */
	if (PQstatus(conn) != CONNECTION_OK)
	{
		fprintf(stderr, "la conexión a %s falló.\n", dbname);
		fprintf(stderr, "%s", PQerrorMessage(conn));

		PQfinish(conn);
		exit(1);
	}

	/* si la conexión está buena, retornar */
	return conn;
}


/*
 * Recibe una conexión y una sentencia SQL, la ejecuta y despliega
 * el resultado en la pantalla.
 */
int
sql_exec(PGconn *conn, const char *sql)
{
	PGresult   *res;

	int         nfields;
	int         nrows;
	int         i, j, l;
	int        *length;
	char       *pad;

	/* Ejecuta la consulta */
	res = PQexec(conn, sql);

	/* Verifica el código de retorno */
	if (!res || PQresultStatus(res) > 2)
	{
		fprintf(stderr, "falló la consulta: %s\n", PQerrorMessage(conn));
		fprintf(stderr, "la consulta era: %s\n", sql);

		PQclear(res);
		PQfinish(conn);
		exit(-1);
	}

	/* Obtiene el número de campos */
	nrows = PQntuples(res);
	nfields = PQnfields(res);

	/* Para cada columna, obtiene el ancho necesario */
	length = (int *) malloc(sizeof(int) * nfields);
	for (j = 0; j < nfields; j++)
		length[j] = strlen(PQfname(res, j));

	for (i = 0; i < nrows; i++)
	{
		for (j = 0; j < nfields; j++)
		{
			l = strlen(PQgetvalue(res, i, j));
			if (l > length[j])
				length[j] = strlen(PQgetvalue(res, i, j));
		}
	}

	/* imprime un encabezado */
	for (j = 0, l = 0; j < nfields; j++)
	{
		fprintf(stdout, "%*s", length[j] + 2, PQfname(res, j));
		l += length[j] + 2;
	}
	fprintf(stdout, "\n");
	pad = (char *) malloc(l + 1);
	memset(pad, '-', l);
	pad[l] = '\0';
	fprintf(stdout, "%s\n", pad);
	free(pad);

	/* imprime cada fila */
	for (i = 0; i < nrows; i++)
	{
		for (j = 0; j < nfields; j++)
			fprintf(stdout, "%*s", length[j] + 2, PQgetvalue(res, i, j));
		fprintf(stdout, "\n");
	}

	/* libera memoria */
	PQclear(res);
	free(length);

	return 0;
}


/*
 * Recibe una consulta SQL en el primer argumento, la ejecuta
 * y muestra el resultado.
 */
int main(int argc, char **argv)
{
	PGconn *pgconn;

	pgconn = sql_conn();

	sql_exec(pgconn, argv[1]);
}

