选择官方c接口,实现Idb通用接口。具体的数据库操做,主要由两个函数ExecQuerySql和ExecNoneQuerySql来封装,底层的操做,主要使用sqlite3_prepare_v2来实现。mysql
由于Sqlit3是文件型数据库,因此用智能指针来保存打开数据库的句柄,防止内存泄漏。c++
std::unique_ptr<sqlite3, Deleter> mSQLitePtr;
对应的释放结构git
struct Deleter { void operator()(sqlite3* apSQLite) { const int ret = sqlite3_close(apSQLite); (void)ret; SQLITECPP_ASSERT(SQLITE_OK == ret, "database is locked"); }; };
Sqlit3Db(const char* apFilename, const int aFlags = OPEN_READWRITE, const int aBusyTimeoutMs = 0, const char* apVfs = nullptr) : mFilename(apFilename) { sqlite3* handle; const int ret = sqlite3_open_v2(apFilename, &handle, aFlags, apVfs); //打开数据库句柄 mSQLitePtr.reset(handle); //保存到智能指针中 ... //错误处理,略 };
Rjson ExecQuerySql(string aQuery, vector<string> fields) { Rjson rs = Utils::MakeJsonObjectForFuncReturn(STSUCCESS); //默认返回成功,使用utils.h中的json组装函数 sqlite3_stmt* stmt = NULL; sqlite3* handle = getHandle(); //取得打开的数据库句柄 string u8Query = Utils::UnicodeToU8(aQuery); const int ret = sqlite3_prepare_v2(handle, u8Query.c_str(), static_cast<int>(u8Query.size()), &stmt, NULL); if (SQLITE_OK != ret) { string errmsg = sqlite3_errmsg(getHandle()); //取得错误信息,重置返回信息 rs.ExtendObject(Utils::MakeJsonObjectForFuncReturn(STDBOPERATEERR, errmsg)); } else { ... //处理获取表字段名称的sql语句,略 sqlite3_get_table(handle, aQueryLimit0.c_str(), &pRes, &nRow, &nCol, &pErr); for (int j = 0; j < nCol; j++) { string fs = *(pRes + j); if (find(fields.begin(), fields.end(), fs) == fields.end()) { fields.push_back(fs); //保存数据表字段名称 } } ... vector<Rjson> arr; //存储查询结果集的json对象数组 while (sqlite3_step(stmt) == SQLITE_ROW) { Rjson al; for (int j = 0; j < nCol; j++) { string k = fields.at(j); int nType = sqlite3_column_type(stmt, j); //取得字段值的类型 if (nType == 1) { //SQLITE_INTEGER al.AddValueInt(k, sqlite3_column_int(stmt, j)); //数值类型处理 } else if (nType == 2) { //SQLITE_FLOAT } else if (nType == 3) { //SQLITE_TEXT 字符串类型处理 al.AddValueString(k, Utils::U8ToUnicode((char*)sqlite3_column_text(stmt, j))); } else if (nType == 4) { //SQLITE_BLOB } else if (nType == 5) { //SQLITE_NULL } //暂时只处理了数值与字符串,其它暂未用到 } arr.push_back(al); } if (arr.empty()) //结果集为空,返回查询空 rs.ExtendObject(Utils::MakeJsonObjectForFuncReturn(STQUERYEMPTY)); rs.AddValueObjectArray("data", arr); //增长结果集,类型为数组 } sqlite3_finalize(stmt); cout << "SQL: " << aQuery << endl; return rs; }
Rjson ExecNoneQuerySql(string aQuery) { Rjson rs = Utils::MakeJsonObjectForFuncReturn(STSUCCESS); sqlite3_stmt* stmt = NULL; sqlite3* handle = getHandle(); string u8Query = Utils::UnicodeToU8(aQuery); const int ret = sqlite3_prepare_v2(handle, u8Query.c_str(), static_cast<int>(u8Query.size()), &stmt, NULL); if (SQLITE_OK != ret) { string errmsg = sqlite3_errmsg(getHandle()); rs.ExtendObject(Utils::MakeJsonObjectForFuncReturn(STDBOPERATEERR, errmsg)); } else { sqlite3_step(stmt); //只须要执行一次就好 } sqlite3_finalize(stmt); cout << "SQL: " << aQuery << endl; return rs; }
提取保留关键字,它们是fuzzy,sort,page,size,sum,count,group,完成排序、分页、分组等特殊查询操做。github
string fuzzy = params.GetStringValueAndRemove("fuzzy"); //精确匹配与模糊查询切换开关 string sort = params.GetStringValueAndRemove("sort"); //排序 int page = atoi(params.GetStringValueAndRemove("page").c_str()); //分页 int size = atoi(params.GetStringValueAndRemove("size").c_str()); //分页大小 string sum = params.GetStringValueAndRemove("sum"); //字段求和 string count = params.GetStringValueAndRemove("count"); //字段统计 string group = params.GetStringValueAndRemove("group"); //分组
处理关键字 ins,lks,ors ,完成in查询,多字段模糊与查询,多字段精确或查询。sql
if (k.compare("ins") == 0) { string c = ele.at(0); //ins参数处理,第一个是字段名,后面是多个查询值 vector<string>(ele.begin() + 1, ele.end()).swap(ele); //拼接in查询sql语句 whereExtra.append(c).append(" in ( ").append(Utils::GetVectorJoinStr(ele)).append(" )"); } else if (k.compare("lks") == 0 || k.compare("ors") == 0) { whereExtra.append(" ( "); for (size_t j = 0; j < ele.size(); j += 2) { //lks与ors参数处理,(字段,值)的重复 if (j > 0) { whereExtra.append(" or "); } whereExtra.append(ele.at(j)).append(" "); //拼接sql语句 string eqStr = k.compare("lks") == 0 ? " like '" : " = '"; string vsStr = ele.at(j + 1); if (k.compare("lks") == 0) { vsStr.insert(0, "%"); vsStr.append("%"); } vsStr.append("'"); whereExtra.append(eqStr).append(vsStr); } whereExtra.append(" ) "); }
处理值,不等操做是在值中加入了不等符号;fuzzy开关。数据库
if (Utils::FindStartsCharArray(QUERY_UNEQ_OPERS, (char*)v.c_str())) { vector<string> vls = Utils::MakeVectorInitFromString(v); if (vls.size() == 2) { //一个不等条件处理 where.append(k).append(vls.at(0)).append("'").append(vls.at(1)).append("'"); } else if (vls.size() == 4) { //一对不等条件处理 where.append(k).append(vls.at(0)).append("'").append(vls.at(1)).append("' and "); where.append(k).append(vls.at(2)).append("'").append(vls.at(3)).append("'"); } } else if (!fuzzy.empty() && vType == kStringType) { //精确查询与模糊查询切换 where.append(k).append(" like '%").append(v).append("%'"); } else { if (vType == kNumberType) //数值类型不加单引号 where.append(k).append(" = ").append(v); else //字符类型要加单引号 where.append(k).append(" = '").append(v).append("'"); }
分页处理json
if (page > 0) { page--; querySql.append(" limit ").append(Utils::IntTransToString(page * size)).append(",").append(Utils::IntTransToString(size)); }
多值插入,sqlit3采用标准sql语法,insert into users (field1,field2) select 'val1','val2' union all select 'val3','val4' union all select ...api
Rjson insertBatch(string tablename, vector<Rjson> elements) { string sql = "insert into "; string keyStr = " ("; keyStr.append(Utils::GetVectorJoinStr(elements[0].GetAllKeys())).append(" ) "); //拼接表字段 for (size_t i = 0; i < elements.size(); i++) { vector<string> keys = elements[i].GetAllKeys(); string valueStr = " select "; for (size_t j = 0; j < keys.size(); j++) { //组装一条纪录 valueStr.append("'").append(elements[i][keys[j]]).append("'"); if (j < keys.size() - 1) { valueStr.append(","); } } if (i < elements.size() - 1) { //准备拼接下一条纪录 valueStr.append(" union all "); } keyStr.append(valueStr); } sql.append(tablename).append(keyStr); return ExecNoneQuerySql(sql); //调用无结果集操做 }
Rjson transGo(vector<string> sqls, bool isAsync = false) { char* zErrMsg = 0; bool isExecSuccess = true; sqlite3_exec(getHandle(), "begin;", 0, 0, &zErrMsg); //开始事务处理 for (size_t i = 0; i < sqls.size(); i++) { string u8Query = Utils::UnicodeToU8(sqls[i]); //处理中文 int rc = sqlite3_exec(getHandle(), u8Query.c_str(), 0, 0, &zErrMsg); //处理一个操做 if (rc != SQLITE_OK) { isExecSuccess = false; cout << "Transaction Fail, sql " << i + 1 << " is wrong. Error: " << zErrMsg << endl; sqlite3_free(zErrMsg); break; } } if (isExecSuccess) //成功,提交到数据库 { sqlite3_exec(getHandle(), "commit;", 0, 0, 0); sqlite3_close(getHandle()); cout << "Transaction Success: run " << sqls.size() << " sqls." << endl; return Utils::MakeJsonObjectForFuncReturn(STSUCCESS, "insertBatch success."); } else //有失败的,回滚 { sqlite3_exec(getHandle(), "rollback;", 0, 0, 0); sqlite3_close(getHandle()); return Utils::MakeJsonObjectForFuncReturn(STDBOPERATEERR, zErrMsg); } }
https://github.com/zhoutk/Jorm
批量插入的标准sql居然很陌生,平时被mysql的方言惯坏了...数组