1 ////////////////////////////////////////////////////////////////////////////////
\r
2 // CppSQLite3 - A C++ wrapper around the SQLite3 embedded database library.
\r
4 // Copyright (c) 2004 Rob Groves. All Rights Reserved. rob.groves@btinternet.com
\r
6 // Permission to use, copy, modify, and distribute this software and its
\r
7 // documentation for any purpose, without fee, and without a written
\r
8 // agreement, is hereby granted, provided that the above copyright notice,
\r
9 // this paragraph and the following two paragraphs appear in all copies,
\r
10 // modifications, and distributions.
\r
12 // IN NO EVENT SHALL THE AUTHOR BE LIABLE TO ANY PARTY FOR DIRECT,
\r
13 // INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST
\r
14 // PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION,
\r
15 // EVEN IF THE AUTHOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\r
17 // THE AUTHOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
\r
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
\r
19 // PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF
\r
20 // ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". THE AUTHOR HAS NO OBLIGATION
\r
21 // TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
\r
23 // V3.0 03/08/2004 -Initial Version for sqlite3
\r
25 // V3.1 16/09/2004 -Implemented getXXXXField using sqlite3 functions
\r
26 // -Added CppSQLiteDB3::tableExists()
\r
27 ////////////////////////////////////////////////////////////////////////////////
\r
28 #include "CppSQLite3.h"
\r
32 // Named constant for passing to CppSQLite3Exception when passing it a string
\r
33 // that cannot be deleted.
\r
34 static const bool DONT_DELETE_MSG=false;
\r
36 ////////////////////////////////////////////////////////////////////////////////
\r
37 // Prototypes for SQLite functions not included in SQLite DLL, but copied below
\r
38 // from SQLite encode.c
\r
39 ////////////////////////////////////////////////////////////////////////////////
\r
40 int sqlite3_encode_binary(const unsigned char *in, int n, unsigned char *out);
\r
41 int sqlite3_decode_binary(const unsigned char *in, unsigned char *out);
\r
43 ////////////////////////////////////////////////////////////////////////////////
\r
45 ////////////////////////////////////////////////////////////////////////////////
\r
47 CppSQLite3Exception::CppSQLite3Exception(const int nErrCode,
\r
49 bool bDeleteMsg/*=true*/) :
\r
52 mpszErrMess = sqlite3_mprintf("%s[%d]: %s",
\r
53 errorCodeAsString(nErrCode),
\r
55 szErrMess ? szErrMess : "");
\r
57 if (bDeleteMsg && szErrMess)
\r
59 sqlite3_free(szErrMess);
\r
64 CppSQLite3Exception::CppSQLite3Exception(const CppSQLite3Exception& e) :
\r
65 mnErrCode(e.mnErrCode)
\r
70 mpszErrMess = sqlite3_mprintf("%s", e.mpszErrMess);
\r
75 const char* CppSQLite3Exception::errorCodeAsString(int nErrCode)
\r
79 case SQLITE_OK : return "SQLITE_OK";
\r
80 case SQLITE_ERROR : return "SQLITE_ERROR";
\r
81 case SQLITE_INTERNAL : return "SQLITE_INTERNAL";
\r
82 case SQLITE_PERM : return "SQLITE_PERM";
\r
83 case SQLITE_ABORT : return "SQLITE_ABORT";
\r
84 case SQLITE_BUSY : return "SQLITE_BUSY";
\r
85 case SQLITE_LOCKED : return "SQLITE_LOCKED";
\r
86 case SQLITE_NOMEM : return "SQLITE_NOMEM";
\r
87 case SQLITE_READONLY : return "SQLITE_READONLY";
\r
88 case SQLITE_INTERRUPT : return "SQLITE_INTERRUPT";
\r
89 case SQLITE_IOERR : return "SQLITE_IOERR";
\r
90 case SQLITE_CORRUPT : return "SQLITE_CORRUPT";
\r
91 case SQLITE_NOTFOUND : return "SQLITE_NOTFOUND";
\r
92 case SQLITE_FULL : return "SQLITE_FULL";
\r
93 case SQLITE_CANTOPEN : return "SQLITE_CANTOPEN";
\r
94 case SQLITE_PROTOCOL : return "SQLITE_PROTOCOL";
\r
95 case SQLITE_EMPTY : return "SQLITE_EMPTY";
\r
96 case SQLITE_SCHEMA : return "SQLITE_SCHEMA";
\r
97 case SQLITE_TOOBIG : return "SQLITE_TOOBIG";
\r
98 case SQLITE_CONSTRAINT : return "SQLITE_CONSTRAINT";
\r
99 case SQLITE_MISMATCH : return "SQLITE_MISMATCH";
\r
100 case SQLITE_MISUSE : return "SQLITE_MISUSE";
\r
101 case SQLITE_NOLFS : return "SQLITE_NOLFS";
\r
102 case SQLITE_AUTH : return "SQLITE_AUTH";
\r
103 case SQLITE_FORMAT : return "SQLITE_FORMAT";
\r
104 case SQLITE_RANGE : return "SQLITE_RANGE";
\r
105 case SQLITE_ROW : return "SQLITE_ROW";
\r
106 case SQLITE_DONE : return "SQLITE_DONE";
\r
107 case CPPSQLITE_ERROR : return "CPPSQLITE_ERROR";
\r
108 default: return "UNKNOWN_ERROR";
\r
113 CppSQLite3Exception::~CppSQLite3Exception()
\r
117 sqlite3_free(mpszErrMess);
\r
123 ////////////////////////////////////////////////////////////////////////////////
\r
125 CppSQLite3Buffer::CppSQLite3Buffer()
\r
131 CppSQLite3Buffer::~CppSQLite3Buffer()
\r
137 void CppSQLite3Buffer::clear()
\r
141 sqlite3_free(mpBuf);
\r
148 const char* CppSQLite3Buffer::format(const char* szFormat, ...)
\r
152 va_start(va, szFormat);
\r
153 mpBuf = sqlite3_vmprintf(szFormat, va);
\r
159 ////////////////////////////////////////////////////////////////////////////////
\r
161 CppSQLite3Binary::CppSQLite3Binary() :
\r
171 CppSQLite3Binary::~CppSQLite3Binary()
\r
177 void CppSQLite3Binary::setBinary(const unsigned char* pBuf, int nLen)
\r
179 mpBuf = allocBuffer(nLen);
\r
180 memcpy(mpBuf, pBuf, nLen);
\r
184 void CppSQLite3Binary::setEncoded(const unsigned char* pBuf)
\r
188 mnEncodedLen = strlen((const char*)pBuf);
\r
189 mnBufferLen = mnEncodedLen + 1; // Allow for NULL terminator
\r
191 mpBuf = (unsigned char*)malloc(mnBufferLen);
\r
195 throw CppSQLite3Exception(CPPSQLITE_ERROR,
\r
196 "Cannot allocate memory",
\r
200 memcpy(mpBuf, pBuf, mnBufferLen);
\r
205 const unsigned char* CppSQLite3Binary::getEncoded()
\r
209 unsigned char* ptmp = (unsigned char*)malloc(mnBinaryLen);
\r
210 memcpy(ptmp, mpBuf, mnBinaryLen);
\r
211 mnEncodedLen = sqlite3_encode_binary(ptmp, mnBinaryLen, mpBuf);
\r
220 const unsigned char* CppSQLite3Binary::getBinary()
\r
224 // in/out buffers can be the same
\r
225 mnBinaryLen = sqlite3_decode_binary(mpBuf, mpBuf);
\r
227 if (mnBinaryLen == -1)
\r
229 throw CppSQLite3Exception(CPPSQLITE_ERROR,
\r
230 "Cannot decode binary",
\r
241 int CppSQLite3Binary::getBinaryLength()
\r
244 return mnBinaryLen;
\r
248 unsigned char* CppSQLite3Binary::allocBuffer(int nLen)
\r
252 // Allow extra space for encoded binary as per comments in
\r
253 // SQLite encode.c See bottom of this file for implementation
\r
254 // of SQLite functions use 3 instead of 2 just to be sure ;-)
\r
255 mnBinaryLen = nLen;
\r
256 mnBufferLen = 3 + (257*nLen)/254;
\r
258 mpBuf = (unsigned char*)malloc(mnBufferLen);
\r
262 throw CppSQLite3Exception(CPPSQLITE_ERROR,
\r
263 "Cannot allocate memory",
\r
273 void CppSQLite3Binary::clear()
\r
285 ////////////////////////////////////////////////////////////////////////////////
\r
287 CppSQLite3Query::CppSQLite3Query()
\r
296 CppSQLite3Query::CppSQLite3Query(const CppSQLite3Query& rQuery)
\r
298 mpVM = rQuery.mpVM;
\r
299 // Only one object can own the VM
\r
300 const_cast<CppSQLite3Query&>(rQuery).mpVM = 0;
\r
301 mbEof = rQuery.mbEof;
\r
302 mnCols = rQuery.mnCols;
\r
303 mbOwnVM = rQuery.mbOwnVM;
\r
307 CppSQLite3Query::CppSQLite3Query(sqlite3* pDB,
\r
310 bool bOwnVM/*=true*/)
\r
315 mnCols = sqlite3_column_count(mpVM);
\r
320 CppSQLite3Query::~CppSQLite3Query()
\r
332 CppSQLite3Query& CppSQLite3Query::operator=(const CppSQLite3Query& rQuery)
\r
341 mpVM = rQuery.mpVM;
\r
342 // Only one object can own the VM
\r
343 const_cast<CppSQLite3Query&>(rQuery).mpVM = 0;
\r
344 mbEof = rQuery.mbEof;
\r
345 mnCols = rQuery.mnCols;
\r
346 mbOwnVM = rQuery.mbOwnVM;
\r
351 int CppSQLite3Query::numFields()
\r
358 const char* CppSQLite3Query::fieldValue(int nField)
\r
362 if (nField < 0 || nField > mnCols-1)
\r
364 throw CppSQLite3Exception(CPPSQLITE_ERROR,
\r
365 "Invalid field index requested",
\r
369 return (const char*)sqlite3_column_text(mpVM, nField);
\r
373 const char* CppSQLite3Query::fieldValue(const char* szField)
\r
375 int nField = fieldIndex(szField);
\r
376 return (const char*)sqlite3_column_text(mpVM, nField);
\r
380 int CppSQLite3Query::getIntField(int nField, int nNullValue/*=0*/)
\r
382 if (fieldDataType(nField) == SQLITE_NULL)
\r
388 return sqlite3_column_int(mpVM, nField);
\r
393 int CppSQLite3Query::getIntField(const char* szField, int nNullValue/*=0*/)
\r
395 int nField = fieldIndex(szField);
\r
396 return getIntField(nField, nNullValue);
\r
400 double CppSQLite3Query::getFloatField(int nField, double fNullValue/*=0.0*/)
\r
402 if (fieldDataType(nField) == SQLITE_NULL)
\r
408 return sqlite3_column_double(mpVM, nField);
\r
413 double CppSQLite3Query::getFloatField(const char* szField, double fNullValue/*=0.0*/)
\r
415 int nField = fieldIndex(szField);
\r
416 return getFloatField(nField, fNullValue);
\r
420 const char* CppSQLite3Query::getStringField(int nField, const char* szNullValue/*=""*/)
\r
422 if (fieldDataType(nField) == SQLITE_NULL)
\r
424 return szNullValue;
\r
428 return (const char*)sqlite3_column_text(mpVM, nField);
\r
433 const char* CppSQLite3Query::getStringField(const char* szField, const char* szNullValue/*=""*/)
\r
435 int nField = fieldIndex(szField);
\r
436 return getStringField(nField, szNullValue);
\r
440 const unsigned char* CppSQLite3Query::getBlobField(int nField, int& nLen)
\r
444 if (nField < 0 || nField > mnCols-1)
\r
446 throw CppSQLite3Exception(CPPSQLITE_ERROR,
\r
447 "Invalid field index requested",
\r
451 nLen = sqlite3_column_bytes(mpVM, nField);
\r
452 return (const unsigned char*)sqlite3_column_blob(mpVM, nField);
\r
456 const unsigned char* CppSQLite3Query::getBlobField(const char* szField, int& nLen)
\r
458 int nField = fieldIndex(szField);
\r
459 return getBlobField(nField, nLen);
\r
463 bool CppSQLite3Query::fieldIsNull(int nField)
\r
465 return (fieldDataType(nField) == SQLITE_NULL);
\r
469 bool CppSQLite3Query::fieldIsNull(const char* szField)
\r
471 int nField = fieldIndex(szField);
\r
472 return (fieldDataType(nField) == SQLITE_NULL);
\r
476 int CppSQLite3Query::fieldIndex(const char* szField)
\r
482 for (int nField = 0; nField < mnCols; nField++)
\r
484 const char* szTemp = sqlite3_column_name(mpVM, nField);
\r
486 if (strcmp(szField, szTemp) == 0)
\r
493 throw CppSQLite3Exception(CPPSQLITE_ERROR,
\r
494 "Invalid field name requested",
\r
499 const char* CppSQLite3Query::fieldName(int nCol)
\r
503 if (nCol < 0 || nCol > mnCols-1)
\r
505 throw CppSQLite3Exception(CPPSQLITE_ERROR,
\r
506 "Invalid field index requested",
\r
510 return sqlite3_column_name(mpVM, nCol);
\r
514 const char* CppSQLite3Query::fieldDeclType(int nCol)
\r
518 if (nCol < 0 || nCol > mnCols-1)
\r
520 throw CppSQLite3Exception(CPPSQLITE_ERROR,
\r
521 "Invalid field index requested",
\r
525 return sqlite3_column_decltype(mpVM, nCol);
\r
529 int CppSQLite3Query::fieldDataType(int nCol)
\r
533 if (nCol < 0 || nCol > mnCols-1)
\r
535 throw CppSQLite3Exception(CPPSQLITE_ERROR,
\r
536 "Invalid field index requested",
\r
540 return sqlite3_column_type(mpVM, nCol);
\r
544 bool CppSQLite3Query::eof()
\r
551 void CppSQLite3Query::nextRow()
\r
555 int nRet = sqlite3_step(mpVM);
\r
557 if (nRet == SQLITE_DONE)
\r
562 else if (nRet == SQLITE_ROW)
\r
564 // more rows, nothing to do
\r
568 nRet = sqlite3_finalize(mpVM);
\r
570 const char* szError = sqlite3_errmsg(mpDB);
\r
571 throw CppSQLite3Exception(nRet,
\r
578 void CppSQLite3Query::finalize()
\r
580 if (mpVM && mbOwnVM)
\r
582 int nRet = sqlite3_finalize(mpVM);
\r
584 if (nRet != SQLITE_OK)
\r
586 const char* szError = sqlite3_errmsg(mpDB);
\r
587 throw CppSQLite3Exception(nRet, (char*)szError, DONT_DELETE_MSG);
\r
593 void CppSQLite3Query::checkVM()
\r
597 throw CppSQLite3Exception(CPPSQLITE_ERROR,
\r
598 "Null Virtual Machine pointer",
\r
604 ////////////////////////////////////////////////////////////////////////////////
\r
606 CppSQLite3Table::CppSQLite3Table()
\r
615 CppSQLite3Table::CppSQLite3Table(const CppSQLite3Table& rTable)
\r
617 mpaszResults = rTable.mpaszResults;
\r
618 // Only one object can own the results
\r
619 const_cast<CppSQLite3Table&>(rTable).mpaszResults = 0;
\r
620 mnRows = rTable.mnRows;
\r
621 mnCols = rTable.mnCols;
\r
622 mnCurrentRow = rTable.mnCurrentRow;
\r
626 CppSQLite3Table::CppSQLite3Table(char** paszResults, int nRows, int nCols)
\r
628 mpaszResults = paszResults;
\r
635 CppSQLite3Table::~CppSQLite3Table()
\r
647 CppSQLite3Table& CppSQLite3Table::operator=(const CppSQLite3Table& rTable)
\r
656 mpaszResults = rTable.mpaszResults;
\r
657 // Only one object can own the results
\r
658 const_cast<CppSQLite3Table&>(rTable).mpaszResults = 0;
\r
659 mnRows = rTable.mnRows;
\r
660 mnCols = rTable.mnCols;
\r
661 mnCurrentRow = rTable.mnCurrentRow;
\r
666 void CppSQLite3Table::finalize()
\r
670 sqlite3_free_table(mpaszResults);
\r
676 int CppSQLite3Table::numFields()
\r
683 int CppSQLite3Table::numRows()
\r
690 const char* CppSQLite3Table::fieldValue(int nField)
\r
694 if (nField < 0 || nField > mnCols-1)
\r
696 throw CppSQLite3Exception(CPPSQLITE_ERROR,
\r
697 "Invalid field index requested",
\r
701 int nIndex = (mnCurrentRow*mnCols) + mnCols + nField;
\r
702 return mpaszResults[nIndex];
\r
706 const char* CppSQLite3Table::fieldValue(const char* szField)
\r
712 for (int nField = 0; nField < mnCols; nField++)
\r
714 if (strcmp(szField, mpaszResults[nField]) == 0)
\r
716 int nIndex = (mnCurrentRow*mnCols) + mnCols + nField;
\r
717 return mpaszResults[nIndex];
\r
722 throw CppSQLite3Exception(CPPSQLITE_ERROR,
\r
723 "Invalid field name requested",
\r
728 int CppSQLite3Table::getIntField(int nField, int nNullValue/*=0*/)
\r
730 if (fieldIsNull(nField))
\r
736 return atoi(fieldValue(nField));
\r
741 int CppSQLite3Table::getIntField(const char* szField, int nNullValue/*=0*/)
\r
743 if (fieldIsNull(szField))
\r
749 return atoi(fieldValue(szField));
\r
754 double CppSQLite3Table::getFloatField(int nField, double fNullValue/*=0.0*/)
\r
756 if (fieldIsNull(nField))
\r
762 return atof(fieldValue(nField));
\r
767 double CppSQLite3Table::getFloatField(const char* szField, double fNullValue/*=0.0*/)
\r
769 if (fieldIsNull(szField))
\r
775 return atof(fieldValue(szField));
\r
780 const char* CppSQLite3Table::getStringField(int nField, const char* szNullValue/*=""*/)
\r
782 if (fieldIsNull(nField))
\r
784 return szNullValue;
\r
788 return fieldValue(nField);
\r
793 const char* CppSQLite3Table::getStringField(const char* szField, const char* szNullValue/*=""*/)
\r
795 if (fieldIsNull(szField))
\r
797 return szNullValue;
\r
801 return fieldValue(szField);
\r
806 bool CppSQLite3Table::fieldIsNull(int nField)
\r
809 return (fieldValue(nField) == 0);
\r
813 bool CppSQLite3Table::fieldIsNull(const char* szField)
\r
816 return (fieldValue(szField) == 0);
\r
820 const char* CppSQLite3Table::fieldName(int nCol)
\r
824 if (nCol < 0 || nCol > mnCols-1)
\r
826 throw CppSQLite3Exception(CPPSQLITE_ERROR,
\r
827 "Invalid field index requested",
\r
831 return mpaszResults[nCol];
\r
835 void CppSQLite3Table::setRow(int nRow)
\r
839 if (nRow < 0 || nRow > mnRows-1)
\r
841 throw CppSQLite3Exception(CPPSQLITE_ERROR,
\r
842 "Invalid row index requested",
\r
846 mnCurrentRow = nRow;
\r
850 void CppSQLite3Table::checkResults()
\r
852 if (mpaszResults == 0)
\r
854 throw CppSQLite3Exception(CPPSQLITE_ERROR,
\r
855 "Null Results pointer",
\r
861 ////////////////////////////////////////////////////////////////////////////////
\r
863 CppSQLite3Statement::CppSQLite3Statement()
\r
870 CppSQLite3Statement::CppSQLite3Statement(const CppSQLite3Statement& rStatement)
\r
872 mpDB = rStatement.mpDB;
\r
873 mpVM = rStatement.mpVM;
\r
874 // Only one object can own VM
\r
875 const_cast<CppSQLite3Statement&>(rStatement).mpVM = 0;
\r
879 CppSQLite3Statement::CppSQLite3Statement(sqlite3* pDB, sqlite3_stmt* pVM)
\r
886 CppSQLite3Statement::~CppSQLite3Statement()
\r
898 CppSQLite3Statement& CppSQLite3Statement::operator=(const CppSQLite3Statement& rStatement)
\r
900 mpDB = rStatement.mpDB;
\r
901 mpVM = rStatement.mpVM;
\r
902 // Only one object can own VM
\r
903 const_cast<CppSQLite3Statement&>(rStatement).mpVM = 0;
\r
908 int CppSQLite3Statement::execDML()
\r
913 const char* szError=0;
\r
915 int nRet = sqlite3_step(mpVM);
\r
917 if (nRet == SQLITE_DONE)
\r
919 int nRowsChanged = sqlite3_changes(mpDB);
\r
921 nRet = sqlite3_reset(mpVM);
\r
923 if (nRet != SQLITE_OK)
\r
925 szError = sqlite3_errmsg(mpDB);
\r
926 throw CppSQLite3Exception(nRet, (char*)szError, DONT_DELETE_MSG);
\r
929 return nRowsChanged;
\r
933 nRet = sqlite3_reset(mpVM);
\r
934 szError = sqlite3_errmsg(mpDB);
\r
935 throw CppSQLite3Exception(nRet, (char*)szError, DONT_DELETE_MSG);
\r
940 CppSQLite3Query CppSQLite3Statement::execQuery()
\r
945 int nRet = sqlite3_step(mpVM);
\r
947 if (nRet == SQLITE_DONE)
\r
950 return CppSQLite3Query(mpDB, mpVM, true/*eof*/, false);
\r
952 else if (nRet == SQLITE_ROW)
\r
955 return CppSQLite3Query(mpDB, mpVM, false/*eof*/, false);
\r
959 nRet = sqlite3_reset(mpVM);
\r
960 const char* szError = sqlite3_errmsg(mpDB);
\r
961 throw CppSQLite3Exception(nRet, (char*)szError, DONT_DELETE_MSG);
\r
966 void CppSQLite3Statement::bind(int nParam, const char* szValue)
\r
969 int nRes = sqlite3_bind_text(mpVM, nParam, szValue, -1, SQLITE_TRANSIENT);
\r
971 if (nRes != SQLITE_OK)
\r
973 throw CppSQLite3Exception(nRes,
\r
974 "Error binding string param",
\r
980 void CppSQLite3Statement::bind(int nParam, const int nValue)
\r
983 int nRes = sqlite3_bind_int(mpVM, nParam, nValue);
\r
985 if (nRes != SQLITE_OK)
\r
987 throw CppSQLite3Exception(nRes,
\r
988 "Error binding int param",
\r
994 void CppSQLite3Statement::bind(int nParam, const double dValue)
\r
997 int nRes = sqlite3_bind_double(mpVM, nParam, dValue);
\r
999 if (nRes != SQLITE_OK)
\r
1001 throw CppSQLite3Exception(nRes,
\r
1002 "Error binding double param",
\r
1008 void CppSQLite3Statement::bind(int nParam, const unsigned char* blobValue, int nLen)
\r
1011 int nRes = sqlite3_bind_blob(mpVM, nParam,
\r
1012 (const void*)blobValue, nLen, SQLITE_TRANSIENT);
\r
1014 if (nRes != SQLITE_OK)
\r
1016 throw CppSQLite3Exception(nRes,
\r
1017 "Error binding blob param",
\r
1023 void CppSQLite3Statement::bindNull(int nParam)
\r
1026 int nRes = sqlite3_bind_null(mpVM, nParam);
\r
1028 if (nRes != SQLITE_OK)
\r
1030 throw CppSQLite3Exception(nRes,
\r
1031 "Error binding NULL param",
\r
1037 void CppSQLite3Statement::reset()
\r
1041 int nRet = sqlite3_reset(mpVM);
\r
1043 if (nRet != SQLITE_OK)
\r
1045 const char* szError = sqlite3_errmsg(mpDB);
\r
1046 throw CppSQLite3Exception(nRet, (char*)szError, DONT_DELETE_MSG);
\r
1052 void CppSQLite3Statement::finalize()
\r
1056 int nRet = sqlite3_finalize(mpVM);
\r
1059 if (nRet != SQLITE_OK)
\r
1061 const char* szError = sqlite3_errmsg(mpDB);
\r
1062 throw CppSQLite3Exception(nRet, (char*)szError, DONT_DELETE_MSG);
\r
1068 void CppSQLite3Statement::checkDB()
\r
1072 throw CppSQLite3Exception(CPPSQLITE_ERROR,
\r
1073 "Database not open",
\r
1079 void CppSQLite3Statement::checkVM()
\r
1083 throw CppSQLite3Exception(CPPSQLITE_ERROR,
\r
1084 "Null Virtual Machine pointer",
\r
1090 ////////////////////////////////////////////////////////////////////////////////
\r
1092 CppSQLite3DB::CppSQLite3DB()
\r
1095 mnBusyTimeoutMs = 60000; // 60 seconds
\r
1099 CppSQLite3DB::CppSQLite3DB(const CppSQLite3DB& db)
\r
1102 mnBusyTimeoutMs = 60000; // 60 seconds
\r
1106 CppSQLite3DB::~CppSQLite3DB()
\r
1112 CppSQLite3DB& CppSQLite3DB::operator=(const CppSQLite3DB& db)
\r
1115 mnBusyTimeoutMs = 60000; // 60 seconds
\r
1120 void CppSQLite3DB::open(const char* szFile)
\r
1122 int nRet = sqlite3_open(szFile, &mpDB);
\r
1124 if (nRet != SQLITE_OK)
\r
1126 const char* szError = sqlite3_errmsg(mpDB);
\r
1127 throw CppSQLite3Exception(nRet, (char*)szError, DONT_DELETE_MSG);
\r
1130 setBusyTimeout(mnBusyTimeoutMs);
\r
1134 void CppSQLite3DB::close()
\r
1138 sqlite3_close(mpDB);
\r
1144 CppSQLite3Statement CppSQLite3DB::compileStatement(const char* szSQL)
\r
1148 sqlite3_stmt* pVM = compile(szSQL);
\r
1149 return CppSQLite3Statement(mpDB, pVM);
\r
1153 bool CppSQLite3DB::tableExists(const char* szTable)
\r
1157 "select count(*) from sqlite_master where type='table' and name='%s'",
\r
1159 int nRet = execScalar(szSQL);
\r
1160 return (nRet > 0);
\r
1164 int CppSQLite3DB::execDML(const char* szSQL)
\r
1170 int nRet = sqlite3_exec(mpDB, szSQL, 0, 0, &szError);
\r
1172 if (nRet == SQLITE_OK)
\r
1174 return sqlite3_changes(mpDB);
\r
1178 throw CppSQLite3Exception(nRet, szError);
\r
1183 CppSQLite3Query CppSQLite3DB::execQuery(const char* szSQL)
\r
1187 sqlite3_stmt* pVM = compile(szSQL);
\r
1189 int nRet = sqlite3_step(pVM);
\r
1191 if (nRet == SQLITE_DONE)
\r
1194 return CppSQLite3Query(mpDB, pVM, true/*eof*/);
\r
1196 else if (nRet == SQLITE_ROW)
\r
1199 return CppSQLite3Query(mpDB, pVM, false/*eof*/);
\r
1203 nRet = sqlite3_finalize(pVM);
\r
1204 const char* szError= sqlite3_errmsg(mpDB);
\r
1205 throw CppSQLite3Exception(nRet, (char*)szError, DONT_DELETE_MSG);
\r
1210 int CppSQLite3DB::execScalar(const char* szSQL)
\r
1212 CppSQLite3Query q = execQuery(szSQL);
\r
1214 if (q.eof() || q.numFields() < 1)
\r
1216 throw CppSQLite3Exception(CPPSQLITE_ERROR,
\r
1217 "Invalid scalar query",
\r
1221 return atoi(q.fieldValue(0));
\r
1225 CppSQLite3Table CppSQLite3DB::getTable(const char* szSQL)
\r
1230 char** paszResults=0;
\r
1235 nRet = sqlite3_get_table(mpDB, szSQL, &paszResults, &nRows, &nCols, &szError);
\r
1237 if (nRet == SQLITE_OK)
\r
1239 return CppSQLite3Table(paszResults, nRows, nCols);
\r
1243 throw CppSQLite3Exception(nRet, szError);
\r
1248 sqlite_int64 CppSQLite3DB::lastRowId()
\r
1250 return sqlite3_last_insert_rowid(mpDB);
\r
1254 void CppSQLite3DB::setBusyTimeout(int nMillisecs)
\r
1256 mnBusyTimeoutMs = nMillisecs;
\r
1257 sqlite3_busy_timeout(mpDB, mnBusyTimeoutMs);
\r
1261 void CppSQLite3DB::checkDB()
\r
1265 throw CppSQLite3Exception(CPPSQLITE_ERROR,
\r
1266 "Database not open",
\r
1272 sqlite3_stmt* CppSQLite3DB::compile(const char* szSQL)
\r
1277 const char* szTail=0;
\r
1278 sqlite3_stmt* pVM;
\r
1280 int nRet = sqlite3_prepare(mpDB, szSQL, -1, &pVM, &szTail);
\r
1282 if (nRet != SQLITE_OK)
\r
1284 throw CppSQLite3Exception(nRet, szError);
\r
1291 ////////////////////////////////////////////////////////////////////////////////
\r
1292 // SQLite encode.c reproduced here, containing implementation notes and source
\r
1293 // for sqlite3_encode_binary() and sqlite3_decode_binary()
\r
1294 ////////////////////////////////////////////////////////////////////////////////
\r
1299 ** The author disclaims copyright to this source code. In place of
\r
1300 ** a legal notice, here is a blessing:
\r
1302 ** May you do good and not evil.
\r
1303 ** May you find forgiveness for yourself and forgive others.
\r
1304 ** May you share freely, never taking more than you give.
\r
1306 *************************************************************************
\r
1307 ** This file contains helper routines used to translate binary data into
\r
1308 ** a null-terminated string (suitable for use in SQLite) and back again.
\r
1309 ** These are convenience routines for use by people who want to store binary
\r
1310 ** data in an SQLite database. The code in this file is not used by any other
\r
1311 ** part of the SQLite library.
\r
1313 ** $Id: CppSQLite3.cpp,v 1.1 2008/09/26 14:15:48 guigues Exp $
\r
1317 ** How This Encoder Works
\r
1319 ** The output is allowed to contain any character except 0x27 (') and
\r
1320 ** 0x00. This is accomplished by using an escape character to encode
\r
1321 ** 0x27 and 0x00 as a two-byte sequence. The escape character is always
\r
1322 ** 0x01. An 0x00 is encoded as the two byte sequence 0x01 0x01. The
\r
1323 ** 0x27 character is encoded as the two byte sequence 0x01 0x03. Finally,
\r
1324 ** the escape character itself is encoded as the two-character sequence
\r
1327 ** To summarize, the encoder works by using an escape sequences as follows:
\r
1329 ** 0x00 -> 0x01 0x01
\r
1330 ** 0x01 -> 0x01 0x02
\r
1331 ** 0x27 -> 0x01 0x03
\r
1333 ** If that were all the encoder did, it would work, but in certain cases
\r
1334 ** it could double the size of the encoded string. For example, to
\r
1335 ** encode a string of 100 0x27 characters would require 100 instances of
\r
1336 ** the 0x01 0x03 escape sequence resulting in a 200-character output.
\r
1337 ** We would prefer to keep the size of the encoded string smaller than
\r
1340 ** To minimize the encoding size, we first add a fixed offset value to each
\r
1341 ** byte in the sequence. The addition is modulo 256. (That is to say, if
\r
1342 ** the sum of the original character value and the offset exceeds 256, then
\r
1343 ** the higher order bits are truncated.) The offset is chosen to minimize
\r
1344 ** the number of characters in the string that need to be escaped. For
\r
1345 ** example, in the case above where the string was composed of 100 0x27
\r
1346 ** characters, the offset might be 0x01. Each of the 0x27 characters would
\r
1347 ** then be converted into an 0x28 character which would not need to be
\r
1348 ** escaped at all and so the 100 character input string would be converted
\r
1349 ** into just 100 characters of output. Actually 101 characters of output -
\r
1350 ** we have to record the offset used as the first byte in the sequence so
\r
1351 ** that the string can be decoded. Since the offset value is stored as
\r
1352 ** part of the output string and the output string is not allowed to contain
\r
1353 ** characters 0x00 or 0x27, the offset cannot be 0x00 or 0x27.
\r
1355 ** Here, then, are the encoding steps:
\r
1357 ** (1) Choose an offset value and make it the first character of
\r
1360 ** (2) Copy each input character into the output buffer, one by
\r
1361 ** one, adding the offset value as you copy.
\r
1363 ** (3) If the value of an input character plus offset is 0x00, replace
\r
1364 ** that one character by the two-character sequence 0x01 0x01.
\r
1365 ** If the sum is 0x01, replace it with 0x01 0x02. If the sum
\r
1366 ** is 0x27, replace it with 0x01 0x03.
\r
1368 ** (4) Put a 0x00 terminator at the end of the output.
\r
1370 ** Decoding is obvious:
\r
1372 ** (5) Copy encoded characters except the first into the decode
\r
1373 ** buffer. Set the first encoded character aside for use as
\r
1374 ** the offset in step 7 below.
\r
1376 ** (6) Convert each 0x01 0x01 sequence into a single character 0x00.
\r
1377 ** Convert 0x01 0x02 into 0x01. Convert 0x01 0x03 into 0x27.
\r
1379 ** (7) Subtract the offset value that was the first character of
\r
1380 ** the encoded buffer from all characters in the output buffer.
\r
1382 ** The only tricky part is step (1) - how to compute an offset value to
\r
1383 ** minimize the size of the output buffer. This is accomplished by testing
\r
1384 ** all offset values and picking the one that results in the fewest number
\r
1385 ** of escapes. To do that, we first scan the entire input and count the
\r
1386 ** number of occurances of each character value in the input. Suppose
\r
1387 ** the number of 0x00 characters is N(0), the number of occurances of 0x01
\r
1388 ** is N(1), and so forth up to the number of occurances of 0xff is N(255).
\r
1389 ** An offset of 0 is not allowed so we don't have to test it. The number
\r
1390 ** of escapes required for an offset of 1 is N(1)+N(2)+N(40). The number
\r
1391 ** of escapes required for an offset of 2 is N(2)+N(3)+N(41). And so forth.
\r
1392 ** In this way we find the offset that gives the minimum number of escapes,
\r
1393 ** and thus minimizes the length of the output string.
\r
1397 ** Encode a binary buffer "in" of size n bytes so that it contains
\r
1398 ** no instances of characters '\'' or '\000'. The output is
\r
1399 ** null-terminated and can be used as a string value in an INSERT
\r
1400 ** or UPDATE statement. Use sqlite3_decode_binary() to convert the
\r
1401 ** string back into its original binary.
\r
1403 ** The result is written into a preallocated output buffer "out".
\r
1404 ** "out" must be able to hold at least 2 +(257*n)/254 bytes.
\r
1405 ** In other words, the output will be expanded by as much as 3
\r
1406 ** bytes for every 254 bytes of input plus 2 bytes of fixed overhead.
\r
1407 ** (This is approximately 2 + 1.0118*n or about a 1.2% size increase.)
\r
1409 ** The return value is the number of characters in the encoded
\r
1410 ** string, excluding the "\000" terminator.
\r
1412 int sqlite3_encode_binary(const unsigned char *in, int n, unsigned char *out){
\r
1420 memset(cnt, 0, sizeof(cnt));
\r
1421 for(i=n-1; i>=0; i--){ cnt[in[i]]++; }
\r
1423 for(i=1; i<256; i++){
\r
1425 if( i=='\'' ) continue;
\r
1426 sum = cnt[i] + cnt[(i+1)&0xff] + cnt[(i+'\'')&0xff];
\r
1435 for(i=0; i<n; i++){
\r
1436 int c = (in[i] - e)&0xff;
\r
1443 }else if( c=='\'' ){
\r
1455 ** Decode the string "in" into binary data and write it into "out".
\r
1456 ** This routine reverses the encoding created by sqlite3_encode_binary().
\r
1457 ** The output will always be a few bytes less than the input. The number
\r
1458 ** of bytes of output is returned. If the input is not a well-formed
\r
1459 ** encoding, -1 is returned.
\r
1461 ** The "in" and "out" parameters may point to the same buffer in order
\r
1462 ** to decode a string in place.
\r
1464 int sqlite3_decode_binary(const unsigned char *in, unsigned char *out){
\r
1468 while( (c = *(in++))!=0 ){
\r
1481 out[i++] = (c + e)&0xff;
\r