WCDB soci 查询语句
测试代码
#pragma once
#include <string>
#include <vector>// Assume OperationLog is a struct representing a row in the table
struct OperationLog {int id;std::string op_type;std::string op_subtype;std::string details;std::string timestamp;
};class OperationLogRepositoryWCDB {
public:// Query by op_typestd::vector<OperationLog> queryByOpType(const std::string& opType);// Query by op_subtypestd::vector<OperationLog> queryByOpSubType(const std::string& opSubType);
};#include "operation_log_repository_wcdb.h"
#include <WCDB/WCDB.h>std::vector<OperationLog> OperationLogRepositoryWCDB::queryByOpType(const std::string& opType) {std::vector<OperationLog> result;WCDB::Database db("operation_log.db");auto rows = db.getRows("operation_log", WCDB::Column::All(), "op_type = ?", {opType});for (const auto& row : rows) {OperationLog log;log.id = row.getValue<int>(0);log.op_type = row.getValue<std::string>(1);log.op_subtype = row.getValue<std::string>(2);log.details = row.getValue<std::string>(3);log.timestamp = row.getValue<std::string>(4);result.push_back(log);}return result;
}std::vector<OperationLog> OperationLogRepositoryWCDB::queryByOpSubType(const std::string& opSubType) {std::vector<OperationLog> result;WCDB::Database db("operation_log.db");auto rows = db.getRows("operation_log", WCDB::Column::All(), "op_subtype = ?", {opSubType});for (const auto& row : rows) {OperationLog log;log.id = row.getValue<int>(0);log.op_type = row.getValue<std::string>(1);log.op_subtype = row.getValue<std::string>(2);log.details = row.getValue<std::string>(3);log.timestamp = row.getValue<std::string>(4);result.push_back(log);}return result;
}#pragma once
#include <string>
#include <vector>// Assume OperationLog is a struct representing a row in the table
struct OperationLog {int id;std::string op_type;std::string op_subtype;std::string details;std::string timestamp;
};class OperationLogRepositorySOCI {
public:// Query by op_typestd::vector<OperationLog> queryByOpType(const std::string& opType);// Query by op_subtypestd::vector<OperationLog> queryByOpSubType(const std::string& opSubType);
};#include "operation_log_repository_soci.h"
#include <soci/soci.h>
#include <soci/sqlite3/soci-sqlite3.h>std::vector<OperationLog> OperationLogRepositorySOCI::queryByOpType(const std::string& opType) {std::vector<OperationLog> result;soci::session sql(soci::sqlite3, "operation_log.db");soci::rowset<soci::row> rs = (sql.prepare << "SELECT id, op_type, op_subtype, details, timestamp FROM operation_log WHERE op_type = :op_type", soci::use(opType));for (const auto& r : rs) {OperationLog log;log.id = r.get<int>(0);log.op_type = r.get<std::string>(1);log.op_subtype = r.get<std::string>(2);log.details = r.get<std::string>(3);log.timestamp = r.get<std::string>(4);result.push_back(log);}return result;
}std::vector<OperationLog> OperationLogRepositorySOCI::queryByOpSubType(const std::string& opSubType) {std::vector<OperationLog> result;soci::session sql(soci::sqlite3, "operation_log.db");soci::rowset<soci::row> rs = (sql.prepare << "SELECT id, op_type, op_subtype, details, timestamp FROM operation_log WHERE op_subtype = :op_subtype", soci::use(opSubType));for (const auto& r : rs) {OperationLog log;log.id = r.get<int>(0);log.op_type = r.get<std::string>(1);log.op_subtype = r.get<std::string>(2);log.details = r.get<std::string>(3);log.timestamp = r.get<std::string>(4);result.push_back(log);}return result;
}
带gtest代码
#pragma once
#include <string>
#include <vector>struct OperationLog {int id;std::string op_type;std::string op_subtype;std::string op_content;std::string timestamp;
};class OperationLogInterface {
public:virtual ~OperationLogInterface() = default;// 1. Query operation_log using op_type as index, limit 20virtual std::vector<OperationLog> queryByOpType(const std::string& op_type) = 0;// 2. Query operation_log using op_subtype as index, limit 20virtual std::vector<OperationLog> queryByOpSubtype(const std::string& op_subtype) = 0;// 3. Query count of total rows in operation_logvirtual int getTotalCount() = 0;
};#include "operation_log_interface.h"
#include <WCDB.h>class OperationLogWCDB : public OperationLogInterface {
public:OperationLogWCDB(const std::string& dbPath): database(dbPath) {}std::vector<OperationLog> queryByOpType(const std::string& op_type) override {std::vector<OperationLog> result;auto statement = WCDB::StatementSelect().from("operation_log").where(WCDB::Column("op_type") == op_type).limit(20);auto rows = database.selectRows(statement);for (const auto& row : rows) {OperationLog log;log.id = row[0].int32Value();log.op_type = row[1].stringValue();log.op_subtype = row[2].stringValue();log.op_content = row[3].stringValue();log.timestamp = row[4].stringValue();result.push_back(log);}return result;}std::vector<OperationLog> queryByOpSubtype(const std::string& op_subtype) override {std::vector<OperationLog> result;auto statement = WCDB::StatementSelect().from("operation_log").where(WCDB::Column("op_subtype") == op_subtype).limit(20);auto rows = database.selectRows(statement);for (const auto& row : rows) {OperationLog log;log.id = row[0].int32Value();log.op_type = row[1].stringValue();log.op_subtype = row[2].stringValue();log.op_content = row[3].stringValue();log.timestamp = row[4].stringValue();result.push_back(log);}return result;}int getTotalCount() override {auto statement = WCDB::StatementSelect().from("operation_log").column(WCDB::Column::count("*"));auto rows = database.selectRows(statement);if (!rows.empty()) {return rows[0][0].int32Value();}return 0;}private:WCDB::Database database;
};#include "operation_log_interface.h"
#include <soci/soci.h>class OperationLogSOCI : public OperationLogInterface {
public:OperationLogSOCI(const std::string& connStr): sql(soci::sqlite3, connStr) {}std::vector<OperationLog> queryByOpType(const std::string& op_type) override {std::vector<OperationLog> result;soci::rowset<soci::row> rs = (sql.prepare << "SELECT id, op_type, op_subtype, op_content, timestamp FROM operation_log WHERE op_type = ? LIMIT 20", op_type);for (auto& r : rs) {OperationLog log;log.id = r.get<int>(0);log.op_type = r.get<std::string>(1);log.op_subtype = r.get<std::string>(2);log.op_content = r.get<std::string>(3);log.timestamp = r.get<std::string>(4);result.push_back(log);}return result;}std::vector<OperationLog> queryByOpSubtype(const std::string& op_subtype) override {std::vector<OperationLog> result;soci::rowset<soci::row> rs = (sql.prepare << "SELECT id, op_type, op_subtype, op_content, timestamp FROM operation_log WHERE op_subtype = ? LIMIT 20", op_subtype);for (auto& r : rs) {OperationLog log;log.id = r.get<int>(0);log.op_type = r.get<std::string>(1);log.op_subtype = r.get<std::string>(2);log.op_content = r.get<std::string>(3);log.timestamp = r.get<std::string>(4);result.push_back(log);}return result;}int getTotalCount() override {int count = 0;sql << "SELECT count(*) FROM operation_log", soci::into(count);return count;}private:soci::session sql;
};#include <gtest/gtest.h>
#include "operation_log_interface.h"// You would need to include the appropriate subclasses and initialize the DB with test data.class OperationLogTest : public ::testing::Test {
protected:void SetUp() override {// initialize db and insert test data for both WCDB and SOCI// You may want to use a test database for this}// Provide implementations for bothOperationLogInterface* wcdb_impl;OperationLogInterface* soci_impl;
};// Test queryByOpType
TEST_F(OperationLogTest, QueryByOpType_WCDB) {auto logs = wcdb_impl->queryByOpType("typeA");ASSERT_LE(logs.size(), 20);for (const auto& log : logs) {EXPECT_EQ(log.op_type, "typeA");}
}
TEST_F(OperationLogTest, QueryByOpType_SOCI) {auto logs = soci_impl->queryByOpType("typeA");ASSERT_LE(logs.size(), 20);for (const auto& log : logs) {EXPECT_EQ(log.op_type, "typeA");}
}// Test queryByOpSubtype
TEST_F(OperationLogTest, QueryByOpSubtype_WCDB) {auto logs = wcdb_impl->queryByOpSubtype("subtypeB");ASSERT_LE(logs.size(), 20);for (const auto& log : logs) {EXPECT_EQ(log.op_subtype, "subtypeB");}
}
TEST_F(OperationLogTest, QueryByOpSubtype_SOCI) {auto logs = soci_impl->queryByOpSubtype("subtypeB");ASSERT_LE(logs.size(), 20);for (const auto& log : logs) {EXPECT_EQ(log.op_subtype, "subtypeB");}
}// Test getTotalCount
TEST_F(OperationLogTest, GetTotalCount_WCDB) {int count = wcdb_impl->getTotalCount();// Expect count equals to number of inserted rowsEXPECT_GT(count, 0);
}
TEST_F(OperationLogTest, GetTotalCount_SOCI) {int count = soci_impl->getTotalCount();EXPECT_GT(count, 0);
}
另一版测试代码
#include "operation_log_wcdb.h"
#include <WCDB/WCDBCpp.h>using namespace WCDB;OperationLogWCDB::OperationLogWCDB(const std::string& dbPath): m_dbPath(dbPath)
{
}OperationLogWCDB::~OperationLogWCDB() = default;bool OperationLogWCDB::InitDB()
{m_db = std::make_unique<Database>(m_dbPath);if (!m_db->isOpened()) {m_db->open();}// Create table if not existsstd::string sql = "CREATE TABLE IF NOT EXISTS operation_log (""id INTEGER PRIMARY KEY AUTOINCREMENT, ""op_type TEXT, ""op_subtype TEXT, ""detail TEXT, ""ts INTEGER)";return m_db->execute(sql);
}bool OperationLogWCDB::Insert(const OperationLogRow& row)
{StatementInsert insert("operation_log");insert.columns({"op_type", "op_subtype", "detail", "ts"});insert.values({row.op_type, row.op_subtype, row.detail, row.ts});return m_db->execute(insert);
}std::vector<OperationLogRow> OperationLogWCDB::QueryByOpType(const std::string& opType, int limit)
{StatementSelect select("operation_log");select.columns({"id", "op_type", "op_subtype", "detail", "ts"});select.where(Column("op_type") == opType);select.limit(limit);std::vector<OperationLogRow> results;auto rows = m_db->getRows(select);for (const auto& row : rows) {OperationLogRow log;log.id = row[0].int64Value();log.op_type = row[1].stringValue();log.op_subtype = row[2].stringValue();log.detail = row[3].stringValue();log.ts = row[4].int64Value();results.push_back(log);}return results;
}std::vector<OperationLogRow> OperationLogWCDB::QueryByOpSubType(const std::string& opSubType, int limit)
{StatementSelect select("operation_log");select.columns({"id", "op_type", "op_subtype", "detail", "ts"});select.where(Column("op_subtype") == opSubType);select.limit(limit);std::vector<OperationLogRow> results;auto rows = m_db->getRows(select);for (const auto& row : rows) {OperationLogRow log;log.id = row[0].int64Value();log.op_type = row[1].stringValue();log.op_subtype = row[2].stringValue();log.detail = row[3].stringValue();log.ts = row[4].int64Value();results.push_back(log);}return results;
}int64_t OperationLogWCDB::QueryRowCount()
{StatementSelect select("operation_log");select.columns({"COUNT(*)"});auto rows = m_db->getRows(select);if (!rows.empty()) {return rows[0][0].int64Value();}return 0;
}#include "operation_log_soci.h"
#include <soci/sqlite3/soci-sqlite3.h>OperationLogSOCI::OperationLogSOCI(const std::string& connectString)
{m_session = std::make_unique<soci::session>(soci::sqlite3, connectString);
}OperationLogSOCI::~OperationLogSOCI() = default;bool OperationLogSOCI::InitDB()
{try {*m_session << "CREATE TABLE IF NOT EXISTS operation_log (""id INTEGER PRIMARY KEY AUTOINCREMENT, ""op_type TEXT, ""op_subtype TEXT, ""detail TEXT, ""ts INTEGER)";return true;} catch (...) {return false;}
}bool OperationLogSOCI::Insert(const OperationLogRow& row)
{try {*m_session << "INSERT INTO operation_log (op_type, op_subtype, detail, ts) VALUES (:op_type, :op_subtype, :detail, :ts)",soci::use(row.op_type), soci::use(row.op_subtype), soci::use(row.detail), soci::use(row.ts);return true;} catch (...) {return false;}
}std::vector<OperationLogRow> OperationLogSOCI::QueryByOpType(const std::string& opType, int limit)
{std::vector<OperationLogRow> results;soci::rowset<soci::row> rs =(m_session->prepare << "SELECT id, op_type, op_subtype, detail, ts FROM operation_log WHERE op_type = :op_type LIMIT :limit",soci::use(opType), soci::use(limit));for (auto it = rs.begin(); it != rs.end(); ++it) {const soci::row& r = *it;OperationLogRow log;log.id = r.get<int64_t>(0);log.op_type = r.get<std::string>(1);log.op_subtype = r.get<std::string>(2);log.detail = r.get<std::string>(3);log.ts = r.get<int64_t>(4);results.push_back(log);}return results;
}std::vector<OperationLogRow> OperationLogSOCI::QueryByOpSubType(const std::string& opSubType, int limit)
{std::vector<OperationLogRow> results;soci::rowset<soci::row> rs =(m_session->prepare << "SELECT id, op_type, op_subtype, detail, ts FROM operation_log WHERE op_subtype = :op_subtype LIMIT :limit",soci::use(opSubType), soci::use(limit));for (auto it = rs.begin(); it != rs.end(); ++it) {const soci::row& r = *it;OperationLogRow log;log.id = r.get<int64_t>(0);log.op_type = r.get<std::string>(1);log.op_subtype = r.get<std::string>(2);log.detail = r.get<std::string>(3);log.ts = r.get<int64_t>(4);results.push_back(log);}return results;
}int64_t OperationLogSOCI::QueryRowCount()
{int64_t cnt = 0;*m_session << "SELECT COUNT(*) FROM operation_log", soci::into(cnt);return cnt;
}#pragma once#include <string>
#include <vector>
#include <memory>// WCDB Forward declarations
class WCDBDatabase;struct OperationLogRow {int64_t id;std::string op_type;std::string op_subtype;std::string detail;int64_t ts;
};class OperationLogWCDB {
public:OperationLogWCDB(const std::string& dbPath);~OperationLogWCDB();bool InitDB();bool Insert(const OperationLogRow& row);std::vector<OperationLogRow> QueryByOpType(const std::string& opType, int limit = 20);std::vector<OperationLogRow> QueryByOpSubType(const std::string& opSubType, int limit = 20);int64_t QueryRowCount();private:std::unique_ptr<WCDBDatabase> m_db;std::string m_dbPath;
};#pragma once#include <string>
#include <vector>
#include <memory>
#include <soci/soci.h>struct OperationLogRow {int64_t id;std::string op_type;std::string op_subtype;std::string detail;int64_t ts;
};class OperationLogSOCI {
public:OperationLogSOCI(const std::string& connectString);~OperationLogSOCI();bool InitDB();bool Insert(const OperationLogRow& row);std::vector<OperationLogRow> QueryByOpType(const std::string& opType, int limit = 20);std::vector<OperationLogRow> QueryByOpSubType(const std::string& opSubType, int limit = 20);int64_t QueryRowCount();private:std::unique_ptr<soci::session> m_session;
};#include <gtest/gtest.h>
#include "operation_log_wcdb.h"
#include "operation_log_soci.h"
#include <cstdio>// Helper to clean up db file
void RemoveDBFile(const std::string& path) {std::remove(path.c_str());
}OperationLogRow MakeTestRow(int idx, const std::string& type = "typeA", const std::string& subtype = "subtypeA") {OperationLogRow row;row.id = 0;row.op_type = type;row.op_subtype = subtype;row.detail = "detail_" + std::to_string(idx);row.ts = 1000 + idx;return row;
}TEST(OperationLogWCDBTest, BasicCRUD) {std::string dbPath = "test_wcdb.sqlite";RemoveDBFile(dbPath);OperationLogWCDB db(dbPath);ASSERT_TRUE(db.InitDB());// Insert 30 rows, 10 with typeA, 20 with typeBfor (int i = 0; i < 10; ++i)ASSERT_TRUE(db.Insert(MakeTestRow(i, "typeA", "subtypeA")));for (int i = 10; i < 30; ++i)ASSERT_TRUE(db.Insert(MakeTestRow(i, "typeB", "subtypeB")));EXPECT_EQ(db.QueryRowCount(), 30);auto typeAList = db.QueryByOpType("typeA", 20);EXPECT_EQ(typeAList.size(), 10);EXPECT_EQ(typeAList[0].op_type, "typeA");auto subtypeBList = db.QueryByOpSubType("subtypeB", 20);EXPECT_EQ(subtypeBList.size(), 20);EXPECT_EQ(subtypeBList[0].op_subtype, "subtypeB");RemoveDBFile(dbPath);
}TEST(OperationLogSOCI, BasicCRUD) {std::string dbPath = "test_soci.sqlite";RemoveDBFile(dbPath);OperationLogSOCI db(dbPath);ASSERT_TRUE(db.InitDB());// Insert 30 rows, 15 with typeA, 15 with typeBfor (int i = 0; i < 15; ++i)ASSERT_TRUE(db.Insert(MakeTestRow(i, "typeA", "subtypeA")));for (int i = 15; i < 30; ++i)ASSERT_TRUE(db.Insert(MakeTestRow(i, "typeB", "subtypeB")));EXPECT_EQ(db.QueryRowCount(), 30);auto typeAList = db.QueryByOpType("typeA", 20);EXPECT_EQ(typeAList.size(), 15);EXPECT_EQ(typeAList[0].op_type, "typeA");auto subtypeBList = db.QueryByOpSubType("subtypeB", 20);EXPECT_EQ(subtypeBList.size(), 15);EXPECT_EQ(subtypeBList[0].op_subtype, "subtypeB");RemoveDBFile(dbPath);
}