/***************************************************************************
                Database Class
                -----------------------------------------
    begin      : 2010/03/09
    copyright  : (C) 2010 SolutionBox Inc.
	author     : Service 1 Team
	email      : svc1@solbox.com
    version    : 1.0

    CopyRight(C) 2010 SolutionBox Inc. All Rights reserved.
    Redistribution and use in source and binary forms, with or with out
    modification, are not permitted in outside of SolutionBox Inc.
***************************************************************************/

#include <string.h>
#include <stdlib.h>
#include <sstream>
#include "Database.h"
#include "Logger.h"


DataBase::~DataBase()
{
	if(m_PGconn != NULL) {
		PgCloseDB();
	}
}

PGconn *DataBase::PgOpenDB(string &strHost, int Port, string &strDBName, string &strAcct, string &strPasswd, int timeout)
{
	ostringstream conninfo;

	conninfo << "host=" << strHost << " port=" << Port << " dbname=" << strDBName <<
		" user=" << strAcct << " password=" << strPasswd << " connect_timeout=" << timeout
		<< " application_name=" << PROG_NAME; 
#ifdef _USE_LIBPQ_KEEPALIVE
 	// This option is supported by at least 9.1.2. and Currently supports Linux systems.
	conninfo <<" keepalives=1";
#endif  //  _USE_LIBPQ_KEEPALIVE
	//m_PGconn = PQsetdbLogin(strHost.c_str(), szPort, NULL, NULL, strDBName.c_str(), strAcct.c_str(), strPasswd.c_str());
	m_PGconn = PQconnectdb(conninfo.str().c_str());
	if(PQstatus(m_PGconn) == CONNECTION_BAD) {
		return NULL;
	}
	
	return m_PGconn;
}

PGconn *DataBase::PgOpenDB(const char *pszDBName)
{
	m_PGconn = PQsetdb(NULL, NULL, NULL, NULL, pszDBName);
	if(PQstatus(m_PGconn) == CONNECTION_BAD) {
		return NULL;
	}
	return m_PGconn;
}

void DataBase::PgCloseDB()
{
	if(m_PGconn != NULL) 
	{
		PQfinish(m_PGconn);
		m_PGconn = NULL;
	}
}

int DataBase::PgResult(CFLAG flag)
{
	int fRet = 0;
	int Result;

	Result = PQresultStatus(m_pRes);
	switch(Result) {
		case  PGRES_EMPTY_QUERY :
									fRet = -1;
									break;
		case  PGRES_BAD_RESPONSE :
									fRet = -2;
									break;
		case  PGRES_NONFATAL_ERROR :
									fRet = -3;
									break;
		case  PGRES_FATAL_ERROR :
									fRet = -4;
									break;
	    case  PGRES_TUPLES_OK :
									fRet = 1;
									break;
		case  PGRES_COMMAND_OK :
									fRet = 2;
									break;
	}
	if(fRet < 0) {
		m_ErrorMessage = PQresultErrorMessage(m_pRes);
	}
	m_ResultCode = Result;
	if(flag == CLEAR && m_pRes) {
		PQclear(m_pRes);
		m_pRes = NULL;
	}
	return fRet;
}

string &DataBase::GetErrorMessage()
{
	return m_ErrorMessage;
}

int DataBase::GetCmdTuples()
{
	//fprintf(stderr, "DataBase::GetCmdTuples PQcmdTuples %s\n", PQcmdTuples(m_pRes));
	return (int)atoi(PQcmdTuples(m_pRes));
}

int DataBase::GetNoTuples()
{
	return PQntuples(m_pRes);
}

int DataBase::GetNoFields()
{
	return PQnfields(m_pRes);
}

PGresult *DataBase::GetRes()
{
	return m_pRes;
}

void DataBase::PgClear()
{
	if(m_pRes)
	{
		PQclear(m_pRes);
		m_pRes = NULL;
	}	
}

char *DataBase::GetValue(int tuple, int field)
{
	return PQgetvalue(m_pRes, tuple, field);
}

int DataBase::PgDoExec(const char *pszQuery)
{
	return this->PgDoExec(pszQuery, NOT_CLEAR);
}

int DataBase::PgDoExec(string &strQuery)
{
	return this->PgDoExec(strQuery.c_str(), NOT_CLEAR);
}

int DataBase::PgDoExec(const char *pszQuery, CFLAG flag)
{
	if(m_PGconn == NULL) return -1;
	if(PQstatus(m_PGconn) != CONNECTION_OK)  return -2;
	m_pRes = PQexec(m_PGconn, pszQuery);
	int r =	PgResult(flag);
	return r;
}

int DataBase::PgDoExecParams(char *pszQuery, int nParamCnt, const char * const *paramValues ,CFLAG flag)
{
	if(m_PGconn == NULL) return -1;
	if(PQstatus(m_PGconn) != CONNECTION_OK)  return -2;
	m_pRes = PQexecParams(m_PGconn, pszQuery, nParamCnt, NULL, paramValues, NULL, NULL, 0);
	int r =	PgResult(flag);
	return r;

}

int DataBase::PgEscapeString(char *to, const char *from, size_t length)
{
	int retval = 0;

	//PQescapeStringConn(m_PGconn, to, from, length, &retval);
	PQescapeString(to, from, length);
	return retval;
}
