//----------------------------------------------------------------------------------------------------------------------------
/*
 * testlibpq.c
 *
 *	  Test the C version of libpq, the PostgreSQL frontend library.
 */
#include <stdio.h>
#include <stdlib.h>
#include <libpq-fe.h>
#include <iostream>
using namespace std;
#include <string.h>
#include <stdio.h>
#include <time.h>

PGconn	 *conn;
int howmany=0;

static void
exit_nicely(void)
{
	PQfinish(conn);
	exit(1);
}

static void
pgexec(void)
{
	printf("using PQexec\n");

	char query[1024]={0};
	for(int i=0; i<howmany;i++)
	{
		PGresult   *res;

		sprintf (query, "INSERT INTO aaaa(a, b, c, d, e, f, g, h, j, k, l, m, n, p) VALUES (67, 'ABRAKADABRA', 'ABRAKADABRA', 'ABRAKADABRA', '1-Dec-2010', 'ABRAKADABRA', 'ABRAKADABRA',  'ABRAKADABRA', '1-Dec-2010', 99999, 99999, %d, 9999, 'ABRAKADABRAABRAKADABRAABRAKADABRAABRAKADABRAABRAKADABRAABRAKADABRAABRAKADABRAABRAKADABRAABRAKADABRAABRAKADABRAABRAKADABRAABRAKADABRA')", i);
		res = PQexec(conn, query);
		if(PQresultStatus(res) != PGRES_COMMAND_OK)
		{
			cout<<"error at iteration "<<i<<":"<<PQresultErrorMessage(res)<<endl;
			PQclear(res);
			break;
		}
		PQclear(res);
	}
}

static void
pgprepare(void)
{
	printf("using PQprepare\n");

	PGresult *res = PQprepare(conn, "my_insert", "INSERT INTO aaaa(a, b, c, d, e, f, g, h, j, k, l, m, n, p) VALUES (67, 'ABRAKADABRA', 'ABRAKADABRA', 'ABRAKADABRA', '1-Dec-2010', 'ABRAKADABRA', 'ABRAKADABRA',  'ABRAKADABRA', '1-Dec-2010', 99999, 99999, $1, 9999, 'ABRAKADABRAABRAKADABRAABRAKADABRAABRAKADABRAABRAKADABRAABRAKADABRAABRAKADABRAABRAKADABRAABRAKADABRAABRAKADABRAABRAKADABRAABRAKADABRA')", 1, NULL);
	if (PQresultStatus(res) != PGRES_COMMAND_OK)
	{
		fprintf(stderr, "insert command failed: %s", PQerrorMessage(conn));
		PQclear(res);
		exit_nicely();
	}
	PQclear(res);

	char **vals = (char**)calloc(1, sizeof(char *));
	if(!vals)
		abort();
	vals[0] = (char*)calloc(10, sizeof(char));
	if(!vals[0])
		abort();

	for (int i=0; i<howmany;i++)
	{
		sprintf(vals[0], "%d", i);
		res = PQexecPrepared(conn, "my_insert", 1, vals, NULL, NULL, 0);

		if(PQresultStatus(res) != PGRES_COMMAND_OK)
		{
			cout<<"error at iteration "<<i<<":"<<PQresultErrorMessage(res)<<endl;
			PQclear(res);
			break;
		}
		PQclear(res);
	}

	free(vals[0]);
	free(vals);
}

static void
pginsert(void)
{
	printf("using one insert command\n");

	const char *line = " (67, 'ABRAKADABRA', 'ABRAKADABRA', 'ABRAKADABRA', '1-Dec-2010', 'ABRAKADABRA', 'ABRAKADABRA',  'ABRAKADABRA', '1-Dec-2010', 99999, 99999, %d, 9999, 'ABRAKADABRAABRAKADABRAABRAKADABRAABRAKADABRAABRAKADABRAABRAKADABRAABRAKADABRAABRAKADABRAABRAKADABRAABRAKADABRAABRAKADABRAABRAKADABRA'),";
	const char *cmd = "insert into aaaa (a, b, c, d, e, f, g, h, j, k, l, m, n, p) values ";
	char *start;
	char *query = (char*)calloc(strlen(cmd) + ((howmany+1) * (strlen(line)+40)) + 1, sizeof(char));
	if(!query)
		abort();

	start = query;
	query += sprintf(query, cmd);

	for(int i=0; i<howmany; i++)
		query += sprintf(query, line, i);

	// chop off last comma
	query[-1] = 0;

	PGresult *res = PQexec(conn, start);
	if(PQresultStatus(res) != PGRES_COMMAND_OK)
		cout<<"error "<<PQresultErrorMessage(res)<<endl;
	PQclear(res);

	free(start);
}

static void
pgcopy(void)
{
	printf("using copy\n");

	char query[1024]={0};
	PGresult *res = PQexec(conn, "copy aaaa from STDIN delimiter \',\';");
	if(PQresultStatus(res) != PGRES_COPY_IN)
	{
		fprintf(stderr, "insert command failed: %s", PQerrorMessage(conn));
		PQclear(res);
		exit_nicely();
	}
	PQclear(res);

	for(int i=0; i<howmany;i++)
	{
		sprintf(query, "67, 'ABRAKADABRA', 'ABRAKADABRA', 'ABRAKADABRA', '1-Dec-2010', 'ABRAKADABRA', 'ABRAKADABRA',  'ABRAKADABRA', '1-Dec-2010', 99999, 99999, %d, 9999, 'ABRAKADABRAABRAKADABRAABRAKADABRAABRAKADABRAABRAKADABRAABRAKADABRAABRAKADABRAABRAKADABRAABRAKADABRAABRAKADABRAABRAKADABRAABRAKADABRA\n", i);
		if(PQputCopyData(conn, query, strlen(query)) != 1)
		{
			cout<<"error at iteration "<<i<<":"<<PQerrorMessage(conn)<<endl;
			break;
		}
	}

	if(PQputCopyEnd(conn, NULL) != 1)
		cout<<"error: "<<PQerrorMessage(conn)<<endl;
}

int
main(int argc, char **argv)
{
	const char *conninfo = "host=192.168.0.15 dbname=whopper port=5432 user=docsysweb password=docsyswebchaos" ;
	PGresult   *res;
	char type;
	if (argc<3)
	{
		cout<<"usage: <# to insert> <method: PQ(e)xec, PQexec(P)repared, one (I)nsert, (C)OPY>"<<endl;
		return -1;
	}
	sscanf(argv[1], "%d", &howmany);
	sscanf(argv[2], "%c", &type);

	time_t startt = time(0);
	cout<<"starting at "<<asctime(localtime(&startt));
	cout<<"inserting "<<howmany<<" records"<<endl;

	/* 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, "Connection to database failed: %s",
				PQerrorMessage(conn));
		exit_nicely();
	}

	/* Start a transaction block */
	res = PQexec(conn, "BEGIN");
	if (PQresultStatus(res) != PGRES_COMMAND_OK)
	{
		fprintf(stderr, "BEGIN command failed: %s", PQerrorMessage(conn));
		PQclear(res);
		exit_nicely();
	}
	PQclear(res);

	switch(type)
	{
		case 'e':
			pgexec();
			break;
		case 'p':
			pgprepare();
			break;
		case 'i':
			pginsert();
			break;
		case 'c':
			pgcopy();
			break;
		default:
			fprintf(stderr, "Dont know how to '%c'\n", type);
			exit_nicely();
			break;
	}

	/* end the transaction */
	res = PQexec(conn, "END");
	PQclear(res);

	time_t endt = time(0);
	cout<<"Finished at "<<asctime(localtime(&endt))<<"total: "<< endt - startt <<"s"<<endl;


	/* close the connection to the database and cleanup */
	PQfinish(conn);

	return 0;
}



//----------------------------------------------------------------------------------------------------------------------------

