271 lines
4.8 KiB
C++
Executable File
271 lines
4.8 KiB
C++
Executable File
#include "sqlite_amx.h"
|
|
|
|
SQL::SQL()
|
|
{
|
|
isFree = true;
|
|
sqlite = NULL;
|
|
}
|
|
|
|
SQL::~SQL()
|
|
{
|
|
if (!isFree)
|
|
Disconnect();
|
|
}
|
|
int SQL::Error()
|
|
{
|
|
if (sqlite == NULL)
|
|
return 0;
|
|
|
|
ErrorCode = sqlite3_errcode(sqlite);
|
|
ErrorStr.assign(sqlite3_errmsg(sqlite));
|
|
|
|
return ErrorCode;
|
|
}
|
|
|
|
int SQL::Connect(const char *base)
|
|
{
|
|
Database.assign(base);
|
|
|
|
isFree = false;
|
|
int err = 0;
|
|
|
|
this->ErrorCode = sqlite3_open(Database.c_str(), &sqlite);
|
|
if (ErrorCode != SQLITE_OK) {
|
|
err = Error();
|
|
if (err)
|
|
{
|
|
MF_Log("DB Connection failed(%d): %s", err, sqlite3_errmsg(sqlite));
|
|
sqlite3_close(sqlite);
|
|
isFree = true;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
isFree = false;
|
|
|
|
return 1;
|
|
}
|
|
|
|
void SQL::Disconnect()
|
|
{
|
|
Database.clear();
|
|
|
|
if (sqlite != NULL)
|
|
sqlite3_close(sqlite);
|
|
|
|
sqlite = NULL;
|
|
|
|
isFree = true;
|
|
}
|
|
|
|
int SQL::Query(const char *query)
|
|
{
|
|
if (sqlite == NULL || isFree)
|
|
{
|
|
ErrorCode = -1;
|
|
return -1;
|
|
}
|
|
|
|
unsigned int i = 0;
|
|
int id = -1;
|
|
for (i=0; i < Results.size(); i++)
|
|
{
|
|
if (Results[i]->isFree) {
|
|
id = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (id < 0) {
|
|
|
|
SQLResult *p = new SQLResult;
|
|
|
|
int ret = p->Query(this, query);
|
|
|
|
if (ret != 0)
|
|
{
|
|
delete p;
|
|
|
|
if (ret == -1)
|
|
return 0;
|
|
else
|
|
return -1;
|
|
} else {
|
|
Results.push_back(p);
|
|
#if defined _DEBUG
|
|
MF_PrintSrvConsole("***STORE: %d (push_back)\n", Results.size());
|
|
SQLResult::latestStoredResultId = Results.size();
|
|
#endif
|
|
|
|
return Results.size();
|
|
}
|
|
} else {
|
|
SQLResult *r = Results[id];
|
|
int ret = Results[id]->Query(this, query);
|
|
if (ret != 0)
|
|
{
|
|
if (ret == -1)
|
|
return 0;
|
|
else
|
|
return -1;
|
|
} else {
|
|
#if defined _DEBUG
|
|
MF_PrintSrvConsole("***STORE: %d\n", id + 1);
|
|
SQLResult::latestStoredResultId = id + 1;
|
|
#endif
|
|
return (id + 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
SQLResult::SQLResult()
|
|
{
|
|
isFree = true;
|
|
m_fieldNames = 0;
|
|
m_hasData = false;
|
|
m_currentRow = -1;
|
|
m_data = NULL;
|
|
m_errorMsg = NULL;
|
|
m_rowCount = 0;
|
|
m_columnCount = 0;
|
|
}
|
|
|
|
SQLResult::~SQLResult()
|
|
{
|
|
if (!isFree)
|
|
FreeResult();
|
|
}
|
|
|
|
int SQLResult::Query(SQL *cn, const char *query)
|
|
{
|
|
/*
|
|
int sqlite3_get_table(
|
|
sqlite3*, // An open database
|
|
const char *sql, // SQL to be executed
|
|
char ***resultp, // Result written to a char *[] that this points to
|
|
int *nrow, // Number of result rows written here
|
|
int *ncolumn, // Number of result columns written here
|
|
char **errmsg // Error msg written here
|
|
);
|
|
*/
|
|
int rowCount, columnCount;
|
|
int result = sqlite3_get_table(cn->sqlite, query, &m_data, &rowCount, &columnCount, &m_errorMsg);
|
|
m_rowCount = rowCount;
|
|
m_columnCount = columnCount;
|
|
if (result != SQLITE_OK)
|
|
{
|
|
MF_Log("Query error: %s", m_errorMsg);
|
|
return 1;
|
|
}
|
|
else {
|
|
if (!m_rowCount)
|
|
return -1;
|
|
m_hasData = true;
|
|
this->m_fieldNames = new String[m_columnCount];
|
|
for (unsigned int i = 0; i < m_columnCount; i++)
|
|
m_fieldNames[i].assign(m_data[i]);
|
|
|
|
#if defined _DEBUG
|
|
MF_PrintSrvConsole("SQLite: Select query returned %d rows in %d columns.\n", m_rowCount, m_columnCount);
|
|
for (unsigned int i = 0; i < m_columnCount; i++) {
|
|
MF_PrintSrvConsole("%15s", m_fieldNames[i].c_str());
|
|
}
|
|
MF_PrintSrvConsole("\n");
|
|
for (unsigned int i = 0; i < m_rowCount; i++) {
|
|
for (unsigned int j = 0; j < m_columnCount; j++) {
|
|
MF_PrintSrvConsole("%15s", m_data[(1 + i) * m_columnCount + j]);
|
|
}
|
|
MF_PrintSrvConsole("\n");
|
|
}
|
|
#endif
|
|
}
|
|
|
|
isFree = false;
|
|
return 0; // Return 0 here? and 1 on error... 0's get stored and 1's get deleted
|
|
}
|
|
|
|
bool SQLResult::Nextrow()
|
|
{
|
|
if (isFree)
|
|
return false;
|
|
|
|
if (++m_currentRow >= (int)this->m_rowCount) {
|
|
//m_currentRow = -1; <-- this is probably bad and inconsistent...
|
|
//FreeResult(); <-- this is probably bad and inconsistent... freeing should be the responsibility of the scripter
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void SQLResult::FreeResult()
|
|
{
|
|
if (isFree)
|
|
return;
|
|
/*
|
|
#if defined _DEBUG
|
|
MF_PrintSrvConsole("FREEING a result!\n");
|
|
#endif
|
|
*/
|
|
isFree = true;
|
|
|
|
if (m_hasData) {
|
|
sqlite3_free_table(m_data);
|
|
|
|
delete [] this->m_fieldNames;
|
|
|
|
m_hasData = false;
|
|
}
|
|
|
|
m_currentRow = -1;
|
|
m_columnCount = 0;
|
|
m_rowCount = 0;
|
|
}
|
|
|
|
const char *SQLResult::GetField(unsigned int field)
|
|
{
|
|
if (isFree || field >= m_columnCount || m_currentRow < 0 || m_currentRow >= (int)m_rowCount)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
char *data = m_data[(m_currentRow + 1) * m_columnCount + field];
|
|
|
|
return (data ? data : "");
|
|
}
|
|
|
|
const char *SQLResult::GetField(const char *field)
|
|
{
|
|
unsigned int i = 0;
|
|
int id = -1;
|
|
if (field == NULL)
|
|
return NULL;
|
|
for (i=0; i < m_columnCount; i++)
|
|
{
|
|
if (strcmp(m_fieldNames[i].c_str(), field) == 0)
|
|
{
|
|
id = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (id<0 || id>=(int)m_columnCount)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
return GetField(id);
|
|
}
|
|
|
|
unsigned int SQLResult::NumRows()
|
|
{
|
|
if (isFree)
|
|
return 0;
|
|
|
|
return m_rowCount;
|
|
}
|
|
#if defined _DEBUG
|
|
unsigned int SQLResult::latestStoredResultId = 0;
|
|
#endif
|
|
|