SQLITE3数据库读写助手(2)


前言

  • 本文将贴出基于Qt5.14读取任意sqlite数据库文件内容的源码
  • 文件有3个
序号 名称 概述
1 SqliteExt.h sqlite数据库读写头文件
2 SqliteExt.cc sqlite数据库读写源文件
3 CommonDef.h 常用定义
  • 后面有空再优化代码吧, 现在起码功能有了
  • 重构的可读写任意sqlite的数据库工具就是基于该模块实现的
  • SqliteExt类还有其他的功能, 见函数, 下一节再细说

CommonDef.h

#ifndef COMMOM_DEF_H_
#define COMMOM_DEF_H_
#include 
#include 

namespace oct_sqlite
{
	/// ----------------------------------------------------------------------------------------
	/// @brief: 保存当前支持的打开的文件
	///  
	/// ----------------------------------------------------------------------------------------
	using mapSqliteSuffix = std::unordered_map;
}

#endif /// COMMOM_DEF_H_

SqliteExt.h

#ifndef COMMON_SQL_H_
#define COMMON_SQL_H_
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include "CommonDef.h"

class QSqlTableModel;
class QTableView;
namespace oct_sqlite
{

	/// ----------------------------------------------------------------------------------------
	/// @brief: 读取类型
	/// ----------------------------------------------------------------------------------------
	enum enTableType
	{
		/// 数据库中的表
		TT_TABLES			= 1,
		/// 数据库中的系统表
		TT_SYSTEM_TABLES	= 2,
		/// 数据库视图
		TT_VIEWS			= 4,
		/// 数据库中的全部表格
		TT_ALL_TABLES		= 0xFF,
	};




	enum enEditStrategy
	{
		ES_FILE_CHANGE = 0,
		ES_ROW_CHANGE	= 1,
		ES_MANUAL_SUBMIT	= 2,
	};


	/// ----------------------------------------------------------------------------------------
	/// @brief: 数据库中的列类型
	/// ----------------------------------------------------------------------------------------
	enum enDBColumnType
	{
		///未知
		DBCT_NONE = 0,

		/// 整形
		DBCT_INT = 1,
		/// TEXT
		DBCT_TEXT = 2,
		/// DOUBLE
		DBCT_DOUBLE = 3,
	};


	/// ----------------------------------------------------------------------------------------
	/// @brief: 初始化参数
	/// ----------------------------------------------------------------------------------------
	struct stSQLInit_
	{
		/// 数据库文件
		QString str_sqlite_file_;
		/// 读取文件类型
		enTableType en_tt_;
		/// 编辑策略
		enEditStrategy en_es_;
	};
	using stSQLInit = stSQLInit_;

	/// ----------------------------------------------------------------------------------------
	/// @brief: 操作model
	/// ----------------------------------------------------------------------------------------
	struct stTableModelView_
	{
		/// model
		QSqlTableModel*	pmodel_	= nullptr;
		/// view
		QTableView* pview_		= nullptr;

		void set_model_to_view_()
		{
			if (pview_)
			{
				pview_->setModel(pmodel_);
			}
		}

		void del_()
		{
			if (pmodel_)
			{
				delete pmodel_;
				pmodel_ = nullptr;
			}

			if (pview_)
			{
				delete pview_;
				pview_ = nullptr;
			}

		}
	};

	using stTableModelView	= stTableModelView_;

	/// ----------------------------------------------------------------------------------------
	/// @brief: 保存tableName
	/// ----------------------------------------------------------------------------------------
	/// <表名,model_view>
	using mapTable		= QMap;











	class SqliteExt;
	/// 对应的数据转换函数
	using type_transfer_func = void* (SqliteExt::*)(void* pdata, const QVariant& var_data);



	/// ----------------------------------------------------------------------------------------
	/// @brief: 对应的数据类型处理函数结构体
	/// ----------------------------------------------------------------------------------------
	struct stTypeTransferFunc
	{
		/// 对应的类型处理函数
		type_transfer_func		func_ = nullptr;
	
		/// 当前是哪个数据类型
		enDBColumnType			enType_ = DBCT_NONE;
	};

	/// <列号,对应的数据类型>
	struct stTableColumn
	{
		/// 列名
		QString str_name_ = "";
		/// 列数据类型
		QString str_type_ = "";
	};

	using mapTableColumn = QMap;





	/// ----------------------------------------------------------------------------------------
	/// @brief: 通用读取sqlite
	/// ----------------------------------------------------------------------------------------
	class SqliteExt ///: public QObject
	{


	public:
		explicit SqliteExt(QObject *parent = nullptr);
		virtual ~SqliteExt();


		/// -------------------------------------------------------------------------------
		/// @brief:		初始化
		/// @param: 	const stSQLInit & st_init - 
		///				0 - 成功
		///				1 - 失败, st_init的第一个参数错误, 文件不存在
		///				2 - 失败, st_init的第二个参数错误, 不在给定的值中
		///				3 - 失败, st_init的第三个参数错误, 不在给定的值中
		///				5 - 失败, 无法打开参数中的数据库文件, 检查是否为sqlite3类型的数据库格式
		///				6 - 失败, 数据库中没有表格,空的数据库
		///				7 - 失败, 数据库解析失败,没有表格
		/// -------------------------------------------------------------------------------
		int initialized_(const stSQLInit& st_init) noexcept;

		/// -------------------------------------------------------------------------------
		/// @brief:		执行sqlite语句
		/// @param: 	const QString & str_sql - sql语句
		/// @param: 	const QString & str_table_name - 对数据库的那张表执行 
		///  @ret:		int
		///				
		/// -------------------------------------------------------------------------------
		int carry_on_sql_(const QString& str_sql, const QString& str_table_name) noexcept;

		/// -------------------------------------------------------------------------------
		/// @brief:		获取sql语句执行结果
		/// @param: 	const QString & str_sql - 
		/// @param: 	const QString & str_table_name - 
		///  @ret:		QT_NAMESPACE::QSqlQuery*
		///				
		/// -------------------------------------------------------------------------------
		QSqlQuery* sql_record_(const QString& str_sql, const QString& str_table_name) noexcept;

		/// -------------------------------------------------------------------------------
		/// @brief:		释放
		///  @ret:		void
		///				
		/// -------------------------------------------------------------------------------
		void uninitialized_() noexcept;


		/// -------------------------------------------------------------------------------
		/// @brief:		获取当数据库中的表
		///  @ret:		oct_sql::mapTable&
		///				
		/// -------------------------------------------------------------------------------
		const mapTable& map_table_();

		/// -------------------------------------------------------------------------------
		/// @brief:		读取当前数据库中名为str_table_name的参数, 
		/// @param: 	const QString str_table_name - 读取哪张表
		/// @param: 	stTableModelView * pout_tmv - 读取结果存放地址, 内部不会赋值, 外部赋值
		///  @ret:		int
		///				0 - 成功
		///				1 - 失败,参数[pout_tmv]为nullptr
		///				2 - 失败, 数据库中没有名为【str_table_name】的表格
		/// -------------------------------------------------------------------------------
		int table_(const QString str_table_name, stTableModelView* pout_tmv);


		/// -------------------------------------------------------------------------------
		/// @brief:		读取str_table_name中的数据到pdata
		/// @param: 	const QString & str_table_name - 哪张表
		/// @param: 	void * pdata - 数据存放地址
		///  @ret:		int
		///				0 - 成功
		///				1 - 失败, 参数中的[pdata]为空, 
		///				2 - 失败, 参数中【str_table_name】的表没有在当前的数据库中
		///				3 - 失败, 无法操作当前表的model
		///				5 - 失败, 查询数据库失败
		///				6 - 失败, 参数[str_table_name]的表格为空表
		///				7 - 失败, 无法获取表格的行数
		/// -------------------------------------------------------------------------------
		int table_data_(const QString& str_table_name, void* pdata) noexcept;

		/// -------------------------------------------------------------------------------
		/// @brief:		初始化参数指定为: ES_MANUAL_SUBMIT , 调用该函数
		/// @param: 	const QString & str_table_name - 哪张表需要提交
		///  @ret:		int
		///				0 - 成功
		///				1 - 失败, 没有找到
		///				2 - 失败,没有对应的model
		///				3 - 失败, 提交失败
		/// -------------------------------------------------------------------------------
		int submit_(const QString& str_table_name) noexcept;


		/// -------------------------------------------------------------------------------
		/// @brief:		读取【str_table_name】中的数据,将结果存放到[pout_map]中
		/// @param: 	const QString str_table_name - 哪张表
		/// @param: 	std::map * pout_map - 存放表数据的map, 外部分配空间, 函数内仅仅赋值,
		/// @param: 	const int ui_key_column_index - map的TKey所在列, 从0开始数
		///  @ret:		int
		///				0 - 成功
		/// -------------------------------------------------------------------------------
		template
		int table_data_map_(const QString str_table_name, std::map* pout_map, const int ui_key_column_index);


		/// -------------------------------------------------------------------------------
		/// @brief:		将数据写入数据库,注意: pdata中的行数应该与数据库中表的数据相同,否则,将返回非0
		/// @param: 	const QString str_table_name - 哪张表
		/// @param: 	void * pdata - 带写入数据的起始地址
		/// @param: 	const uint key_index - 主键在哪一列,从0 开始数, 
		///  @ret:		int
		///				0 - 成功
		///				1 - 失败, 参数pdata为空
		///				2 - 失败, 无法获取对应表
		/// -------------------------------------------------------------------------------
		int update_table_(const QString str_table_name, void* pdata, const uint key_index);


		/// -------------------------------------------------------------------------------
		/// @brief:		将pmap_data中的数据写入[str_table_name]中, 注意: pmap_data中的行数应该与数据库中表的数据相同,否则,将返回6
		/// @param: 	const QString str_table_name - 对应书库中表的名字
		/// @param: 	const std::map * pmap_value - 待写入数据内容
		/// @param: 	const uint key_column_index - str_table_name的主键在哪一列, 从0 开始数
		///  @ret:		int
		///				
		/// -------------------------------------------------------------------------------
		template
		int update_table_map_(const QString str_table_name, const std::map* pmap_data, const uint key_column_index);


		/// -------------------------------------------------------------------------------
		/// @brief:		检查文件后缀是否为可支持类型
		/// @param: 	const QString & str_suffix - 待检查的文件后缀
		///  @ret:		bool
		///				true - 支持, 
		///				false - 不支持
		/// -------------------------------------------------------------------------------
		bool file_suffix_is_right_(const QString& str_suffix);

		/// -------------------------------------------------------------------------------
		/// @brief:		将支持的文件以字符串的形式返回
		///  @ret:		QT_NAMESPACE::QString
		///				
		/// -------------------------------------------------------------------------------
		QString suffix_() noexcept;

	private:


		/// -------------------------------------------------------------------------------
		/// @brief:		初始化
		/// @param: 	const stSQLInit & st_init - 
		///  @ret:		int
		///				0 - 成功
		///				1 - 失败, st_init的第一个参数错误, 文件不存在
		///				2 - 失败, st_init的第二个参数错误, 不在给定的值中
		///				3 - 失败, st_init的第三个参数错误, 不在给定的值中
		///				
		/// -------------------------------------------------------------------------------
		int pre_initialized_(const stSQLInit& st_init) noexcept;

		/// -------------------------------------------------------------------------------
		/// @brief:		初始化数据库驱动
		///  @ret:		void
		///				
		/// -------------------------------------------------------------------------------
		void initialize_data_base_();


		/// -------------------------------------------------------------------------------
		/// @brief:		解析数据库默认数据类型
		///  @ret:		void
		///				
		/// -------------------------------------------------------------------------------
		void init_analysis_db_data_type_();

		/// -------------------------------------------------------------------------------
		/// @brief:		构造函数中调用
		///  @ret:		void
		///				
		/// -------------------------------------------------------------------------------
		void init_other_();


		/// -------------------------------------------------------------------------------
		/// @brief:		将单元格中的数据放入对应的处理函数
		/// @param: 	void * pdata - 
		/// @param: 	const QVariant & var_data - 
		///  @ret:		void
		///				
		/// -------------------------------------------------------------------------------
		void* analysis_cell_value_int_(void* pdata, const QVariant& var_data);
		void* analysis_cell_value_str_(void* pdata, const QVariant& var_data);
		void* analysis_cell_value_double_(void* pdata, const QVariant& var_data);


		QSqlTableModel* table_model_(const QString& str_table_name);


		/// -------------------------------------------------------------------------------
		/// @brief:		获取列名
		/// @param: 	const QString & str_table_name - 哪张表
		///  @ret:		QT_NAMESPACE::QStringList
		///				
		/// -------------------------------------------------------------------------------
		mapTableColumn table_column_type_(QSqlQueryModel* pModel, const QString& str_table_name);

		/// -------------------------------------------------------------------------------
		/// @brief:		读取表的行数
		/// @param: 	QSqlQueryModel * pModel - 
		/// @param: 	const QString & str_table_name - 
		///  @ret:		int
		///				
		/// -------------------------------------------------------------------------------
		int table_row_count_(QSqlQueryModel* pModel, const QString& str_table_name);


		/// -------------------------------------------------------------------------------
		/// @brief:		根据参数, 得到对应sql语句对应的部分
		/// @param: 	const QString & str_key_type - 当前数据是那种类型: TEXT 还是INTEGER
		/// @param: 	void * pdata - 对应的数据
		/// @param: 	QString * pout_value - 解析结果
		///  @ret:		void *
		///				数据区的下一个首地址
		/// -------------------------------------------------------------------------------
		void *column_sql_str_(const QString& str_key_type, void* pdata, QString* pout_value);


	private:
		/// 是否执行了释放资源
		bool	b_has_uninitialized_ = false;
		/// 数据库连链接名称
		QString		str_data_base_connect_name_;
		/// 数据库操作对象
		QSqlDatabase		sql_data_base_;
		/// 保存对应数据库中的表
		mapTable		map_db_table_;

		using mapStrDataType = std::map;/// QMap;
		/// <解析数据类型, 解析数据类型>
		mapStrDataType			map_analysis_db_type_;
		/// 保存当前支持的sqlite3的数据库类型
		mapSqliteSuffix		map_sqlite_suffix_;


	};

	/// --------------------------------------------------------------------------------
	/// @brief: oct_sqlite::SqliteExt::table_data_map_
	/// --------------------------------------------------------------------------------
	template
	int oct_sqlite::SqliteExt::table_data_map_(const QString str_table_name, std::map* pout_map, const int ui_key_column_index)
	{
		/// 1. 参数第二个无效,
		if (nullptr == pout_map)
		{
			return 1;
		}

		/// 2. 无法找到参数中的key, 
		QSqlTableModel* pmodel = table_model_(str_table_name);
		if (nullptr == pmodel)
		{
			return 2;
		}

		mapTableColumn map_column_type = table_column_type_(pmodel, str_table_name);

		/// ---------------------------------------------------------------------------------------
		/// 3. 主键也有效, 直接读取数据
		/// ---------------------------------------------------------------------------------------
		/// 得到当前表列数
		const int column_total_count = map_column_type.count();
		/// 检查参数中的主键索引
		if ((0 > ui_key_column_index) || (ui_key_column_index > column_total_count))
		{
			return 3;
		}


		/// ---------------------------------------------------------------------------------------
		/// 将数据读入pdata中: 逐行读取, 逐行的同时,读取逐列
		int row_total_count = table_row_count_(pmodel, str_table_name);

		QSqlQuery sql_query = pmodel->query();
		sql_query.first();

		/// 读取行
		for (int row_index = 0; row_index < row_total_count; ++row_index)
		{
			/// ---------------------------------------------------------------------------------------
			/// 这里开始插入map
			TValue map_item_value;
			TKey* pkey = nullptr;
			TKey map_item_key = 0;

			void* pdata = (void*)&map_item_value;

			/// 读取列
			for (int column_index = 0; column_index < column_total_count; ++column_index)
			{
				/// 检查当前行是否为key
				if (column_index == ui_key_column_index)
				{
					pkey = (TKey*)pdata;
				}

				QString str_cur_column_type = map_column_type.value(column_index).str_type_;

				/// 当前类型为空,则跳过当前行
				if (true == str_cur_column_type.isEmpty())
				{
					break;
				}

				/// 如果当前的数据类型不在给定的解析列表中,则pass
				auto find_current_type_is_exist = map_analysis_db_type_.find(str_cur_column_type);
				/// 不在给定的类型中, 则pass
				if (find_current_type_is_exist == map_analysis_db_type_.end())
				{
					break;
				}

				/// 根据对应的数据类型做转换
				if (find_current_type_is_exist->second.func_)
				{
					pdata = (this->*find_current_type_is_exist->second.func_)(pdata, sql_query.value(column_index));
				}
				else
				{
					;/// 数据类型处理函数无效
				}
			}


			if (nullptr != pkey)
			{
				map_item_key = *pkey;

				///  一行读取结束, 将其插入map
				pout_map->emplace(map_item_key, map_item_value);
			}


			/// 读取下一行, 无法读取,则pass
			if (false == sql_query.next())
			{
				break;
			}
		}


		return 0;
	}

	/// --------------------------------------------------------------------------------
	/// @brief: oct_sqlite::SqliteExt::update_table_map_
	/// --------------------------------------------------------------------------------
	template
	int oct_sqlite::SqliteExt::update_table_map_(const QString str_table_name, const std::map* pmap_data, const uint key_column_index)
	{
		/// 1. 检查 参数 pmap_data
		if (nullptr == pmap_data)
		{
			return 1;
		}

		/// 2, 获取对应表格的model
		QSqlQueryModel* pmodel = table_model_(str_table_name);
		if (nullptr == pmodel)
		{
			return 2;
		}


		/// 3. 将数据写入数据库, 逐个单元格写入
		/// UPDATE 表名称 SET 列名称 = 新值 WHERE 列名称 = 某值
		/// UPDATE Person SET FirstName = 'Fred' WHERE LastName = 'Wilson' 
		/// UPDATE Person SET Address = 'Zhongshan 23', City = 'Nanjing'
		///							WHERE LastName = 'Wilson'

		/// 5. 获取表的列
		mapTableColumn map_table_column_name	= table_column_type_(pmodel, str_table_name);

		/// 6. 检查列
		const uint table_column_total_count		= map_table_column_name.count();
		if ((0 == table_column_total_count) || (key_column_index > table_column_total_count))
		{
			return 3;
		}

		/// 7. 获取表的行数, 用于确定要写多少个单元格
		int row_total_count = table_row_count_(pmodel, str_table_name);
		/// 如果表的行为0
		if (0 >= row_total_count)
		{
			return 5;
		}

		/// 8. 如果参数中map的个数与当前数据库中行的个数不等,则返回
		if (row_total_count != pmap_data->size())
		{
			return 6;
		}


		/// 9. 将数据写入数据库
		//std::map::iterator find_value_it = pmap_data->begin();
		auto find_value_it = pmap_data->begin();

		/// 一共有这么多行的数据需要写入
		for (; find_value_it != pmap_data->end(); ++find_value_it)
		{

			QString str_update_sql = "UPDATE " + str_table_name + " SET ";
			/// 主键列名
			QString str_key_name = map_table_column_name.value(key_column_index).str_name_;
			QString str_key_type = map_table_column_name.value(key_column_index).str_type_;
			QString str_where_value;/// = where_value(str_key_name, pkey_value);

			/// 是否读取下一行
			bool is_read_next_line = false;

			/// 统计set 列数
			int set_index = 0;

			/// 列数据的起始地址
			void* pdata			= (void*)&find_value_it->second;

			/// 每一行有这么多列的数据需要写入
			for (int column_index = 0; column_index < table_column_total_count; ++column_index)
			{
				QString str_value;
				/// 不能更新主键列
				if (key_column_index == column_index)
				{
					pdata = column_sql_str_(str_key_type, pdata, &str_where_value);
					continue;
				}

				/// 第 X列的名称: id, name, value
				QString str_column_type = map_table_column_name.value(column_index).str_type_;
				QString str_column_name = map_table_column_name.value(column_index).str_name_;

				/// 拼接sql: set column=value
				pdata = column_sql_str_(str_column_type, pdata, &str_value);

				/// 无法解析
				if (true == str_value.isEmpty())
				{
					is_read_next_line = true;
					break;
				}

				/// 如果这是第二次执行, 则需要添加 逗号
				if (0 < set_index)
				{
					str_update_sql += ", " + str_column_name + "=" + str_value;
					++set_index;
				}
				else
				{
					str_update_sql += str_column_name + "=" + str_value;
					++set_index;
				}
			}	/// end 总列数



				/// 如果不是读取下一行
			if (false == is_read_next_line)
			{
				/// 构建完整的sql语句
				str_update_sql += " WHERE " + str_key_name + "=" + str_where_value + ";";

				qDebug() << "sql_str=" << str_update_sql;

				///  执行sql语句
				QSqlQuery sql_query = pmodel->query();
				sql_query.first();

				bool prepare_ret = sql_query.prepare(str_update_sql);

				/// 语法错误
				if (false == prepare_ret)
				{
					;
				}
				else
				{
					bool exec_ret = sql_query.exec();
					qDebug() << "exec_ret=" << exec_ret;
				}
			}/// 读取下一行


			/// 上面的一行已经写入完成, 下面开始写入下一行数据
		}	/// 有这么多行数据

		return 0;
	}






}

#endif /// COMMON_SQL_H_

SqliteExt.cc

#include 
#include 
#include 
#include 
#include 
#include "SqliteExt.h"

namespace oct_sqlite
{


	SqliteExt::SqliteExt(QObject *parent)
		//: QObject(parent)
	{
		str_data_base_connect_name_ = QString("");
		initialize_data_base_();
		init_analysis_db_data_type_();
		init_other_();
	}

	SqliteExt::~SqliteExt()
	{
		uninitialized_();
	}

	/// --------------------------------------------------------------------------------
	/// @brief: CommonSql::initialized_
	/// --------------------------------------------------------------------------------
	int SqliteExt::initialized_(const stSQLInit& st_init) noexcept
	{
		{
			///1. 参数检查
			int ret			= pre_initialized_(st_init);
			if (0			!= ret)
			{
				return ret;
			}
		}

		/// 2. 避免多次初始化
		uninitialized_();

		/// 3. 尝试打开数据库文件
		sql_data_base_.setDatabaseName(st_init.str_sqlite_file_);

		/// 打开失败
		if (false == sql_data_base_.open())
		{
			QSqlError error = sql_data_base_.lastError();
			return 5;
		}

		{
			/// 5. 打开成功,读取数据库中数据
			/// 读取表名
			QStringList list_table_name = sql_data_base_.tables(static_cast(st_init.en_tt_));

			/// 6. 如果没有表
			if (0 == list_table_name.count())
			{
				return 6;
			}

			/// 7. 存在, 创建对应的sqlmodel和tableview, 
			for (auto str_table_name : list_table_name)
			{
				stTableModelView st_tmv;

				/// 8, 创建tableview
				st_tmv.pview_				= new(std::nothrow) QTableView;
				st_tmv.pmodel_				= new(std::nothrow) QSqlTableModel(st_tmv.pview_, sql_data_base_);

				QSqlTableModel* pmodel		= st_tmv.pmodel_;
				/// 9. 设置model的参数
				if (pmodel)
				{
					pmodel->setTable(str_table_name);
					/// 设置编辑策略
					pmodel->setEditStrategy(static_cast(st_init.en_es_));
					/// 查询山上
					pmodel->select();
					/// 解除256行的限制
					while (pmodel->canFetchMore())
					{
						pmodel->fetchMore();
					}
				}

				st_tmv.set_model_to_view_();
				/// 10. 设置view的参数
				QTableView* pview		= st_tmv.pview_;
				if (pview)
				{
					pview->verticalHeader()->setVisible(false);
					pview->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
					pview->horizontalHeader()->setStretchLastSection(true);
					pview->setSelectionBehavior(QAbstractItemView::SelectItems);
				}

				/// 加入map
				map_db_table_.insert(str_table_name, st_tmv);
			}
		}

		/// 11. 读取结束, 检查map中的个数
		if (0 == map_db_table_.count())
		{
			return 7;
		}

		/// 12, 保存当前操作的数据库名称
		str_data_base_connect_name_ = st_init.str_sqlite_file_;

		return 0;

	}

	/// --------------------------------------------------------------------------------
	/// @brief: 执行sqlite语句
	/// --------------------------------------------------------------------------------
	int SqliteExt::carry_on_sql_(const QString& str_sql, const QString& str_table_name) noexcept
	{
		/// 1. 如果数据库没有打开,则返回
		if (false == sql_data_base_.isOpen())
		{
			return 1;
		}


		/// 2. 参数为空
		if (true == str_sql.isEmpty())
		{
			return 2;
		}
		
	

		/// 3. 执行sql
		auto find_sql_model_it = map_db_table_.find(str_table_name);
		/// 表名不存在
		if (find_sql_model_it == map_db_table_.end())
		{
			return 3;
		}

		QSqlQueryModel* pmodel = find_sql_model_it->pmodel_;
		if (nullptr == pmodel)
		{
			/// 指针无效
			return 5;
		}

		bool prepare_ret = pmodel->query().prepare(str_sql);

		/// 语法错误
		if (false == prepare_ret)
		{
			return 6;
		}

		/// 
		bool exec_ret = pmodel->query().exec();

		/// 返回执行结果
		return (true == exec_ret ? 0 : 7);
	}

	/// --------------------------------------------------------------------------------
	/// @brief: CommonSql::sql_record_
	/// --------------------------------------------------------------------------------
	QSqlQuery* SqliteExt::sql_record_(const QString& str_sql, const QString& str_table_name) noexcept
	{
		/// 1. 如果数据库没有打开,则返回
		if (false == sql_data_base_.isOpen())
		{
			return nullptr;
		}


		/// 2. 参数为空
		if (true == str_sql.isEmpty())
		{
			return nullptr;
		}



		/// 3. 执行sql
		auto find_sql_model_it = map_db_table_.find(str_table_name);
		/// 表名不存在
		if (find_sql_model_it == map_db_table_.end())
		{
			return nullptr;
		}

		QSqlQueryModel* pmodel = find_sql_model_it->pmodel_;
		if (nullptr == pmodel)
		{
			/// 指针无效
			return nullptr;
		}

		bool prepare_ret = pmodel->query().prepare(str_sql);

		/// 语法错误
		if (false == prepare_ret)
		{
			return nullptr;
		}

		/// 
		bool exec_ret = pmodel->query().exec();

		/// 返回执行结果
		return (true == exec_ret ? &pmodel->query() : nullptr);
	}

	/// --------------------------------------------------------------------------------
	/// @brief: CommonSql::uninitialized_
	/// --------------------------------------------------------------------------------
	void SqliteExt::uninitialized_() noexcept
	{
		try
		{
			for (auto item: map_db_table_)
			{
				item.del_();
			}

			/// 重置map
			if (0 < map_db_table_.count())
			{
				mapTable map_tmp;
				map_db_table_.swap(map_tmp);
			}

			/// 关闭数据库
			if (true == sql_data_base_.isOpen())
			{
				sql_data_base_.close();
			}

		}
		catch (...)
		{
			;
		}
	}

	/// --------------------------------------------------------------------------------
	/// @brief: CommonSql::map_table_
	/// --------------------------------------------------------------------------------
	const oct_sqlite::mapTable& SqliteExt::map_table_() 
	{
		return map_db_table_;
	}


	/// --------------------------------------------------------------------------------
	/// @brief: SqliteAssistant::table_model_
	/// --------------------------------------------------------------------------------
	QSqlTableModel* SqliteExt::table_model_(const QString& str_table_name)
	{
		/// 1. 找到对应的表
		auto find_model_it = map_db_table_.find(str_table_name);
		if (find_model_it == map_db_table_.end())
		{
			return nullptr;
		}

		/// 3. 获取数据库表的字段类型
		return find_model_it->pmodel_;;
	}

	/// --------------------------------------------------------------------------------
	/// @brief: SqliteAssistant::table_column_name_
	/// --------------------------------------------------------------------------------
	mapTableColumn SqliteExt::table_column_type_(QSqlQueryModel* pModel, const QString& str_table_name)
	{
		mapTableColumn ret_map;
		if (nullptr == pModel)
		{
			return ret_map;
		}



		QString str_sql_column_type = QString("PRAGMA table_info( " + str_table_name + " ) ");
		QSqlQuery  sqlquery = pModel->query();

		bool ret = sqlquery.prepare(str_sql_column_type);
		if (false == ret)
		{
			return ret_map;
		}


		if (true == sqlquery.exec())
		{
			/// 7. 将列的数据类型放入list
			uint index = 0;
			while (sqlquery.next())
			{
				stTableColumn map_insert_value;
				map_insert_value.str_name_	= sqlquery.value(1).toString();
				map_insert_value.str_type_	= sqlquery.value(2).toString();


				ret_map.insert(index, map_insert_value);
				++index;
			}
		}


		sqlquery.first();

		return ret_map;
	}


	/// --------------------------------------------------------------------------------
	/// @brief: SqliteAssistant::table_row_count_
	/// --------------------------------------------------------------------------------
	int SqliteExt::table_row_count_(QSqlQueryModel* pmodel, const QString& str_table_name)
	{
		if (nullptr == pmodel)
		{
			return 0;
		}

		/// 继续读取行数
		QSqlQuery sql_query = pmodel->query();
		QString str_sql_query = QString("select * from %1").arg(str_table_name);
		sql_query.prepare(str_sql_query);
		QSqlRecord table_record = sql_query.record();
		if (false == sql_query.exec())
		{
			return 7;
		}

		/// 8. 读取行数
		int row_total_count = 0;
		if (true == sql_query.last())
		{
			row_total_count = sql_query.at() + 1;
			sql_query.first();
		}

		return row_total_count;
	}


	/// --------------------------------------------------------------------------------
	/// @brief: 读取str_table_name中的数据到pdata中
	/// --------------------------------------------------------------------------------
	int SqliteExt::table_data_(const QString& str_table_name, void* pdata) noexcept
	{
		/// 0. 指针无效
		if (nullptr == pdata)
		{
			return 1;
		}

		/// 1. 得到数据库模型
		QSqlQueryModel* pmodel = table_model_(str_table_name);
		if (nullptr == pmodel)
		{
			return 2;
		}


		/// ---------------------------------------------------------------------------------------
		/// 5. 准备查询数据库字段的sql语句
		
		/// 6. 读取表的列数
		mapTableColumn		map_column_type = table_column_type_(pmodel, str_table_name);

		/// 得到当前表列数
		const int column_total_count	= map_column_type.count();

	


		/// ---------------------------------------------------------------------------------------
		/// 将数据读入pdata中: 逐行读取, 逐行的同时,读取逐列
		int row_total_count = table_row_count_(pmodel, str_table_name);
		QSqlQuery sql_query = pmodel->query();
		sql_query.first();

		/// 读取行
		for (int row_index = 0; row_index < row_total_count; ++row_index)
		{
			/// 读取列
			for (int column_index = 0; column_index < column_total_count; ++column_index)
			{
				QString str_cur_column_type = map_column_type.value(column_index).str_type_;

				/// 当前类型为空,则跳过当前行
				if (true == str_cur_column_type.isEmpty())
				{
					break;
				}

				/// 如果当前的数据类型不在给定的解析列表中,则pass
				auto find_current_type_is_exist = map_analysis_db_type_.find(str_cur_column_type);
				/// 不在给定的类型中, 则pass
				if (find_current_type_is_exist == map_analysis_db_type_.end())
				{
					break;
				}

				/// 根据对应的数据类型做转换
				if (find_current_type_is_exist->second.func_)
				{
					pdata = (this->*find_current_type_is_exist->second.func_)(pdata, sql_query.value(column_index));
				}
				else
				{
					;/// 数据类型处理函数无效
				}
			}

			/// 读取下一行, 无法读取,则pass
			if (false == sql_query.next())
			{
				break;
			}
		}

		return 0;
	}

	/// --------------------------------------------------------------------------------
	/// @brief: CommonSql::pre_initialized_
	/// --------------------------------------------------------------------------------
	int SqliteExt::pre_initialized_(const stSQLInit& st_init) noexcept
	{
		/// 1. 数据库文件不存在
		{
			QFile file_db(st_init.str_sqlite_file_);
			if (false == file_db.exists())
			{
				return 1;
			}

			/// 2. 检查参数
			const uint en_tt = st_init.en_tt_;
			if ( (TT_TABLES  != en_tt) && (TT_VIEWS != en_tt) && (TT_SYSTEM_TABLES != en_tt) && (TT_ALL_TABLES != en_tt) )
			{
				return 2;
			}

			/// 检查第三个参数
			if ((ES_FILE_CHANGE != st_init.en_es_) && (ES_ROW_CHANGE != st_init.en_es_) && (ES_MANUAL_SUBMIT != st_init.en_es_))
			{
				return 3;
			}
		}

		return 0;
		
	}

	/// --------------------------------------------------------------------------------
	/// @brief: CommonSql::initialize_data_base_
	/// --------------------------------------------------------------------------------
	void SqliteExt::initialize_data_base_()
	{
		bool is_contain = QSqlDatabase::contains(str_data_base_connect_name_);
		if (true == is_contain)
		{
			sql_data_base_ = QSqlDatabase::database(str_data_base_connect_name_);
		}
		else
		{
			sql_data_base_ = QSqlDatabase::addDatabase("QSQLITE", str_data_base_connect_name_);
			str_data_base_connect_name_ = "QSQLITE";
		}
	}



	/// --------------------------------------------------------------------------------
	/// @brief: 解析数据库默认数据类型
	/// --------------------------------------------------------------------------------
	void SqliteExt::init_analysis_db_data_type_()
	{

		auto insert_map = [&](const QString str_type, type_transfer_func func, enDBColumnType en_dbct)
		{
			stTypeTransferFunc map_item_value;
			map_item_value.func_ = func;
			map_item_value.enType_ = en_dbct;

			map_analysis_db_type_.emplace(str_type, map_item_value);
		};

		/// 1. 文本
		insert_map("TEXT",	&SqliteExt::analysis_cell_value_str_, DBCT_TEXT);
		/// 2. 整数
		insert_map("INTEGER", &SqliteExt::analysis_cell_value_int_, DBCT_INT);
		/// 3. double
		insert_map("DOUBLE",	&SqliteExt::analysis_cell_value_double_, DBCT_DOUBLE);
		/// 5. char 
		////insert_map("CHAR", &SqliteAssistant::analysis_cell_value_char_, );


	}

	/// --------------------------------------------------------------------------------
	/// @brief: CommonSql::analysis_cell_value_int_
	/// --------------------------------------------------------------------------------
	void* SqliteExt::analysis_cell_value_int_(void* pdata, const QVariant& var_data)
	{
		if (nullptr == pdata)
		{
			return pdata;
		}

		int *pvalue = (int*)(pdata);
		*pvalue = var_data.toInt();
	
		++pvalue;
		pdata = (void*)pvalue;

		return pdata;
	}

	/// --------------------------------------------------------------------------------
	/// @brief: CommonSql::analysis_cell_value_str_
	/// --------------------------------------------------------------------------------
	void* SqliteExt::analysis_cell_value_str_(void* pdata, const QVariant& var_data)
	{
		if (nullptr == pdata)
		{
			return pdata;
		}

		QString *pvalue = (QString*)(pdata);
		*pvalue = var_data.toString();;

		++pvalue;

		pdata = (void*)pvalue;

		return pdata;
	}

	/// --------------------------------------------------------------------------------
	/// @brief: CommonSql::analysis_cell_value_double_
	/// --------------------------------------------------------------------------------
	void* SqliteExt::analysis_cell_value_double_(void* pdata, const QVariant& var_data)
	{
		if (nullptr == pdata)
		{
			return pdata;
		}

		double *pvalue = (double*)(pdata);
		*pvalue = var_data.toDouble();

		++pvalue;

		pdata = (void*)pvalue;

		return pdata;
	}


	/// --------------------------------------------------------------------------------
	/// @brief: CommonSql::读取当前数据库中名为str_table_name的参数
	/// --------------------------------------------------------------------------------
	int SqliteExt::table_(const QString str_table_name, stTableModelView* pout_tmv)
	{
		/// 1. 参数为空无法存放读取结果
		if (nullptr == pout_tmv)
		{
			return 1;
		}


		/// 2. 找参数中的表格
		auto find_table_it = map_db_table_.find(str_table_name);

		/// 3. 没找到; 返回2
		if (find_table_it == map_db_table_.end())
		{
			return 2;
		}

		/// 5 找到了,返回结果
		*pout_tmv = find_table_it.value();

		return 0;
	}

	/// -------------------------------------------------------------------------------
	/// @brief:		检查参数中的key是否在给定的listColumnName中
	/// @param: 	const QStringList & listColumnName - 
	///  @ret:		bool
	///				-1 -不存在列
	///				X > 0 , key是第几列
	/// -------------------------------------------------------------------------------

	/// --------------------------------------------------------------------------------
	/// @brief: oct_sqlite::SqliteAssistant::is_right_key_
	/// --------------------------------------------------------------------------------
	template
	int SqliteExt::is_right_key_(const mapTableColumn& listColumnName)
	{
		int ret = 0;

		return ret;
	}

	/// --------------------------------------------------------------------------------
	/// @brief: 将数据写入数据库
	/// --------------------------------------------------------------------------------
	int SqliteExt::update_table_(const QString str_table_name, void* pdata, const uint key_column_index)
	{
		/// 1. 检查 参数 pdata
		if (nullptr == pdata)
		{
			return 1;
		}

		/// 2, 获取对应表格的model
		QSqlQueryModel* pmodel = table_model_(str_table_name);
		if (nullptr == pmodel)
		{
			return 2;
		}


		/// 3. 将数据写入数据库, 逐个单元格写入
		/// UPDATE 表名称 SET 列名称 = 新值 WHERE 列名称 = 某值
		/// UPDATE Person SET FirstName = 'Fred' WHERE LastName = 'Wilson' 
		/// UPDATE Person SET Address = 'Zhongshan 23', City = 'Nanjing'
		///							WHERE LastName = 'Wilson'

		/// 5. 获取表的列
		mapTableColumn map_table_column_name = table_column_type_(pmodel, str_table_name);

		/// 6. 检查列
		const uint table_column_total_count = map_table_column_name.count();
		if ((0 == table_column_total_count) || (key_column_index > table_column_total_count))
		{
			return 3;
		}

		/// 7. 获取表的行数, 用于确定要写多少个单元格
		int row_total_count = table_row_count_(pmodel, str_table_name);
		/// 如果表的行为0
		if (0 >= row_total_count)
		{
			return 5;
		}

		/// ---------------------------------------------------------------------------------------
		/// 有这么多行
		for (int row_index = 0; row_index < row_total_count; ++row_index)
		{
			QString str_update_sql = "UPDATE " + str_table_name + " SET ";
			/// 主键列名
			QString str_key_name = map_table_column_name.value(key_column_index).str_name_;
			QString str_key_type = map_table_column_name.value(key_column_index).str_type_;
			QString str_where_value;/// = where_value(str_key_name, pkey_value);

			/// 是否读取下一行
			bool is_read_next_line = false;

			/// 统计set 列数
			int set_index = 0;

			/// 有这么多列
			for (int column_index = 0; column_index < table_column_total_count; ++column_index)
			{
				QString str_value;
				/// 不能更新主键列
				if (key_column_index == column_index)
				{
					pdata = column_sql_str_(str_key_type, pdata, &str_where_value);
					continue;
				}

				/// 第 X列的名称: id, name, value
				QString str_column_type = map_table_column_name.value(column_index).str_type_;
				QString str_column_name = map_table_column_name.value(column_index).str_name_;

				/// 拼接sql: set column=value
				pdata = column_sql_str_(str_column_type, pdata, &str_value);
				
				/// 无法解析
				if (true == str_value.isEmpty())
				{
					is_read_next_line = true;
					break;
				}

				/// 如果这是第二次执行, 则需要添加 逗号
				if (0 < set_index)
				{
					str_update_sql += ", " + str_column_name + "=" + str_value;
					++set_index;
				}
				else
				{
					str_update_sql += str_column_name + "=" + str_value;
					++set_index;
				}
			}

			/// 如果不是读取下一行
			if (false == is_read_next_line)
			{
				/// 构建完整的sql语句
				str_update_sql += " WHERE " + str_key_name + "=" + str_where_value + ";";

				///  执行sql语句
				QSqlQuery sql_query = pmodel->query();
				sql_query.first();

				bool prepare_ret = sql_query.prepare(str_update_sql);

				/// 语法错误
				if (false == prepare_ret)
				{
					;
				}
				else
				{
					bool exec_ret = sql_query.exec();
					//qDebug() << "exec_ret=" << exec_ret;
				}
			}
			/// 继续下一行
		}


		return 0;
	}

	/// --------------------------------------------------------------------------------
	/// @brief: SqliteExt::column_sql_str_
	/// --------------------------------------------------------------------------------
	void * SqliteExt::column_sql_str_(const QString& str_key_type, void* pdata, QString* pout_value)
	{
		void *ret_value = nullptr;
		/// 如果是text
		if ("TEXT" == str_key_type)
		{
			QString *pstr = (QString*)pdata;
			*pout_value = "'" + *pstr + "'";
			++pstr;
			ret_value = (void*)pstr;

		}
		/// 如果是INT
		else if ("INTEGER" == str_key_type)
		{
			int* pint = (int*)pdata;
			*pout_value = QString::number(*pint);
			++pint;
			ret_value = (void*)pint;
		}
		/// 如果是double
		else if ("DOUBLE" == str_key_type)
		{
			double* pdb = (double*)pdata;
			*pout_value = QString::number(*pdb);
			++pdb;
			ret_value = (void*)pdb;
		}
		else
		{
			;
		}

		return ret_value;
	}

	/// --------------------------------------------------------------------------------
	/// @brief: SqliteExt::init_other_
	/// --------------------------------------------------------------------------------
	void SqliteExt::init_other_()
	{
		/// 参数1: sqlite的后缀, 比如: .slite
		auto insert_map = [=](const QString& str_suffix)
		{
			map_sqlite_suffix_.emplace(str_suffix, 0);
		};

		insert_map(".db");
		insert_map(".sdb");
		insert_map(".sqlite");
		insert_map(".db3");
		insert_map(".s3db");
		insert_map(".sqlite3");
		insert_map(".sl3");
	}

	/// --------------------------------------------------------------------------------
	/// @brief: 检查文件后缀是否为可支持类型
	/// --------------------------------------------------------------------------------
	bool SqliteExt::file_suffix_is_right_(const QString& str_suffix)
	{
		auto find_suffix_it = map_sqlite_suffix_.find(str_suffix);
		if (find_suffix_it == map_sqlite_suffix_.end())
		{
			return false;
		}

		return true;
	}

	/// --------------------------------------------------------------------------------
	/// @brief: SqliteExt::submit_
	/// --------------------------------------------------------------------------------
	int SqliteExt::submit_(const QString& str_table_name) noexcept
	{
		auto find_table_it = map_db_table_.find(str_table_name);

		/// 1. 没有找到
		if (find_table_it == map_db_table_.end())
		{
			return 1;
		}

		/// 2. 找到了,检查提交结果
		auto pmodel = find_table_it.value().pmodel_;
		if (pmodel)
		{
			if (false == pmodel->submitAll())
			{
				return 3;
			}
		}
		else
		{
			return 2;
		}

		return 0;
	}

	/// --------------------------------------------------------------------------------
	/// @brief: 将支持的文件以字符串的形式返回
	/// --------------------------------------------------------------------------------
	QString SqliteExt::suffix_() noexcept
	{
		QString str_ret;
		
		for (auto find_it = map_sqlite_suffix_.begin(); find_it != map_sqlite_suffix_.end(); ++ find_it)
		{
			str_ret += find_it->first + " ";
		}

		return str_ret;
	}

}