#include "CivPgDbConnection.h"
#include "CivCommonUtils.h"
#include "StringUtils.h"

#include <iostream>

CivPgDbConnection::CivPgDbConnection()
	:CivConnection(),mConn(nullptr),mResult(nullptr)
{

}

CivPgDbConnection::~CivPgDbConnection()
{
    disconnect();
}

bool CivPgDbConnection::connect(const std::string& url)
{
    disconnect();

    mConn = PQconnectdb(url.c_str());
    if (PQstatus(mConn) == CONNECTION_BAD) {
        mConn = NULL;
        PQfinish(mConn);
        return false;
    }
    return true;
}

bool CivPgDbConnection::disconnect()
{
    if (mConn != NULL)
    {
        PQfinish(mConn);
        mConn = NULL;
    }
    return true;
}

bool CivPgDbConnection::queryResult(std::vector<std::map<std::string,std::string>>& result)
{
    int rows = PQntuples(mResult);
    int columns = PQnfields(mResult);
    for (int i = 0; i < rows; i++)
    {
        std::map<std::string, std::string> map;
        for (int j = 0; j < columns; j++)
        {
            std::string filedName = CivCommonUtils::UTF8_To_string(PQfname(mResult, j));
            std::string filedValue = CivCommonUtils::UTF8_To_string(PQgetvalue(mResult, i, j));

            StringUtils::trim(filedName);
            StringUtils::trim(filedValue);

             map.insert(std::pair<std::string, std::string>(filedName,filedValue));
        } 
        result.push_back(map);
    }
    PQclear(mResult);
}

bool CivPgDbConnection::execSql(const std::string& sql)
{
    if (!mConn || sql.empty() )
        return false;

   
    std::string utf8Sql = CivCommonUtils::string_To_UTF8(sql);
    mResult = PQexec(mConn, utf8Sql.c_str());
    std::string errorStr = PQresultErrorMessage(mResult);

    if (!errorStr.empty())
    {
        mLastError = errorStr;
        std::cout << sql << std::endl;
        std::cout << mLastError << std::endl;
        PQclear(mResult);
        return false;
    }

    return true;
}

bool CivPgDbConnection::beginTransaction()
{ 
    return execSql("BEGIN");
}

bool CivPgDbConnection::commitTransaction()
{
    return execSql("COMMIT");
}

