// Sqlite_db.h: interface for the CSqlite_db class.
//
//
/************************************************************************
CSqlite_db db;
db.Open("test.db");
db.ExecSQL("create table tmp(a INTEGER PRIMARY KEY,b int, c char(1))");
db.ExecSQL("insert into tmp(b,c) select 1,'a'");
db.Query("select * from tmp");
for(int i=0; i<db.RowCount(); i++)
{
for(int j=0; j<db.ColCount(); j++)
{
printf("%s | ",db.Data(i,j));
}
printf("\n");
}
sqlite_data data;
db.Query(data,"select * from tmp");
for(int i=0; i<data.RowCount(); i++)
{
for(int j=0; j<data.ColCount(); j++)
{
printf("%s | ",data(i,j));
}
printf("\n");
}
db.Close();
*/
#if !defined(AFX_SQLITE_DB_H__D626E0AF_2058_4C2F_B304_CC3C7E6B25CA__INCLUDED_)
#define AFX_SQLITE_DB_H__D626E0AF_2058_4C2F_B304_CC3C7E6B25CA__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
//------------------------------------------------------------------------
#include "include/sqlite3.h"
#include <string.h>
//------------------------------------------------------------------------
#define MAX_DBNAME 255
//------------------------------------------------------------------------
class CSqlite_db;
//class CSqlite_cursor;
//结果集类
class CSqlite_ResultSet
{
public:
CSqlite_ResultSet();
~CSqlite_ResultSet();
//克隆结果集,未完成
void Clone(CSqlite_ResultSet &X);
//重载(),取得结果,不存在则返回NULL
//从0,0开始计算
const char* operator()(int Row, int Col)
{
return GetData(Row, Col);
}
//重载(),取得结果,不存在则返回NULL
//从0行开始计算
const char* operator()(int Row, const char *ColName)
{
return GetData(Row, ColName);
}
//以下两个[]重载使得游标使用更像数组
//重载[],取得结果,不存在则返回NULL
//从0,0开始计算
const char* operator[](int Col)
{
return GetData( Col);
}
//重载[],取得结果,不存在则返回NULL
//从0,0开始计算
const char* operator[](const char *ColName)
{
return GetData( ColName);
}
//取得某行某列结果,不存在则返回NULL
//从0,0开始计算
const char* GetData(int Row, int Col);
//取得某行某列结果,不存在则返回NULL,列用字符串表示
//从0行开始计算
const char* GetData(int Row,const char *ColName)
{
return GetData(Row,colname2col(ColName));
}
//取得当前游标行某列结果,不存在则返回NULL
//从0,0开始计算
const char* GetData(int Col)
{
return GetData(m_cursor,Col);
}
//取得当前游标行某列结果,不存在则返回NULL,列用字符串表示
//从0行开始计算
const char* GetData( const char *ColName)
{
return GetData(m_cursor,ColName);
}
//获得列的名字,如果没有结果则返回NULL
const char *GetColName(int Col);
//释放结果集
void Free();
public:
//返回结果行数,实际结果中还额外包含一行标题行
int RowCount()
{
return m_RowCount;
}
//返回结果列数
int ColCount()
{
return m_ColCount;
}
//结果集是否打开
bool Active()
{
return (m_data == NULL);
}
//结果集是否为空
bool IsEmpty()
{
return (m_RowCount <= 0 || m_ColCount <= 0);
}
public: //游标函数,如果成功,则返回true
//移动游标到下一行,如果已经是最后一行,则返回false
bool moveToNext();
//移动游标到前一行,如果已经是第一行,则返回false
bool moveToPrevious();
//移动游标到第一行,如果结果集为空,则返回false
bool moveToFirst();
//移动游标到最后一行,如果结果集为空,则返回false
bool moveToLast();
//注意:以下函数对于不存在的位置返回与GetData不同
//取得当前游标Col列的字符串,如果不存在则返回""
const char *getString(int Col);
//取得当前游标Col列的数值,最大是4字节整数
//如果结果集不存在或者不是数字则返回0
int getInt(int Col)
{
return atoi(getString(Col));
}
//取得当前游标Col列的数值,最大是长整数
//如果结果集不存在或者不是数字则返回0
long getLong(int Col)
{
return atol(getString(Col));
}
//取得当前游标Col列的双精度浮点数
//如果结果集不存在或者不是数字则返回0.0
double getFloat(int Col)
{
return atof(getString(Col));
}
//按列的名字获得相应数值
//取得当前游标ColName列的字符串,如果不存在则返回"",而不是NULL
const char *getString(const char *ColName)
{
return getString(colname2col(ColName));
}
//取得当前游标ColName列的数值,最大是4字节整数
//如果结果集不存在或者不是数字则返回0
int getInt(const char *ColName)
{
return atoi(getString(ColName));
}
//取得当前游标ColName列的数值,最大是长整数
//如果结果集不存在或者不是数字则返回0
long getLong(const char *ColName)
{
return atol(getString(ColName));
}
//取得当前游标ColName列的双精度浮点数
//如果结果集不存在或者不是数字则返回0.0
double getFloat(const char *ColName)
{
return atof(getString(ColName));
}
private:
int m_cursor;
//由列名获得列的序号,如果无效则返回-1
int colname2col(const char *ColName);
friend CSqlite_db;
// friend CSqlite_cursor;
char** m_data;
int m_RowCount;
int m_ColCount;
CSqlite_ResultSet(const CSqlite_ResultSet &X);
CSqlite_ResultSet& operator=(const CSqlite_ResultSet &X);
};
class CSqlite_db
{
public:
CSqlite_db();
virtual ~CSqlite_db();
CSqlite_db(const char* dbName);
bool Open(const char* dbName);
void Close();
//执行Sql
//返回-1错误,其他结果为执行结果行数
int ExecSQL(const char* SQL);
//执行查询,通常用于多结果集时使用
//返回结果行数
int Query(CSqlite_ResultSet &ResultData, const char* SQL);
//执行查询,使用内置的结果集
//返回结果行数
int Query(const char* SQL)
{
Free(); //++释放Data
return Query(Data, SQL);
}
public:
//是否打开数据库状态
bool Connected()
{
return (NULL != m_db);
}
//返回SQLite的版本
const char* Version();
//返回打开的数据库名
const char* DataBaseName()
{
return m_dbName;
}
public:
CSqlite_ResultSet Data;
void Free()
{
Data.Free();
}
bool IsEmpty()
{
return Data.IsEmpty();
}
bool Active()
{
return Data.Active();
}
int RowCount()
{
return Data.RowCount();
}
int ColCount()
{
return Data.ColCount();
}
private:
sqlite3 *m_db;
char m_dbName[MAX_DBNAME];
//以下合并了 class CUnicode2Utf8 的内容
char *mbcs2Utf8(const char *zFilename);
char * m_zFilename;
WCHAR *m_zMbcsFilename;
char *unicodeToUtf8(const WCHAR *zWideFilename);
WCHAR *mbcsToUnicode(const char *zFilename);
// static int sqlite_callback(void *param,int colcount,char **cols,char **colnames);
};
static int sqlite_callback(void *param,int colcount,char **cols,char **colnames);
//结果集游标类
/*
class CSqlite_cursor
{
public:
CSqlite_cursor();
~CSqlite_cursor();
bool moveToNext();
bool moveToPrevious();
bool moveToFirst();
bool moveToLast();
const char *getString(int Col);
int getInt(int Col);
long getLong(int Col);
double getFloat(int Col);
};
*/
#endif // !defined(AFX_SQLITE_DB_H__D626E0AF_2058_4C2F_B304_CC3C7E6B25CA__INCLUDED_)
// Sqlite_db.cpp: implementation of the CSqlite_db class.
//
//
#include "stdafx.h"
#pragma hdrstop
#include "Sqlite_db.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
#pragma comment(lib, "sqlite3.lib")
//
// Construction/Destruction
//
CSqlite_ResultSet::CSqlite_ResultSet()
{
m_data = NULL;
m_RowCount = 0;
m_ColCount = 0;
m_cursor = 0;
}
//---------------------------------------------------------------------------
CSqlite_ResultSet::~CSqlite_ResultSet()
{
Free();
}
//---------------------------------------------------------------------------
//复制一个结果集,待完善
void CSqlite_ResultSet::Clone(CSqlite_ResultSet &X)
{
m_RowCount = X.m_RowCount;
m_ColCount = X.m_ColCount;
// m_data
}
//---------------------------------------------------------------------------
//取得某行某列结果,不存在则返回NULL
//(0,0)对应于结果的第1行,第一列
//无法用此函数获得标题行
const char* CSqlite_ResultSet::GetData(int Row, int Col)
{
if( IsEmpty()
|| Row >= m_RowCount || Row < 0
|| Col >= m_ColCount || Col < 0)
return NULL;
else
{
return m_data[m_ColCount*(Row+1)+Col];
}
}
//获得列的名字,如果没有结果则返回NULL
const char *CSqlite_ResultSet::GetColName(int Col)
{
if( IsEmpty()
|| Col >= m_ColCount || Col < 0)
return NULL;
else
{
return m_data[Col];
}
}
//释放结果集
void CSqlite_ResultSet::Free()
{
if(NULL != m_data)
{
sqlite3_free_table(m_data);
m_data = NULL;
m_RowCount = 0;
m_ColCount = 0;
m_cursor = 0;
}
}
//移动游标到下一行,如果已经是最后一行,则返回false
bool CSqlite_ResultSet::moveToNext()
{
if ( IsEmpty() || m_cursor == (m_RowCount-1) )
return false;
m_cursor ++ ;
return true;
}
//移动游标到前一行,如果已经是第一行,则返回false
bool CSqlite_ResultSet::moveToPrevious()
{
if ( IsEmpty() || m_cursor == 0 )
return false;
m_cursor -- ;
return true;
}
//移动游标到第一行,如果结果集为空,则返回false
bool CSqlite_ResultSet::moveToFirst()
{
if ( IsEmpty() )
return false;
m_cursor = 0;
return true;
}
//移动游标到最后一行,如果结果集为空,则返回false
bool CSqlite_ResultSet::moveToLast()
{
if ( IsEmpty() )
return false;
m_cursor = m_RowCount - 1;
return true;
}
//取得当前游标Col列的字符串,如果不存在则返回"";
const char *CSqlite_ResultSet::getString(int Col)
{
if ( IsEmpty() || Col < 0 || Col >= m_ColCount )
return "";
const char *result = GetData(m_cursor,Col);
return ( NULL == result ) ? "" : result ;
}
//由列名获得列的序号,如果无效则返回-1
int CSqlite_ResultSet::colname2col(const char *ColName)
{
if ( IsEmpty())
return -1;
int i;
//为了对付wchar和unicode,暂时没好办法,只好用CString
//如果用strncmp,不知道是否支持这些,待测试
CString colname=ColName;
CString colstr;
for ( i = 0 ; i < m_ColCount ; i++ )
{
colstr = GetColName(i);
if ( colstr == colname )
return i;
}
return -1;
}
//---------------一以下CSqlite_db-----------------
CSqlite_db::CSqlite_db()
{
m_db = NULL;
m_zMbcsFilename = NULL;
m_zFilename = NULL;
memset(m_dbName, 0, MAX_DBNAME);
}
CSqlite_db::~CSqlite_db()
{
Close();
}
CSqlite_db::CSqlite_db(const char* dbName)
{
m_db = NULL;
m_zMbcsFilename = NULL;
m_zFilename = NULL;
memset(m_dbName, 0, MAX_DBNAME);
Open(dbName);
}
//返回SQLite的版本
const char* CSqlite_db::Version()
{
return SQLITE_VERSION;
}
//打开数据库
bool CSqlite_db::Open(const char* dbName)
{
if(Connected())
{
Close();
}
if(NULL == dbName)
{
return false;
}
if(strlen(dbName) >= MAX_DBNAME)
{
return false;
}
strcpy(m_dbName, dbName);
//mbcs2Utf8()是为了解决sqlite不支持中文路径问题
int r = sqlite3_open(mbcs2Utf8(m_dbName),&m_db);
if(SQLITE_OK == r)
{
return true;
}
else
{
Close();
return false;
}
}
//关闭数据库
void CSqlite_db::Close()
{
Free();
if(NULL != m_db)
{
sqlite3_close(m_db);
m_db = NULL;
memset(m_dbName, 0, MAX_DBNAME);
}
if(m_zFilename)
{
delete []m_zFilename;
m_zFilename = NULL ;
}
if(m_zMbcsFilename)
{
delete []m_zMbcsFilename;
m_zMbcsFilename = NULL ;
}
}
//执行查询,返回行数
int CSqlite_db::Query(CSqlite_ResultSet &ResultData, const char* SQL)
{
if(!Connected())
{
return -1;
}
if(NULL == SQL)
{
return -1;
}
ResultData.Free();
char *pcErrMsg; /* 返回错误信息*/
int r = sqlite3_get_table(m_db, SQL, &ResultData.m_data
, &ResultData.m_RowCount, &ResultData.m_ColCount, &pcErrMsg);
if(SQLITE_OK == r)
{
return ResultData.RowCount();
}
else
{
// sqlite3_free(pcErrMsg);
pcErrMsg = NULL;
ResultData.Free();
return -1;
}
}
//执行SQL命令
int CSqlite_db::ExecSQL(const char* SQL)
{
if(!Connected())
{
return -1;
}
if(NULL == SQL)
{
return -1;
}
char *pcErrMsg = NULL;
int Row = 0;
int r = sqlite3_exec(m_db, SQL, sqlite_callback, (void*)&Row, &pcErrMsg);
if(SQLITE_OK == r)
{
return Row;
}
else
{
// sqlite3_free(pcErrMsg);
pcErrMsg = NULL;
return -1;
}
}
char *CSqlite_db::unicodeToUtf8(const WCHAR *zWideFilename)
{
int nByte;
nByte = WideCharToMultiByte(CP_UTF8, 0, zWideFilename, -1, 0, 0, 0, 0);
if ( m_zFilename != NULL )
{
delete []m_zFilename;
m_zFilename = NULL;
}
m_zFilename = new char[ nByte * sizeof(m_zFilename[0])];
if(m_zFilename == 0)
{
return 0;
}
nByte = WideCharToMultiByte(CP_UTF8, 0, zWideFilename, -1, m_zFilename, nByte,
0, 0);
if(nByte == 0)
{
delete []m_zFilename;
m_zFilename = NULL;
}
return m_zFilename;
}
WCHAR *CSqlite_db::mbcsToUnicode(const char *zFilename)
{
int nByte;
int codepage = AreFileApisANSI() ? CP_ACP : CP_OEMCP;
nByte = MultiByteToWideChar(codepage, 0, zFilename, -1, NULL, 0) * sizeof(WCHAR);
if ( m_zMbcsFilename != NULL )
{
delete []m_zMbcsFilename;
m_zMbcsFilename = NULL ;
}
m_zMbcsFilename = new WCHAR[ nByte*sizeof(m_zMbcsFilename[0])];
if(m_zMbcsFilename == NULL)
{
return 0;
}
nByte = MultiByteToWideChar(codepage, 0, zFilename, -1, m_zMbcsFilename, nByte);
if(nByte == 0)
{
delete []m_zMbcsFilename;
m_zMbcsFilename = NULL;
}
return m_zMbcsFilename;
}
char *CSqlite_db::mbcs2Utf8(const char *zFilename)
{
return unicodeToUtf8(mbcsToUnicode(zFilename));
}
//回调函数
int sqlite_callback(void *param,int colcount,char **cols,char **colnames)
{
return 0;
}