/**
* vim: set ts=4 :
* =============================================================================
* SourceMod PostgreSQL Extension
* Copyright (C) 2013 AlliedModders LLC. All rights reserved.
* =============================================================================
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see .
*
* As a special exception, AlliedModders LLC gives you permission to link the
* code of this program (as well as its derivative works) to "Half-Life 2," the
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
* by the Valve Corporation. You must obey the GNU General Public License in
* all respects for all other code used. Additionally, AlliedModders LLC grants
* this exception to all derivative works. AlliedModders LLC defines further
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
* or .
*
* Version: $Id$
*/
#include
#include "PgBasicResults.h"
PgBasicResults::PgBasicResults(PGresult *res)
: m_pRes(res)
{
Update();
}
PgBasicResults::~PgBasicResults()
{
}
void PgBasicResults::Update()
{
if (m_pRes)
{
m_ColCount = (unsigned int)PQnfields(m_pRes);
m_RowCount = (unsigned int)PQntuples(m_pRes);
m_CurRow = 0;
m_RowFetched = false;
}
}
unsigned int PgBasicResults::GetRowCount()
{
return m_RowCount;
}
unsigned int PgBasicResults::GetFieldCount()
{
return m_ColCount;
}
bool PgBasicResults::FieldNameToNum(const char *name, unsigned int *columnId)
{
int id = PQfnumber(m_pRes, name);
if (id == -1)
return false;
*columnId = (unsigned int)id;
return true;
}
const char *PgBasicResults::FieldNumToName(unsigned int colId)
{
if (colId >= m_ColCount)
return nullptr;
return PQfname(m_pRes, colId);
}
bool PgBasicResults::MoreRows()
{
return ((!m_RowFetched && m_RowCount > 0) || (m_RowFetched && m_CurRow < m_RowCount-1));
}
IResultRow *PgBasicResults::FetchRow()
{
// Rows start at 0. Start incrementing the current row when fetching the second time.
if (m_RowFetched)
m_CurRow++;
// Reached the end of the rows.
if (m_CurRow >= m_RowCount)
{
m_CurRow = m_RowCount;
return nullptr;
}
// We fetched some rows.
m_RowFetched = true;
return this;
}
IResultRow *PgBasicResults::CurrentRow()
{
if (!m_pRes
|| !m_RowFetched
|| m_CurRow >= m_RowCount)
{
return nullptr;
}
return this;
}
bool PgBasicResults::Rewind()
{
m_RowFetched = false;
m_CurRow = 0;
return true;
}
DBType PgBasicResults::GetFieldType(unsigned int field)
{
if (field >= m_ColCount)
{
return DBType_Unknown;
}
Oid fld = PQftype(m_pRes, field);
if (fld == InvalidOid)
{
return DBType_Unknown;
}
return GetOurType(fld);
}
DBType PgBasicResults::GetFieldDataType(unsigned int field)
{
if (field >= m_ColCount)
{
return DBType_Unknown;
}
if (PQfformat(m_pRes, field) == 1)
{
return DBType_Blob;
} else {
return DBType_String;
}
}
bool PgBasicResults::IsNull(unsigned int columnId)
{
if (columnId >= m_ColCount)
{
return true;
}
return (PQgetisnull(m_pRes, m_CurRow, columnId) == 1);
}
DBResult PgBasicResults::GetString(unsigned int columnId, const char **pString, size_t *length)
{
if (columnId >= m_ColCount)
{
return DBVal_Error;
} else if (IsNull(columnId)) {
*pString = "";
if (length)
{
*length = 0;
}
return DBVal_Null;
}
*pString = PQgetvalue(m_pRes, m_CurRow, columnId);
if (length)
{
*length = GetDataSize(columnId);
}
return DBVal_Data;
}
DBResult PgBasicResults::CopyString(unsigned int columnId,
char *buffer,
size_t maxlength,
size_t *written)
{
DBResult res;
const char *str;
if ((res=GetString(columnId, &str, nullptr)) == DBVal_Error)
{
return DBVal_Error;
}
size_t wr = strncopy(buffer, str, maxlength);
if (written)
{
*written = wr;
}
return res;
}
size_t PgBasicResults::GetDataSize(unsigned int columnId)
{
if (columnId >= m_ColCount)
{
return 0;
}
return (size_t)PQgetlength(m_pRes, m_CurRow, columnId);
}
DBResult PgBasicResults::GetFloat(unsigned int col, float *fval)
{
if (col >= m_ColCount)
{
return DBVal_Error;
} else if (IsNull(col)) {
*fval = 0.0f;
return DBVal_Null;
}
*fval = (float)atof(PQgetvalue(m_pRes, m_CurRow, col));
return DBVal_Data;
}
DBResult PgBasicResults::GetInt(unsigned int col, int *val)
{
if (col >= m_ColCount)
{
return DBVal_Error;
} else if (IsNull(col)) {
*val = 0;
return DBVal_Null;
}
*val = atoi(PQgetvalue(m_pRes, m_CurRow, col));
return DBVal_Data;
}
DBResult PgBasicResults::GetBlob(unsigned int col, const void **pData, size_t *length)
{
if (col >= m_ColCount)
{
return DBVal_Error;
} else if (IsNull(col)) {
*pData = nullptr;
if (length)
{
*length = 0;
}
return DBVal_Null;
}
*pData = PQgetvalue(m_pRes, m_CurRow, col);
if (length)
{
*length = GetDataSize(col);
}
return DBVal_Data;
}
DBResult PgBasicResults::CopyBlob(unsigned int columnId, void *buffer, size_t maxlength, size_t *written)
{
const void *addr;
size_t length;
DBResult res;
if ((res=GetBlob(columnId, &addr, &length)) == DBVal_Error)
{
return DBVal_Error;
}
if (!addr)
{
return DBVal_Null;
}
if (length > maxlength)
{
length = maxlength;
}
memcpy(buffer, addr, length);
if (written)
{
*written = length;
}
return res;
}
PgQuery::PgQuery(PgDatabase *db, PGresult *res)
: m_pParent(db), m_rs(res)
{
m_InsertID = (unsigned int)PQoidValue(res);
m_AffectedRows = atoi(PQcmdTuples(res));
m_pParent->SetLastIDAndRows(m_InsertID, m_AffectedRows);
}
IResultSet *PgQuery::GetResultSet()
{
if (!m_rs.m_pRes)
{
return nullptr;
}
return &m_rs;
}
unsigned int PgQuery::GetInsertID()
{
return m_InsertID;
}
unsigned int PgQuery::GetAffectedRows()
{
return m_AffectedRows;
}
bool PgQuery::FetchMoreResults()
{
return false;
}
void PgQuery::Destroy()
{
if (m_rs.m_pRes != nullptr)
{
PQclear(m_rs.m_pRes);
}
/* Self destruct */
delete this;
}