因为工作原因需要在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 }

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
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);
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· 写一个简单的SQL生成工具
· Manus的开源复刻OpenManus初探