CppSQLite3 的MFC 桥接

发布时间 2023-04-12 17:41:30作者: 天地浮游
因为工作原因需要在MFC中使用SQLite,历史原因只能使用C++11,C++20的新特性都用不上,好在有boost,对CppSQLite3 进行了桥接,并且简化了使用方式
  1 //头文件
  2 #include <memory>
  3 #include <unordered_map>
  4 #include <typeindex>
  5 #include "boost\\any.hpp"
  6 #include <functional>
  7 
  8 class  SQLiteDB
  9 {
 10 public:
 11 
 12     SQLiteDB();
 13     virtual ~SQLiteDB();
 14     void open(const CString szFile = L":memory:");
 15     void open_v2(const CString szFile);
 16     void close();
 17     bool tableExists(CString szTable);
 18     int execDML(CString szSQL);
 19 
 20     SQLiteQuery execQuery(const CString szSQL);
 21 
 22     int execScalar(const CString szSQL, int nNullValue = 0);
 23 
 24     SQLiteTable getTable(const CString szSQL);
 25 
 26     SQLiteStatement compileStatement(const CString szSQL);
 27 
 28     __int64 lastRowId();
 29     void interrupt();
 30     void setBusyTimeout(int nMillisecs);
 31     bool IsAutoCommitOn();
 32 private:
 33     std::unique_ptr<CppSQLite3DB> m_pDB;    
 34 };
 35 
 36 class  Database
 37 {
 38 public:
 39     Database(CString dbName);
 40     ~Database();
 41     bool Query(CString sql);//查询数据库
 42     int execDML(CString sql);//执行语句
 43     template< class... Types >
 44     bool GetNextRowData(Types&... args);
 45     void GetTest(int col, unsigned  short*val);
 46     bool eof();
 47     SQLiteDB* GetSqliteDb(){ return m_pSQLiteDB.get(); }
 48 private:
 49     std::shared_ptr<SQLiteQuery> m_ptr_result;//查询结果
 50     std::shared_ptr<SQLiteDB> m_pSQLiteDB;//数据库
 51     CString m_sDatabasePath;
 52     std::unordered_map<std::type_index, std::function<void(CString&, boost::any &)>> m_any_visitor;//根据字段
 53     std::unordered_map<std::type_index, std::function<void(int, boost::any&)>> m_any_visitor2;//根据行号
 54 
 55     template<class T, class F>
 56     inline std::pair<const std::type_index, std::function<void(int col, boost::any &)>> to_any_visitor2(F const& f);
 57 };
 58 namespace dtofxls
 59 {
 60     //C++参考 std::any::type
 61     template<class T, class F>
 62     inline std::pair<const std::type_index, std::function<void(CString &colName, boost::any &)>> to_any_visitor(F const& f)
 63     {
 64         return{
 65             std::type_index(typeid(T)),
 66             [&](CString& colName, boost::any & a)
 67             {
 68                 f(colName, boost::any_cast<T>(a));
 69             }
 70         };
 71     }
 72 
 73     template<class T, class F>
 74     inline std::pair<const std::type_index, std::function<void(int col, boost::any &)>> to_any_visitor2(F f)
 75     {
 76         return{
 77             std::type_index(typeid(T)),
 78             [=](int col, boost::any & a)
 79             {
 80                 F g = f;
 81                 g(col, boost::any_cast<T>(a));
 82             }
 83         };
 84     }
 85 
 86     //遍历 Tuple
 87     template<typename Tuple, size_t N>
 88     struct tuple_print
 89     {
 90         template<typename FuncT>
 91         inline static void print(Tuple t, FuncT func)
 92         {
 93             tuple_print<Tuple, N - 1>::print(t, func);
 94             //std::any any_val = std::ref<std::tuple_element_t<N - 1, Tuple>&>(std::get<N - 1>(t));
 95             boost::any any_val = &(std::get<N - 1>(t));
 96             func(N-1, any_val);
 97         }
 98     };
 99     template<typename Tuple>
100     struct tuple_print<Tuple, 1>
101     {
102         template<typename FuncT>
103         inline static void print(Tuple t, FuncT func)
104         {
105             //std::any any_val = std::ref<std::tuple_element_t<0, Tuple>&>(std::get<0>(t));
106             boost::any any_val = &(std::get<0>(t));
107             func(0, any_val);
108         }
109     };
110     // 对tuple每一个元素执行操作
111     template<typename FuncT, typename... Args>
112     inline void ForEachTuple(FuncT func, const std::tuple<Args...> t)
113     {
114         tuple_print<decltype(t), sizeof...(Args)>::print(t, func);
115     }
116 }
117 template< class... Types >
118 bool Database::GetNextRowData(Types&... args)
119 {
120     //std::lock_guard<std::recursive_mutex> lock(m_mutex);
121     auto t = std::tuple<Types&...>(args...);
122     try
123     {
124         if (eof()) return false;// 无数据了
125 
126         dtofxls::ForEachTuple([&](int col, boost::any& a)
127         {
128             const auto it = m_any_visitor2.find(std::type_index(a.type()));
129             if (it != m_any_visitor2.cend())
130             {
131                 it->second(col, a);
132             }
133             else
134             {
135                 TB::FormatMsgBox(L"Database::GetNextRowData Unregistered type  %s", CString(a.type().name()));
136                 return false;
137             }
138             return true;
139         }, t);
140 
141     }
142     catch (...)
143     {
144         TB::FormatMsgBox(L"Database::GetNextRowData 遇到未经处理的异常。");
145         return false;
146     }
147     return true;
148 }
.h
  1 #pragma region SQLiteDB
  2 
  3 
  4 SQLiteDB::SQLiteDB()
  5 {
  6     m_pDB = std::make_unique<CppSQLite3DB>();
  7 }
  8 
  9 SQLiteDB::~SQLiteDB()
 10 {
 11 
 12 }
 13 
 14 void SQLiteDB::open(const CString szFile /*= L":memory:"*/)
 15 {
 16     TRY_SQL
 17     auto utf8_str = unicode_utf8(szFile);
 18     m_pDB->open(utf8_str.GetBuffer());
 19     CATCH_SQL
 20 }
 21 void SQLiteDB::open_v2(const CString szFile /*= L":memory:"*/)
 22 {
 23     TRY_SQL
 24         auto utf8_str = unicode_utf8(szFile);
 25     m_pDB->open_v2(utf8_str.GetBuffer());
 26     CATCH_SQL
 27 }
 28 
 29 void SQLiteDB::close()
 30 {
 31     TRY_SQL
 32     m_pDB->close();
 33     CATCH_SQL
 34 }
 35 
 36 bool SQLiteDB::tableExists(CString szTable)
 37 {
 38     TRY_SQL
 39     auto utf8_str = unicode_utf8(szTable);
 40     return m_pDB->tableExists(utf8_str);
 41     CATCH_SQL
 42     return false;
 43 }
 44 
 45 int SQLiteDB::execDML(CString szSQL)
 46 {
 47     TRY_SQL
 48         auto utf8_str = unicode_utf8(szSQL);
 49         return m_pDB->execDML(utf8_str);
 50     CATCH_SQL
 51     return 0;
 52 }
 53 
 54 SQLiteQuery SQLiteDB::execQuery(const CString szSQL)
 55 {
 56     TRY_SQL
 57     auto utf8_str = unicode_utf8(szSQL);
 58     auto result = m_pDB->execQuery(utf8_str);
 59     return SQLiteQuery(result);
 60     CATCH_SQL
 61     return SQLiteQuery();
 62 }
 63 
 64 int SQLiteDB::execScalar(const CString szSQL, int nNullValue /*= 0*/)
 65 {
 66     TRY_SQL
 67     auto utf8_str = unicode_utf8(szSQL);
 68     return m_pDB->execScalar(utf8_str);
 69     CATCH_SQL
 70         return 0;
 71 }
 72 
 73 SQLiteTable SQLiteDB::getTable(const CString szSQL)
 74 {
 75     TRY_SQL
 76     auto utf8_str = unicode_utf8(szSQL);
 77     auto result = m_pDB->getTable(utf8_str);
 78     return SQLiteTable(result);
 79     CATCH_SQL
 80         return SQLiteTable();
 81 }
 82 
 83 SQLiteStatement SQLiteDB::compileStatement(const CString szSQL)
 84 {
 85     TRY_SQL
 86     auto utf8_str = unicode_utf8(szSQL);
 87     auto result = m_pDB->compileStatement(utf8_str);
 88     return SQLiteStatement(result);
 89     CATCH_SQL
 90 
 91         return SQLiteStatement();
 92 }
 93 
 94 __int64 SQLiteDB::lastRowId()
 95 {
 96     return m_pDB->lastRowId();
 97 }
 98 
 99 void SQLiteDB::interrupt()
100 {
101     return m_pDB->interrupt();
102 }
103 
104 void SQLiteDB::setBusyTimeout(int nMillisecs)
105 {
106     return m_pDB->setBusyTimeout(nMillisecs);
107 }
108 
109 bool SQLiteDB::IsAutoCommitOn()
110 {
111     return m_pDB->IsAutoCommitOn();
112 }
113 #pragma endregion SQLiteDB
114 
115 #pragma region Database
116 
117 Database::Database(CString dbName) :
118 m_sDatabasePath(dbName), 
119 m_pSQLiteDB(std::make_shared<SQLiteDB>())
120 {
121     m_pSQLiteDB->open(m_sDatabasePath);
122     //这里填写的是对每一种数据类型的处理,后续有新的类型需求在这里修改
123     m_any_visitor.insert(dtofxls::to_any_visitor<char*>([&](const CString& colName, char* val) { *val = m_ptr_result->getIntField(colName); }));
124     m_any_visitor.insert(dtofxls::to_any_visitor<short*>([&](const CString& colName, short* val) { *val = m_ptr_result->getIntField(colName); }));
125     m_any_visitor.insert(dtofxls::to_any_visitor<int*>([&](const CString& colName, int* val) { *val = m_ptr_result->getIntField(colName); }));
126     m_any_visitor.insert(dtofxls::to_any_visitor<__int64*>([&](const CString& colName, __int64* val) { *val = m_ptr_result->getInt64Field(colName); }));
127     m_any_visitor.insert(dtofxls::to_any_visitor<CString*>([&](const CString& colName, CString* val) { *val = m_ptr_result->getStringField(colName); }));
128     m_any_visitor.insert(dtofxls::to_any_visitor<unsigned char*>([&](const CString& colName, unsigned  char* val) { *val = m_ptr_result->getIntField(colName); }));
129     m_any_visitor.insert(dtofxls::to_any_visitor<unsigned short*>([&](const CString& colName, unsigned short* val) { *val = m_ptr_result->getIntField(colName); }));
130     m_any_visitor.insert(dtofxls::to_any_visitor<unsigned int*>([&](const CString& colName, unsigned int* val) { *val = m_ptr_result->getIntField(colName); }));
131     m_any_visitor.insert(dtofxls::to_any_visitor<unsigned __int64*>([&](const CString& colName, unsigned __int64* val) { *val = m_ptr_result->getInt64Field(colName); }));
132 
133 
134      m_any_visitor2.insert(dtofxls::to_any_visitor2<char*>([&](const int col, char* val) { *val = m_ptr_result->getIntField(col); }));
135      m_any_visitor2.insert(dtofxls::to_any_visitor2<short*>([&](const int col, short* val) { *val = m_ptr_result->getIntField(col); }));
136      m_any_visitor2.insert(dtofxls::to_any_visitor2<int*>([&](const int col, int* val) { *val = m_ptr_result->getIntField(col); }));
137      m_any_visitor2.insert(dtofxls::to_any_visitor2<__int64*>([&](const int col, __int64* val) { *val = m_ptr_result->getInt64Field(col); }));
138      m_any_visitor2.insert(dtofxls::to_any_visitor2<CString*>([&](const int col, CString* val) { *val = m_ptr_result->getStringField(col); }));
139      m_any_visitor2.insert(dtofxls::to_any_visitor2<unsigned char*>([&](const int col, unsigned  char* val) { *val = m_ptr_result->getIntField(col); }));
140     m_any_visitor2.insert(dtofxls::to_any_visitor2<unsigned short*>([&](const int col, unsigned  short* val) {*val = m_ptr_result->getIntField(col);}));
141      m_any_visitor2.insert(dtofxls::to_any_visitor2<unsigned int*>([&](const int col, unsigned  int* val) { *val = m_ptr_result->getIntField(col); }));
142      m_any_visitor2.insert(dtofxls::to_any_visitor2<unsigned __int64*>([&](const int col, unsigned  __int64* val) { *val = m_ptr_result->getInt64Field(col); }));
143     
144 }
145 
146 bool Database::Query(CString sql)
147 {
148     TRY_SQL
149     m_ptr_result = std::make_shared<SQLiteQuery >(m_pSQLiteDB->execQuery(sql));
150     CATCH_SQL
151     return !eof();
152 }
153 
154 int Database::execDML(CString sql)
155 {
156     TRY_SQL
157     return m_pSQLiteDB->execDML(sql);
158     CATCH_SQL
159     return 0;
160 }
161 
162 void Database::GetTest(int col, unsigned  short*val)
163 {
164     *val = m_ptr_result->getIntField(col);
165 //     auto f = [&](const int col, unsigned  short* val) {
166 //         *val = m_ptr_result->getIntField(col);
167 //     };
168 //     auto p = m_any_visitor2.find(std::type_index(typeid(unsigned short*)));
169 //     auto f = p->second;
170 //     f(col, val);
171 }
172 
173 bool Database::eof()
174 {
175     return !m_ptr_result->operator bool() || m_ptr_result->eof();
176 }
177 
178 Database::~Database()
179 {
180     m_pSQLiteDB->close();
181 }
182 #pragma endregion Database
.cpp
 1     //使用方法
 2     auto db = SingletonSQL::get()->Open(L"list.db");
 3     CString sql;
 4     sql.Format(L"select id,name,class from lsit where class='%s' ;", 1);
 5     if (!db->Query(sql))
 6     {
 7         AddErrorMsg(sql + L"查询失败");
 8     }
 9 
10     int id;
11     CString name;
12     short class;
13     db->GetNextRowData(id,name,class);