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);
}
相关推荐
lsp-072 小时前
JS 模块化与打包工具
开发语言·javascript·ecmascript
sali-tec3 小时前
C# 基于halcon的视觉工作流-章29-边缘提取-亚像素
开发语言·图像处理·算法·计算机视觉·c#
屁股割了还要学4 小时前
【数据结构入门】堆
c语言·开发语言·数据结构·c++·考研·算法·链表
Flobby5295 小时前
Go 语言中的结构体、切片与映射:构建高效数据模型的基石
开发语言·后端·golang
lsx2024066 小时前
Vue.js 响应接口:深度解析与实践指南
开发语言
froginwe116 小时前
Vue.js 样式绑定
开发语言
草莓熊Lotso7 小时前
【洛谷题单】--分支结构(三)
c语言·c++·刷题·洛谷
GetcharZp8 小时前
C++日志库新纪元:为什么说spdlog是现代C++开发者必备神器?
c++·后端
Algebraaaaa8 小时前
为什么C++主函数 main 要写成 int 返回值 | main(int argc, char* argv[]) 这种写法是什么意思?
开发语言·c++
java1234_小锋9 小时前
一周学会Matplotlib3 Python 数据可视化-绘制饼状图(Pie)
开发语言·python·信息可视化