znone
2021-10-05 6a6b55518847de8d8de8b963a117c53f0c93f67f
Query_iterator remove std::iterator.
MySQL: Fix some error.
PostgreSQL: Support binding to std::any and std::optional.
5 files modified
142 ■■■■■ changed files
include/qtl_common.hpp 10 ●●●● patch | view | raw | blame | history
include/qtl_mysql.hpp 2 ●●● patch | view | raw | blame | history
include/qtl_postgres.hpp 122 ●●●●● patch | view | raw | blame | history
test/TestPostgres.cpp 6 ●●●●● patch | view | raw | blame | history
test/test_mariadb.mak 2 ●●● patch | view | raw | blame | history
include/qtl_common.hpp
@@ -768,9 +768,15 @@
}
template<typename Command, typename Record>
class query_iterator final : public std::iterator<std::forward_iterator_tag, Record>
class query_iterator final
{
public:
    using iterator_category = std::forward_iterator_tag;
    using value_type = Record;
    using difference_type = ptrdiff_t;
    using pointer = Record*;
    using reference = Record&;
    explicit query_iterator(Command& command) 
        : m_command(command) { }
    Record* operator->() const { return m_record.get(); }
@@ -780,7 +786,7 @@
    {
        if(!m_record)
            m_record=std::make_shared<Record>();
        if(m_record.unique())
        if(m_record.use_count()==1)
        {
            if(!m_command.fetch(std::forward<Record>(*m_record)))
                m_record.reset();
include/qtl_mysql.hpp
@@ -936,7 +936,7 @@
    }
    int read(char *buf, unsigned int buf_len)
    {
        fread(buf, 1, buf_len, m_fp);
        return fread(buf, 1, buf_len, m_fp);
    }
    void close()
    {
include/qtl_postgres.hpp
@@ -216,6 +216,8 @@
        else m_errmsg.clear();
    }
    explicit error(const char* errmsg) : m_errmsg(errmsg) { }
    virtual const char* what() const NOEXCEPT override { return m_errmsg.data(); }
    operator bool() const { return !m_errmsg.empty(); }
@@ -1682,6 +1684,116 @@
            m_binders[index].get(value);
    }
#ifdef _QTL_ENABLE_CPP17
    template<typename T>
    inline void bind_field(size_t index, std::optional<T>&& value)
    {
        if (m_res.is_null(0, static_cast<int>(index)))
        {
            value.reset();
        }
        else
        {
            T v;
            bind_field(index, v);
            value = std::move(v);
        }
    }
    void bind_field(size_t index, std::any&& value)
    {
        if (m_res.is_null(0, static_cast<int>(index)))
        {
            value = nullptr;
        }
        else
        {
            Oid oid = m_res.get_column_type(index);
            switch (oid)
            {
            case object_traits<bool>::type_id:
                value = field_cast<bool>(index);
                break;
            case object_traits<char>::type_id:
                value = field_cast<char>(index);
                break;
            case object_traits<float>::type_id:
                value = field_cast<float>(index);
                break;
            case object_traits<double>::type_id:
                value = field_cast<double>(index);
                break;
            case object_traits<int16_t>::type_id:
                value = field_cast<int16_t>(index);
                break;
            case object_traits<int32_t>::type_id:
                value = field_cast<int32_t>(index);
                break;
            case object_traits<int64_t>::type_id:
                value = field_cast<int64_t>(index);
                break;
            case object_traits<Oid>::type_id:
                value = field_cast<Oid>(index);
                break;
            case object_traits<std::string>::type_id:
                value = field_cast<std::string>(index);
                break;
            case object_traits<timestamp>::type_id:
                value = field_cast<timestamp>(index);
                break;
            case object_traits<interval>::type_id:
                value = field_cast<interval>(index);
                break;
            case object_traits<date>::type_id:
                value = field_cast<date>(index);
                break;
            case object_traits<std::vector<uint8_t>>::type_id:
                value = field_cast<std::vector<uint8_t>>(index);
                break;
            case object_traits<bool>::array_type_id:
                value = field_cast<std::vector<bool>>(index);
                break;
            case object_traits<char>::array_type_id:
                value = field_cast<std::vector<char>>(index);
                break;
            case object_traits<float>::array_type_id:
                value = field_cast<std::vector<float>>(index);
                break;
            case object_traits<double>::array_type_id:
                value = field_cast<std::vector<double>>(index);
                break;
            case object_traits<int16_t>::array_type_id:
                value = field_cast<std::vector<int16_t>>(index);
                break;
            case object_traits<int32_t>::array_type_id:
                value = field_cast<std::vector<int32_t>>(index);
                break;
            case object_traits<int64_t>::array_type_id:
                value = field_cast<std::vector<int64_t>>(index);
                break;
            case object_traits<Oid>::array_type_id:
                value = field_cast<std::vector<Oid>>(index);
                break;
            case object_traits<std::string>::array_type_id:
                value = field_cast<std::vector<std::string>>(index);
                break;
            case object_traits<timestamp>::array_type_id:
                value = field_cast<std::vector<timestamp>>(index);
                break;
            case object_traits<interval>::array_type_id:
                value = field_cast<std::vector<interval>>(index);
                break;
            case object_traits<date>::array_type_id:
                value = field_cast<std::vector<date>>(index);
                break;
            default:
                throw postgres::error("Unsupported field type");
            }
        }
    }
#endif // C++17
protected:
    PGconn* m_conn;
@@ -1703,6 +1815,14 @@
        {
            res = PQgetResult(m_conn);
        }
    }
    template<typename T>
    T field_cast(size_t index)
    {
        T v;
        m_binders[index].get(v);
        return v;
    }
};
@@ -2654,7 +2774,7 @@
    }
    template<typename Handler>
    bool is_alive(Handler&& handler) NOEXCEPT
    void is_alive(Handler&& handler) NOEXCEPT
    {
        simple_execute(std::forward<Handler>(handler), "");
    }
test/TestPostgres.cpp
@@ -320,12 +320,10 @@
    {
        db.query("select 0, 'hello world', LOCALTIMESTAMP",
            [](const std::any& i, const std::any& str, const std::any& now) {
            const qtl::postgres::time& time = std::any_cast<const qtl::postgres::time&>(now);
            struct tm tm;
            time.as_tm(tm);
            const qtl::postgres::timestamp& time = std::any_cast<const qtl::postgres::timestamp&>(now);
            cout << "0=\"" << std::any_cast<int32_t>(i) << "\", 'hello world'=\"" <<
                std::any_cast<const std::string&>(str) << "\", now=\"" <<
                std::put_time(&tm, "%c") << "\" \n";
                time.to_string() << "\" \n";
        });
    }
    catch (qtl::postgres::error& e)
test/test_mariadb.mak
@@ -5,7 +5,7 @@
OBJ=TestMariaDB.o
CFLAGS=-g -D_DEBUG -O2 -D_QTL_USE_MARIADB -I/usr/include $(shell mariadb_config --cflags)
CXXFLAGS=-I../include -std=c++11
LDFLAGS= -L/usr/local/lib $(shell -L/usr/local/lib/mariadb/ -lmariadb)
LDFLAGS= -L/usr/local/lib $(shell mariadb_config --libs)
all : $(TARGET)