Ferenc Szontágh
2024-07-01 abf49b44cc47f39d6cceb83866f915bc03b7d900
reformat files
13 files modified
950 ■■■■■ changed files
include/apply_tuple.h 12 ●●●●● patch | view | raw | blame | history
include/qtl_asio.hpp 109 ●●●●● patch | view | raw | blame | history
include/qtl_async.hpp 40 ●●●● patch | view | raw | blame | history
include/qtl_common.hpp 81 ●●●●● patch | view | raw | blame | history
include/qtl_database_pool.hpp 60 ●●●● patch | view | raw | blame | history
include/qtl_mysql.hpp 205 ●●●●● patch | view | raw | blame | history
include/qtl_mysql_pool.hpp 7 ●●●●● patch | view | raw | blame | history
include/qtl_odbc.hpp 163 ●●●●● patch | view | raw | blame | history
include/qtl_odbc_pool.hpp 7 ●●●●● patch | view | raw | blame | history
include/qtl_postgres.hpp 237 ●●●●● patch | view | raw | blame | history
include/qtl_postgres_pool.hpp 7 ●●●●● patch | view | raw | blame | history
include/qtl_sqlite.hpp 21 ●●●● patch | view | raw | blame | history
include/qtl_sqlite_pool.hpp 1 ●●●● patch | view | raw | blame | history
include/apply_tuple.h
@@ -31,12 +31,10 @@
        static inline auto apply_tuple(F&& f, T&& t, A&&... a)
            -> decltype(apply<N-1>::apply_tuple(
            std::forward<F>(f), std::forward<T>(t),
            std::get<N-1>(std::forward<T>(t)), std::forward<A>(a)...
            ))
                        std::get<N - 1>(std::forward<T>(t)), std::forward<A>(a)...))
        {
            return apply<N-1>::apply_tuple(std::forward<F>(f), std::forward<T>(t),
                std::get<N-1>(std::forward<T>(t)), std::forward<A>(a)...
                );
                                                     std::get<N - 1>(std::forward<T>(t)), std::forward<A>(a)...);
        }
    };
@@ -54,12 +52,10 @@
template<typename F, typename T>
inline auto apply_tuple(F&& f, T&& t)
    -> decltype(detail::apply< std::tuple_size<
        typename std::decay<T>::type
    >::value>::apply_tuple(std::forward<F>(f), std::forward<T>(t)))
                            typename std::decay<T>::type>::value>::apply_tuple(std::forward<F>(f), std::forward<T>(t)))
{
    return detail::apply< std::tuple_size<
        typename std::decay<T>::type
    >::value>::apply_tuple(std::forward<F>(f), std::forward<T>(t));
                typename std::decay<T>::type>::value>::apply_tuple(std::forward<F>(f), std::forward<T>(t));
}
#endif // C++17
include/qtl_asio.hpp
@@ -59,7 +59,6 @@
    service_type& context() NOEXCEPT { return _service; }
private:
    class event_item : public qtl::event
    {
    public:
@@ -76,9 +75,11 @@
            if (flags&qtl::event::ef_read)
            {
#if ASIO_VERSION < 101200
                _socket.async_read_some(NS_ASIO::null_buffers(), _strand.wrap([this, handler](const NS_ASIO::error_code& ec, size_t bytes_transferred) {
                        _socket.async_read_some(NS_ASIO::null_buffers(), _strand.wrap([this, handler](const NS_ASIO::error_code &ec, size_t bytes_transferred)
                                                                                      {
#else
                _socket.async_wait(NS_ASIO::socket_base::wait_read, _strand.wrap([this, handler](const NS_ASIO::error_code& ec) {
                        _socket.async_wait(NS_ASIO::socket_base::wait_read, _strand.wrap([this, handler](const NS_ASIO::error_code &ec)
                                                                                         {
#endif // ASIO_VERSION
                    if (!ec)
                        handler(qtl::event::ef_read);
@@ -87,16 +88,17 @@
                    else
                        handler(qtl::event::ef_exception);
                    _busying = false;
                    _timer.cancel();
                }));
                    _timer.cancel(); }));
                _busying = true;
            }
            if (flags&qtl::event::ef_write)
            {
#if ASIO_VERSION < 101200
                _socket.async_write_some(NS_ASIO::null_buffers(), _strand.wrap([this, handler](const NS_ASIO::error_code& ec, size_t bytes_transferred) {
                        _socket.async_write_some(NS_ASIO::null_buffers(), _strand.wrap([this, handler](const NS_ASIO::error_code &ec, size_t bytes_transferred)
                                                                                       {
#else
                _socket.async_wait(NS_ASIO::socket_base::wait_write, _strand.wrap([this, handler](const NS_ASIO::error_code& ec) {
                        _socket.async_wait(NS_ASIO::socket_base::wait_write, _strand.wrap([this, handler](const NS_ASIO::error_code &ec)
                                                                                          {
#endif //ASIO_VERSION
                    if (!ec)
                        handler(qtl::event::ef_write);
@@ -105,8 +107,7 @@
                    else
                        handler(qtl::event::ef_exception);
                    _timer.cancel();
                    _busying = false;
                }));
                    _busying = false; }));
                _busying = true;
            }
            if (timeout > 0)
@@ -116,18 +117,19 @@
#else
                _timer.expires_after(NS_ASIO::chrono::seconds(timeout));
#endif // ASIO_VERSION
                _timer.async_wait(_strand.wrap([this, handler](NS_ASIO::error_code ec) {
                        _timer.async_wait(_strand.wrap([this, handler](NS_ASIO::error_code ec)
                                                       {
                    if (!ec)
                    {
                        _socket.cancel(ec);
                    }
                }));
                    } }));
            }
        }
        virtual void remove() override
        {
            if (_busying) return;
                    if (_busying)
                        return;
#if ASIO_VERSION >= 101200 && (!defined(_WIN32) || _WIN32_WINNT >= 0x0603 )
            _socket.release();
#endif //Windows 8.1
@@ -147,7 +149,6 @@
    };
public:
    template<typename Connection>
    event_item* add(Connection* connection)
    {
@@ -165,10 +166,10 @@
    void remove(event_item* item)
    {
        std::lock_guard<std::mutex> lock(_mutex);
        auto it = std::find_if(_events.begin(), _events.end(), [item](std::unique_ptr<event_item>& v) {
            return item==v.get();
        });
        if (it != _events.end()) _events.erase(it);
                auto it = std::find_if(_events.begin(), _events.end(), [item](std::unique_ptr<event_item> &v)
                                       { return item == v.get(); });
                if (it != _events.end())
                    _events.erase(it);
    }
};
@@ -204,10 +205,12 @@
{
#if ASIO_VERSION < 101200
    async_init_type<OpenHandler,
        void(typename Connection::exception_type)> init(std::forward<OpenHandler>(handler));
                            void(typename Connection::exception_type)>
                init(std::forward<OpenHandler>(handler));
#else
    async_init_type<OpenHandler,
        void(typename Connection::exception_type)> init(handler);
                            void(typename Connection::exception_type)>
                init(handler);
#endif
    db.open(service, get_async_handler(init), std::forward<Args>(args)...);
@@ -220,10 +223,12 @@
{
#if ASIO_VERSION < 101200
    async_init_type<CloseHandler,
        void()> init(std::forward<CloseHandler>(std::forward<CloseHandler>(handler)));
                            void()>
                init(std::forward<CloseHandler>(std::forward<CloseHandler>(handler)));
#else
    async_init_type<CloseHandler,
        void()> init(std::forward<CloseHandler>(handler));
                            void()>
                init(std::forward<CloseHandler>(handler));
#endif
    db.close(get_async_handler(init), std::forward<Args>(args)...);
@@ -236,10 +241,12 @@
{
#if ASIO_VERSION < 101200
    async_init_type<ExecuteHandler,
        void(typename Connection::exception_type, uint64_t)> init(std::forward<ExecuteHandler>(handler));
                            void(typename Connection::exception_type, uint64_t)>
                init(std::forward<ExecuteHandler>(handler));
#else
    async_init_type<ExecuteHandler,
        void(typename Connection::exception_type, uint64_t)> init(handler);
                            void(typename Connection::exception_type, uint64_t)>
                init(handler);
#endif
    db.execute(get_async_handler(init), std::forward<Args>(args)...);
@@ -252,10 +259,12 @@
{
#if ASIO_VERSION < 101200
    async_init_type<ExecuteHandler,
        void(typename Connection::exception_type, uint64_t)> init(std::forward<ExecuteHandler>(handler));
                            void(typename Connection::exception_type, uint64_t)>
                init(std::forward<ExecuteHandler>(handler));
#else
    async_init_type<ExecuteHandler,
        void(typename Connection::exception_type, uint64_t)> init(handler);
                            void(typename Connection::exception_type, uint64_t)>
                init(handler);
#endif
    db.execute_direct(get_async_handler(init), std::forward<Args>(args)...);
@@ -268,10 +277,12 @@
{
#if ASIO_VERSION < 101200
    async_init_type<ExecuteHandler,
        void(typename Connection::exception_type, uint64_t)> init(std::forward<ExecuteHandler>(handler));
                            void(typename Connection::exception_type, uint64_t)>
                init(std::forward<ExecuteHandler>(handler));
#else
    async_init_type<ExecuteHandler,
        void(typename Connection::exception_type, uint64_t)> init(handler);
                            void(typename Connection::exception_type, uint64_t)>
                init(handler);
#endif
    db.insert(get_async_handler(init), std::forward<Args>(args)...);
@@ -284,10 +295,12 @@
{
#if ASIO_VERSION < 101200
    async_init_type<ExecuteHandler,
        void(typename Connection::exception_type, uint64_t)> init(std::forward<ExecuteHandler>(handler));
                            void(typename Connection::exception_type, uint64_t)>
                init(std::forward<ExecuteHandler>(handler));
#else
    async_init_type<ExecuteHandler,
        void(typename Connection::exception_type, uint64_t)> init(handler);
                            void(typename Connection::exception_type, uint64_t)>
                init(handler);
#endif
    db.insert_direct(get_async_handler(init), std::forward<Args>(args)...);
@@ -300,10 +313,12 @@
{
#if ASIO_VERSION < 101200
    async_init_type<FinishHandler,
        void(typename Connection::exception_type)> init(std::forward<FinishHandler>(handler));
                            void(typename Connection::exception_type)>
                init(std::forward<FinishHandler>(handler));
#else
    async_init_type<FinishHandler,
        void(typename Connection::exception_type)> init(handler);
                            void(typename Connection::exception_type)>
                init(handler);
#endif
    db.query(std::forward<Args>(args)..., get_async_handler(init));
@@ -316,10 +331,12 @@
{
#if ASIO_VERSION < 101200
    async_init_type<FinishHandler,
        void(typename Connection::exception_type)> init(std::forward<FinishHandler>(handler));
                            void(typename Connection::exception_type)>
                init(std::forward<FinishHandler>(handler));
#else
    async_init_type<FinishHandler,
        void(typename Connection::exception_type)> init(handler);
                            void(typename Connection::exception_type)>
                init(handler);
#endif
    db.query_explicit(std::forward<Args>(args)..., get_async_handler(init));
@@ -332,10 +349,12 @@
{
#if ASIO_VERSION < 101200
    async_init_type<FinishHandler,
        void(typename Connection::exception_type)> init(std::forward<FinishHandler>(handler));
                            void(typename Connection::exception_type)>
                init(std::forward<FinishHandler>(handler));
#else
    async_init_type<FinishHandler,
        void(typename Connection::exception_type)> init(handler);
                            void(typename Connection::exception_type)>
                init(handler);
#endif
    db.query_multi_with_params(std::forward<A1>(a1), std::forward<A2>(a2), get_async_handler(init), std::forward<RowHandlers>(row_handlers)...);
@@ -348,10 +367,12 @@
{
#if ASIO_VERSION < 101200
    async_init_type<FinishHandler,
        void(typename Connection::exception_type)> init(std::forward<FinishHandler>(handler));
                            void(typename Connection::exception_type)>
                init(std::forward<FinishHandler>(handler));
#else
    async_init_type<FinishHandler,
        void(typename Connection::exception_type)> init(handler);
                            void(typename Connection::exception_type)>
                init(handler);
#endif
    db.query_multi_with_params(std::forward<A1>(a1), get_async_handler(init), std::forward<RowHandlers>(row_handlers)...);
@@ -364,10 +385,12 @@
{
#if ASIO_VERSION < 101200
    async_init_type<FinishHandler,
        void(typename Connection::exception_type)> init(std::forward<FinishHandler>(handler));
                            void(typename Connection::exception_type)>
                init(std::forward<FinishHandler>(handler));
#else
    async_init_type<FinishHandler,
        void(typename Connection::exception_type)> init(handler);
                            void(typename Connection::exception_type)>
                init(handler);
#endif
    db.query_multi(std::forward<A1>(a1), std::forward<A2>(a2), get_async_handler(init), std::forward<RowHandlers>(row_handlers)...);
@@ -380,10 +403,12 @@
{
#if ASIO_VERSION < 101200
    async_init_type<FinishHandler,
        void(typename Connection::exception_type)> init(std::forward<FinishHandler>(handler));
                            void(typename Connection::exception_type)>
                init(std::forward<FinishHandler>(handler));
#else
    async_init_type<FinishHandler,
        void(typename Connection::exception_type)> init(handler);
                            void(typename Connection::exception_type)>
                init(handler);
#endif
    db.query_multi(std::forward<A1>(a1), get_async_handler(init), std::forward<RowHandlers>(row_handlers)...);
include/qtl_async.hpp
@@ -30,9 +30,9 @@
    void start(const std::shared_ptr<Command>& command)
    {
        auto self = this->shared_from_this();
        command->fetch(std::forward<Values>(m_values), [this, command]() {
            return qtl::detail::apply<RowHandler, Values>(std::forward<RowHandler>(m_row_handler), std::forward<Values>(m_values));
        }, [self, command](const Exception& e) {
                command->fetch(std::forward<Values>(m_values), [this, command]()
                               { return qtl::detail::apply<RowHandler, Values>(std::forward<RowHandler>(m_row_handler), std::forward<Values>(m_values)); }, [self, command](const Exception &e)
                               {
            if (e || self->m_auto_close_command)
            {
                command->close([self, command, e](const Exception& new_e) {
@@ -42,8 +42,7 @@
            else 
            {
                self->m_finish_handler(e);
            }
        });
            } });
    }
    
    void auto_close_command(bool auto_close)
@@ -64,7 +63,6 @@
    return std::make_shared<async_fetch_helper<Values, RowHandler, FinishHandler>>(values, row_handler, cpmplete_handler);
}
template<typename Exception, typename Command, typename RowHandler, typename FinishHandler>
inline void async_fetch_command(const std::shared_ptr<Command>& command, FinishHandler&& finish_handler, RowHandler&& row_handler)
{
@@ -78,7 +76,8 @@
template<typename Exception, typename Command, typename RowHandler, typename FinishHandler, typename... OtherHandler>
inline void async_fetch_command(const std::shared_ptr<Command>& command, FinishHandler&& finish_handler, RowHandler&& row_handler, OtherHandler&&... other)
{
    async_fetch_command<Exception>(command, [command, finish_handler, other...](const Exception& e) mutable {
            async_fetch_command<Exception>(command, [command, finish_handler, other...](const Exception &e) mutable
                                           {
        if (e)
        {
            finish_handler(e);
@@ -91,8 +90,7 @@
                else
                    async_fetch_command<Exception>(command, std::forward<FinishHandler>(finish_handler), std::forward<OtherHandler>(other)...);
            });
        }
    }, std::forward<RowHandler>(row_handler));
        } }, std::forward<RowHandler>(row_handler));
}
}
@@ -160,7 +158,8 @@
    void execute(ResultHandler handler, const char* query_text, size_t text_length, const Params& params)
    {
        T* pThis = static_cast<T*>(this);
        pThis->open_command(query_text, text_length, [handler, params](const typename T::exception_type& e, std::shared_ptr<Command>& command) mutable {
            pThis->open_command(query_text, text_length, [handler, params](const typename T::exception_type &e, std::shared_ptr<Command> &command) mutable
                                {
            if(e)
            {
                command->close([command, e, handler](const typename T::exception_type& ae) mutable {
@@ -172,8 +171,7 @@
                command->close([command, handler, e, affected](const typename T::exception_type& ae) mutable {
                    handler(e ? e : ae, affected);
                });
            });
        });
            }); });
    }
    template<typename Params, typename ResultHandler>
    void execute(ResultHandler handler, const char* query_text, const Params& params)
@@ -214,7 +212,8 @@
    void insert(ResultHandler handler, const char* query_text, size_t text_length, const Params& params)
    {
        T* pThis = static_cast<T*>(this);
        pThis->open_command(query_text, text_length, [handler, params](const typename T::exception_type& e, std::shared_ptr<Command>& command) {
            pThis->open_command(query_text, text_length, [handler, params](const typename T::exception_type &e, std::shared_ptr<Command> &command)
                                {
            if(e)
            {
                command->close([command, e, handler](const typename T::exception_type& ae) mutable {
@@ -231,8 +230,7 @@
                        handler(e ? e : ae, insert_id);
                    });
                });
            }
        });
            } });
    }
    template<typename Params, typename ResultHandler>
@@ -277,7 +275,8 @@
    void query_explicit(const char* query_text, size_t text_length, const Params& params, Values&& values, RowHandler&& row_handler, FinishHandler&& finish_handler)
    {
        T* pThis = static_cast<T*>(this);
        pThis->open_command(query_text, text_length, [values, row_handler, finish_handler, params](const typename T::exception_type& e, const std::shared_ptr<Command>& command) mutable {
            pThis->open_command(query_text, text_length, [values, row_handler, finish_handler, params](const typename T::exception_type &e, const std::shared_ptr<Command> &command) mutable
                                {
            if(e)
            {
                finish_handler(e);
@@ -288,8 +287,7 @@
                    auto helper=detail::make_fetch_helper(values, row_handler, finish_handler);
                    helper->template start<Command, typename T::exception_type>(command);
                });
            }
        });
            } });
    }
    template<typename Params, typename Values, typename RowHandler, typename FinishHandler>
@@ -353,7 +351,8 @@
    void query_multi_with_params(const char* query_text, size_t text_length, const Params& params, FinishHandler&& finish_handler, RowHandlers&&... row_handlers)
    {
        T* pThis = static_cast<T*>(this);
        pThis->open_command(query_text, text_length, [params, finish_handler, row_handlers...](const typename T::exception_type& e, const std::shared_ptr<Command>& command) mutable {
            pThis->open_command(query_text, text_length, [params, finish_handler, row_handlers...](const typename T::exception_type &e, const std::shared_ptr<Command> &command) mutable
                                {
            if (e)
            {
                finish_handler(e);
@@ -366,8 +365,7 @@
                    else
                        qtl::detail::async_fetch_command<typename T::exception_type>(command, std::forward<FinishHandler>(finish_handler), std::forward<RowHandlers>(row_handlers)...);
                });
            }
        });
            } });
    }
    template<typename Params, typename FinishHandler, typename... RowHandlers>
    void query_multi_with_params(const char* query_text, const Params& params, FinishHandler&& finish_handler, RowHandlers&&... row_handlers)
include/qtl_common.hpp
@@ -31,7 +31,9 @@
namespace qtl
{
struct null { };
    struct null
    {
    };
struct blob_data
{
@@ -114,11 +116,16 @@
    }
    void clear() { m_value.clear(); }
    char_type* alloc(size_t n) { m_value.resize(n); return (char_type*)m_value.data(); }
        char_type *alloc(size_t n)
        {
            m_value.resize(n);
            return (char_type *)m_value.data();
        }
    void truncate(size_t n) { m_value.resize(n); }
    void assign(const char_type* str, size_t n) { m_value.assign(str, n); }
    const char_type* data() const { return m_value.data(); }
    size_t size() const { return m_value.size(); }
private:
    string_type&& m_value;
};
@@ -250,7 +257,8 @@
    size_t index=command.find_field(name);
    if (index == -1)
    {
        if (length > 0) value[0] = '\0';
            if (length > 0)
                value[0] = '\0';
    }
    else
        command.bind_field(index, value, length);
@@ -262,7 +270,8 @@
    size_t index=command.find_field(name);
    if (index == -1)
    {
        if (length > 0) value[0] = '\0';
            if (length > 0)
                value[0] = '\0';
    }
    else
        command.bind_field(index, value, length);
@@ -328,7 +337,9 @@
    typedef typename std::result_of<F(T)>::type raw_result_type;
#endif
    template<typename Ret, bool>
    struct impl {};
            struct impl
            {
            };
    template<typename Ret>
    struct impl<Ret, true>
    {
@@ -369,7 +380,9 @@
    typedef typename std::result_of<F(Types...)>::type raw_result_type;
#endif
    template<typename Ret, bool>
    struct impl {};
            struct impl
            {
            };
    template<typename Ret>
    struct impl<Ret, true>
    {
@@ -405,7 +418,9 @@
    typedef R (Type::*fun_type)();
    typedef R raw_result_type;
    template<typename Ret, bool>
    struct impl {};
            struct impl
            {
            };
    template<typename Ret>
    struct impl<Ret, true>
    {
@@ -441,7 +456,9 @@
    typedef R (Type::*fun_type)() const;
    typedef R raw_result_type;
    template<typename Ret, bool>
    struct impl {};
            struct impl
            {
            };
    template<typename Ret>
    struct impl<Ret, true>
    {
@@ -492,6 +509,7 @@
        bind_field(m_command, N-1, std::forward<param_type>(std::get<N-1>(std::forward<tuple_type>(params))));
        (bind_helper<Command, N-1, Types...>(m_command))(std::forward<tuple_type>(params));
    }
private:
    typedef std::tuple<Types...> tuple_type;
    Command& m_command;
@@ -511,6 +529,7 @@
        typedef typename std::remove_reference<typename std::tuple_element<0, tuple_type>::type>::type param_type;
        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;
    Command& m_command;
@@ -622,7 +641,10 @@
template<typename Command, typename T>
struct params_binder
{
    enum { size = 1 };
        enum
        {
            size = 1
        };
    inline void operator()(Command& command, const T& param) const
    {
        qtl::bind_param(command, 0, param);
@@ -632,7 +654,10 @@
template<typename Command, typename... Types>
struct params_binder<Command, std::tuple<Types...>>
{
    enum { size = sizeof...(Types) };
        enum
        {
            size = sizeof...(Types)
        };
    void operator()(Command& command, const std::tuple<Types...>& params) const
    {
        (detail::bind_helper<Command, std::tuple_size<std::tuple<Types...>>::value, Types...>(command))(params);
@@ -642,7 +667,10 @@
template<typename Command, typename Type1, typename Type2>
struct params_binder<Command, std::pair<Type1, Type2>>
{
    enum { size = 2 };
        enum
        {
            size = 2
        };
    void operator()(Command& command, std::pair<Type1, Type2>&& values) const
    {
        qtl::bind_param(command, 0, std::forward<Type1>(values.first));
@@ -680,8 +708,7 @@
{
    void operator()(Command& command, std::tuple<Types...>&& values) const
    {
        (detail::bind_helper<Command, std::tuple_size<std::tuple<Types...>>::value, Types...>(command))
            (std::forward<std::tuple<Types...>>(values));
            (detail::bind_helper<Command, std::tuple_size<std::tuple<Types...>>::value, Types...>(command))(std::forward<std::tuple<Types...>>(values));
    }
};
@@ -751,7 +778,6 @@
private:
    Pred m_pred;
};
template<typename T, typename Pred>
inline custom_binder_type<T, Pred> custom_bind(T&& v, Pred pred)
@@ -882,7 +908,8 @@
        T* pThis=static_cast<T*>(this);
        Command command=pThis->open_command(query_text, text_length);
        command.execute(params);
        if(affected) *affected=command.affetced_rows();
            if (affected)
                *affected = command.affetced_rows();
        command.close();
        return *this;
    }
@@ -997,7 +1024,8 @@
        command.execute(params);
        while(command.fetch(std::forward<Values>(values)))
        {
            if(!detail::apply(std::forward<ValueProc>(proc), std::forward<Values>(values))) break;
                if (!detail::apply(std::forward<ValueProc>(proc), std::forward<Values>(values)))
                    break;
        }
        command.close();
        return *this;
@@ -1165,12 +1193,18 @@
protected:
    struct nothing 
    {
        template<typename... Values> bool operator()(Values&&...) const {  return true; }
            template <typename... Values>
            bool operator()(Values &&...) const { return true; }
    };
    struct first_record 
    {
        first_record() : _found(false) { }
        template<typename... Values> bool operator()(Values&&...) { _found = true; return false; }
            template <typename... Values>
            bool operator()(Values &&...)
            {
                _found = true;
                return false;
            }
        operator bool() const { return _found; }
    private:
@@ -1311,17 +1345,13 @@
            //    eback()[intersection.first - m_pos] = c;
            //}
            m_pos += 1;
        }
        return ch;
    }
    virtual int_type pbackfail(int_type c = traits_type::eof()) override
    {
        if (gptr() == 0
            || gptr() <= eback()
            || (!traits_type::eq_int_type(traits_type::eof(), c)
                && !traits_type::eq(traits_type::to_char_type(c), gptr()[-1])))
            if (gptr() == 0 || gptr() <= eback() || (!traits_type::eq_int_type(traits_type::eof(), c) && !traits_type::eq(traits_type::to_char_type(c), gptr()[-1])))
        {
            return (traits_type::eof());    // can't put back, fail
        }
@@ -1335,7 +1365,6 @@
    }
private:
    off_type seekoff(off_type position, off_type off, std::ios_base::seekdir dir)
    {
        off_type result = 0;
@@ -1432,6 +1461,7 @@
            m_commited=true;
        }
    }
private:
    bool m_commited;
    Database& m_db;
@@ -1442,7 +1472,8 @@
{
    command.reset();
    command.execute(params);
    if(affected) *affected+=command.affetced_rows();
        if (affected)
            *affected += command.affetced_rows();
}
template<typename Command, typename Params, typename... Others>
include/qtl_database_pool.hpp
@@ -46,9 +46,8 @@
        Database* db=popup();
        if(db==NULL && m_trying_connection==false)
            db=create_database();
        return pointer(db, [this](Database* db) {
            recovery(db);
        });
            return pointer(db, [this](Database *db)
                           { recovery(db); });
    }
    bool test_alive()
@@ -76,7 +75,8 @@
            try_connect();
            return false;
        }
        else return true;
            else
                return true;
    }
private:
@@ -89,7 +89,8 @@
    virtual Database* new_database() throw()=0;
    void recovery(Database* db)
    {
        if(db==NULL) return;
            if (db == NULL)
                return;
        if(db->is_alive())
        {
            std::lock_guard<std::mutex> lock(m_pool_mutex);
@@ -109,7 +110,8 @@
    Database* create_database()
    {
        Database* db=new_database();
        if(db) return db;
            if (db)
                return db;
        {
            std::lock_guard<std::mutex> lock(m_pool_mutex);
@@ -158,7 +160,8 @@
            if(db==NULL)
            {
                std::this_thread::sleep_for(std::chrono::seconds(interval));
                if(interval<60) interval<<=1;
                    if (interval < 60)
                        interval <<= 1;
            }
        }
        if(db)
@@ -201,7 +204,8 @@
    void get(Handler&& handler, EventLoop* ev=nullptr)
    {
        Connection* db = popup();
        if(ev==nullptr) ev=&m_ev;
            if (ev == nullptr)
                ev = &m_ev;
        
        if(db)
        {
@@ -210,9 +214,8 @@
        }
        else if (m_trying_connecting == false)
        {
            create_connection(ev, [this, handler](const typename Connection::exception_type& e,  Connection* db) {
                handler(e, wrap(db));
            });
                create_connection(ev, [this, handler](const typename Connection::exception_type &e, Connection *db)
                                  { handler(e, wrap(db)); });
        }
        else
        {
@@ -229,7 +232,8 @@
        while (it != m_connections.end())
        {
            Connection* db = *it;
            db->is_alive([this, db](const typename Connection::exception_type& e) {
                db->is_alive([this, db](const typename Connection::exception_type &e)
                             {
                if (e)
                {
                    std::unique_lock<std::mutex> lock(m_pool_mutex);
@@ -238,8 +242,7 @@
                    m_connections.erase(it);
                    if (m_connections.empty())
                        try_connect();
                }
            });
                } });
            ++it;
        }
    }
@@ -252,8 +255,10 @@
    void recovery(Connection* db)
    {
        if (db == NULL) return;
        db->is_alive([this, db](const typename Connection::exception_type& e) {
            if (db == NULL)
                return;
            db->is_alive([this, db](const typename Connection::exception_type &e)
                         {
            if (e)
            {
                {
@@ -268,15 +273,15 @@
                    throw std::runtime_error("destroy a busysing connection.");
                std::lock_guard<std::recursive_mutex> lock(m_pool_mutex);
                m_connections.push_back(db);
            }
        });
            } });
    }
    template<typename Handler>
    void create_connection(EventLoop* ev, Handler&& handler)
    {
        T* pThis = static_cast<T*>(this);
        pThis->new_connection(*ev, [this, handler](const typename Connection::exception_type& e, Connection* db) {
            pThis->new_connection(*ev, [this, handler](const typename Connection::exception_type &e, Connection *db)
                                  {
            handler(e, db);
            if (!db)
            {
@@ -287,8 +292,7 @@
                m_ev.set_timeout(tv, [this]() {
                    try_connect();
                });
            }
        });
            } });
    }
    Connection* popup()
@@ -309,7 +313,8 @@
            return;
        m_trying_connecting = true;
        create_connection(&m_ev, [this](const typename Connection::exception_type& e, Connection* db) {
            create_connection(&m_ev, [this](const typename Connection::exception_type &e, Connection *db)
                              {
            if (db)
            {
                std::lock_guard<std::recursive_mutex> lock(m_pool_mutex);
@@ -318,8 +323,7 @@
            else
            {
                m_trying_connecting = false;
            }
        });
            } });
    }
    void clear()
@@ -332,11 +336,11 @@
    {
        if (db)
        {
            return pointer(db, [this](Connection* db) {
                recovery(db);
            });
                return pointer(db, [this](Connection *db)
                               { recovery(db); });
        }
        else return nullptr;
            else
                return nullptr;
    }
};
include/qtl_mysql.hpp
@@ -60,6 +60,7 @@
class binder : public MYSQL_BIND
{
    friend class statement;
public:
    binder()
    {
@@ -182,7 +183,6 @@
    }
};
template<typename T>
inline void bind(binder& binder, const T& v)
{
@@ -197,7 +197,8 @@
inline void bind(binder& binder, const char* str, size_t length=0)
{
    if(length==0) length=strlen(str);
            if (length == 0)
                length = strlen(str);
    binder.bind(const_cast<char*>(str), static_cast<unsigned long>(length), MYSQL_TYPE_VAR_STRING);
}
@@ -216,6 +217,7 @@
    int code() const throw() { return m_error; }
    operator bool() const { return m_error != 0;  }
    virtual const char* what() const NOEXCEPT override { return m_errmsg.data(); }
private:
    unsigned int m_error;
    std::string m_errmsg;
@@ -242,7 +244,8 @@
        m_stmt = stmt;
        m_field = field;
        m_binder = b;
        if (b.length) m_size = *b.length;
                if (b.length)
                    m_size = *b.length;
        init_buffer(mode);
    }
@@ -445,7 +448,8 @@
    void bind_param(size_t index, std::istream& param)
    {
        m_binders[index].bind(nullptr, 0, MYSQL_TYPE_LONG_BLOB);
        m_binderAddins[index].m_after_fetch = [this, index, &param](const binder&) {
                m_binderAddins[index].m_after_fetch = [this, index, &param](const binder &)
                {
            std::array<char, blob_buffer_size> buffer;
            unsigned long readed = 0;
            while (!param.eof() && !param.fail())
@@ -464,7 +468,8 @@
    void bind_param(size_t index, const blob_writer& param)
    {
        m_binders[index].bind(nullptr, 0, MYSQL_TYPE_LONG_BLOB);
        m_binderAddins[index].m_after_fetch = [this, index, &param](const binder& b) {
                m_binderAddins[index].m_after_fetch = [this, index, &param](const binder &b)
                {
            blobbuf buf;
            buf.open(m_stmt, index, b, std::ios::out);
            std::ostream s(&buf);
@@ -492,7 +497,8 @@
    void bind_field(size_t index, char* value, size_t length)
    {
        m_binders[index].bind(value, length - 1, MYSQL_TYPE_VAR_STRING);
        m_binderAddins[index].m_after_fetch = [](const binder& bind) {
                m_binderAddins[index].m_after_fetch = [](const binder &bind)
                {
            if (*bind.is_null)
                memset(bind.buffer, 0, bind.buffer_length + 1);
            else
@@ -515,10 +521,12 @@
        if (m_result)
        {
            MYSQL_FIELD* field = mysql_fetch_field_direct(m_result, (unsigned int)index);
            if (field == nullptr) throw_exception();
                    if (field == nullptr)
                        throw_exception();
            value.clear();
            typename bind_string_helper<T>::char_type* data = value.alloc(field->length);
            m_binderAddins[index].m_before_fetch = [this, value](binder& b) mutable {
                    m_binderAddins[index].m_before_fetch = [this, value](binder &b) mutable
                    {
                if (value.size() < b.buffer_length)
                {
                    value.alloc(b.buffer_length);
@@ -529,9 +537,12 @@
                    }
                }
            };
            m_binderAddins[index].m_after_fetch = [value](const binder& b) mutable {
                if (*b.is_null) value.clear();
                else value.truncate(*b.length);
                    m_binderAddins[index].m_after_fetch = [value](const binder &b) mutable
                    {
                        if (*b.is_null)
                            value.clear();
                        else
                            value.truncate(*b.length);
            };
            m_binders[index].bind((void*)data, field->length, field->type);
        }
@@ -544,11 +555,13 @@
            MYSQL_FIELD* field = mysql_fetch_field_direct(m_result, (unsigned int)index);
            assert(IS_LONGDATA(field->type));
            m_binders[index].bind(nullptr, 0, field->type);
            m_binderAddins[index].m_after_fetch = [this, index, &value](const binder& b) {
                    m_binderAddins[index].m_after_fetch = [this, index, &value](const binder &b)
                    {
                unsigned long readed = 0;
                std::array<char, blob_buffer_size> buffer;
                binder& bb = const_cast<binder&>(b);
                if (*b.is_null) return;
                        if (*b.is_null)
                            return;
                bb.buffer = const_cast<char*>(buffer.data());
                bb.buffer_length = buffer.size();
                while (readed <= *b.length)
@@ -570,8 +583,10 @@
            MYSQL_FIELD* field = mysql_fetch_field_direct(m_result, (unsigned int)index);
            assert(IS_LONGDATA(field->type));
            m_binders[index].bind(nullptr, 0, field->type);
            m_binderAddins[index].m_after_fetch = [this, index, &value](const binder& b) {
                if (*b.is_null) return;
                    m_binderAddins[index].m_after_fetch = [this, index, &value](const binder &b)
                    {
                        if (*b.is_null)
                            return;
                value.open(m_stmt, index, b, std::ios::in);
            };
        }
@@ -585,11 +600,13 @@
            qtl::bind_field(*this, index, value.data);
            binder_addin& addin = m_binderAddins[index];
            auto fetch_fun = addin.m_after_fetch;
            addin.m_after_fetch = [&addin, fetch_fun, &value](const binder& b) {
                    addin.m_after_fetch = [&addin, fetch_fun, &value](const binder &b)
                    {
                value.is_null = *b.is_null != 0;
                value.length = *b.length;
                value.is_truncated = addin.is_truncated;
                if (fetch_fun) fetch_fun(b);
                        if (fetch_fun)
                            fetch_fun(b);
            };
        }
    }
@@ -604,9 +621,12 @@
            qtl::bind_field(*this, index, *value);
            binder_addin& addin = m_binderAddins[index];
            auto fetch_fun = addin.m_after_fetch;
            addin.m_after_fetch = [&addin, fetch_fun, &value](const binder& b) {
                if (fetch_fun) fetch_fun(b);
                if (*b.is_null) value.reset();
                    addin.m_after_fetch = [&addin, fetch_fun, &value](const binder &b)
                    {
                        if (fetch_fun)
                            fetch_fun(b);
                        if (*b.is_null)
                            value.reset();
            };
        }
    }
@@ -616,7 +636,8 @@
        if (m_result)
        {
            MYSQL_FIELD* field = mysql_fetch_field_direct(m_result, (unsigned int)index);
            if (field == nullptr) throw_exception();
                    if (field == nullptr)
                        throw_exception();
            switch (field->type)
            {
            case MYSQL_TYPE_NULL:
@@ -685,9 +706,12 @@
            }
            binder_addin& addin = m_binderAddins[index];
            auto fetch_fun = addin.m_after_fetch;
            addin.m_after_fetch = [&addin, fetch_fun, &value](const binder& b) {
                if (fetch_fun) fetch_fun(b);
                if (*b.is_null) value.reset();
                    addin.m_after_fetch = [&addin, fetch_fun, &value](const binder &b)
                    {
                        if (fetch_fun)
                            fetch_fun(b);
                        if (*b.is_null)
                            value.reset();
            };
        }
    }
@@ -750,12 +774,12 @@
        explicit if_null(Value& value, Value&& def=Value()) : m_value(value), m_def(std::move(def)) { }
        void operator()(const binder& b)
        {
            if(*b.is_null) m_value=m_def;
                    if (*b.is_null)
                        m_value = m_def;
        }
        Value& m_value;
        Value m_def;
    };
};
class statement : public base_statement
@@ -777,7 +801,8 @@
    void open(const char *query_text, unsigned long text_length=0)
    {
        mysql_stmt_reset(m_stmt);
        if(text_length==0) text_length=(unsigned long)strlen(query_text);
                if (text_length == 0)
                    text_length = (unsigned long)strlen(query_text);
        if(mysql_stmt_prepare(m_stmt, query_text, text_length)!=0)
            throw_exception();
    }
@@ -812,9 +837,8 @@
    template<typename Types>
    void execute(const Types& params)
    {
        execute_custom([&params](statement& stmt) {
            qtl::bind_params(stmt, params);
        });
                execute_custom([&params](statement &stmt)
                               { qtl::bind_params(stmt, params); });
    }
    template<typename Types>
@@ -826,7 +850,8 @@
            if(count>0)
            {
                m_result=mysql_stmt_result_metadata(m_stmt);
                if(m_result==nullptr) throw_exception();
                        if (m_result == nullptr)
                            throw_exception();
                resize_binders(count);
                qtl::bind_record(*this, std::forward<Types>(values));
                set_binders();
@@ -872,7 +897,8 @@
        do
        {
            ret=mysql_stmt_next_result(m_stmt);
            if(ret>0) throw_exception();
                    if (ret > 0)
                        throw_exception();
        }while(ret==0 && mysql_stmt_field_count(m_stmt)<=0);
        return ret==0;
    }
@@ -1058,7 +1084,8 @@
    bool open(const char *host, const char *user, const char *passwd, const char *db,
        unsigned long clientflag = 0, unsigned int port = 0, const char *unix_socket = nullptr)
    {
        if (m_mysql == nullptr) m_mysql = mysql_init(nullptr);
                if (m_mysql == nullptr)
                    m_mysql = mysql_init(nullptr);
        return mysql_real_connect(m_mysql, host, user, passwd, db, port, unix_socket, clientflag) != nullptr;
    }
    void close()
@@ -1098,14 +1125,17 @@
    {
        if (mysql_query(m_mysql, query_text) != 0)
            throw_exception();
        if (paffected) *paffected = affected_rows();
                if (paffected)
                    *paffected = affected_rows();
    }
    void simple_execute(const char* query_text, unsigned long text_length, uint64_t* paffected = nullptr)
    {
        if (text_length == 0) text_length = (unsigned long)strlen(query_text);
                if (text_length == 0)
                    text_length = (unsigned long)strlen(query_text);
        if (mysql_real_query(m_mysql, query_text, text_length) != 0)
            throw_exception();
        if (paffected) *paffected = affected_rows();
                if (paffected)
                    *paffected = affected_rows();
    }
    void auto_commit(bool on)
@@ -1183,7 +1213,6 @@
    async_connection async_mode();
#endif //MariaDB
};
#if MARIADB_VERSION_ID >= 100000
@@ -1246,19 +1275,20 @@
    template<typename Handler>
    void open(Handler&& handler, const char *query_text, size_t text_length=0)
    {
        if(text_length==0) text_length=strlen(query_text);
                if (text_length == 0)
                    text_length = strlen(query_text);
        if(m_stmt)
        {
            std::string text(query_text, text_length);
            reset([this, text, handler](const mysql::error& e) mutable {
                    reset([this, text, handler](const mysql::error &e) mutable
                          {
                if(e)
                {
                    handler(e);
                    return;
                }
                prepare(text.data(), text.size(), std::forward<Handler>(handler));
            });
                prepare(text.data(), text.size(), std::forward<Handler>(handler)); });
        }
        else
        {
@@ -1312,7 +1342,8 @@
            if(count>0)
            {
                m_result=mysql_stmt_result_metadata(m_stmt);
                if(m_result==nullptr) throw_exception();
                        if (m_result == nullptr)
                            throw_exception();
                resize_binders(count);
                qtl::bind_record(*this, std::forward<Types>(values));
                set_binders();
@@ -1362,13 +1393,13 @@
            int status = mysql_stmt_free_result_start(&ret, m_stmt);
            if(status)
            {
                this->wait_free_result(status, [this, handler](const mysql::error& e) mutable {
                        this->wait_free_result(status, [this, handler](const mysql::error &e) mutable
                                               {
                    m_result=nullptr;
                    if (e)
                        handler(e);
                    else
                        close(handler);
                });
                        close(handler); });
            }
            else if(ret)
                handler(mysql::error(*this));
@@ -1381,10 +1412,11 @@
            int status = mysql_stmt_close_start(&ret, m_stmt);
            if(status)
            {
                wait_operation<my_bool>(status, &mysql_stmt_close_cont, [this, handler](const mysql::error& e) mutable {
                        wait_operation<my_bool>(status, &mysql_stmt_close_cont, [this, handler](const mysql::error &e) mutable
                                                {
                    m_stmt=nullptr;
                    handler(e);
                });;
                    handler(e); });
                        ;
            }
            else
            {
@@ -1415,7 +1447,6 @@
        handler((ret) ? mysql::error(*this) : mysql::error());
    }
private:
    event* m_event;
@@ -1434,7 +1465,8 @@
    void wait_operation(int status, Func func, Handler&& handler)
    {
        m_event->set_io_handler(event_flags(status), mysql_get_timeout_value(m_stmt->mysql),
            [this, func, handler](int flags) mutable {
                                        [this, func, handler](int flags) mutable
                                        {
                Ret ret = 0;
                int status = func(&ret, m_stmt, mysql_status(flags));
                if (status)
@@ -1448,7 +1480,8 @@
    void wait_execute(int status, ExecuteHandler&& handler)
    {
        m_event->set_io_handler(event_flags(status), mysql_get_timeout_value(m_stmt->mysql),
            [this, handler](int flags) mutable {
                                        [this, handler](int flags) mutable
                                        {
                int ret = 0;
                int status = mysql_stmt_execute_cont(&ret, m_stmt, mysql_status(flags));
                if (status)
@@ -1464,7 +1497,8 @@
    void wait_fetch(int status, RowHandler&& row_handler, FinishHandler&& finish_handler)
    {
        m_event->set_io_handler(event_flags(status), mysql_get_timeout_value(m_stmt->mysql),
            [this, row_handler, finish_handler](int flags) mutable {
                                        [this, row_handler, finish_handler](int flags) mutable
                                        {
                int ret = 0;
                int status = mysql_stmt_fetch_cont(&ret, m_stmt, mysql_status(flags));
                if (status == 0)
@@ -1523,7 +1557,8 @@
    void wait_free_result(int status, ResultHandler&& handler) NOEXCEPT
    {
        m_event->set_io_handler(event_flags(status), mysql_get_timeout_value(m_stmt->mysql),
            [this, handler](int flags) mutable {
                                        [this, handler](int flags) mutable
                                        {
                my_bool ret = false;
                int status = mysql_stmt_free_result_cont(&ret, m_stmt, mysql_status(flags));
                if (status)
@@ -1537,7 +1572,8 @@
    void wait_next_result(int status, Handler&& handler)
    {
        m_event->set_io_handler(event_flags(status), mysql_get_timeout_value(m_stmt->mysql),
            [this, handler](int flags) mutable {
                                        [this, handler](int flags) mutable
                                        {
            int ret = 0;
            int status = mysql_stmt_next_result_cont(&ret, m_stmt, mysql_status(flags));
            if (status)
@@ -1550,7 +1586,6 @@
                next_result(std::forward<Handler>(handler));
        });
    }
};
class async_connection : public basic_database, public qtl::async_connection<async_connection, async_statement>
@@ -1590,10 +1625,10 @@
        int status  = mysql_close_start(m_mysql);
        if (status)
        {
            wait_close(status, [this, handler]() mutable {
                    wait_close(status, [this, handler]() mutable
                               {
                handler();
                m_mysql = nullptr;
            });
                m_mysql = nullptr; });
        }
        else
        {
@@ -1650,16 +1685,17 @@
        int status = mysql_query_start(&ret, m_mysql, query_text);
        if (status)
        {
            wait_operation(status, &mysql_query_cont, [this, handler](const mysql::error& e) {
                    wait_operation(status, &mysql_query_cont, [this, handler](const mysql::error &e)
                                   {
                uint64_t affected = 0;
                if (!e) affected = affected_rows();
                handler(e, affected);
            });
                handler(e, affected); });
        }
        else
        {
            uint64_t affected = 0;
            if (ret >= 0) affected = affected_rows();
                    if (ret >= 0)
                        affected = affected_rows();
            handler((ret) ? mysql::error(*this) : mysql::error(), affected);
        }
    }
@@ -1671,16 +1707,17 @@
        int status = mysql_real_query_start(&ret, m_mysql, query_text, text_length);
        if (status)
        {
            wait_operation(status, &mysql_real_query_cont, [this, handler](const mysql::error& e) mutable {
                    wait_operation(status, &mysql_real_query_cont, [this, handler](const mysql::error &e) mutable
                                   {
                uint64_t affected = 0;
                if (!e) affected = affected_rows();
                handler(e, affected);
            });
                handler(e, affected); });
        }
        else
        {
            uint64_t affected = 0;
            if (ret >= 0) affected = affected_rows();
                    if (ret >= 0)
                        affected = affected_rows();
            handler((ret) ? mysql::error(*this) : mysql::error(), affected);
        }
    }
@@ -1733,7 +1770,8 @@
    template<typename RowHandler, typename ResultHandler>
    void simple_query(const char* query, unsigned long length, RowHandler&& row_handler, ResultHandler&& result_handler) NOEXCEPT
    {
        simple_execute([this, row_handler, result_handler](const mysql::error& e, uint64_t affected) mutable {
                simple_execute([this, row_handler, result_handler](const mysql::error &e, uint64_t affected) mutable
                               {
            if (e)
            {
                result_handler(e, 0);
@@ -1755,17 +1793,15 @@
            else
            {
                result_handler(mysql::error(), 0);
            }
        }, query, length);
            } }, query, length);
    }
    template<typename Handler>
    void open_command(const char* query_text, size_t text_length, Handler&& handler)
    {
        std::shared_ptr<async_statement> stmt=std::make_shared<async_statement>(*this);
        stmt->open([stmt, handler](const mysql::error& e) mutable {
            handler(e, stmt);
        }, query_text, (unsigned long)text_length);
                stmt->open([stmt, handler](const mysql::error &e) mutable
                           { handler(e, stmt); }, query_text, (unsigned long)text_length);
    }
    socket_type socket() const NOEXCEPT { return mysql_get_socket(m_mysql); }
@@ -1775,7 +1811,8 @@
    void wait_connect(int status, OpenHandler&& handler) NOEXCEPT
    {
        m_event_handler->set_io_handler(event_flags(status), mysql_get_timeout_value(m_mysql),
            [this, handler](int flags) mutable {
                                                [this, handler](int flags) mutable
                                                {
            MYSQL* ret = nullptr;
            int status = mysql_real_connect_cont(&ret, m_mysql, mysql_status(flags));
            if (status)
@@ -1789,7 +1826,8 @@
    void wait_close(int status, CloseHandler&& handler) NOEXCEPT
    {
        m_event_handler->set_io_handler(event_flags(status), mysql_get_timeout_value(m_mysql),
            [this, handler](int flags) mutable {
                                                [this, handler](int flags) mutable
                                                {
            MYSQL* ret = nullptr;
            int status = mysql_close_cont(m_mysql, mysql_status(flags));
            if (status)
@@ -1803,7 +1841,8 @@
    void wait_operation(int status, Func func, Handler&& handler) NOEXCEPT
    {
        m_event_handler->set_io_handler(event_flags(status), mysql_get_timeout_value(m_mysql),
            [this, func, handler](int flags) mutable {
                                                [this, func, handler](int flags) mutable
                                                {
            int ret = 0;
            int status = func(&ret, m_mysql, mysql_status(flags));
            if (status)
@@ -1817,7 +1856,8 @@
    void wait_query(int status, int field_count, RowHandler&& row_handler, ResultHandler&& result_handler) NOEXCEPT
    {
        m_event_handler->set_io_handler(event_flags(status), mysql_get_timeout_value(m_mysql),
            [this, field_count, row_handler, result_handler](int flags) mutable {
                                                [this, field_count, row_handler, result_handler](int flags) mutable
                                                {
            MYSQL_RES* result = 0;
            int status = mysql_store_result_cont(&result, m_mysql, mysql_status(flags));
            if (status)
@@ -1856,7 +1896,8 @@
    void wait_fetch(int status, MYSQL_RES* result, int field_count,  size_t row_count, RowHandler&& row_handler, ResultHandler&& result_handler)
    {
        m_event_handler->set_io_handler(event_flags(status), mysql_get_timeout_value(m_mysql),
            [this, result, field_count, row_count, row_handler, result_handler](int flags) mutable {
                                                [this, result, field_count, row_count, row_handler, result_handler](int flags) mutable
                                                {
            MYSQL_ROW row;
            int status = mysql_fetch_row_cont(&row, result, mysql_status(flags));
            if (status)
@@ -1872,7 +1913,8 @@
    void wait_free_result(int status, MYSQL_RES* result, size_t row_count, ResultHandler&& handler) NOEXCEPT
    {
        m_event_handler->set_io_handler(event_flags(status), mysql_get_timeout_value(m_mysql),
            [this, result, row_count, handler](int flags) mutable {
                                                [this, result, row_count, handler](int flags) mutable
                                                {
            MYSQL* ret = nullptr;
            int status = mysql_free_result_cont(result, mysql_status(flags));
            if (status)
@@ -1881,7 +1923,6 @@
                handler(mysql::error(), row_count);
        });
    }
};
inline     async_statement::async_statement(async_connection& db) 
@@ -1912,14 +1953,16 @@
{
    const char* errmsg=stmt.errmsg();
    m_error=stmt.error();
    if(errmsg) m_errmsg=errmsg;
            if (errmsg)
                m_errmsg = errmsg;
}
inline error::error(const basic_database& db)
{
    const char* errmsg=db.errmsg();
    m_error=db.error();
    if(errmsg) m_errmsg=errmsg;
            if (errmsg)
                m_errmsg = errmsg;
}
inline base_statement::base_statement(basic_database& db)
include/qtl_mysql_pool.hpp
@@ -44,6 +44,7 @@
class async_pool : public qtl::async_pool<async_pool<EventLoop>, EventLoop, async_connection>
{
    typedef qtl::async_pool<async_pool<EventLoop>, EventLoop, async_connection> base_class;
public:
    async_pool(EventLoop& ev) : base_class(ev), m_port(0) { }
    virtual ~async_pool() { }
@@ -52,7 +53,8 @@
    void new_connection(EventLoop& ev, Handler&& handler) throw()
    {
        async_connection* db = new async_connection;
        db->open(ev, [this, handler, db](const mysql::error& e) mutable {
                db->open(ev, [this, handler, db](const mysql::error &e) mutable
                         {
            if (e)
            {
                delete db;
@@ -62,8 +64,7 @@
            {
                db->charset_name("utf8");
            }
            handler(e, db);
        }, m_host.data(), m_user.data(), m_password.data(), m_database.data(), 0, m_port);
            handler(e, db); }, m_host.data(), m_user.data(), m_password.data(), m_database.data(), 0, m_port);
    }
protected:
include/qtl_odbc.hpp
@@ -20,7 +20,6 @@
#define QTL_ODBC_ENABLE_ASYNC_MODE 1
#endif //ODBC 3.80 && Windows
#include "qtl_common.hpp"
#include "qtl_async.hpp"
@@ -30,7 +29,8 @@
namespace odbc
{
template<SQLSMALLINT> class object;
        template <SQLSMALLINT>
        class object;
class base_database;
class error : public std::exception
@@ -43,6 +43,7 @@
    SQLINTEGER code() const { return m_errno; }
    operator bool() const { return m_errno!=SQL_SUCCESS && m_errno!=SQL_SUCCESS_WITH_INFO; }
    virtual const char* what() const throw() override { return m_errmsg.data(); }
private:
    SQLINTEGER m_errno;
    std::string m_errmsg;
@@ -52,7 +53,10 @@
class object
{
public:
    enum { handler_type=Type };
            enum
            {
                handler_type = Type
            };
    object() : m_handle(SQL_NULL_HANDLE) { };
    object(const object&) = delete;
    object(object&& src) : m_handle(src.m_handle)
@@ -134,12 +138,12 @@
        SQLRETURN ret = SQLGetData(m_stmt->handle(), m_field + 1, SQL_C_BINARY, buffer, static_cast<SQLINTEGER>(count), const_cast<SQLLEN*>(&indicator));
        if (ret != SQL_NO_DATA)
        {
            count = (indicator > count) || (indicator == SQL_NO_TOTAL) ?
                count : indicator;
                    count = (indicator > count) || (indicator == SQL_NO_TOTAL) ? count : indicator;
            m_stmt->verify_error(ret);
            return true;
        }
        else return false;
                else
                    return false;
    }
    virtual void write_blob(const char* buffer, size_t count) override
@@ -294,14 +298,16 @@
    void bind_param(size_t index, const char* v, size_t n=SQL_NTS, SQLULEN size=0)
    {
        m_params[index].m_indicator=n;
        if(size==0) size=strlen(v);
                if (size == 0)
                    size = strlen(v);
        verify_error(SQLBindParameter(m_handle, static_cast<SQLUSMALLINT>(index+1), SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, 
            size, 0, (SQLPOINTER)v, 0, &m_params[index].m_indicator));
    }
    void bind_param(size_t index, const wchar_t* v, size_t n=SQL_NTS, SQLULEN size=0)
    {
        m_params[index].m_indicator=n;
        if(size==0) size=wcslen(v);
                if (size == 0)
                    size = wcslen(v);
        verify_error(SQLBindParameter(m_handle, static_cast<SQLUSMALLINT>(index+1), SQL_PARAM_INPUT, SQL_C_WCHAR, SQL_WCHAR, 
            size, 0, (SQLPOINTER)v, 0, &m_params[index].m_indicator));
    }
@@ -328,7 +334,8 @@
        m_params[index].m_indicator=SQL_LEN_DATA_AT_EXEC(m_params[index].m_size);
        verify_error(SQLBindParameter(m_handle, static_cast<SQLUSMALLINT>(index+1), SQL_PARAM_INPUT, SQL_C_BINARY, SQL_LONGVARBINARY, 
            INT_MAX, 0, &m_params[index], 0, &m_params[index].m_indicator));
        m_params[index].m_after_fetch=[this, &s](const param_data& p) {
                m_params[index].m_after_fetch = [this, &s](const param_data &p)
                {
            SQLLEN readed=SQL_NULL_DATA;
            while(!s.eof() && !s.fail())
            {
@@ -349,7 +356,8 @@
        m_params[index].m_indicator = SQL_LEN_DATA_AT_EXEC(m_params[index].m_size);
        verify_error(SQLBindParameter(m_handle, static_cast<SQLSMALLINT>(index + 1), SQL_PARAM_INPUT, SQL_C_BINARY, SQL_LONGVARBINARY,
            INT_MAX, 0, &m_params[index], 0, &m_params[index].m_indicator));
        m_params[index].m_after_fetch = [this, index, &param](const param_data& b) {
                m_params[index].m_after_fetch = [this, index, &param](const param_data &b)
                {
            blobbuf buf;
            buf.open(this, static_cast<SQLSMALLINT>(index), std::ios::out);
            std::ostream s(&buf);
@@ -425,7 +433,8 @@
    {
        m_params[index].m_data=v;
        m_params[index].m_size=n;
        m_params[index].m_after_fetch=[](const param_data& p) {
                m_params[index].m_after_fetch = [](const param_data &p)
                {
            if(p.m_indicator==SQL_NULL_DATA)
                memset(p.m_data, 0, p.m_size*sizeof(char));
            else
@@ -440,7 +449,8 @@
    {
        m_params[index].m_data=v;
        m_params[index].m_size=n;
        m_params[index].m_after_fetch=[](const param_data& p) {
                m_params[index].m_after_fetch = [](const param_data &p)
                {
            if(p.m_indicator==SQL_NULL_DATA)
                memset(p.m_data, 0, p.m_size*sizeof(wchar_t));
            else
@@ -458,7 +468,8 @@
        verify_error(SQLColAttribute(m_handle, static_cast<SQLUSMALLINT>(index+1), SQL_DESC_LENGTH, NULL, 0, NULL, &length));
        typename qtl::bind_string_helper<T>::char_type* data=v.alloc(length);
        bind_field(index, data, length+1);
        m_params[index].m_after_fetch=[v](const param_data& p) mutable {
                m_params[index].m_after_fetch = [v](const param_data &p) mutable
                {
            if(p.m_indicator==SQL_NULL_DATA)
                v.clear();
            else
@@ -485,12 +496,12 @@
            m_blob_buffer=malloc(blob_buffer_size);
        m_params[index].m_data=m_blob_buffer;
        m_params[index].m_size=blob_buffer_size;
        m_params[index].m_after_fetch=[this, index, &v](const param_data& p) {
                m_params[index].m_after_fetch = [this, index, &v](const param_data &p)
                {
            SQLRETURN ret=SQLGetData(m_handle, static_cast<SQLUSMALLINT>(index+1), SQL_C_BINARY, p.m_data, p.m_size, const_cast<SQLLEN*>(&p.m_indicator));
            while(ret!=SQL_NO_DATA)
            {
                size_t n = (p.m_indicator > blob_buffer_size) || (p.m_indicator == SQL_NO_TOTAL) ?
                    blob_buffer_size : p.m_indicator;
                        size_t n = (p.m_indicator > blob_buffer_size) || (p.m_indicator == SQL_NO_TOTAL) ? blob_buffer_size : p.m_indicator;
                verify_error(ret);
                v.write((const char*)p.m_data, n);
                ret=SQLGetData(m_handle, static_cast<SQLUSMALLINT>(index+1), SQL_C_BINARY, p.m_data, p.m_size, const_cast<SQLLEN*>(&p.m_indicator));
@@ -502,7 +513,8 @@
    {
        m_params[index].m_data = nullptr;
        m_params[index].m_size = 0;
        m_params[index].m_after_fetch = [this, index, &value](const param_data& p) {
                m_params[index].m_after_fetch = [this, index, &value](const param_data &p)
                {
            value.open(this, static_cast<SQLSMALLINT>(index), std::ios::in);
        };
    }
@@ -513,7 +525,8 @@
        qtl::bind_field(*this, index, value.data);
        param_data& param=m_params[index];
        auto fetch_fun=param.m_after_fetch;
        param.m_after_fetch=[fetch_fun, &value](const param_data& p) {
                param.m_after_fetch = [fetch_fun, &value](const param_data &p)
                {
            value.is_truncated=false;
            if(p.m_indicator==SQL_NULL_DATA)
            {
@@ -527,7 +540,8 @@
                if(p.m_size>0 && p.m_indicator>=p.m_size)
                    value.is_truncated=true;
            }
            if(fetch_fun) fetch_fun(p);
                    if (fetch_fun)
                        fetch_fun(p);
        };
    }
@@ -539,8 +553,10 @@
        qtl::bind_field(*this, index, *value);
        param_data& param = m_params[index];
        auto fetch_fun = param.m_after_fetch;
        param.m_after_fetch = [fetch_fun, &value](const param_data& p) {
            if (fetch_fun) fetch_fun(p);
                param.m_after_fetch = [fetch_fun, &value](const param_data &p)
                {
                    if (fetch_fun)
                        fetch_fun(p);
            if (p.m_indicator == SQL_NULL_DATA)
                value.reset();
        };
@@ -662,8 +678,10 @@
        }
        param_data& param = m_params[index];
        auto fetch_fun = param.m_after_fetch;
        param.m_after_fetch = [fetch_fun, &value](const param_data& p) {
            if (fetch_fun) fetch_fun(p);
                param.m_after_fetch = [fetch_fun, &value](const param_data &p)
                {
                    if (fetch_fun)
                        fetch_fun(p);
            if (p.m_indicator == SQL_NULL_DATA)
                value.reset();
        };
@@ -755,7 +773,6 @@
    {
        open(query_text.data(), query_text.size());
    }
    template<typename Types>
    void execute(const Types& params)
@@ -1035,7 +1052,8 @@
    void open(const char* server_name, size_t server_name_length,
        const char* user_name, size_t user_name_length, const char* password, size_t password_length)
    {
        if (m_opened) close();
                if (m_opened)
                    close();
        verify_error(SQLConnectA(m_handle, (SQLCHAR*)server_name, static_cast<SQLSMALLINT>(server_name_length), 
            (SQLCHAR*)user_name, static_cast<SQLSMALLINT>(user_name_length), (SQLCHAR*)password, static_cast<SQLSMALLINT>(password_length)));
        m_opened = true;
@@ -1052,7 +1070,8 @@
    {
        m_connection.resize(512);
        SQLSMALLINT out_len=0;
        if (m_opened) close();
                if (m_opened)
                    close();
        verify_error(SQLDriverConnectA(m_handle, hwnd, (SQLCHAR*)input_text, (SQLSMALLINT)text_length,
            (SQLCHAR*)m_connection.data(), (SQLSMALLINT)m_connection.size(), &out_len, driver_completion));
        m_connection.resize(out_len);
@@ -1074,7 +1093,8 @@
        SQLSMALLINT length = 0;
        SQLRETURN ret = SQL_SUCCESS;
        std::string input_text;
        if (m_opened) close();
                if (m_opened)
                    close();
        if (text_length == SQL_NTS)
            input_text = connection_text;
        else
@@ -1162,7 +1182,6 @@
    //async_connection async_mode();
#endif //ODBC 3.80
};
struct date : public SQL_DATE_STRUCT
@@ -1297,7 +1316,8 @@
    template<typename Handler>
    void open(Handler&& handler, const char *query_text, size_t text_length = 0)
    {
        if (text_length == 0) text_length = strlen(query_text);
                if (text_length == 0)
                    text_length = strlen(query_text);
        reset();
        SQLRETURN ret = SQLPrepareA(m_handle, (SQLCHAR*)query_text, text_length);
        async_wait(ret, std::forward<Handler>(handler));
@@ -1326,15 +1346,15 @@
        if (m_nQueryTimeout == 0)
            m_nQueryTimeout = query_timeout();
        ret = SQLExecute(m_handle);
        async_wait(ret, [this, count, handler](const error& e) mutable {
                async_wait(ret, [this, count, handler](const error &e) mutable
                           {
            SQLINTEGER ret = e.code();
            if (ret == SQL_NEED_DATA)
                async_param_data(0, count, std::forward<Handler>(handler));
            else if(ret>=0)
                handler(error(*this, ret), affetced_rows());
            else
                handler(error(*this, ret), 0);
        });
                handler(error(*this, ret), 0); });
    }
    template<typename Types, typename RowHandler, typename FinishHandler>
@@ -1363,7 +1383,8 @@
    void fetch(RowHandler&& row_handler, FinishHandler&& finish_handler)
    {
        SQLRETURN ret = SQLFetch(m_handle);
        async_wait(ret, [this, row_handler, finish_handler](const error& e) mutable {
                async_wait(ret, [this, row_handler, finish_handler](const error &e) mutable
                           {
            SQLINTEGER ret = e.code();
            if (ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO)
            {
@@ -1383,8 +1404,7 @@
                    finish_handler(error());
                else
                    finish_handler(e);
            }
        });
            } });
    }
    template<typename Handler>
@@ -1393,7 +1413,8 @@
        SQLRETURN ret;
        m_binded_cols = false;
        ret = SQLMoreResults(m_handle);
        async_wait(ret, [this, handler](const error& e) mutable {
                async_wait(ret, [this, handler](const error &e) mutable
                           {
            SQLINTEGER ret=e.code();
            SQLSMALLINT count = 0;
            if (ret == SQL_ERROR || ret == SQL_INVALID_HANDLE)
@@ -1412,8 +1433,7 @@
            if (count > 0)
                handler(error());
            else
                next_result(handler);
        });
                next_result(handler); });
    }
    HANDLE event_handle() const { return m_hCompleteEvent; }
@@ -1442,7 +1462,6 @@
    }
private:
    void close_event()
    {
        if (m_hCompleteEvent)
@@ -1463,7 +1482,8 @@
        if(is_still_executing(ret))
        {
            m_event->set_io_handler(0, m_nQueryTimeout,
                [this, handler](int flags) mutable {
                                            [this, handler](int flags) mutable
                                            {
                    RETCODE code;
                    SQLCompleteAsync(SQL_HANDLE_STMT, m_handle, &code);
                    if (SQL_SUCCEEDED(code))
@@ -1488,7 +1508,8 @@
    {
        SQLPOINTER token;
        SQLRETURN ret = SQLParamData(m_handle, &token);
        async_wait(ret, [this, index, count, token, handler](const error& e) mutable {
                async_wait(ret, [this, index, count, token, handler](const error &e) mutable
                           {
            SQLINTEGER ret = e.code();
            if (ret == SQL_NEED_DATA)
            {
@@ -1507,8 +1528,7 @@
            else
            {
                handler(error(*this, ret), affetced_rows());
            }
        });
            } });
    }
    int query_timeout() const
@@ -1537,8 +1557,7 @@
        }
        set_attribute(SQL_ATTR_ASYNC_DBC_EVENT, m_hCompleteEvent);
    }
    async_connection(async_connection&& src) :
        base_database(std::move(src)),
            async_connection(async_connection &&src) : base_database(std::move(src)),
        qtl::async_connection<async_connection, async_statement>(std::move(src)),
        m_BindFunc(std::move(src.m_BindFunc))
    {
@@ -1572,7 +1591,8 @@
    void open(EventLoop& ev, OpenHandler&& handler, const char* server_name, size_t server_name_length,
        const char* user_name, size_t user_name_length, const char* password, size_t password_length)
    {
        if (m_opened) close();
                if (m_opened)
                    close();
        SQLRETURN err = SQLConnectA(m_handle, (SQLCHAR*)server_name, static_cast<SQLSMALLINT>(server_name_length), 
            (SQLCHAR*)user_name, static_cast<SQLSMALLINT>(user_name_length), (SQLCHAR*)password, static_cast<SQLSMALLINT>(password_length));
        async_wait_connect(err, ev, std::forward<OpenHandler>(handler));
@@ -1580,7 +1600,8 @@
    template<class EventLoop, typename OpenHandler>
    void open(EventLoop& ev, OpenHandler&& handler, const char* server_name, const char* user_name, const char* password)
    {
        if (m_opened) close();
                if (m_opened)
                    close();
        SQLRETURN err = SQLConnectA(m_handle, (SQLCHAR*)server_name, SQL_NTS, (SQLCHAR*)user_name, SQL_NTS, (SQLCHAR*)password, SQL_NTS);
        async_wait_connect(err, ev, std::forward<OpenHandler>(handler));
    }
@@ -1619,10 +1640,10 @@
    {
        SQLRETURN ret = SQLDisconnect(m_handle);
        m_opened = false;
        async_wait(ret, [this, handler](const error& e) {
                async_wait(ret, [this, handler](const error &e)
                           {
            if (!e) m_opened = false;
            handler(e);
        });
            handler(e); });
    }
    /*
@@ -1646,9 +1667,8 @@
    void open_command(const char* query_text, size_t text_length, Handler&& handler)
    {
        std::shared_ptr<async_statement> stmt = std::make_shared<async_statement>(*this);
        stmt->open([stmt, handler](const odbc::error& e) mutable {
            handler(e, stmt);
        }, query_text, text_length);
                stmt->open([stmt, handler](const odbc::error &e) mutable
                           { handler(e, stmt); }, query_text, text_length);
    }
    HANDLE event_handle() const { return m_hCompleteEvent; }
@@ -1659,14 +1679,14 @@
    }
private:
    template<typename Handler>
    void async_wait(SQLRETURN ret, Handler&& handler) NOEXCEPT
    {
        if (is_still_executing(ret))
        {
            m_event_handler->set_io_handler(0, connect_timeout(),
                [this, handler](int flags) mutable {
                                                    [this, handler](int flags) mutable
                                                    {
                RETCODE code;
                SQLCompleteAsync(SQL_HANDLE_DBC, m_handle, &code);
                if (SQL_SUCCEEDED(code))
@@ -1690,15 +1710,16 @@
    void async_wait_connect(SQLRETURN err, EventLoop& ev, Handler&& handler)
    {
        bind(ev);
        m_BindFunc = [&ev](HANDLE hEvent) {
                m_BindFunc = [&ev](HANDLE hEvent)
                {
            return ev.add(hEvent);
        };
        if(is_still_executing(err))
        {
            async_wait(err, [this, handler](const error& e) mutable {
                    async_wait(err, [this, handler](const error &e) mutable
                               {
                if (!e) m_opened = true;
                handler(e);
            });
                handler(e); });
        }
        else
        {
@@ -1779,7 +1800,13 @@
inline void base_database::parse_browse_string(const char* output_text, size_t text_length, connection_parameters& parameters)
{
    enum { part_name, part_prompt, part_list, part_value };
            enum
            {
                part_name,
                part_prompt,
                part_list,
                part_value
            };
    const char* sp=output_text;
    const char* token=sp;
    connection_parameter parameter;
@@ -1810,7 +1837,8 @@
            part_type=part_list;
            parameter.m_value_list.clear();
            token=sp+1;
            break;;
                    break;
                    ;
        case '}':
        case ',':
            if(part_type==part_list)
@@ -1872,7 +1900,8 @@
        else
        {
            oss<<"UID="<<user<<";PWD=";
            if(password) oss<<password;
                    if (password)
                        oss << password;
            oss<<";Trusted_Connection=no;";
        }
        oss<<"DATABASE="<<db;
@@ -1898,13 +1927,13 @@
        else
        {
            oss << "UID=" << user << ";PWD=";
            if (password) oss << password;
                    if (password)
                        oss << password;
            oss << ";Trusted_Connection=no;";
        }
        oss << "DATABASE=" << db;
        odbc::async_connection::open(ev, handler, oss.str());
    }
};
#endif
@@ -1924,8 +1953,10 @@
    {
        std::ostringstream oss;
        oss<<"DRIVER={Microsoft Access Driver};DBQ="<<filename;
        if(user) oss<<";UID:"<<user;
        if(password) oss<<";PWD="<<password;
                if (user)
                    oss << ";UID:" << user;
                if (password)
                    oss << ";PWD=" << password;
        odbc::database::open(oss.str());
    }
};
include/qtl_odbc_pool.hpp
@@ -45,6 +45,7 @@
class async_pool : public qtl::async_pool<async_pool<EventLoop>, EventLoop, async_connection>
{
    typedef qtl::async_pool<async_pool<EventLoop>, EventLoop, async_connection> base_class;
public:
    async_pool(EventLoop& ev) : base_class(ev) { }
    virtual ~async_pool() { }
@@ -53,14 +54,14 @@
    void new_connection(EventLoop& ev, Handler&& handler) throw()
    {
        async_connection* db = new async_connection(env);
        db->open(ev, [this, handler, db](const mysql::error& e) mutable {
                db->open(ev, [this, handler, db](const mysql::error &e) mutable
                         {
            if (e)
            {
                delete db;
                db = nullptr;
            }
            handler(e, db);
        }, m_connection);
            handler(e, db); }, m_connection);
    }
protected:
include/qtl_postgres.hpp
@@ -31,7 +31,6 @@
#include <catalog/pg_type.h>
}
#ifdef open
#undef open
#endif //open
@@ -205,15 +204,19 @@
        //PQsetErrorVerbosity(conn, verbosity);
        //PQsetErrorContextVisibility(conn, show_context);
        const char* errmsg = PQerrorMessage(conn);
        if (errmsg) m_errmsg = errmsg;
        else m_errmsg.clear();
                if (errmsg)
                    m_errmsg = errmsg;
                else
                    m_errmsg.clear();
    }
    explicit error(PGresult* res)
    {
        const char* errmsg = PQresultErrorMessage(res);
        if (errmsg) m_errmsg = errmsg;
        else m_errmsg.clear();
                if (errmsg)
                    m_errmsg = errmsg;
                else
                    m_errmsg.clear();
    }
    explicit error(const char* errmsg) : m_errmsg(errmsg) { }
@@ -342,7 +345,6 @@
    result -= b;
    return result;
}
struct timestamptz
{
@@ -728,7 +730,10 @@
    }
protected:
    enum { default_buffer_size = 4096 };
            enum
            {
                default_buffer_size = 4096
            };
    virtual bool read_blob(char* buffer, off_type& count, pos_type position) override
    {
@@ -751,7 +756,8 @@
    int32_t ndim;
    int32_t flags;
    int32_t elemtype;
    struct dimension {
            struct dimension
            {
        int32_t length;
        int32_t lower_bound;
    } dims[1];
@@ -773,7 +779,10 @@
struct base_object_traits
{
    typedef T value_type;
    enum { type_id = id };
            enum
            {
                type_id = id
            };
    static bool is_match(Oid v)
    {
        return v == type_id;
@@ -784,14 +793,20 @@
struct object_traits;
#define QTL_POSTGRES_SIMPLE_TRAITS(T, oid, array_oid) \
template<> struct object_traits<T> : public base_object_traits<T, oid> { \
    enum { array_type_id = array_oid }; \
    template <>                                                                               \
    struct object_traits<T> : public base_object_traits<T, oid>                               \
    {                                                                                         \
        enum                                                                                  \
        {                                                                                     \
            array_type_id = array_oid                                                         \
        };                                                                                    \
    static const char* get(value_type& result, const char* data, const char* end) \
    { \
        result = *reinterpret_cast<const value_type*>(data); \
        return data+sizeof(value_type); \
    } \
    static std::pair<const char*, size_t> data(const T& v, std::vector<char>& /*data*/) { \
        static std::pair<const char *, size_t> data(const T &v, std::vector<char> & /*data*/) \
        {                                                                                     \
        return std::make_pair(reinterpret_cast<const char*>(&v), sizeof(T)); \
    } \
};
@@ -804,7 +819,10 @@
template<typename T, Oid id, Oid array_id>
struct integral_traits : public base_object_traits<T, id>
{
    enum { array_type_id  = array_id };
            enum
            {
                array_type_id = array_id
            };
    typedef typename base_object_traits<T, id>::value_type value_type;
    static const char* get(value_type& v, const char* data, const char* end)
    {
@@ -818,29 +836,37 @@
    }
};
template<> struct object_traits<int16_t> : public integral_traits<int16_t, INT2OID, INT2ARRAYOID>
        template <>
        struct object_traits<int16_t> : public integral_traits<int16_t, INT2OID, INT2ARRAYOID>
{
};
template<> struct object_traits<int32_t> : public integral_traits<int32_t, INT4OID, INT4ARRAYOID>
        template <>
        struct object_traits<int32_t> : public integral_traits<int32_t, INT4OID, INT4ARRAYOID>
{
};
template<> struct object_traits<int64_t> : public integral_traits<int64_t, INT8OID, 1016>
        template <>
        struct object_traits<int64_t> : public integral_traits<int64_t, INT8OID, 1016>
{
};
template<> struct object_traits<Oid> : public integral_traits<Oid, OIDOID, OIDARRAYOID>
        template <>
        struct object_traits<Oid> : public integral_traits<Oid, OIDOID, OIDARRAYOID>
{
};
template<typename T>
struct text_traits : public base_object_traits<T, TEXTOID>
{
    enum { array_type_id = TEXTARRAYOID };
            enum
            {
                array_type_id = TEXTARRAYOID
            };
};
template<> struct object_traits<const char*> : public text_traits<const char*>
        template <>
        struct object_traits<const char *> : public text_traits<const char *>
{
    static bool is_match(Oid v)
    {
@@ -857,11 +883,13 @@
    }
};
template<> struct object_traits<char*> : public object_traits<const char*>
        template <>
        struct object_traits<char *> : public object_traits<const char *>
{
};
template<> struct object_traits<std::string> : public text_traits<std::string>
        template <>
        struct object_traits<std::string> : public text_traits<std::string>
{
    static bool is_match(Oid v)
    {
@@ -878,9 +906,13 @@
    }
};
template<> struct object_traits<timestamp> : public base_object_traits<timestamp, TIMESTAMPOID>
        template <>
        struct object_traits<timestamp> : public base_object_traits<timestamp, TIMESTAMPOID>
{
    enum { array_type_id = TIMESTAMPOID+1 };
            enum
            {
                array_type_id = TIMESTAMPOID + 1
            };
    static const char* get(value_type& result, const char* data, const char* end)
    {
        result = *reinterpret_cast<const timestamp*>(data);
@@ -895,9 +927,13 @@
    }
};
template<> struct object_traits<timestamptz> : public base_object_traits<timestamptz, TIMESTAMPTZOID>
        template <>
        struct object_traits<timestamptz> : public base_object_traits<timestamptz, TIMESTAMPTZOID>
{
    enum { array_type_id = TIMESTAMPTZOID+1 };
            enum
            {
                array_type_id = TIMESTAMPTZOID + 1
            };
    static const char* get(value_type& result, const char* data, const char* end)
    {
        result = *reinterpret_cast<const timestamptz*>(data);
@@ -912,9 +948,13 @@
    }
};
template<> struct object_traits<interval> : public base_object_traits<interval, INTERVALOID>
        template <>
        struct object_traits<interval> : public base_object_traits<interval, INTERVALOID>
{
    enum { array_type_id = INTERVALOID+1 };
            enum
            {
                array_type_id = INTERVALOID + 1
            };
    static const char* get(value_type& result, const char* data, const char* end)
    {
        const ::interval* value = reinterpret_cast<const ::interval*>(data);
@@ -931,9 +971,13 @@
    }
};
template<> struct object_traits<date> : public base_object_traits<date, DATEOID>
        template <>
        struct object_traits<date> : public base_object_traits<date, DATEOID>
{
    enum { array_type_id = 1182 };
            enum
            {
                array_type_id = 1182
            };
    static const char* get(value_type& result, const char* data, const char* end)
    {
        result = *reinterpret_cast<const date*>(data);
@@ -951,10 +995,14 @@
template<typename T>
struct bytea_traits : public base_object_traits<T, BYTEAOID>
{
    enum { array_type_id = 1001 };
            enum
            {
                array_type_id = 1001
            };
};
template<> struct object_traits<qtl::const_blob_data> : public bytea_traits<qtl::const_blob_data>
        template <>
        struct object_traits<qtl::const_blob_data> : public bytea_traits<qtl::const_blob_data>
{
    static const char* get(value_type& result, const char* data, const char* end)
    {
@@ -969,7 +1017,8 @@
    }
};
template<> struct object_traits<qtl::blob_data> : public bytea_traits<qtl::blob_data>
        template <>
        struct object_traits<qtl::blob_data> : public bytea_traits<qtl::blob_data>
{
    static const char* get(qtl::blob_data& value, const char* data, const char* end)
    {
@@ -985,7 +1034,8 @@
    }
};
template<> struct object_traits<std::vector<uint8_t>> : public bytea_traits<std::vector<uint8_t>>
        template <>
        struct object_traits<std::vector<uint8_t>> : public bytea_traits<std::vector<uint8_t>>
{
    static const char* get(value_type& result, const char* data, const char* end)
    {
@@ -999,9 +1049,13 @@
    }
};
template<> struct object_traits<large_object> : public base_object_traits<large_object, OIDOID>
        template <>
        struct object_traits<large_object> : public base_object_traits<large_object, OIDOID>
{
    enum { array_type_id = OIDARRAYOID };
            enum
            {
                array_type_id = OIDARRAYOID
            };
    static value_type get(PGconn* conn, const char* data, const char* end)
    {
        int32_t oid;
@@ -1148,8 +1202,7 @@
};
template<typename Iterator>
struct object_traits<std::pair<typename std::enable_if<std::is_object<typename std::iterator_traits<Iterator>::value_type>::value, Iterator>::type, Iterator>> :
    public range_traits<Iterator, object_traits<typename std::iterator_traits<Iterator>::value_type>::array_type_id>
        struct object_traits<std::pair<typename std::enable_if<std::is_object<typename std::iterator_traits<Iterator>::value_type>::value, Iterator>::type, Iterator>> : public range_traits<Iterator, object_traits<typename std::iterator_traits<Iterator>::value_type>::array_type_id>
{
};
@@ -1179,11 +1232,13 @@
    }
};
template<typename T, size_t N> struct object_traits<T (&)[N]> : public carray_traits<T, N, object_traits<T>::array_type_id>
        template <typename T, size_t N>
        struct object_traits<T (&)[N]> : public carray_traits<T, N, object_traits<T>::array_type_id>
{
};
template<typename T, size_t N> struct object_traits<std::array<T, N>> : public array_traits<T, N, object_traits<T>::array_type_id>
        template <typename T, size_t N>
        struct object_traits<std::array<T, N>> : public array_traits<T, N, object_traits<T>::array_type_id>
{
};
@@ -1386,8 +1441,10 @@
    void bind(const char* data, size_t length=0)
    {
        m_value = data;
        if(length>0) m_length = length;
        else m_length = strlen(data);
                if (length > 0)
                    m_length = length;
                else
                    m_length = strlen(data);
    }
    template<typename T, size_t N>
    void bind(const T(&v)[N])
@@ -1572,6 +1629,7 @@
class base_statement
{
    friend class error;
public:
     explicit base_statement(base_database& db);
     ~base_statement()
@@ -1864,9 +1922,8 @@
    {
        auto binder_list = make_binder_list(Types()...);
        std::array<Oid, sizeof...(Types)> types;
        std::transform(binder_list.begin(), binder_list.end(), types.begin(), [](const binder& b) {
            return b.type();
        });
                std::transform(binder_list.begin(), binder_list.end(), types.begin(), [](const binder &b)
                               { return b.type(); });
        open(command, types.size(), types.data());
    }
@@ -2174,15 +2231,18 @@
    void simple_execute(const char* query_text, uint64_t* paffected = nullptr)
    {
        qtl::postgres::result res(PQexec(m_conn, query_text));
        if (!res) throw_exception();
                if (!res)
                    throw_exception();
        res.verify_error<PGRES_COMMAND_OK, PGRES_TUPLES_OK>();
        if (paffected) *paffected = res.affected_rows();
                if (paffected)
                    *paffected = res.affected_rows();
    }
    template<typename ValueProc>
    void simple_query(const char* query_text, ValueProc&& proc)
    {
        qtl::postgres::result res(PQexec(m_conn, query_text));
        if (!res) throw_exception();
                if (!res)
                    throw_exception();
        res.verify_error<PGRES_COMMAND_OK, PGRES_TUPLES_OK>();
        if (res.status() == PGRES_TUPLES_OK)
        {
@@ -2217,7 +2277,6 @@
        qtl::postgres::result res(PQexec(m_conn, ""));
        return res && res.status() == PGRES_COMMAND_OK;
    }
};
inline int event_flags(PostgresPollingStatusType status)
@@ -2246,7 +2305,8 @@
    if (flushed == 1)
    {
        event->set_io_handler(qtl::event::ef_read | qtl::event::ef_write, timeout,
            [event, conn, timeout, handler](int flags) mutable {
                                      [event, conn, timeout, handler](int flags) mutable
                                      {
            if (flags&qtl::event::ef_timeout)
            {
                handler(postgres::timeout());
@@ -2267,7 +2327,8 @@
    else
    {
        event->set_io_handler(qtl::event::ef_read, 10,
            [event, conn, timeout, handler](int flags) mutable {
                                      [event, conn, timeout, handler](int flags) mutable
                                      {
            if (flags&qtl::event::ef_timeout)
            {
                handler(postgres::timeout());
@@ -2334,7 +2395,8 @@
        std::transform(_name.begin(), _name.end(), _name.begin(), tolower);
        if (PQsendPrepare(m_conn, _name.data(), command, nParams, paramTypes))
        {
            async_wait([this, handler](error e) mutable {
                    async_wait([this, handler](error e) mutable
                               {
                if (!e)
                {
                    m_res = PQgetResult(m_conn);
@@ -2345,8 +2407,7 @@
                            m_res = PQgetResult(m_conn);
                    }
                }
                handler(e);
            });
                handler(e); });
        }
        else
        {
@@ -2360,9 +2421,8 @@
    {
        auto binder_list = make_binder_list(Types()...);
        std::array<Oid, sizeof...(Types)> types;
        std::transform(binder_list.begin(), binder_list.end(), types.begin(), [](const binder& b) {
            return b.type();
        });
                std::transform(binder_list.begin(), binder_list.end(), types.begin(), [](const binder &b)
                               { return b.type(); });
        open(std::forward<Handler>(handler), command, types.size(), types.data());
    }
@@ -2382,7 +2442,8 @@
            error e;
            res.verify_error<PGRES_COMMAND_OK, PGRES_TUPLES_OK>(e);
            finish(res);
            if(e) throw e;
                    if (e)
                        throw e;
        }
        base_statement::close();
    }
@@ -2394,9 +2455,8 @@
        {
            if(PQisBusy(m_conn))
            {
                async_wait([this, handler](const error& e) mutable {
                    close(handler);
                });
                        async_wait([this, handler](const error &e) mutable
                                   { close(handler); });
            }
            else
            {
@@ -2411,7 +2471,8 @@
            bool ok = PQsendQuery(m_conn, oss.str().data());
            if (ok)
            {
                async_wait([this, handler](postgres::error e) mutable {
                        async_wait([this, handler](postgres::error e) mutable
                                   {
                    if (PQstatus(m_conn) == CONNECTION_OK)
                    {
                        result res(PQgetResult(m_conn));
@@ -2425,8 +2486,7 @@
                    {
                        _name.clear();
                        handler(error());
                    }
                });
                    } });
            }
            else
            {
@@ -2449,15 +2509,15 @@
        if (PQsendQueryPrepared(m_conn, _name.data(), 0, nullptr, nullptr, nullptr, 1) &&
            PQsetSingleRowMode(m_conn))
        {
            async_wait([this, handler](error e) {
                    async_wait([this, handler](error e)
                               {
                if (!e)
                {
                    m_res = PQgetResult(m_conn);
                    m_res.verify_error<PGRES_COMMAND_OK, PGRES_SINGLE_TUPLE>(e);
                    finish(m_res);
                }
                handler(e);
            });
                handler(e); });
        }
        else
        {
@@ -2504,7 +2564,8 @@
        }
        if (PQisBusy(m_conn))
        {
            async_wait([this, handler](error e) mutable {
                    async_wait([this, handler](error e) mutable
                               {
                if (!e)
                {
                    m_res = PQgetResult(m_conn);
@@ -2516,8 +2577,7 @@
                else
                {
                    handler(e, 0);
                }
            });
                } });
        }
    }
@@ -2543,7 +2603,8 @@
                row_handler();
                if (PQisBusy(m_conn))
                {
                    async_wait([this, &values, row_handler, finish_handler](const error& e) {
                            async_wait([this, &values, row_handler, finish_handler](const error &e)
                                       {
                        if (e)
                        {
                            finish_handler(e);
@@ -2552,8 +2613,7 @@
                        {
                            m_res = PQgetResult(m_conn);
                            fetch(std::forward<Types>(values), row_handler, finish_handler);
                        }
                    });
                        } });
                }
                else
                {
@@ -2577,7 +2637,8 @@
    template<typename Handler>
    void next_result(Handler&& handler)
    {
        async_wait([this, handler](const error& e) {
                async_wait([this, handler](const error &e)
                           {
            if (e)
            {
                handler(e);
@@ -2586,8 +2647,7 @@
            {
                m_res = PQgetResult(m_conn);
                handler(error());
            }
        });
            } });
    }
private:
@@ -2690,14 +2750,14 @@
        bool ok = PQsendQuery(m_conn, query_text);
        if (ok)
        {
            async_wait([this, handler](postgres::error e) mutable {
                    async_wait([this, handler](postgres::error e) mutable
                               {
                result res(PQgetResult(m_conn));
                res.verify_error<PGRES_COMMAND_OK, PGRES_TUPLES_OK>(e);
                uint64_t affected = res.affected_rows();
                handler(e, affected);
                while (res)
                    res = PQgetResult(m_conn);
            });
                    res = PQgetResult(m_conn); });
        }
        else
        {
@@ -2740,7 +2800,8 @@
        bool ok = PQsendQuery(m_conn, query);
        if (ok)
        {
            async_wait([this, row_handler, result_handler](postgres::error e) mutable {
                    async_wait([this, row_handler, result_handler](postgres::error e) mutable
                               {
                result res(PQgetResult(m_conn));
                res.verify_error<PGRES_COMMAND_OK, PGRES_TUPLES_OK>(e);
                if (e)
@@ -2755,8 +2816,7 @@
                    stmt.fetch_all(row_handler);
                    res = PQgetResult(m_conn);
                }
                result_handler(e, affected);
            });
                result_handler(e, affected); });
        }
        else
        {
@@ -2768,9 +2828,8 @@
    void open_command(const char* query_text, size_t /*text_length*/, Handler&& handler)
    {
        std::shared_ptr<async_statement> stmt = std::make_shared<async_statement>(*this);
        stmt->open([stmt, handler](const postgres::error& e) mutable {
            handler(e, stmt);
        }, query_text, 0);
                stmt->open([stmt, handler](const postgres::error &e) mutable
                           { handler(e, stmt); }, query_text, 0);
    }
    template<typename Handler>
@@ -2815,7 +2874,8 @@
        case PGRES_POLLING_READING:
        case PGRES_POLLING_WRITING:
            m_event_handler->set_io_handler(event_flags(status), m_connect_timeout,
                [this, handler](int flags) mutable {
                                                    [this, handler](int flags) mutable
                                                    {
                if (flags&event::ef_timeout)
                {
                    handler(postgres::timeout());
@@ -2842,7 +2902,8 @@
        case PGRES_POLLING_READING:
        case PGRES_POLLING_WRITING:
            m_event_handler->set_io_handler(event_flags(status), m_connect_timeout,
                [this, handler](int flags) mutable {
                                                    [this, handler](int flags) mutable
                                                    {
                if (flags&event::ef_timeout)
                {
                    handler(postgres::timeout());
@@ -2864,7 +2925,6 @@
    {
        qtl::postgres::async_wait(event(), m_conn, m_query_timeout, std::forward<Handler>(handler));
    }
};
inline async_statement::async_statement(async_connection& db)
@@ -2873,7 +2933,6 @@
    m_event = db.event();
    m_timeout = db.query_timeout();
}
typedef qtl::transaction<database> transaction;
@@ -2893,6 +2952,4 @@
}
#endif //_SQL_POSTGRES_H_
include/qtl_postgres_pool.hpp
@@ -42,6 +42,7 @@
class async_pool : public qtl::async_pool<async_pool<EventLoop>, EventLoop, async_connection>
{
    typedef qtl::async_pool<async_pool<EventLoop>, EventLoop, async_connection> base_class;
public:
    async_pool(EventLoop& ev) : base_class(ev) { }
    virtual ~async_pool() { }
@@ -50,14 +51,14 @@
    void new_connection(EventLoop& ev, Handler&& handler) throw()
    {
        async_connection* db = new async_connection;
        db->open(ev, [this, handler, db](const postgres::error& e) mutable {
                db->open(ev, [this, handler, db](const postgres::error &e) mutable
                         {
            if (e)
            {
                delete db;
                db = nullptr;
            }
            handler(e, db);
        }, m_params);
            handler(e, db); }, m_params);
    }
protected:
include/qtl_sqlite.hpp
@@ -408,7 +408,8 @@
                m_fetch_result=SQLITE_OK;
            }
        }while(!m_tail_text.empty() && count==0);
        return count>0;;
                return count > 0;
                ;
    }
    int affetced_rows() const
@@ -430,7 +431,8 @@
    int m_fetch_result;
    void verify_error(int e)
    {
        if(e!=SQLITE_OK) throw error(e);
                if (e != SQLITE_OK)
                    throw error(e);
    }
};
@@ -614,7 +616,8 @@
        std::ios_base::openmode mode, const char* dbname="main")
    {
        int flags=0;
        if(mode&std::ios_base::out) flags=1;
                if (mode & std::ios_base::out)
                    flags = 1;
        if(sqlite3_blob_open(db.handle(), dbname, table, column, row, flags, &m_blob)==SQLITE_OK)
        {
            m_size=sqlite3_blob_bytes(m_blob)/sizeof(char);
@@ -661,7 +664,10 @@
    }
protected:
    enum { default_buffer_size = 4096 };
            enum
            {
                default_buffer_size = 4096
            };
    virtual pos_type seekoff( off_type off, std::ios_base::seekdir dir,
        std::ios_base::openmode which = std::ios_base::in | std::ios_base::out ) override
@@ -793,17 +799,13 @@
                eback()[intersection.first-m_inpos]=c;
            }
            m_outpos+=1;
        }
        return ch;
    }
    virtual int_type pbackfail( int_type c = traits_type::eof() ) override
    {
        if (gptr() == 0
            || gptr() <= eback()
            || (!traits_type::eq_int_type(traits_type::eof(), c)
            && !traits_type::eq(traits_type::to_char_type(c), gptr()[-1])))
                if (gptr() == 0 || gptr() <= eback() || (!traits_type::eq_int_type(traits_type::eof(), c) && !traits_type::eq(traits_type::to_char_type(c), gptr()[-1])))
        {
            return (traits_type::eof());    // can't put back, fail
        }
@@ -1097,7 +1099,6 @@
private:
    blobbuf m_buffer;
};
typedef qtl::transaction<database> transaction;
include/qtl_sqlite_pool.hpp
@@ -40,4 +40,3 @@
}
#endif //_QTL_SQLITE_POOL_H_