📄 cppsqlite3u.cpp
字号:
////////////////////////////////////////////////////////////////////////////////
// CppSQLite3U is a C++ unicode wrapper around the SQLite3 embedded database library.
//
// Copyright (c) 2006 Tyushkov Nikolay. All Rights Reserved. http://softvoile.com
//
//
// Based on beautiful wrapper written by Rob Groves
// (https://secure.codeproject.com/database/CppSQLite.asp).
// Very good wrapper, but without unicode support unfortunately.
// So, I have reconstructed it for unicode.
//
// CppSQLite3 wrapper:
// Copyright (c) 2004 Rob Groves. All Rights Reserved. rob.groves@btinternet.com
//
// Permission to use, copy, modify, and distribute this software and its
// documentation for any purpose, without fee, and without a written
// agreement, is hereby granted, provided that the above copyright notice,
// this paragraph and the following two paragraphs appear in all copies,
// modifications, and distributions.
//
// IN NO EVENT SHALL THE AUTHOR BE LIABLE TO ANY PARTY FOR DIRECT,
// INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST
// PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION,
// EVEN IF THE AUTHOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// THE AUTHOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
// PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF
// ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". THE AUTHOR HAS NO OBLIGATION
// TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
//
// If you want to get some documentation look at
// https://secure.codeproject.com/database/CppSQLite.asp
// Note, not all features from CppSQLite3 were implemented in CppSQLite3U
//
// V1.0 11/06/2006 - Initial Public Version
//
// Noteses :
// I have tested this wrapper only in unicode version, so I have no idea
// about its work in ANSI configuration, I think it doesn't work without modification;)
//
// Home page : http://softvoile.com/development/CppSQLite3U/
// Please send all bug report and comment to mail2@softvoile.com
//
//
////////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "CppSQLite3U.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CppSQLite3Exception
CppSQLite3Exception::CppSQLite3Exception(const int nErrCode,
LPTSTR szErrMess,
bool bDeleteMsg/*=true*/) :
mnErrCode(nErrCode)
{
mpszErrMess=new TCHAR[ szErrMess ? _tcslen(szErrMess)+50 : 50];
_stprintf(mpszErrMess, _T("%s[%d]: %s"),
errorCodeAsString(nErrCode),
nErrCode,
szErrMess ? szErrMess : _T(""));
if (bDeleteMsg && szErrMess)
{
_sqlite3_free((char*)szErrMess);
}
}
CppSQLite3Exception::CppSQLite3Exception(const CppSQLite3Exception& e) :
mnErrCode(e.mnErrCode)
{
mpszErrMess = 0;
if (e.mpszErrMess)
{
mpszErrMess=new TCHAR[_tcslen(e.mpszErrMess)+10];
_stprintf(mpszErrMess, _T("%s"), e.mpszErrMess);
}
}
LPCTSTR CppSQLite3Exception::errorCodeAsString(int nErrCode)
{
switch (nErrCode)
{
case SQLITE_OK : return _T("SQLITE_OK");
case SQLITE_ERROR : return _T("SQLITE_ERROR");
case SQLITE_INTERNAL : return _T("SQLITE_INTERNAL");
case SQLITE_PERM : return _T("SQLITE_PERM");
case SQLITE_ABORT : return _T("SQLITE_ABORT");
case SQLITE_BUSY : return _T("SQLITE_BUSY");
case SQLITE_LOCKED : return _T("SQLITE_LOCKED");
case SQLITE_NOMEM : return _T("SQLITE_NOMEM");
case SQLITE_READONLY : return _T("SQLITE_READONLY");
case SQLITE_INTERRUPT : return _T("SQLITE_INTERRUPT");
case SQLITE_IOERR : return _T("SQLITE_IOERR");
case SQLITE_CORRUPT : return _T("SQLITE_CORRUPT");
case SQLITE_NOTFOUND : return _T("SQLITE_NOTFOUND");
case SQLITE_FULL : return _T("SQLITE_FULL");
case SQLITE_CANTOPEN : return _T("SQLITE_CANTOPEN");
case SQLITE_PROTOCOL : return _T("SQLITE_PROTOCOL");
case SQLITE_EMPTY : return _T("SQLITE_EMPTY");
case SQLITE_SCHEMA : return _T("SQLITE_SCHEMA");
case SQLITE_TOOBIG : return _T("SQLITE_TOOBIG");
case SQLITE_CONSTRAINT : return _T("SQLITE_CONSTRAINT");
case SQLITE_MISMATCH : return _T("SQLITE_MISMATCH");
case SQLITE_MISUSE : return _T("SQLITE_MISUSE");
case SQLITE_NOLFS : return _T("SQLITE_NOLFS");
case SQLITE_AUTH : return _T("SQLITE_AUTH");
case SQLITE_FORMAT : return _T("SQLITE_FORMAT");
case SQLITE_RANGE : return _T("SQLITE_RANGE");
case SQLITE_ROW : return _T("SQLITE_ROW");
case SQLITE_DONE : return _T("SQLITE_DONE");
case CPPSQLITE_ERROR : return _T("CPPSQLITE_ERROR");
default: return _T("UNKNOWN_ERROR");
}
}
CppSQLite3Exception::~CppSQLite3Exception()
{
if (mpszErrMess)
{
delete [] mpszErrMess;
mpszErrMess = 0;
}
}
/////////////////////////////////////////////////////////////////////////////
// CppSQLite3DB
CppSQLite3DB::CppSQLite3DB()
{
mpDB = 0;
mnBusyTimeoutMs = 60000; // 60 seconds
}
CppSQLite3DB::CppSQLite3DB(const CppSQLite3DB& db)
{
mpDB = db.mpDB;
mnBusyTimeoutMs = 60000; // 60 seconds
}
CppSQLite3DB::~CppSQLite3DB()
{
close();
}
////////////////////////////////////////////////////////////////////////////////
CppSQLite3DB& CppSQLite3DB::operator=(const CppSQLite3DB& db)
{
mpDB = db.mpDB;
mnBusyTimeoutMs = 60000; // 60 seconds
return *this;
}
void CppSQLite3DB::open(LPCTSTR szFile)
{
int nRet;
#if defined(_UNICODE) || defined(UNICODE)
nRet = sqlite3_open16(szFile, &mpDB); // not tested under window 98
#else // For Ansi Version
//*************- Added by Begemot szFile must be in unicode- 23/03/06 11:04 - ****
OSVERSIONINFOEX osvi;
ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
GetVersionEx ((OSVERSIONINFO *) &osvi);
if ( osvi.dwMajorVersion == 5)
{
WCHAR pMultiByteStr[MAX_PATH+1];
MultiByteToWideChar( CP_ACP, 0, szFile,
_tcslen(szFile)+1, pMultiByteStr,
sizeof(pMultiByteStr)/sizeof(pMultiByteStr[0]) );
nRet = sqlite3_open16(pMultiByteStr, &mpDB);
}
else
nRet = sqlite3_open(szFile,&mpDB);
#endif
//*************************
if (nRet != SQLITE_OK)
{
LPCTSTR szError = (LPCTSTR) _sqlite3_errmsg(mpDB);
throw CppSQLite3Exception(nRet, (LPTSTR)szError, DONT_DELETE_MSG);
}
setBusyTimeout(mnBusyTimeoutMs);
}
void CppSQLite3DB::close()
{
if (mpDB)
{
int nRet = _sqlite3_close(mpDB);
if (nRet != SQLITE_OK)
{
LPCTSTR szError = (LPCTSTR)_sqlite3_errmsg(mpDB);
throw CppSQLite3Exception(nRet, (LPTSTR)szError, DONT_DELETE_MSG);
}
mpDB = 0;
}
}
CppSQLite3Statement CppSQLite3DB::compileStatement(LPCTSTR szSQL)
{
checkDB();
sqlite3_stmt* pVM = compile(szSQL);
return CppSQLite3Statement(mpDB, pVM);
}
bool CppSQLite3DB::tableExists(LPCTSTR szTable)
{
TCHAR szSQL[128];
_stprintf(szSQL, _T("select count(*) from sqlite_master where type='table' and name='%s'"), szTable);
int nRet = execScalar(szSQL);
return (nRet > 0);
}
int CppSQLite3DB::execDML(LPCTSTR szSQL)
{
int nRet;
sqlite3_stmt* pVM;
checkDB();
do{
pVM = compile(szSQL);
nRet = _sqlite3_step(pVM);
if (nRet == SQLITE_ERROR)
{
LPCTSTR szError = (LPCTSTR) _sqlite3_errmsg(mpDB);
throw CppSQLite3Exception(nRet, (LPTSTR)szError, DONT_DELETE_MSG);
}
nRet = _sqlite3_finalize(pVM);
}
while( nRet == SQLITE_SCHEMA );
}
CppSQLite3Query CppSQLite3DB::execQuery(LPCTSTR szSQL)
{
checkDB();
int nRet;
sqlite3_stmt* pVM;
do{
pVM = compile(szSQL);
nRet = _sqlite3_step(pVM);
if (nRet == SQLITE_DONE)
{ // no rows
return CppSQLite3Query(mpDB, pVM, true/*eof*/);
}
else if (nRet == SQLITE_ROW)
{ // at least 1 row
return CppSQLite3Query(mpDB, pVM, false/*eof*/);
}
nRet = _sqlite3_finalize(pVM);
}
while( nRet == SQLITE_SCHEMA ); // Edit By Begemot 08/16/06 12:44:35 - read SQLite FAQ
LPCTSTR szError = (LPCTSTR) _sqlite3_errmsg(mpDB);
throw CppSQLite3Exception(nRet, (LPTSTR)szError, DONT_DELETE_MSG);
}
int CppSQLite3DB::execScalar(LPCTSTR szSQL)
{
CppSQLite3Query q = execQuery(szSQL);
if (q.eof() || q.numFields() < 1)
throw CppSQLite3Exception(CPPSQLITE_ERROR, _T("Invalid scalar query"), DONT_DELETE_MSG);
return _tstoi(q.fieldValue(0));
}
// Added By Begemot, exact as execScalar but return CString 08/06/06 16:30:37
CString CppSQLite3DB::execScalarStr(LPCTSTR szSQL)
{
CppSQLite3Query q = execQuery(szSQL);
if (q.eof() || q.numFields() < 1)
throw CppSQLite3Exception(CPPSQLITE_ERROR, _T("Invalid scalar query"), DONT_DELETE_MSG);
return (CString)q.getStringField(0);
}
sqlite_int64 CppSQLite3DB::lastRowId()
{
return sqlite3_last_insert_rowid(mpDB);
}
void CppSQLite3DB::setBusyTimeout(int nMillisecs)
{
mnBusyTimeoutMs = nMillisecs;
sqlite3_busy_timeout(mpDB, mnBusyTimeoutMs);
}
void CppSQLite3DB::checkDB()
{
if (!mpDB)
throw CppSQLite3Exception(CPPSQLITE_ERROR,_T("Database not open"), DONT_DELETE_MSG);
}
sqlite3_stmt* CppSQLite3DB::compile(LPCTSTR szSQL)
{
checkDB();
sqlite3_stmt* pVM;
int nRet = _sqlite3_prepare(mpDB, szSQL, -1, &pVM, NULL);
if (nRet != SQLITE_OK)
{
pVM=NULL;
LPCTSTR szError = (LPCTSTR) _sqlite3_errmsg(mpDB);
throw CppSQLite3Exception(nRet, (LPTSTR)szError, DONT_DELETE_MSG);
}
return pVM;
}
//////////////////////// CppSQLite3Statement ///////////////////////////////////////////
CppSQLite3Statement::CppSQLite3Statement()
{
mpDB = 0;
mpVM = 0;
}
CppSQLite3Statement::CppSQLite3Statement(const CppSQLite3Statement& rStatement)
{
mpDB = rStatement.mpDB;
mpVM = rStatement.mpVM;
// Only one object can own VM
const_cast<CppSQLite3Statement&>(rStatement).mpVM = 0;
}
CppSQLite3Statement::CppSQLite3Statement(sqlite3* pDB, sqlite3_stmt* pVM)
{
mpDB = pDB;
mpVM = pVM;
}
CppSQLite3Statement::~CppSQLite3Statement()
{
try
{
finalize();
}
catch (...) {}
}
CppSQLite3Statement& CppSQLite3Statement::operator=(const CppSQLite3Statement& rStatement)
{
mpDB = rStatement.mpDB;
mpVM = rStatement.mpVM;
// Only one object can own VM
const_cast<CppSQLite3Statement&>(rStatement).mpVM = 0;
return *this;
}
int CppSQLite3Statement::execDML()
{
checkDB();
checkVM();
int nRet = sqlite3_step(mpVM);
if (nRet == SQLITE_DONE)
{
int nRowsChanged = sqlite3_changes(mpDB);
nRet = sqlite3_reset(mpVM);
if (nRet != SQLITE_OK)
{
LPCTSTR szError = (LPCTSTR) _sqlite3_errmsg(mpDB);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -