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
48 const char* szErrMess,
\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 int nErrCode,
\r
66 bool bDeleteMsg/*=true*/) :
\r
69 mpszErrMess = sqlite3_mprintf("%s[%d]: %s",
\r
70 errorCodeAsString(nErrCode),
\r
72 szErrMess ? szErrMess : "");
\r
74 if (bDeleteMsg && szErrMess)
\r
76 sqlite3_free(szErrMess);
\r
80 CppSQLite3Exception::CppSQLite3Exception(const CppSQLite3Exception& e) :
\r
81 mnErrCode(e.mnErrCode)
\r
86 mpszErrMess = sqlite3_mprintf("%s", e.mpszErrMess);
\r
91 const char* CppSQLite3Exception::errorCodeAsString(int nErrCode)
\r
95 case SQLITE_OK : return "SQLITE_OK";
\r
96 case SQLITE_ERROR : return "SQLITE_ERROR";
\r
97 case SQLITE_INTERNAL : return "SQLITE_INTERNAL";
\r
98 case SQLITE_PERM : return "SQLITE_PERM";
\r
99 case SQLITE_ABORT : return "SQLITE_ABORT";
\r
100 case SQLITE_BUSY : return "SQLITE_BUSY";
\r
101 case SQLITE_LOCKED : return "SQLITE_LOCKED";
\r
102 case SQLITE_NOMEM : return "SQLITE_NOMEM";
\r
103 case SQLITE_READONLY : return "SQLITE_READONLY";
\r
104 case SQLITE_INTERRUPT : return "SQLITE_INTERRUPT";
\r
105 case SQLITE_IOERR : return "SQLITE_IOERR";
\r
106 case SQLITE_CORRUPT : return "SQLITE_CORRUPT";
\r
107 case SQLITE_NOTFOUND : return "SQLITE_NOTFOUND";
\r
108 case SQLITE_FULL : return "SQLITE_FULL";
\r
109 case SQLITE_CANTOPEN : return "SQLITE_CANTOPEN";
\r
110 case SQLITE_PROTOCOL : return "SQLITE_PROTOCOL";
\r
111 case SQLITE_EMPTY : return "SQLITE_EMPTY";
\r
112 case SQLITE_SCHEMA : return "SQLITE_SCHEMA";
\r
113 case SQLITE_TOOBIG : return "SQLITE_TOOBIG";
\r
114 case SQLITE_CONSTRAINT : return "SQLITE_CONSTRAINT";
\r
115 case SQLITE_MISMATCH : return "SQLITE_MISMATCH";
\r
116 case SQLITE_MISUSE : return "SQLITE_MISUSE";
\r
117 case SQLITE_NOLFS : return "SQLITE_NOLFS";
\r
118 case SQLITE_AUTH : return "SQLITE_AUTH";
\r
119 case SQLITE_FORMAT : return "SQLITE_FORMAT";
\r
120 case SQLITE_RANGE : return "SQLITE_RANGE";
\r
121 case SQLITE_ROW : return "SQLITE_ROW";
\r
122 case SQLITE_DONE : return "SQLITE_DONE";
\r
123 case CPPSQLITE_ERROR : return "CPPSQLITE_ERROR";
\r
124 default: return "UNKNOWN_ERROR";
\r
129 CppSQLite3Exception::~CppSQLite3Exception()
\r
133 sqlite3_free(mpszErrMess);
\r
139 ////////////////////////////////////////////////////////////////////////////////
\r
141 CppSQLite3Buffer::CppSQLite3Buffer()
\r
147 CppSQLite3Buffer::~CppSQLite3Buffer()
\r
153 void CppSQLite3Buffer::clear()
\r
157 sqlite3_free(mpBuf);
\r
164 const char* CppSQLite3Buffer::format(const char* szFormat, ...)
\r
168 va_start(va, szFormat);
\r
169 mpBuf = sqlite3_vmprintf(szFormat, va);
\r
175 ////////////////////////////////////////////////////////////////////////////////
\r
177 CppSQLite3Binary::CppSQLite3Binary() :
\r
187 CppSQLite3Binary::~CppSQLite3Binary()
\r
193 void CppSQLite3Binary::setBinary(const unsigned char* pBuf, int nLen)
\r
195 mpBuf = allocBuffer(nLen);
\r
196 memcpy(mpBuf, pBuf, nLen);
\r
200 void CppSQLite3Binary::setEncoded(const unsigned char* pBuf)
\r
204 mnEncodedLen = strlen((const char*)pBuf);
\r
205 mnBufferLen = mnEncodedLen + 1; // Allow for NULL terminator
\r
207 mpBuf = (unsigned char*)malloc(mnBufferLen);
\r
211 throw CppSQLite3Exception(CPPSQLITE_ERROR,
\r
212 "Cannot allocate memory",
\r
216 memcpy(mpBuf, pBuf, mnBufferLen);
\r
221 const unsigned char* CppSQLite3Binary::getEncoded()
\r
225 unsigned char* ptmp = (unsigned char*)malloc(mnBinaryLen);
\r
226 memcpy(ptmp, mpBuf, mnBinaryLen);
\r
227 mnEncodedLen = sqlite3_encode_binary(ptmp, mnBinaryLen, mpBuf);
\r
236 const unsigned char* CppSQLite3Binary::getBinary()
\r
240 // in/out buffers can be the same
\r
241 mnBinaryLen = sqlite3_decode_binary(mpBuf, mpBuf);
\r
243 if (mnBinaryLen == -1)
\r
245 throw CppSQLite3Exception(CPPSQLITE_ERROR,
\r
246 "Cannot decode binary",
\r
257 int CppSQLite3Binary::getBinaryLength()
\r
260 return mnBinaryLen;
\r
264 unsigned char* CppSQLite3Binary::allocBuffer(int nLen)
\r
268 // Allow extra space for encoded binary as per comments in
\r
269 // SQLite encode.c See bottom of this file for implementation
\r
270 // of SQLite functions use 3 instead of 2 just to be sure ;-)
\r
271 mnBinaryLen = nLen;
\r
272 mnBufferLen = 3 + (257*nLen)/254;
\r
274 mpBuf = (unsigned char*)malloc(mnBufferLen);
\r
278 throw CppSQLite3Exception(CPPSQLITE_ERROR,
\r
279 "Cannot allocate memory",
\r
289 void CppSQLite3Binary::clear()
\r
301 ////////////////////////////////////////////////////////////////////////////////
\r
303 CppSQLite3Query::CppSQLite3Query()
\r
312 CppSQLite3Query::CppSQLite3Query(const CppSQLite3Query& rQuery)
\r
314 mpVM = rQuery.mpVM;
\r
315 // Only one object can own the VM
\r
316 const_cast<CppSQLite3Query&>(rQuery).mpVM = 0;
\r
317 mbEof = rQuery.mbEof;
\r
318 mnCols = rQuery.mnCols;
\r
319 mbOwnVM = rQuery.mbOwnVM;
\r
323 CppSQLite3Query::CppSQLite3Query(sqlite3* pDB,
\r
326 bool bOwnVM/*=true*/)
\r
331 mnCols = sqlite3_column_count(mpVM);
\r
336 CppSQLite3Query::~CppSQLite3Query()
\r
348 CppSQLite3Query& CppSQLite3Query::operator=(const CppSQLite3Query& rQuery)
\r
357 mpVM = rQuery.mpVM;
\r
358 // Only one object can own the VM
\r
359 const_cast<CppSQLite3Query&>(rQuery).mpVM = 0;
\r
360 mbEof = rQuery.mbEof;
\r
361 mnCols = rQuery.mnCols;
\r
362 mbOwnVM = rQuery.mbOwnVM;
\r
367 int CppSQLite3Query::numFields()
\r
374 const char* CppSQLite3Query::fieldValue(int nField)
\r
378 if (nField < 0 || nField > mnCols-1)
\r
380 throw CppSQLite3Exception(CPPSQLITE_ERROR,
\r
381 "Invalid field index requested",
\r
385 return (const char*)sqlite3_column_text(mpVM, nField);
\r
389 const char* CppSQLite3Query::fieldValue(const char* szField)
\r
391 int nField = fieldIndex(szField);
\r
392 return (const char*)sqlite3_column_text(mpVM, nField);
\r
396 int CppSQLite3Query::getIntField(int nField, int nNullValue/*=0*/)
\r
398 if (fieldDataType(nField) == SQLITE_NULL)
\r
404 return sqlite3_column_int(mpVM, nField);
\r
409 int CppSQLite3Query::getIntField(const char* szField, int nNullValue/*=0*/)
\r
411 int nField = fieldIndex(szField);
\r
412 return getIntField(nField, nNullValue);
\r
416 double CppSQLite3Query::getFloatField(int nField, double fNullValue/*=0.0*/)
\r
418 if (fieldDataType(nField) == SQLITE_NULL)
\r
424 return sqlite3_column_double(mpVM, nField);
\r
429 double CppSQLite3Query::getFloatField(const char* szField, double fNullValue/*=0.0*/)
\r
431 int nField = fieldIndex(szField);
\r
432 return getFloatField(nField, fNullValue);
\r
436 const char* CppSQLite3Query::getStringField(int nField, const char* szNullValue/*=""*/)
\r
438 if (fieldDataType(nField) == SQLITE_NULL)
\r
440 return szNullValue;
\r
444 return (const char*)sqlite3_column_text(mpVM, nField);
\r
449 const char* CppSQLite3Query::getStringField(const char* szField, const char* szNullValue/*=""*/)
\r
451 int nField = fieldIndex(szField);
\r
452 return getStringField(nField, szNullValue);
\r
456 const unsigned char* CppSQLite3Query::getBlobField(int nField, int& nLen)
\r
460 if (nField < 0 || nField > mnCols-1)
\r
462 throw CppSQLite3Exception(CPPSQLITE_ERROR,
\r
463 "Invalid field index requested",
\r
467 nLen = sqlite3_column_bytes(mpVM, nField);
\r
468 return (const unsigned char*)sqlite3_column_blob(mpVM, nField);
\r
472 const unsigned char* CppSQLite3Query::getBlobField(const char* szField, int& nLen)
\r
474 int nField = fieldIndex(szField);
\r
475 return getBlobField(nField, nLen);
\r
479 bool CppSQLite3Query::fieldIsNull(int nField)
\r
481 return (fieldDataType(nField) == SQLITE_NULL);
\r
485 bool CppSQLite3Query::fieldIsNull(const char* szField)
\r
487 int nField = fieldIndex(szField);
\r
488 return (fieldDataType(nField) == SQLITE_NULL);
\r
492 int CppSQLite3Query::fieldIndex(const char* szField)
\r
498 for (int nField = 0; nField < mnCols; nField++)
\r
500 const char* szTemp = sqlite3_column_name(mpVM, nField);
\r
502 if (strcmp(szField, szTemp) == 0)
\r
509 throw CppSQLite3Exception(CPPSQLITE_ERROR,
\r
510 "Invalid field name requested",
\r
515 const char* CppSQLite3Query::fieldName(int nCol)
\r
519 if (nCol < 0 || nCol > mnCols-1)
\r
521 throw CppSQLite3Exception(CPPSQLITE_ERROR,
\r
522 "Invalid field index requested",
\r
526 return sqlite3_column_name(mpVM, nCol);
\r
530 const char* CppSQLite3Query::fieldDeclType(int nCol)
\r
534 if (nCol < 0 || nCol > mnCols-1)
\r
536 throw CppSQLite3Exception(CPPSQLITE_ERROR,
\r
537 "Invalid field index requested",
\r
541 return sqlite3_column_decltype(mpVM, nCol);
\r
545 int CppSQLite3Query::fieldDataType(int nCol)
\r
549 if (nCol < 0 || nCol > mnCols-1)
\r
551 throw CppSQLite3Exception(CPPSQLITE_ERROR,
\r
552 "Invalid field index requested",
\r
556 return sqlite3_column_type(mpVM, nCol);
\r
560 bool CppSQLite3Query::eof()
\r
567 void CppSQLite3Query::nextRow()
\r
571 int nRet = sqlite3_step(mpVM);
\r
573 if (nRet == SQLITE_DONE)
\r
578 else if (nRet == SQLITE_ROW)
\r
580 // more rows, nothing to do
\r
584 nRet = sqlite3_finalize(mpVM);
\r
586 const char* szError = sqlite3_errmsg(mpDB);
\r
587 throw CppSQLite3Exception(nRet,
\r
594 void CppSQLite3Query::finalize()
\r
596 if (mpVM && mbOwnVM)
\r
598 int nRet = sqlite3_finalize(mpVM);
\r
600 if (nRet != SQLITE_OK)
\r
602 const char* szError = sqlite3_errmsg(mpDB);
\r
603 throw CppSQLite3Exception(nRet, (char*)szError, DONT_DELETE_MSG);
\r
609 void CppSQLite3Query::checkVM()
\r
613 throw CppSQLite3Exception(CPPSQLITE_ERROR,
\r
614 "Null Virtual Machine pointer",
\r
620 ////////////////////////////////////////////////////////////////////////////////
\r
622 CppSQLite3Table::CppSQLite3Table()
\r
631 CppSQLite3Table::CppSQLite3Table(const CppSQLite3Table& rTable)
\r
633 mpaszResults = rTable.mpaszResults;
\r
634 // Only one object can own the results
\r
635 const_cast<CppSQLite3Table&>(rTable).mpaszResults = 0;
\r
636 mnRows = rTable.mnRows;
\r
637 mnCols = rTable.mnCols;
\r
638 mnCurrentRow = rTable.mnCurrentRow;
\r
642 CppSQLite3Table::CppSQLite3Table(char** paszResults, int nRows, int nCols)
\r
644 mpaszResults = paszResults;
\r
651 CppSQLite3Table::~CppSQLite3Table()
\r
663 CppSQLite3Table& CppSQLite3Table::operator=(const CppSQLite3Table& rTable)
\r
672 mpaszResults = rTable.mpaszResults;
\r
673 // Only one object can own the results
\r
674 const_cast<CppSQLite3Table&>(rTable).mpaszResults = 0;
\r
675 mnRows = rTable.mnRows;
\r
676 mnCols = rTable.mnCols;
\r
677 mnCurrentRow = rTable.mnCurrentRow;
\r
682 void CppSQLite3Table::finalize()
\r
686 sqlite3_free_table(mpaszResults);
\r
692 int CppSQLite3Table::numFields()
\r
699 int CppSQLite3Table::numRows()
\r
706 const char* CppSQLite3Table::fieldValue(int nField)
\r
710 if (nField < 0 || nField > mnCols-1)
\r
712 throw CppSQLite3Exception(CPPSQLITE_ERROR,
\r
713 "Invalid field index requested",
\r
717 int nIndex = (mnCurrentRow*mnCols) + mnCols + nField;
\r
718 return mpaszResults[nIndex];
\r
722 const char* CppSQLite3Table::fieldValue(const char* szField)
\r
728 for (int nField = 0; nField < mnCols; nField++)
\r
730 if (strcmp(szField, mpaszResults[nField]) == 0)
\r
732 int nIndex = (mnCurrentRow*mnCols) + mnCols + nField;
\r
733 return mpaszResults[nIndex];
\r
738 throw CppSQLite3Exception(CPPSQLITE_ERROR,
\r
739 "Invalid field name requested",
\r
744 int CppSQLite3Table::getIntField(int nField, int nNullValue/*=0*/)
\r
746 if (fieldIsNull(nField))
\r
752 return atoi(fieldValue(nField));
\r
757 int CppSQLite3Table::getIntField(const char* szField, int nNullValue/*=0*/)
\r
759 if (fieldIsNull(szField))
\r
765 return atoi(fieldValue(szField));
\r
770 double CppSQLite3Table::getFloatField(int nField, double fNullValue/*=0.0*/)
\r
772 if (fieldIsNull(nField))
\r
778 return atof(fieldValue(nField));
\r
783 double CppSQLite3Table::getFloatField(const char* szField, double fNullValue/*=0.0*/)
\r
785 if (fieldIsNull(szField))
\r
791 return atof(fieldValue(szField));
\r
796 const char* CppSQLite3Table::getStringField(int nField, const char* szNullValue/*=""*/)
\r
798 if (fieldIsNull(nField))
\r
800 return szNullValue;
\r
804 return fieldValue(nField);
\r
809 const char* CppSQLite3Table::getStringField(const char* szField, const char* szNullValue/*=""*/)
\r
811 if (fieldIsNull(szField))
\r
813 return szNullValue;
\r
817 return fieldValue(szField);
\r
822 bool CppSQLite3Table::fieldIsNull(int nField)
\r
825 return (fieldValue(nField) == 0);
\r
829 bool CppSQLite3Table::fieldIsNull(const char* szField)
\r
832 return (fieldValue(szField) == 0);
\r
836 const char* CppSQLite3Table::fieldName(int nCol)
\r
840 if (nCol < 0 || nCol > mnCols-1)
\r
842 throw CppSQLite3Exception(CPPSQLITE_ERROR,
\r
843 "Invalid field index requested",
\r
847 return mpaszResults[nCol];
\r
851 void CppSQLite3Table::setRow(int nRow)
\r
855 if (nRow < 0 || nRow > mnRows-1)
\r
857 throw CppSQLite3Exception(CPPSQLITE_ERROR,
\r
858 "Invalid row index requested",
\r
862 mnCurrentRow = nRow;
\r
866 void CppSQLite3Table::checkResults()
\r
868 if (mpaszResults == 0)
\r
870 throw CppSQLite3Exception(CPPSQLITE_ERROR,
\r
871 "Null Results pointer",
\r
877 ////////////////////////////////////////////////////////////////////////////////
\r
879 CppSQLite3Statement::CppSQLite3Statement()
\r
886 CppSQLite3Statement::CppSQLite3Statement(const CppSQLite3Statement& rStatement)
\r
888 mpDB = rStatement.mpDB;
\r
889 mpVM = rStatement.mpVM;
\r
890 // Only one object can own VM
\r
891 const_cast<CppSQLite3Statement&>(rStatement).mpVM = 0;
\r
895 CppSQLite3Statement::CppSQLite3Statement(sqlite3* pDB, sqlite3_stmt* pVM)
\r
902 CppSQLite3Statement::~CppSQLite3Statement()
\r
914 CppSQLite3Statement& CppSQLite3Statement::operator=(const CppSQLite3Statement& rStatement)
\r
916 mpDB = rStatement.mpDB;
\r
917 mpVM = rStatement.mpVM;
\r
918 // Only one object can own VM
\r
919 const_cast<CppSQLite3Statement&>(rStatement).mpVM = 0;
\r
924 int CppSQLite3Statement::execDML()
\r
929 const char* szError=0;
\r
931 int nRet = sqlite3_step(mpVM);
\r
933 if (nRet == SQLITE_DONE)
\r
935 int nRowsChanged = sqlite3_changes(mpDB);
\r
937 nRet = sqlite3_reset(mpVM);
\r
939 if (nRet != SQLITE_OK)
\r
941 szError = sqlite3_errmsg(mpDB);
\r
942 throw CppSQLite3Exception(nRet, (char*)szError, DONT_DELETE_MSG);
\r
945 return nRowsChanged;
\r
949 nRet = sqlite3_reset(mpVM);
\r
950 szError = sqlite3_errmsg(mpDB);
\r
951 throw CppSQLite3Exception(nRet, (char*)szError, DONT_DELETE_MSG);
\r
956 CppSQLite3Query CppSQLite3Statement::execQuery()
\r
961 int nRet = sqlite3_step(mpVM);
\r
963 if (nRet == SQLITE_DONE)
\r
966 return CppSQLite3Query(mpDB, mpVM, true/*eof*/, false);
\r
968 else if (nRet == SQLITE_ROW)
\r
971 return CppSQLite3Query(mpDB, mpVM, false/*eof*/, false);
\r
975 nRet = sqlite3_reset(mpVM);
\r
976 const char* szError = sqlite3_errmsg(mpDB);
\r
977 throw CppSQLite3Exception(nRet, (char*)szError, DONT_DELETE_MSG);
\r
982 void CppSQLite3Statement::bind(int nParam, const char* szValue)
\r
985 int nRes = sqlite3_bind_text(mpVM, nParam, szValue, -1, SQLITE_TRANSIENT);
\r
987 if (nRes != SQLITE_OK)
\r
989 throw CppSQLite3Exception(nRes,
\r
990 "Error binding string param",
\r
996 void CppSQLite3Statement::bind(int nParam, const int nValue)
\r
999 int nRes = sqlite3_bind_int(mpVM, nParam, nValue);
\r
1001 if (nRes != SQLITE_OK)
\r
1003 throw CppSQLite3Exception(nRes,
\r
1004 "Error binding int param",
\r
1010 void CppSQLite3Statement::bind(int nParam, const double dValue)
\r
1013 int nRes = sqlite3_bind_double(mpVM, nParam, dValue);
\r
1015 if (nRes != SQLITE_OK)
\r
1017 throw CppSQLite3Exception(nRes,
\r
1018 "Error binding double param",
\r
1024 void CppSQLite3Statement::bind(int nParam, const unsigned char* blobValue, int nLen)
\r
1027 int nRes = sqlite3_bind_blob(mpVM, nParam,
\r
1028 (const void*)blobValue, nLen, SQLITE_TRANSIENT);
\r
1030 if (nRes != SQLITE_OK)
\r
1032 throw CppSQLite3Exception(nRes,
\r
1033 "Error binding blob param",
\r
1039 void CppSQLite3Statement::bindNull(int nParam)
\r
1042 int nRes = sqlite3_bind_null(mpVM, nParam);
\r
1044 if (nRes != SQLITE_OK)
\r
1046 throw CppSQLite3Exception(nRes,
\r
1047 "Error binding NULL param",
\r
1053 void CppSQLite3Statement::reset()
\r
1057 int nRet = sqlite3_reset(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::finalize()
\r
1072 int nRet = sqlite3_finalize(mpVM);
\r
1075 if (nRet != SQLITE_OK)
\r
1077 const char* szError = sqlite3_errmsg(mpDB);
\r
1078 throw CppSQLite3Exception(nRet, (char*)szError, DONT_DELETE_MSG);
\r
1084 void CppSQLite3Statement::checkDB()
\r
1088 throw CppSQLite3Exception(CPPSQLITE_ERROR,
\r
1089 "Database not open",
\r
1095 void CppSQLite3Statement::checkVM()
\r
1099 throw CppSQLite3Exception(CPPSQLITE_ERROR,
\r
1100 "Null Virtual Machine pointer",
\r
1106 ////////////////////////////////////////////////////////////////////////////////
\r
1108 CppSQLite3DB::CppSQLite3DB()
\r
1111 mnBusyTimeoutMs = 60000; // 60 seconds
\r
1115 CppSQLite3DB::CppSQLite3DB(const CppSQLite3DB& db)
\r
1118 mnBusyTimeoutMs = 60000; // 60 seconds
\r
1122 CppSQLite3DB::~CppSQLite3DB()
\r
1128 CppSQLite3DB& CppSQLite3DB::operator=(const CppSQLite3DB& db)
\r
1131 mnBusyTimeoutMs = 60000; // 60 seconds
\r
1136 void CppSQLite3DB::open(const char* szFile)
\r
1138 int nRet = sqlite3_open(szFile, &mpDB);
\r
1140 if (nRet != SQLITE_OK)
\r
1142 const char* szError = sqlite3_errmsg(mpDB);
\r
1143 throw CppSQLite3Exception(nRet, (char*)szError, DONT_DELETE_MSG);
\r
1146 setBusyTimeout(mnBusyTimeoutMs);
\r
1150 void CppSQLite3DB::close()
\r
1154 sqlite3_close(mpDB);
\r
1160 CppSQLite3Statement CppSQLite3DB::compileStatement(const char* szSQL)
\r
1164 sqlite3_stmt* pVM = compile(szSQL);
\r
1165 return CppSQLite3Statement(mpDB, pVM);
\r
1169 bool CppSQLite3DB::tableExists(const char* szTable)
\r
1173 "select count(*) from sqlite_master where type='table' and name='%s'",
\r
1175 int nRet = execScalar(szSQL);
\r
1176 return (nRet > 0);
\r
1180 int CppSQLite3DB::execDML(const char* szSQL)
\r
1186 int nRet = sqlite3_exec(mpDB, szSQL, 0, 0, &szError);
\r
1188 if (nRet == SQLITE_OK)
\r
1190 return sqlite3_changes(mpDB);
\r
1194 throw CppSQLite3Exception(nRet, szError);
\r
1199 CppSQLite3Query CppSQLite3DB::execQuery(const char* szSQL)
\r
1203 sqlite3_stmt* pVM = compile(szSQL);
\r
1205 int nRet = sqlite3_step(pVM);
\r
1207 if (nRet == SQLITE_DONE)
\r
1210 return CppSQLite3Query(mpDB, pVM, true/*eof*/);
\r
1212 else if (nRet == SQLITE_ROW)
\r
1215 return CppSQLite3Query(mpDB, pVM, false/*eof*/);
\r
1219 nRet = sqlite3_finalize(pVM);
\r
1220 const char* szError= sqlite3_errmsg(mpDB);
\r
1221 throw CppSQLite3Exception(nRet, (char*)szError, DONT_DELETE_MSG);
\r
1226 int CppSQLite3DB::execScalar(const char* szSQL)
\r
1228 CppSQLite3Query q = execQuery(szSQL);
\r
1230 if (q.eof() || q.numFields() < 1)
\r
1232 throw CppSQLite3Exception(CPPSQLITE_ERROR,
\r
1233 "Invalid scalar query",
\r
1237 return atoi(q.fieldValue(0));
\r
1241 CppSQLite3Table CppSQLite3DB::getTable(const char* szSQL)
\r
1246 char** paszResults=0;
\r
1251 nRet = sqlite3_get_table(mpDB, szSQL, &paszResults, &nRows, &nCols, &szError);
\r
1253 if (nRet == SQLITE_OK)
\r
1255 return CppSQLite3Table(paszResults, nRows, nCols);
\r
1259 throw CppSQLite3Exception(nRet, szError);
\r
1264 sqlite_int64 CppSQLite3DB::lastRowId()
\r
1266 return sqlite3_last_insert_rowid(mpDB);
\r
1270 void CppSQLite3DB::setBusyTimeout(int nMillisecs)
\r
1272 mnBusyTimeoutMs = nMillisecs;
\r
1273 sqlite3_busy_timeout(mpDB, mnBusyTimeoutMs);
\r
1277 void CppSQLite3DB::checkDB()
\r
1281 throw CppSQLite3Exception(CPPSQLITE_ERROR,
\r
1282 "Database not open",
\r
1288 sqlite3_stmt* CppSQLite3DB::compile(const char* szSQL)
\r
1293 const char* szTail=0;
\r
1294 sqlite3_stmt* pVM;
\r
1296 int nRet = sqlite3_prepare(mpDB, szSQL, -1, &pVM, &szTail);
\r
1298 if (nRet != SQLITE_OK)
\r
1300 throw CppSQLite3Exception(nRet, szError);
\r
1307 ////////////////////////////////////////////////////////////////////////////////
\r
1308 // SQLite encode.c reproduced here, containing implementation notes and source
\r
1309 // for sqlite3_encode_binary() and sqlite3_decode_binary()
\r
1310 ////////////////////////////////////////////////////////////////////////////////
\r
1315 ** The author disclaims copyright to this source code. In place of
\r
1316 ** a legal notice, here is a blessing:
\r
1318 ** May you do good and not evil.
\r
1319 ** May you find forgiveness for yourself and forgive others.
\r
1320 ** May you share freely, never taking more than you give.
\r
1322 *************************************************************************
\r
1323 ** This file contains helper routines used to translate binary data into
\r
1324 ** a null-terminated string (suitable for use in SQLite) and back again.
\r
1325 ** These are convenience routines for use by people who want to store binary
\r
1326 ** data in an SQLite database. The code in this file is not used by any other
\r
1327 ** part of the SQLite library.
\r
1329 ** $Id: CppSQLite3.cpp,v 1.2 2008/12/15 12:54:44 guigues Exp $
\r
1333 ** How This Encoder Works
\r
1335 ** The output is allowed to contain any character except 0x27 (') and
\r
1336 ** 0x00. This is accomplished by using an escape character to encode
\r
1337 ** 0x27 and 0x00 as a two-byte sequence. The escape character is always
\r
1338 ** 0x01. An 0x00 is encoded as the two byte sequence 0x01 0x01. The
\r
1339 ** 0x27 character is encoded as the two byte sequence 0x01 0x03. Finally,
\r
1340 ** the escape character itself is encoded as the two-character sequence
\r
1343 ** To summarize, the encoder works by using an escape sequences as follows:
\r
1345 ** 0x00 -> 0x01 0x01
\r
1346 ** 0x01 -> 0x01 0x02
\r
1347 ** 0x27 -> 0x01 0x03
\r
1349 ** If that were all the encoder did, it would work, but in certain cases
\r
1350 ** it could double the size of the encoded string. For example, to
\r
1351 ** encode a string of 100 0x27 characters would require 100 instances of
\r
1352 ** the 0x01 0x03 escape sequence resulting in a 200-character output.
\r
1353 ** We would prefer to keep the size of the encoded string smaller than
\r
1356 ** To minimize the encoding size, we first add a fixed offset value to each
\r
1357 ** byte in the sequence. The addition is modulo 256. (That is to say, if
\r
1358 ** the sum of the original character value and the offset exceeds 256, then
\r
1359 ** the higher order bits are truncated.) The offset is chosen to minimize
\r
1360 ** the number of characters in the string that need to be escaped. For
\r
1361 ** example, in the case above where the string was composed of 100 0x27
\r
1362 ** characters, the offset might be 0x01. Each of the 0x27 characters would
\r
1363 ** then be converted into an 0x28 character which would not need to be
\r
1364 ** escaped at all and so the 100 character input string would be converted
\r
1365 ** into just 100 characters of output. Actually 101 characters of output -
\r
1366 ** we have to record the offset used as the first byte in the sequence so
\r
1367 ** that the string can be decoded. Since the offset value is stored as
\r
1368 ** part of the output string and the output string is not allowed to contain
\r
1369 ** characters 0x00 or 0x27, the offset cannot be 0x00 or 0x27.
\r
1371 ** Here, then, are the encoding steps:
\r
1373 ** (1) Choose an offset value and make it the first character of
\r
1376 ** (2) Copy each input character into the output buffer, one by
\r
1377 ** one, adding the offset value as you copy.
\r
1379 ** (3) If the value of an input character plus offset is 0x00, replace
\r
1380 ** that one character by the two-character sequence 0x01 0x01.
\r
1381 ** If the sum is 0x01, replace it with 0x01 0x02. If the sum
\r
1382 ** is 0x27, replace it with 0x01 0x03.
\r
1384 ** (4) Put a 0x00 terminator at the end of the output.
\r
1386 ** Decoding is obvious:
\r
1388 ** (5) Copy encoded characters except the first into the decode
\r
1389 ** buffer. Set the first encoded character aside for use as
\r
1390 ** the offset in step 7 below.
\r
1392 ** (6) Convert each 0x01 0x01 sequence into a single character 0x00.
\r
1393 ** Convert 0x01 0x02 into 0x01. Convert 0x01 0x03 into 0x27.
\r
1395 ** (7) Subtract the offset value that was the first character of
\r
1396 ** the encoded buffer from all characters in the output buffer.
\r
1398 ** The only tricky part is step (1) - how to compute an offset value to
\r
1399 ** minimize the size of the output buffer. This is accomplished by testing
\r
1400 ** all offset values and picking the one that results in the fewest number
\r
1401 ** of escapes. To do that, we first scan the entire input and count the
\r
1402 ** number of occurances of each character value in the input. Suppose
\r
1403 ** the number of 0x00 characters is N(0), the number of occurances of 0x01
\r
1404 ** is N(1), and so forth up to the number of occurances of 0xff is N(255).
\r
1405 ** An offset of 0 is not allowed so we don't have to test it. The number
\r
1406 ** of escapes required for an offset of 1 is N(1)+N(2)+N(40). The number
\r
1407 ** of escapes required for an offset of 2 is N(2)+N(3)+N(41). And so forth.
\r
1408 ** In this way we find the offset that gives the minimum number of escapes,
\r
1409 ** and thus minimizes the length of the output string.
\r
1413 ** Encode a binary buffer "in" of size n bytes so that it contains
\r
1414 ** no instances of characters '\'' or '\000'. The output is
\r
1415 ** null-terminated and can be used as a string value in an INSERT
\r
1416 ** or UPDATE statement. Use sqlite3_decode_binary() to convert the
\r
1417 ** string back into its original binary.
\r
1419 ** The result is written into a preallocated output buffer "out".
\r
1420 ** "out" must be able to hold at least 2 +(257*n)/254 bytes.
\r
1421 ** In other words, the output will be expanded by as much as 3
\r
1422 ** bytes for every 254 bytes of input plus 2 bytes of fixed overhead.
\r
1423 ** (This is approximately 2 + 1.0118*n or about a 1.2% size increase.)
\r
1425 ** The return value is the number of characters in the encoded
\r
1426 ** string, excluding the "\000" terminator.
\r
1428 int sqlite3_encode_binary(const unsigned char *in, int n, unsigned char *out){
\r
1436 memset(cnt, 0, sizeof(cnt));
\r
1437 for(i=n-1; i>=0; i--){ cnt[in[i]]++; }
\r
1439 for(i=1; i<256; i++){
\r
1441 if( i=='\'' ) continue;
\r
1442 sum = cnt[i] + cnt[(i+1)&0xff] + cnt[(i+'\'')&0xff];
\r
1451 for(i=0; i<n; i++){
\r
1452 int c = (in[i] - e)&0xff;
\r
1459 }else if( c=='\'' ){
\r
1471 ** Decode the string "in" into binary data and write it into "out".
\r
1472 ** This routine reverses the encoding created by sqlite3_encode_binary().
\r
1473 ** The output will always be a few bytes less than the input. The number
\r
1474 ** of bytes of output is returned. If the input is not a well-formed
\r
1475 ** encoding, -1 is returned.
\r
1477 ** The "in" and "out" parameters may point to the same buffer in order
\r
1478 ** to decode a string in place.
\r
1480 int sqlite3_decode_binary(const unsigned char *in, unsigned char *out){
\r
1484 while( (c = *(in++))!=0 ){
\r
1497 out[i++] = (c + e)&0xff;
\r