/*
 * pg_cxn.c
 */

#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include "libpq-fe.h"

struct cmd_list;
typedef struct cmd_list cmd_list;

struct cmd_list
{
	char   *cmd;
	cmd_list   *next;
};

static void pg_connect(const char *conninfo, cmd_list *);
static cmd_list *add_command(cmd_list *, char *);
static void usage(void);

int
main(int argc, char **argv)
{
	int		c;
	int		n = 1;
	int		optindex;
	int		i;
	const char *conninfo;
	cmd_list   *cmds;

	while ((c = getopt_long(argc, argv, "n:c:", NULL, &optindex)) != -1)
	{
		switch (c)
		{
			case 'n':
				n = atoi(optarg);
				break;
			case 'c':
				cmds = add_command(cmds, optarg);
				break;
			default:
				usage();
				break;
		}
	}
	argv += optind;
	argc -= optind;

	if (argc > 0)
		conninfo = argv[0];
	else
		conninfo = "";

	for (i = 0; i < n; ++i)
		pg_connect(conninfo, cmds);

	printf("Established %d connections.\n", n);

	while (1)
		sleep(3600);

	return 0;
}

static cmd_list *
add_command(cmd_list *cmds, char *cmd)
{
	cmd_list   *newnode;

	newnode = malloc(sizeof(cmd_list));
	if (newnode == NULL)
	{
		perror("malloc");
		exit(1);
	}
	newnode->cmd = cmd;
	newnode->next = cmds;
	return newnode;
}

static void
pg_connect(const char *conninfo, cmd_list *cmds)
{
	PGconn	   *conn;

	/* Make a connection to the database */
	conn = PQconnectdb(conninfo);

	/* Check to see that the backend connection was successfully made */
	if (PQstatus(conn) != CONNECTION_OK)
	{
		fprintf(stderr, "%s", PQerrorMessage(conn));
		exit(1);
	}

	/* Execute commands. */
	while (cmds != NULL)
	{
		PGresult *res;

		res = PQexec(conn, cmds->cmd);
		if (PQresultStatus(res) == PGRES_FATAL_ERROR)
		{
			fprintf(stderr, "%s", PQresultErrorMessage(res));
			exit(1);
		}
		if (PQresultStatus(res) != PGRES_COMMAND_OK
			&& PQresultStatus(res) != PGRES_TUPLES_OK)
		{
			fprintf(stderr, "unexpected result status: %s\n",
					PQresStatus(PQresultStatus(res)));
			exit(1);
		}
		PQclear(res);
		cmds = cmds->next;
	}
}

static void
usage()
{
	fprintf(stderr, "Usage: pg_cxn [OPTION] [CONNECTION-STRING]\n\n"
		"Options:\n"
		"  -n NUM		Number of connections to open.\n"
		"  -c SQL		SQL to execute on each connection.\n"
		"				(You can repeat this option more than once.)\n");
	exit(1);
}
