WCDB soci 查询语句

测试代码

cpp 复制代码
#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_type
    std::vector<OperationLog> queryByOpType(const std::string& opType);

    // Query by op_subtype
    std::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_type
    std::vector<OperationLog> queryByOpType(const std::string& opType);

    // Query by op_subtype
    std::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代码

cpp 复制代码
#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 20
    virtual std::vector<OperationLog> queryByOpType(const std::string& op_type) = 0;

    // 2. Query operation_log using op_subtype as index, limit 20
    virtual std::vector<OperationLog> queryByOpSubtype(const std::string& op_subtype) = 0;

    // 3. Query count of total rows in operation_log
    virtual 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 both
    OperationLogInterface* 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 rows
    EXPECT_GT(count, 0);
}
TEST_F(OperationLogTest, GetTotalCount_SOCI) {
    int count = soci_impl->getTotalCount();
    EXPECT_GT(count, 0);
}

另一版测试代码

cpp 复制代码
#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 exists
    std::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 typeB
    for (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 typeB
    for (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);
}
相关推荐
tomato096 分钟前
河南萌新联赛2025第(一)场:河南工业大学(补题)
c++·算法
inwith37 分钟前
C#语法基础总结(超级全面)(二)
开发语言·c#
_pengliang1 小时前
小程序按住说话
开发语言·javascript·小程序
秋千码途1 小时前
小架构step系列17:getter-setter-toString
java·开发语言·架构
AI 嗯啦2 小时前
python基础语法9,用os库实现系统操作并用sys库实现文件操作(简单易上手的python语法教学)
开发语言·python
屁股割了还要学2 小时前
【C语言进阶】内存函数
c语言·开发语言·学习·算法·青少年编程
耳总是一颗苹果2 小时前
C语言---自定义类型(上)(结构体类型)
c语言·开发语言
玩代码2 小时前
模板方法设计模式
java·开发语言·设计模式·模板方法设计模式
每一天都要努力^3 小时前
C++拷贝构造
开发语言·c++
GeminiGlory3 小时前
从0到1开发网页版五子棋:我的Java实战之旅
java·开发语言