C++11 封装nanodbc库可变长模板参数方式

代码结构和昨天一样,但是使用了varidic args,这样代码就只能在头文件里面了,在CPP文件里面就会报错。

好处是代码逻辑更加清晰,更加易于扩展。

代码如下,
CMakeLists.txt


cmake_minimum_required(VERSION 2.6)
project(sf_db2_test)

add_definitions(-std=c++17)
add_definitions(-g)



find_package(Boost REQUIRED COMPONENTS
    system
    filesystem
    serialization
    program_options
    thread
    )

include_directories(${Boost_INCLUDE_DIRS} /usr/local/include /usr/local/iODBC/include /opt/snowflake/snowflakeodbc/include/ ${CMAKE_CURRENT_SOURCE_DIR}/../../)

LINK_DIRECTORIES(/usr/local/lib /usr/local/iODBC/lib /opt/snowflake/snowflakeodbc/lib/universal)

file( GLOB APP_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp ${CMAKE_CURRENT_SOURCE_DIR}/*.h ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp)
foreach( sourcefile ${APP_SOURCES} )
        file(RELATIVE_PATH filename ${CMAKE_CURRENT_SOURCE_DIR} ${sourcefile})
    
        string(FIND "${filename}"  "test.cpp" "TEMP")
    if( NOT "${TEMP}" STREQUAL "-1" )
        string(REPLACE ".cpp" "" file ${filename})
        add_executable(${file}  ${APP_SOURCES})
        target_link_libraries(${file} ${Boost_LIBRARIES})
        target_link_libraries(${file}  ssl crypto libgtest.a libgtest_main.a libgmock.a iodbc iodbcinst libnanodbc.a pthread)
    endif()
endforeach( sourcefile ${APP_SOURCES})

sf_db2.h

#ifndef _FREDRIC_SF_DB2_H_
#define _FREDRIC_SF_DB2_H_

#include "nanodbc/convert.h"
#include "nanodbc/nanodbc.h"

#include 
#include 
#include 
#include 


using db_result = nanodbc::result;

struct sf_connection {
    nanodbc::connection conn_;

    sf_connection(const std::string& conn_str) {
        conn_ = nanodbc::connection{convert(conn_str)};
    }

    db_result exec_raw_query(const std::string& raw_query) {
        auto res = execute(conn_, NANODBC_TEXT(raw_query));
        return std::move(res);
    }

    template 
    db_result exec_prpare_statement(const std::string& pre_stmt,
                                    Params... params) {
        nanodbc::statement statement(conn_);
        std::cout << pre_stmt << std::endl;
        prepare(statement, NANODBC_TEXT(pre_stmt));
        int index = 0;
        int bind_arr[] = {(bind(statement, index, params), ++index)...};

        auto res = execute(statement);
        return std::move(res);
    }

    virtual ~sf_connection() {}

   private:
    template 
    void bind(nanodbc::statement& stmt, int index, T param) {
        std::vector v{std::to_string(param)};
        stmt.bind_strings(index, v);
    }

    void bind(nanodbc::statement& stmt, int index, const char* param) {
        stmt.bind(index, param);
    }

    void bind(nanodbc::statement& stmt, int index, std::string param) {
        stmt.bind(index, param.c_str());
    }
};

#endif

sf_db2_test.cpp

#include "sf_db2/sf_db2.h"

#include 

const std::string ConnStr = "dsn=product_odbc;pwd={YOUR_PASSWORD}";

GTEST_TEST(SFDBTests, TestExecQuery) {
    auto conn_str = ConnStr;
    auto raw_query =
        "select  product_key,change_time,EVENT_TYPE_NAME, change_column, "
        "old_value, new_value,meta from "
        "AA_INTELLIGENCE_PRODUCTION.ADL_MASTER.dim_event_service_v1 where  "
        "event_type_name='screenshot_change' and product_key=20600000009072 "
        "order by change_time desc limit 2;";
    sf_connection sf{conn_str};
    auto res = sf.exec_raw_query(raw_query);
    ASSERT_EQ(2, res.affected_rows());

    const auto columns = res.columns();
    for (short i = 0; i < columns; ++i) std::cout << res.column_name(i) << "\t";

    std::cout << std::endl;

    const std::string null_value = "null";
    while (res.next()) {
        for (short col = 0; col < columns; ++col) {
            auto const value = res.get(col, null_value);
            std::cout << "(" << value << ")\t";
        }
        std::cout << std::endl;
    }
}

GTEST_TEST(SFDBTests, TestExecPreStatement) {
    auto conn_str = ConnStr;
    auto pre_query =
        "select  product_key,change_time,EVENT_TYPE_NAME, change_column, "
        "old_value, new_value,meta from "
        "AA_INTELLIGENCE_PRODUCTION.ADL_MASTER.dim_event_service_v1 where  "
        "event_type_name=? and product_key=? and change_time=? order by "
        "change_time desc limit 2;";

    sf_connection sf{conn_str};

    auto res = sf.exec_prpare_statement(pre_query, "screenshot_change",
                                        20600000009072, "2021-06-07");
    ASSERT_EQ(1, res.affected_rows());

    const auto columns = res.columns();
    for (short i = 0; i < columns; ++i) std::cout << res.column_name(i) << "\t";

    std::cout << std::endl;

    const std::string null_value = "null";
    while (res.next()) {
        for (short col = 0; col < columns; ++col) {
            auto const value = res.get(col, null_value);
            std::cout << "(" << value << ")\t";
        }
        std::cout << std::endl;
    }
}

程序输出和昨天一样,但是可扩展性大大增强。
另外输入参数也比之前好传一点。


image.png

你可能感兴趣的:(C++11 封装nanodbc库可变长模板参数方式)