extensions/sqlite/driver/SqQuery.cpp
author David Anderson <dvander@alliedmods.net>
Sun Jul 29 14:56:24 2007 +0000 (2007-07-29)
changeset 1210 18e60c8737a2
parent 1203 633c25ce6405
child 1226 478550a4d5ec
permissions -rw-r--r--
fixed an sqlite bug where empty results would count as no result set
     1 /**
     2  * vim: set ts=4 :
     3  * ===============================================================
     4  * SourceMod SQLite Driver Extension
     5  * Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
     6  * ===============================================================
     7  *
     8  * This program is free software; you can redistribute it and/or
     9  * modify it under the terms of the GNU General Public License
    10  * as published by the Free Software Foundation; either version 2
    11  * of the License, or (at your option) any later version.
    12  * This program is distributed in the hope that it will be useful,
    13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    15  * GNU General Public License for more details.
    16  * 
    17  * You should have received a copy of the GNU General Public License
    18  * along with this program; if not, write to the Free Software
    19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
    20  *
    21  * Version: $Id$
    22  */
    23 
    24 #include "SqQuery.h"
    25 
    26 SqQuery::SqQuery(SqDatabase *parent, sqlite3_stmt *stmt) : 
    27  m_pParent(parent), m_pStmt(stmt), m_pResults(NULL), m_AffectedRows(0), m_InsertID(0)
    28 {
    29 	m_ParamCount = sqlite3_bind_parameter_count(m_pStmt);
    30 	m_ColCount = sqlite3_column_count(m_pStmt);
    31 	m_pParent->IncReferenceCount();
    32 }
    33 
    34 SqQuery::~SqQuery()
    35 {
    36 	delete m_pResults;
    37 	sqlite3_finalize(m_pStmt);
    38 	m_pParent->Close();
    39 }
    40 
    41 IResultSet *SqQuery::GetResultSet()
    42 {
    43 	return m_pResults;
    44 }
    45 
    46 bool SqQuery::FetchMoreResults()
    47 {
    48 	/* We never have multiple result sets */
    49 	return false;
    50 }
    51 
    52 void SqQuery::Destroy()
    53 {
    54 	delete this;
    55 }
    56 
    57 bool SqQuery::BindParamFloat(unsigned int param, float f)
    58 {
    59 	/* SQLite is 1 indexed */
    60 	param++;
    61 
    62 	if (param > m_ParamCount)
    63 	{
    64 		return false;
    65 	}
    66 
    67 	return (sqlite3_bind_double(m_pStmt, param, (double)f) == SQLITE_OK);
    68 }
    69 
    70 bool SqQuery::BindParamNull(unsigned int param)
    71 {
    72 	/* SQLite is 1 indexed */
    73 	param++;
    74 
    75 	if (param > m_ParamCount)
    76 	{
    77 		return false;
    78 	}
    79 
    80 	return (sqlite3_bind_null(m_pStmt, param) == SQLITE_OK);
    81 }
    82 
    83 bool SqQuery::BindParamString(unsigned int param, const char *text, bool copy)
    84 {
    85 	/* SQLite is 1 indexed */
    86 	param++;
    87 
    88 	if (param > m_ParamCount)
    89 	{
    90 		return false;
    91 	}
    92 
    93 	return (sqlite3_bind_text(m_pStmt, param, text, -1, copy ? SQLITE_TRANSIENT : SQLITE_STATIC) == SQLITE_OK);
    94 }
    95 
    96 bool SqQuery::BindParamInt(unsigned int param, int num, bool signd/* =true */)
    97 {
    98 	/* SQLite is 1 indexed */
    99 	param++;
   100 
   101 	if (param > m_ParamCount)
   102 	{
   103 		return false;
   104 	}
   105 
   106 	return (sqlite3_bind_int(m_pStmt, param, num) == SQLITE_OK);
   107 }
   108 
   109 bool SqQuery::BindParamBlob(unsigned int param, const void *data, size_t length, bool copy)
   110 {
   111 	/* SQLite is 1 indexed */
   112 	param++;
   113 
   114 	if (param > m_ParamCount)
   115 	{
   116 		return false;
   117 	}
   118 
   119 	return (sqlite3_bind_blob(m_pStmt, param, data, length, copy ? SQLITE_TRANSIENT : SQLITE_STATIC) == SQLITE_OK);
   120 }
   121 
   122 sqlite3_stmt *SqQuery::GetStmt()
   123 {
   124 	return m_pStmt;
   125 }
   126 
   127 bool SqQuery::Execute()
   128 {
   129 	int rc;
   130 
   131 	/* If we don't have a result set and we have a column count, 
   132 	 * create a result set pre-emptively.  This is in case there
   133 	 * are no rows in the upcoming result set.
   134 	 */
   135 	if (!m_pResults && m_ColCount)
   136 	{
   137 		m_pResults = new SqResults(this);
   138 	}
   139 
   140 	/* If we've got results, throw them away */
   141 	if (m_pResults)
   142 	{
   143 		m_pResults->ResetResultCount();
   144 	}
   145 
   146 	/* Fetch each row, if any */
   147 	while ((rc = sqlite3_step(m_pStmt)) == SQLITE_ROW)
   148 	{
   149 		/* This should NEVER happen but we're being safe. */
   150 		if (!m_pResults)
   151 		{
   152 			m_pResults = new SqResults(this);
   153 		}
   154 		m_pResults->PushResult();
   155 	}
   156 
   157 	sqlite3 *db = m_pParent->GetDb();
   158 	if (rc != SQLITE_OK && rc != SQLITE_DONE && rc == sqlite3_errcode(db))
   159 	{
   160 		/* Something happened... */
   161 		m_LastErrorCode = rc;
   162 		m_LastError.assign(sqlite3_errmsg(db));
   163 		m_AffectedRows = 0;
   164 		m_InsertID = 0;
   165 	} else {
   166 		m_LastErrorCode = SQLITE_OK;
   167 		m_AffectedRows = (unsigned int)sqlite3_changes(db);
   168 		m_InsertID = (unsigned int)sqlite3_last_insert_rowid(db);
   169 	}
   170 
   171 	/* Reset everything for the next execute */
   172 	sqlite3_reset(m_pStmt);
   173 	sqlite3_clear_bindings(m_pStmt);
   174 
   175 	return (m_LastErrorCode == SQLITE_OK);
   176 }
   177 
   178 const char *SqQuery::GetError(int *errCode/* =NULL */)
   179 {
   180 	if (errCode)
   181 	{
   182 		*errCode = m_LastErrorCode;
   183 	}
   184 	return m_LastError.c_str();
   185 }
   186 
   187 unsigned int SqQuery::GetAffectedRows()
   188 {
   189 	return m_AffectedRows;
   190 }
   191 
   192 unsigned int SqQuery::GetInsertID()
   193 {
   194 	return m_InsertID;
   195 }
   196 
   197