Forums  +  C++ and Sockets  +  C++ and SQL: MySQL, sqlite, ODBC  +  Miscellaneous Projects
Logo
~Database~
~ C++ ~
~Contact~

Query.cpp

Go to the documentation of this file.
00001 /*
00002  **     Query.cpp
00003  **
00004  **     Published / author: 2005-08-12 / grymse@alhem.net
00005  **/
00006 
00007 /*
00008 Copyright (C) 2001-2006  Anders Hedstrom
00009 
00010 This program is made available under the terms of the GNU GPL.
00011 
00012 If you would like to use this program in a closed-source application,
00013 a separate license agreement is available. For information about 
00014 the closed-source license agreement for this program, please
00015 visit http://www.alhem.net/sqlwrapped/license.html and/or
00016 email license@alhem.net.
00017 
00018 This program is free software; you can redistribute it and/or
00019 modify it under the terms of the GNU General Public License
00020 as published by the Free Software Foundation; either version 2
00021 of the License, or (at your option) any later version.
00022 
00023 This program is distributed in the hope that it will be useful,
00024 but WITHOUT ANY WARRANTY; without even the implied warranty of
00025 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00026 GNU General Public License for more details.
00027 
00028 You should have received a copy of the GNU General Public License
00029 along with this program; if not, write to the Free Software
00030 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00031 */
00032 #ifdef _WIN32
00033 #pragma warning(disable:4786)
00034 #endif
00035 
00036 #include <string>
00037 #include <map>
00038 #include <stdio.h>
00039 #include <stdlib.h>
00040 #include <string.h>
00041 #include <sqlite3.h>
00042 
00043 #include "Database.h"
00044 #include "Query.h"
00045 
00046 
00047 #ifdef SQLITEW_NAMESPACE
00048 namespace SQLITEW_NAMESPACE {
00049 #endif
00050 
00051 
00052 Query::Query(Database& dbin) 
00053 : m_db(dbin)
00054 ,odb(dbin.grabdb())
00055 ,res(NULL)
00056 ,row(false)
00057 ,cache_rc(0)
00058 ,cache_rc_valid(false)
00059 ,m_row_count(0)
00060 ,m_num_cols(0)
00061 {
00062 }
00063 
00064 
00065 Query::Query(Database& dbin,const std::string& sql) 
00066 : m_db(dbin)
00067 ,odb(dbin.grabdb())
00068 ,res(NULL)
00069 ,row(false)
00070 ,cache_rc(0)
00071 ,cache_rc_valid(false)
00072 ,m_row_count(0)
00073 ,m_num_cols(0)
00074 {
00075         execute(sql);
00076 }
00077 
00078 
00079 Query::~Query()
00080 {
00081         if (res)
00082         {
00083                 GetDatabase().error(*this, "sqlite3_finalize in destructor");
00084                 sqlite3_finalize(res);
00085         }
00086         if (odb)
00087         {
00088                 m_db.freedb(odb);
00089         }
00090 }
00091 
00092 
00093 Database& Query::GetDatabase() const
00094 {
00095         return m_db;
00096 }
00097 
00098 
00099 /*
00100 The sqlite3_finalize() routine deallocates a prepared SQL statement. 
00101 All prepared statements must be finalized before the database can be closed.
00102 */
00103 bool Query::execute(const std::string& sql)
00104 {
00105         // query, no result
00106         m_last_query = sql;
00107         if (odb && res)
00108         {
00109                 GetDatabase().error(*this, "execute: query busy");
00110         }
00111         if (odb && !res)
00112         {
00113                 const char *s = NULL;
00114                 int rc = sqlite3_prepare(odb -> db, sql.c_str(), sql.size(), &res, &s);
00115                 if (rc != SQLITE_OK)
00116                 {
00117                         GetDatabase().error(*this, "execute: prepare query failed");
00118                         return false;
00119                 }
00120                 if (!res)
00121                 {
00122                         GetDatabase().error(*this, "execute: query failed");
00123                         return false;
00124                 }
00125                 rc = sqlite3_step(res); // execute
00126                 sqlite3_finalize(res); // deallocate statement
00127                 res = NULL;
00128                 switch (rc)
00129                 {
00130                 case SQLITE_BUSY:
00131                         GetDatabase().error(*this, "execute: database busy");
00132                         return false;
00133                 case SQLITE_DONE:
00134                 case SQLITE_ROW:
00135                         return true;
00136                 case SQLITE_ERROR:
00137                         GetDatabase().error(*this, sqlite3_errmsg(odb -> db));
00138                         return false;
00139                 case SQLITE_MISUSE:
00140                         GetDatabase().error(*this, "execute: database misuse");
00141                         return false;
00142                 }
00143                 GetDatabase().error(*this, "execute: unknown result code");
00144         }
00145         return false;
00146 }
00147 
00148 
00149 
00150 // methods using db specific api calls
00151 
00152 sqlite3_stmt *Query::get_result(const std::string& sql)
00153 {
00154         // query, result
00155         m_last_query = sql;
00156         if (odb && res)
00157         {
00158                 GetDatabase().error(*this, "get_result: query busy");
00159         }
00160         if (odb && !res)
00161         {
00162                 const char *s = NULL;
00163                 int rc = sqlite3_prepare(odb -> db, sql.c_str(), sql.size(), &res, &s);
00164                 if (rc != SQLITE_OK)
00165                 {
00166                         GetDatabase().error(*this, "get_result: prepare query failed");
00167                         return NULL;
00168                 }
00169                 if (!res)
00170                 {
00171                         GetDatabase().error(*this, "get_result: query failed");
00172                         return NULL;
00173                 }
00174                 // get column names from result
00175                 {
00176                         int i = 0;
00177                         do
00178                         {
00179                                 const char *p = sqlite3_column_name(res, i);
00180                                 if (!p)
00181                                         break;
00182                                 m_nmap[p] = ++i;
00183                         } while (true);
00184                         m_num_cols = i;
00185                 }
00186                 cache_rc = sqlite3_step(res);
00187                 cache_rc_valid = true;
00188                 m_row_count = (cache_rc == SQLITE_ROW) ? 1 : 0;
00189         }
00190         return res;
00191 }
00192 
00193 
00194 void Query::free_result()
00195 {
00196         if (odb && res)
00197         {
00198                 sqlite3_finalize(res);
00199                 res = NULL;
00200                 row = false;
00201                 cache_rc_valid = false;
00202         }
00203         // clear column names
00204         while (m_nmap.size())
00205         {
00206                 std::map<std::string,int>::iterator it = m_nmap.begin();
00207                 m_nmap.erase(it);
00208         }
00209 }
00210 
00211 
00212 bool Query::fetch_row()
00213 {
00214         rowcount = 0;
00215         row = false;
00216         if (odb && res)
00217         {
00218                 int rc = cache_rc_valid ? cache_rc : sqlite3_step(res); // execute
00219                 cache_rc_valid = false;
00220                 switch (rc)
00221                 {
00222                 case SQLITE_BUSY:
00223                         GetDatabase().error(*this, "execute: database busy");
00224                         return false;
00225                 case SQLITE_DONE:
00226                         return false;
00227                 case SQLITE_ROW:
00228                         row = true;
00229                         return true;
00230                 case SQLITE_ERROR:
00231                         GetDatabase().error(*this, sqlite3_errmsg(odb -> db));
00232                         return false;
00233                 case SQLITE_MISUSE:
00234                         GetDatabase().error(*this, "execute: database misuse");
00235                         return false;
00236                 }
00237                 GetDatabase().error(*this, "execute: unknown result code");
00238         }
00239         return false;
00240 }
00241 
00242 
00243 sqlite_int64 Query::insert_id()
00244 {
00245         if (odb)
00246         {
00247                 return sqlite3_last_insert_rowid(odb -> db);
00248         }
00249         else
00250         {
00251                 return 0;
00252         }
00253 }
00254 
00255 
00256 long Query::num_rows()
00257 {
00258         return odb && res ? m_row_count : 0;
00259 }
00260 
00261 
00262 int Query::num_cols()
00263 {
00264         return m_num_cols;
00265 }
00266 
00267 
00268 bool Query::is_null(int x)
00269 {
00270         if (odb && res && row)
00271         {
00272                 if (sqlite3_column_type(res, x) == SQLITE_NULL)
00273                         return true;
00274         }
00275         return false; // ...
00276 }
00277 
00278 
00279 const char *Query::getstr(const std::string& x)
00280 {
00281         int index = m_nmap[x] - 1;
00282         if (index >= 0)
00283                 return getstr(index);
00284         error("Column name lookup failure: " + x);
00285         return "";
00286 }
00287 
00288 
00289 const char *Query::getstr(int x)
00290 {
00291         if (odb && res && row && x < sqlite3_column_count(res) )
00292         {
00293                 const unsigned char *tmp = sqlite3_column_text(res, x);
00294                 return tmp ? (const char *)tmp : "";
00295         }
00296         return "";
00297 }
00298 
00299 
00300 const char *Query::getstr()
00301 {
00302         return getstr(rowcount++);
00303 }
00304 
00305 
00306 double Query::getnum(const std::string& x)
00307 {
00308         int index = m_nmap[x] - 1;
00309         if (index >= 0)
00310                 return getnum(index);
00311         error("Column name lookup failure: " + x);
00312         return 0;
00313 }
00314 
00315 
00316 double Query::getnum(int x)
00317 {
00318         if (odb && res && row)
00319         {
00320                 return sqlite3_column_double(res, x);
00321         }
00322         return 0;
00323 }
00324 
00325 
00326 long Query::getval(const std::string& x)
00327 {
00328         int index = m_nmap[x] - 1;
00329         if (index >= 0)
00330                 return getval(index);
00331         error("Column name lookup failure: " + x);
00332         return 0;
00333 }
00334 
00335 
00336 long Query::getval(int x)
00337 {
00338         if (odb && res && row)
00339         {
00340                 return sqlite3_column_int(res, x);
00341         }
00342         return 0;
00343 }
00344 
00345 
00346 double Query::getnum()
00347 {
00348         return getnum(rowcount++);
00349 }
00350 
00351 
00352 long Query::getval()
00353 {
00354         return getval(rowcount++);
00355 }
00356 
00357 
00358 unsigned long Query::getuval(const std::string& x)
00359 {
00360         int index = m_nmap[x] - 1;
00361         if (index >= 0)
00362                 return getuval(index);
00363         error("Column name lookup failure: " + x);
00364         return 0;
00365 }
00366 
00367 
00368 unsigned long Query::getuval(int x)
00369 {
00370         unsigned long l = 0;
00371         if (odb && res && row)
00372         {
00373                 l = sqlite3_column_int(res, x);
00374         }
00375         return l;
00376 }
00377 
00378 
00379 unsigned long Query::getuval()
00380 {
00381         return getuval(rowcount++);
00382 }
00383 
00384 
00385 int64_t Query::getbigint(const std::string& x)
00386 {
00387         int index = m_nmap[x] - 1;
00388         if (index >= 0)
00389                 return getbigint(index);
00390         error("Column name lookup failure: " + x);
00391         return 0;
00392 }
00393 
00394 
00395 int64_t Query::getbigint(int x)
00396 {
00397         if (odb && res && row)
00398         {
00399                 return sqlite3_column_int64(res, x);
00400         }
00401         return 0;
00402 }
00403 
00404 
00405 int64_t Query::getbigint()
00406 {
00407         return getbigint(rowcount++);
00408 }
00409 
00410 
00411 uint64_t Query::getubigint(const std::string& x)
00412 {
00413         int index = m_nmap[x] - 1;
00414         if (index >= 0)
00415                 return getubigint(index);
00416         error("Column name lookup failure: " + x);
00417         return 0;
00418 }
00419 
00420 
00421 uint64_t Query::getubigint(int x)
00422 {
00423         uint64_t l = 0;
00424         if (odb && res && row)
00425         {
00426                 l = sqlite3_column_int64(res, x);
00427         }
00428         return l;
00429 }
00430 
00431 
00432 uint64_t Query::getubigint()
00433 {
00434         return getubigint(rowcount++);
00435 }
00436 
00437 
00438 double Query::get_num(const std::string& sql)
00439 {
00440         double l = 0;
00441         if (get_result(sql))
00442         {
00443                 if (fetch_row())
00444                 {
00445                         l = getnum();
00446                 }
00447                 free_result();
00448         }
00449         return l;
00450 }
00451 
00452 
00453 long Query::get_count(const std::string& sql)
00454 {
00455         long l = 0;
00456         if (get_result(sql))
00457         {
00458                 if (fetch_row())
00459                         l = getval();
00460                 free_result();
00461         }
00462         return l;
00463 }
00464 
00465 
00466 const char *Query::get_string(const std::string& sql)
00467 {
00468         bool found = false;
00469         m_tmpstr = "";
00470         if (get_result(sql))
00471         {
00472                 if (fetch_row())
00473                 {
00474                         m_tmpstr = getstr();
00475                         found = true;
00476                 }
00477                 free_result();
00478         }
00479         return m_tmpstr.c_str(); // %! changed from 1.0 which didn't return NULL on failed query
00480 }
00481 
00482 
00483 const std::string& Query::GetLastQuery()
00484 {
00485         return m_last_query;
00486 }
00487 
00488 
00489 std::string Query::GetError()
00490 {
00491         if (odb)
00492                 return sqlite3_errmsg(odb -> db);
00493         return "";
00494 }
00495 
00496 
00497 int Query::GetErrno()
00498 {
00499         if (odb)
00500                 return sqlite3_errcode(odb -> db);
00501         return 0;
00502 }
00503 
00504 
00505 bool Query::Connected()
00506 {
00507         return odb ? true : false;
00508 }
00509 
00510 
00511 
00512 
00513 void Query::ViewRes()
00514 {
00515         if (!res)
00516         {
00517                 printf("no result stored\n");
00518                 return;
00519         }
00520         printf("result column count = %d\n", sqlite3_column_count(res));
00521         for (int i = 0; i < sqlite3_column_count(res); i++)
00522         {
00523                 printf(" %2d   type %d   name '%s'", i, sqlite3_column_type(res, i), sqlite3_column_name(res, i));
00524                 printf("  / '%s'", (char *)sqlite3_column_text(res, i));
00525                 printf("  / %d", sqlite3_column_int(res, i));
00526                 printf("  / %f", sqlite3_column_double(res, i));
00527                 printf("\n");
00528         }
00529 }
00530 
00531 
00532 void Query::error(const std::string& msg)
00533 {
00534         GetDatabase().error(*this, msg);
00535 }
00536 
00537 
00538 #ifdef SQLITEW_NAMESPACE
00539 } // namespace SQLITEW_NAMESPACE {
00540 #endif
00541 
Page, code, and content Copyright (C) 2006 by Anders Hedström