允许用字段名绑定数据(会影响性能)
允许对同一个数据结构进行不同的绑定
4 files modified
137 ■■■■■ changed files
include/qtl_common.hpp 73 ●●●●● patch | view | raw | blame | history
include/qtl_mysql.hpp 29 ●●●● patch | view | raw | blame | history
include/qtl_odbc.hpp 22 ●●●●● patch | view | raw | blame | history
include/qtl_sqlite.hpp 13 ●●●●● patch | view | raw | blame | history
include/qtl_common.hpp
@@ -218,6 +218,66 @@
    fun(value, temp);
}
template<typename Command, typename T, typename=typename std::enable_if<!std::is_reference<T>::value>::type>
inline void bind_field(Command& command, const char* name, T&& value)
{
    size_t index=command.find_field(name);
    if(index==-1)
        value=T();
    else
        command.bind_field(index, std::forward<T>(value));
}
template<typename Command, typename T>
inline void bind_field(Command& command, const char* name, T& value)
{
    size_t index=command.find_field(name);
    if(index==-1)
        value=T();
    else
        bind_field(command, index, std::forward<T>(value));
}
template<typename FieldType, typename Command, typename BindType>
inline void bind_field(Command& command, const char* name, BindType& value)
{
    size_t index=command.find_field(name);
    if(index==-1)
        value=BindType();
    else
        bind_field<FieldType>(command, index, value);
}
template<typename FieldType, typename Command, typename BindType, typename CastFun>
inline void bind_field(Command& command, const char* name, BindType& value, CastFun&& fun)
{
    size_t index=command.find_field(name);
    if(index==-1)
        value=BindType();
    else
        bind_field<FieldType>(command, index, value, fun);
}
template<typename Command>
inline void bind_field(Command& command, const char* name, char* value, size_t length)
{
    size_t index=command.find_field(name);
    if(index==-1)
        value[0]='\0';
    else
        command.bind_field(index, value, length);
}
template<typename Command>
inline void bind_field(Command& command, const char* name, wchar_t* value, size_t length)
{
    size_t index=command.find_field(name);
    if(index==-1)
        value[0]='\0';
    else
        command.bind_field(index, value, length);
}
namespace detail
{
@@ -404,7 +464,7 @@
    void operator()(std::tuple<Types...>&& params) const
    {
        typedef typename std::remove_reference<typename std::tuple_element<0, tuple_type>::type>::type param_type;
        bind_field(m_command, 0, std::forward<param_type>(std::get<0>(std::forward<tuple_type>(params))));
        bind_field(m_command, static_cast<size_t>(0), std::forward<param_type>(std::get<0>(std::forward<tuple_type>(params))));
    }
private:
    typedef std::tuple<Types...> tuple_type;
@@ -554,7 +614,7 @@
{
    inline void operator()(Command& command, T&& value) const
    {
        bind_field(command, 0, std::forward<typename std::remove_reference<T>::type>(value));
        bind_field(command, static_cast<size_t>(0), std::forward<typename std::remove_reference<T>::type>(value));
    }
};
@@ -573,11 +633,16 @@
{
    void operator()(Command& command, std::pair<Type1, Type2>&& values) const
    {
        bind_field(command, 0, std::forward<Type1>(values.first));
        bind_field(command, 1, std::forward<Type2>(values.second));
        bind_field(command, static_cast<size_t>(0), std::forward<Type1>(values.first));
        bind_field(command, static_cast<size_t>(1), std::forward<Type2>(values.second));
    }
};
template<typename T, typename Tag>
struct record_with_tag : public T
{
};
template<typename Command, typename T>
inline void bind_record(Command& command, T&& value)
{
include/qtl_mysql.hpp
@@ -195,8 +195,8 @@
{
public:
    error() : m_error(0) { }
    error(int err, const char* errmsg) : m_error(err), m_errmsg(errmsg) { }
    explicit error(int err) : m_error(err), m_errmsg(ER(err)) { }
    error(unsigned int err, const char* errmsg) : m_error(err), m_errmsg(errmsg) { }
    explicit error(unsigned int err) : m_error(err), m_errmsg(ER(err)) { }
    explicit error(statement& stmt);
    explicit error(database& db);
    error(const error& src) = default;
@@ -204,7 +204,7 @@
    int code() const throw() { return m_error; }
    virtual const char* what() const throw() override { return m_errmsg.data(); }
private:
    int m_error;
    unsigned int m_error;
    std::string m_errmsg;
};
@@ -444,6 +444,19 @@
        return m_binderAddins[index].m_isNull!=0;
    }
    size_t find_field(const char* name) const
    {
        if(m_result)
        {
            for(size_t i=0; i!=m_result->field_count; i++)
            {
                if(strncmp(m_result->fields[i].name, name, m_result->fields[i].name_length)==0)
                    return i;
            }
        }
        return -1;
    }
    void close()
    {
        if(m_result)
@@ -512,11 +525,11 @@
        return &m_binders[index];
    }
    unsigned int error()
    unsigned int error() const
    {
        return mysql_stmt_errno(m_stmt);
    }
    const char* errmsg()
    const char* errmsg() const
    {
        return mysql_stmt_error(m_stmt);
    }
@@ -577,7 +590,7 @@
class database final : public qtl::base_database<database, statement>
{
public:
    typedef error exception_type;
    typedef mysql::error exception_type;
    database()
    {
@@ -654,11 +667,11 @@
        return m_mysql->db;
    }
    unsigned int error()
    unsigned int error() const
    {
        return mysql_errno(m_mysql);
    }
    const char* errmsg()
    const char* errmsg() const
    {
        return mysql_error(m_mysql);
    }
include/qtl_odbc.hpp
@@ -538,6 +538,26 @@
        return count;
    }
    size_t find_field(const char* name) const
    {
        SQLSMALLINT count=0;
        verify_error(SQLNumResultCols(m_handle, &count));
        for(SQLSMALLINT i=0; i!=count; i++)
        {
            SQLCHAR field_name[256]={0};
            SQLSMALLINT name_length=0;
            SQLSMALLINT data_type;
            SQLULEN column_size;
            SQLSMALLINT digits;
            SQLSMALLINT nullable;
            verify_error(SQLDescribeCol(m_handle, i, field_name, sizeof(field_name), &name_length,
                &data_type, &column_size, &digits, &nullable));
            if(strncmp((char*)field_name, name, name_length)==0)
                return i;
        }
        return -1;
    }
    /*
        ODBC do not support this function, but you can use query to instead it:
        For MS SQL Server: SELECT @@IDENTITY;
@@ -595,6 +615,8 @@
class database : public object<SQL_HANDLE_DBC>, public qtl::base_database<database, statement>
{
public:
    typedef odbc::error exception_type;
    explicit database(environment& env) : object(env.handle()), m_opened(false)
    {
    }
include/qtl_sqlite.hpp
@@ -215,6 +215,17 @@
        bind_field(index, value.data(), value.size());
    }
    size_t find_field(const char* name) const
    {
        size_t count=get_column_count();
        for(size_t i=0; i!=count; i++)
        {
            if(strcmp(get_column_name(i), name)==0)
                return i;
        }
        return -1;
    }
    bool fetch()
    {
        m_fetch_result=sqlite3_step(m_stmt);
@@ -374,6 +385,8 @@
class database final : public qtl::base_database<database, statement>
{
public:    
    typedef sqlite::error exception_type;
    database() : m_db(NULL) { }
    ~database() { close(); }
    database(const database&) = delete;