C++ A database package that supports Sqlite3 and MySQL, supports cross-platform (Window and Linux)

Warehouse code address: https://gitee.com/liudegui/DatabaseLayer

overview

  • When we need to use the MySQL database business, we sometimes want to quickly build an application. At this time, we can use temporary SQLite instead of MySQL for development; wait for the business to stabilize before switching to the MySQL database, which can also prevent multiple people from sharing a MySQL database. conflict.
  • DatabaseLayer is a database package that supports Sqlite3 and MySQL, and supports cross-platform (Window and Linux). Refer to the database implementation in CppSQLite and POCO .

Features:

1. Provide a unified Sqlite3 and MySQL operation interface
2. Only simple packaging of Sqlite3 and MySQL API, the code is simple and easy to understand
3. CppSqlite3 does not use stl, and supports embedded platforms; CppMySQL uses a small amount of STL, Support cross-platform.
4. Does not support Unicode
5. For specific matters and methods, please refer to the examples in the demos

External header file DatabaseLayer.h

Enable MySQL or SQLite through C++ macro in DatabaseLayer.h. Of course, you can also use CppSQLite3.h or CppMySQL.h directly. The APIs of these two databases are as unified as possible.

/*! 
	\file		DatabaseLayer.h
*	\brief		数据库适配组件的基类
	\remmarks	只定义了基本的函数,具体请查看各个子类
*/

#pragma once

#ifndef _CppDBLayer_H_
#define _CppDBLayer_H_

#define POCO_VERSION 0x01010001

#ifdef _SQLITE3_DB
class	CppSQLite3Exception;
class	CppSQLite3DB;
class	CppSQLite3Query;
class	CppSQLite3ResultSet;
class	CppSQLite3Statement;

typedef  CppSQLite3Exception	CppDBException;
typedef  CppSQLite3DB			CppDB; 
typedef  CppSQLite3Query		CppDBQuery; 
typedef  CppSQLite3ResultSet	CppDBResultSet; 
typedef  CppSQLite3Statement	CppDBStatement; 
#endif

#ifdef _MySQL_DB
class	CppMySQLException;
class	CppMySQLDB;
class	CppMySQLQuery;
class	CppMySQLResultSet;
class	CppMySQLStatement;

typedef  CppMySQLException	CppDBException;
typedef  CppMySQLDB			CppDB; 
typedef  CppMySQLQuery		CppDBQuery; 
typedef  CppMySQLResultSet	CppDBResultSet; 
typedef  CppMySQLStatement	CppDBStatement;
#endif

/*!
	\class		DatabaseException 
	\brief		数据库异常处理基类
*/
class DatabaseException
{
    
    
public:
	virtual const int		errorCode()		= 0;
	virtual const char*		errorMessage()	= 0;
};

/*!
	\class		DatabaseLayer 
	\brief		数据库基本操作基类
*/
class DatabaseLayer	
{
    
    
public:
	virtual void			open(const char* szFile)	= 0;
	virtual void			close()						= 0;

	virtual bool			tableExists(const char* szTable) = 0;
	virtual int				execDML(const char* szSQL)	= 0;
	virtual CppDBQuery		execQuery(const char* szSQL) = 0;
	virtual int				execScalar(const char* szSQL, int nNullValue=0) = 0;

	virtual void			startTransaction()			= 0;
	virtual void			commitTransaction()			= 0;
	virtual void			rollback()					= 0;
	virtual bool			isTransaction()				= 0;
};

/*!
	\class		DatabaseQuery 
	\brief		数据库查询基类,不包含所有的数据
*/
class DatabaseQuery
{
    
    
public:
    virtual int				numFields()						= 0;
    virtual int				fieldIndex(const char* szField) = 0;
    virtual const char*		fieldName(int nCol)				= 0;
    virtual int				fieldDataType(int nCol)			= 0;

	virtual const char*		fieldValue(int nField)			= 0;
	virtual const char*		fieldValue(const char* szField) = 0;
	virtual bool			fieldDataIsNull(int nField)		= 0;

    virtual bool			eof()					= 0;
    virtual void			nextRow()				= 0;
	virtual	void			clear()					= 0;

	virtual	int				getIntField(int nField, int nNullValue = 0)							= 0;
	virtual	int				getIntField(const char* szField, int nNullValue = 0)				= 0;
	virtual	double			getDoubleField(int nField, double fNullValue = 0.0)					= 0;
	virtual	double			getDoubleField(const char* szField, double fNullValue = 0.0)		= 0;	
	virtual	const char*		getStringField(int nField, const char* szNullValue = "")			= 0;
	virtual	const char*		getStringField(const char* szField, const char* szNullValue = "")	= 0;
};

/*!
	\class		DatabaseResultSet 
	\brief		数据库查询结果集基类,包含所有的数据
*/
class DatabaseResultSet
{
    
    
public:
    virtual int				numFields() = 0;
    virtual unsigned long	numRows()	= 0;

	virtual int				FieldColIndex(const char* szField)	= 0;
    virtual const char*		fieldName(int nCol)					= 0;
    virtual const char*		fieldValue(int nField)				= 0;
    virtual const char*		fieldValue(const char* szField)		= 0;
	virtual bool			fieldDataIsNull(int nField)			= 0;

	virtual bool			eof()		= 0;
	virtual void			nextRow()	= 0;
    virtual int				seekRow(unsigned long nRow) = 0;
	virtual	void			clear()		= 0;
};

/*!
	\class		DatabaseStatement 
	\brief		Statement基类
				
*/
class DatabaseStatement
{
    
    
public:
	virtual int				execDML()		= 0;

	virtual void			bind(int nParam, const char* szValue)	= 0;
	virtual void			bind(int nParam, const int nValue)		= 0;
	virtual void			bind(int nParam, const double dwValue)	= 0;

	virtual void			reset() = 0;
	virtual void			clear() = 0;
};

#if defined _SQLITE3_DB && !defined _CppSQLite3_H_
#include "CppSQLite3.h"
#endif

#if defined _MySQL_DB && !defined _CPPMYSQL_H_
#include "CppMySQL.h"
#endif

#ifdef _WIN32
#include "Platform_WIN32.h"
#endif

#endif

Example of use

The sample code demonstrates how to quickly switch data between SQLite and MySQL in business code


#include <stdlib.h>
#include <stdio.h>
#include <ctime>
#include <iostream>

#include "DatabaseLayer.h"

using namespace std;

#ifdef _SQLITE3_DB
const char* gszDB = "CppSQLite3Demo.db";
#endif

#ifdef _MySQL_DB
const char* gszDB = "CppMySQLDemo";
#endif

int main()
{
    
    
	try
	{
    
    
		CppDB db;
		int i, fld;

#ifdef _SQLITE3_DB
		  remove(gszDB);
#endif
#ifdef _MySQL_DB
		db.connect("127.0.0.1", "root", "root");
		db.dropDB(gszDB);
		db.createDB(gszDB);
#endif

		db.open(gszDB);

		cout << endl << "emp table exists=" << (db.tableExists("emp") ? "TRUE":"FALSE") << endl;
		cout << endl << "Creating emp table" << endl;
		db.execDML("create table emp(empno int, empname char(20));");
		cout << endl << "emp table exists=" << (db.tableExists("emp") ? "TRUE":"FALSE") << endl;

		
		// 测试DML,打印影响行
		
		cout << endl << "= 测试DML,打印影响行 =" << endl;
		int nRows = db.execDML("insert into emp values (6, '勒布朗·詹姆斯');");
		cout << nRows << " rows inserted" << endl;

		nRows = db.execDML("update emp set empname = 'LeBron James' where empno = 6;");
		cout << nRows << " rows updated" << endl;

		nRows = db.execDML("delete from emp where empno = 7;");
		cout << nRows << " rows deleted" << endl;

		nRows = db.execDML("delete from emp where empno = 6;");
		cout << nRows << " rows deleted" << endl;

		
		// 测试事务和execScalar
		
		cout << endl << "= 测试事务和execScalar =" << endl;
		int nRowsToCreate(25000);
		cout << endl << "Transaction test, creating " << nRowsToCreate;
		cout << " rows please wait..." << endl;

		db.startTransaction();

		for (i = 0; i < nRowsToCreate; i++)
		{
    
    
			char buf[128];
			sprintf(buf, "insert into emp values (%d, 'Empname%06d');", i, i);
			db.execDML(buf);
		}

		db.commitTransaction();

		cout << db.execScalar("select count(*) from emp;") << " rows in emp table";

		
		// 重新创建表emp
		
		cout << endl << "= 重新创建表emp = " << endl;
		db.execDML("drop table emp;");
	#ifdef _SQLITE3_DB
		db.execDML("create table emp(empno integer primary key, empname char(20));");
	#endif
	#ifdef _MySQL_DB
		db.execDML("CREATE TABLE emp(empno int not null auto_increment, empname char(20) not null, primary key (empno)) ENGINE=InnoDB;");
	#endif	
		cout << nRows << " rows deleted" << endl;

		for (i = 0; i < 5; i++)
		{
    
    
			char buf[128];
			sprintf(buf, "insert into emp (empname) values ('帅锅%02d');", i+1);
			db.execDML(buf);
		}

		
		// 测试CppDBQuery
		
		cout << endl << "= 测试CppDBQuery =" << endl;
		CppDBQuery q = db.execQuery("select * from emp order by 1;");

		cout <<endl<<"Num of fields: "<< q.numFields() << endl;
	#ifdef _SQLITE3_DB
		cout <<endl<<"Num of rows: "<< db.execScalar("select count(*) from emp") << endl<<endl;
	#endif
	#ifdef _MySQL_DB
		cout <<endl<<"Num of rows: "<< q.numRows() << endl<<endl;
	#endif

		for (fld = 0; fld < q.numFields(); fld++)
		{
    
    
			cout << q.fieldName(fld) << "|";
		}
		cout << endl;

		while(!q.eof())
		{
    
    
			cout << q.getStringField(0) << "|";
			cout << q.getStringField(1) << "|" << endl;
			q.nextRow();
		}

		cout << endl << "= 赋值构造函数测试 =" << endl;
		q = db.execQuery("select empname from emp;");
		cout <<endl<<"Num of fields: "<< q.numFields() << endl;

		q.clear();

		
		// CppDBResultSet测试
		
		cout << endl << "= CppDBResultSet测试 =" << endl;
		CppDBResultSet t = db.getResultSet("select * from emp order by 1;");

		cout <<endl<<"Num of fields: "<< t.numFields() << endl;
		cout <<endl<<"Num of rows: "<< t.numRows() << endl << endl;

		for (fld = 0; fld < t.numFields(); fld++)
		{
    
    
			cout << t.fieldName(fld) << "|";
		}
		cout << endl;

		int row;
		for (row = 0; row < (int)t.numRows(); row++)
		{
    
    
			t.seekRow(row);
			for (fld = 0; fld < t.numFields(); fld++)
			{
    
    
				cout << t.fieldValue(fld) << "|";
			}
			cout << endl;
		}

		cout << endl << "另一种显示ResultSet的方法" << endl;
		t.seekRow(0);	//这步不可少
		while (!t.eof())
		{
    
    
			cout << t.fieldValue(0) << "|";
			cout << t.fieldValue(1) << "|";
			cout << endl;

			t.nextRow();
		}
		t.clear();

		
		// 测试CppDBStatement
		
		cout << endl << "= 测试CppDBStatement = " << endl;
		cout << " rows please wait..." << endl;
		db.execDML("drop table emp;");
		db.execDML("create table emp(empno int, empname char(20));");

		db.startTransaction();

		nRowsToCreate = 200;
		cout << endl << "Creating with bind by number" << endl;
		CppDBStatement stmt = db.compileStatement("insert into emp values (?, ?);");
		for (i = 0; i < nRowsToCreate; i++)
		{
    
    
			char buf[16];
			sprintf(buf, "EmpName%02d", i);
			stmt.bind(1, i);
			stmt.bind(2, buf);
			stmt.execDML();
			stmt.reset();
		}
		stmt.clear();
		db.commitTransaction();
		
		cout << db.execScalar("select count(*) from emp;") << " rows in emp table " << endl;

		t = db.getResultSet("select * from emp limit 10;");

		for (fld = 0; fld < t.numFields(); fld++)
		{
    
    
			cout << t.fieldName(fld) << "|";
		}
		cout << endl;

		for (row = 0; row < (int)t.numRows(); row++)
		{
    
    
			t.seekRow(row);
			for (fld = 0; fld < t.numFields(); fld++)
			{
    
    
				cout << t.fieldValue(fld) << "|";
			}
			cout << endl;
		}

		cout << endl << "End of tests" << endl;

	}
	catch (CppDBException& e)
	{
    
    
		cerr <<endl<< "Exception:"<<e.errorCode() << ":" << e.errorMessage() << endl;
	}

	
	// Loop until user enters q or Q
	
	char c(' ');

	while (c != 'q' && c != 'Q')
	{
    
    
		cout << "Press q then enter to quit: ";
		cin >> c;
	}

	return 0;
}



Guess you like

Origin blog.csdn.net/stallion5632/article/details/125819143