added data binding traits
This commit is contained in:
parent
8ad13076c8
commit
1c92e07173
|
|
@ -2,7 +2,9 @@
|
||||||
#define QUERY_OBJECT_BINDER_HPP
|
#define QUERY_OBJECT_BINDER_HPP
|
||||||
|
|
||||||
#include "matador/sql/parameter_binder.hpp"
|
#include "matador/sql/parameter_binder.hpp"
|
||||||
|
#include "matador/sql/types.hpp"
|
||||||
|
|
||||||
|
#include "matador/utils/access.hpp"
|
||||||
#include "matador/utils/cascade_type.hpp"
|
#include "matador/utils/cascade_type.hpp"
|
||||||
#include "matador/utils/field_attributes.hpp"
|
#include "matador/utils/field_attributes.hpp"
|
||||||
|
|
||||||
|
|
@ -10,37 +12,31 @@
|
||||||
|
|
||||||
namespace matador::sql {
|
namespace matador::sql {
|
||||||
|
|
||||||
class object_binder
|
namespace detail {
|
||||||
|
class fk_binder
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit object_binder(parameter_binder &binder);
|
explicit fk_binder(parameter_binder &binder);
|
||||||
|
|
||||||
void reset();
|
template<class Type>
|
||||||
|
void bind(Type &obj, size_t column_index)
|
||||||
template < class V >
|
|
||||||
void on_primary_key(const char *id, V &val, typename std::enable_if<std::is_integral<V>::value && !std::is_same<bool, V>::value>::type* = 0)
|
|
||||||
{
|
{
|
||||||
binder_.bind(index_++, val);
|
index_ = column_index;
|
||||||
}
|
utils::access::process(*this, obj);
|
||||||
void on_primary_key(const char *id, std::string &, size_t);
|
|
||||||
void on_revision(const char *id, unsigned long long &/*rev*/);
|
|
||||||
|
|
||||||
template<typename Type>
|
|
||||||
void on_attribute(const char *id, Type &val, const utils::field_attributes &/*attr*/ = utils::null_attributes)
|
|
||||||
{
|
|
||||||
binder_.bind(index_++, val);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Type, template < class ... > class Pointer>
|
template<typename ValueType>
|
||||||
void on_belongs_to(const char *id, Pointer<Type> &x, utils::cascade_type)
|
void on_primary_key(const char *id, ValueType &value, typename std::enable_if<std::is_integral<ValueType>::value && !std::is_same<bool, ValueType>::value>::type* = 0);
|
||||||
{
|
void on_primary_key(const char *id, std::string &value, size_t size);
|
||||||
// binder_.bind(index_++, val);
|
void on_revision(const char * /*id*/, unsigned long long &/*rev*/) {}
|
||||||
}
|
|
||||||
template<class Type, template < class ... > class Pointer>
|
template < class Type >
|
||||||
void on_has_one(const char *id, Pointer<Type> &x, utils::cascade_type)
|
void on_attribute(const char * /*id*/, Type &/*x*/, const utils::field_attributes &/*attr*/ = utils::null_attributes) {}
|
||||||
{
|
template < class Pointer >
|
||||||
// binder_.bind(index_++, val);
|
void on_belongs_to(const char * /*id*/, Pointer &/*x*/, utils::cascade_type) {}
|
||||||
}
|
template < class Pointer >
|
||||||
|
void on_has_one(const char * /*id*/, Pointer &/*x*/, utils::cascade_type) {}
|
||||||
|
|
||||||
template<class ContainerType>
|
template<class ContainerType>
|
||||||
void on_has_many(const char *, ContainerType &, const char *, const char *, utils::cascade_type) {}
|
void on_has_many(const char *, ContainerType &, const char *, const char *, utils::cascade_type) {}
|
||||||
template<class ContainerType>
|
template<class ContainerType>
|
||||||
|
|
@ -51,5 +47,58 @@ private:
|
||||||
size_t index_{0};
|
size_t index_{0};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class object_binder
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit object_binder(parameter_binder &binder);
|
||||||
|
|
||||||
|
void reset();
|
||||||
|
|
||||||
|
template < class Type >
|
||||||
|
void on_primary_key(const char *id, Type &val, typename std::enable_if<std::is_integral<Type>::value && !std::is_same<bool, Type>::value>::type* = 0)
|
||||||
|
{
|
||||||
|
data_type_traits<Type>::bind_value(binder_, index_++, val);
|
||||||
|
}
|
||||||
|
void on_primary_key(const char *id, std::string &, size_t size);
|
||||||
|
void on_revision(const char *id, unsigned long long &/*rev*/);
|
||||||
|
|
||||||
|
template<typename Type>
|
||||||
|
void on_attribute(const char *id, Type &val, const utils::field_attributes &/*attr*/ = utils::null_attributes)
|
||||||
|
{
|
||||||
|
data_type_traits<Type>::bind_value(binder_, index_++, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Type, template < class ... > class Pointer>
|
||||||
|
void on_belongs_to(const char *id, Pointer<Type> &x, utils::cascade_type)
|
||||||
|
{
|
||||||
|
fk_binder_.bind(index_++, x);
|
||||||
|
}
|
||||||
|
template<class Type, template < class ... > class Pointer>
|
||||||
|
void on_has_one(const char *id, Pointer<Type> &x, utils::cascade_type)
|
||||||
|
{
|
||||||
|
fk_binder_.bind(index_++, x);
|
||||||
|
}
|
||||||
|
template<class ContainerType>
|
||||||
|
void on_has_many(const char *, ContainerType &, const char *, const char *, utils::cascade_type) {}
|
||||||
|
template<class ContainerType>
|
||||||
|
void on_has_many(const char *, ContainerType &, utils::cascade_type) {}
|
||||||
|
|
||||||
|
private:
|
||||||
|
parameter_binder &binder_;
|
||||||
|
size_t index_{0};
|
||||||
|
detail::fk_binder fk_binder_;
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
template<typename ValueType>
|
||||||
|
void fk_binder::on_primary_key(const char *id, ValueType &value, typename std::enable_if<std::is_integral<ValueType>::value && !std::is_same<bool, ValueType>::value>::type *)
|
||||||
|
{
|
||||||
|
data_type_traits<ValueType>::bind_value(binder_, index_++, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif //QUERY_OBJECT_BINDER_HPP
|
#endif //QUERY_OBJECT_BINDER_HPP
|
||||||
|
|
|
||||||
|
|
@ -123,7 +123,7 @@ namespace detail {
|
||||||
template<typename ValueType>
|
template<typename ValueType>
|
||||||
void detail::pk_reader::on_primary_key(const char *id, ValueType &value, typename std::enable_if<std::is_integral<ValueType>::value && !std::is_same<bool, ValueType>::value>::type *)
|
void detail::pk_reader::on_primary_key(const char *id, ValueType &value, typename std::enable_if<std::is_integral<ValueType>::value && !std::is_same<bool, ValueType>::value>::type *)
|
||||||
{
|
{
|
||||||
reader_.read_value(id, column_index_++, value);
|
data_type_traits<ValueType>::read_value(reader_, id, column_index_++, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,8 @@ public:
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
statement& bind(size_t pos, const char *value);
|
||||||
|
|
||||||
statement& bind(size_t pos, std::string &val, size_t size);
|
statement& bind(size_t pos, std::string &val, size_t size);
|
||||||
|
|
||||||
template < class Type >
|
template < class Type >
|
||||||
|
|
|
||||||
|
|
@ -14,14 +14,15 @@ class connection;
|
||||||
|
|
||||||
struct cache_info
|
struct cache_info
|
||||||
{
|
{
|
||||||
std::unique_ptr<statement> statement_;
|
statement statement_;
|
||||||
|
// std::unique_ptr<statement> statement_;
|
||||||
size_t connection_id_;
|
size_t connection_id_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class statement_cache
|
class statement_cache
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
statement& acquire(const std::string &stmt, const connection &conn);
|
statement& acquire(query_context &&context, const connection &conn);
|
||||||
void release(const statement &stmt);
|
void release(const statement &stmt);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
#include "matador/sql/query_context.hpp"
|
#include "matador/sql/query_context.hpp"
|
||||||
#include "matador/sql/query_result_impl.hpp"
|
#include "matador/sql/query_result_impl.hpp"
|
||||||
#include "matador/sql/parameter_binder.hpp"
|
#include "matador/sql/parameter_binder.hpp"
|
||||||
|
#include "matador/sql/types.hpp"
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
|
|
@ -20,15 +21,20 @@ public:
|
||||||
virtual size_t execute() = 0;
|
virtual size_t execute() = 0;
|
||||||
virtual std::unique_ptr<query_result_impl> fetch() = 0;
|
virtual std::unique_ptr<query_result_impl> fetch() = 0;
|
||||||
|
|
||||||
template < class V >
|
template < class Type >
|
||||||
void bind(size_t pos, V &val)
|
void bind(size_t pos, Type &val)
|
||||||
{
|
{
|
||||||
binder().bind(pos, val);
|
data_type_traits<Type>::bind_value(binder(), pos, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
void bind(size_t pos, const char *value, size_t size)
|
||||||
|
{
|
||||||
|
data_type_traits<const char*>::bind_value(binder(), pos, value, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void bind(size_t pos, std::string &val, size_t size)
|
void bind(size_t pos, std::string &val, size_t size)
|
||||||
{
|
{
|
||||||
binder().bind(pos, val, size);
|
data_type_traits<std::string>::bind_value(binder(), pos, val, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void reset() = 0;
|
virtual void reset() = 0;
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,15 @@
|
||||||
#ifndef QUERY_TYPES_HPP
|
#ifndef QUERY_TYPES_HPP
|
||||||
#define QUERY_TYPES_HPP
|
#define QUERY_TYPES_HPP
|
||||||
|
|
||||||
|
#include "matador/sql/any_type.hpp"
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace matador::sql {
|
namespace matador::sql {
|
||||||
|
|
||||||
class query_result_reader;
|
class query_result_reader;
|
||||||
|
class parameter_binder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Enumeration type of all supported builtin data types
|
* @brief Enumeration type of all supported builtin data types
|
||||||
|
|
@ -34,26 +37,6 @@ enum class data_type_t : uint8_t {
|
||||||
type_null, /*!< Data type null */
|
type_null, /*!< Data type null */
|
||||||
type_unknown /*!< Data type unknown */
|
type_unknown /*!< Data type unknown */
|
||||||
};
|
};
|
||||||
/**
|
|
||||||
* @brief Enumeration of database data types
|
|
||||||
*/
|
|
||||||
enum struct database_type_t : uint8_t {
|
|
||||||
type_char = 0, /*!< Data type char */
|
|
||||||
type_float, /*!< Data type float */
|
|
||||||
type_double, /*!< Data type double */
|
|
||||||
type_smallint, /*!< Data type small int */
|
|
||||||
type_int, /*!< Data type integer */
|
|
||||||
type_bigint, /*!< Data type big integer */
|
|
||||||
type_bool, /*!< Data type bool */
|
|
||||||
type_char_pointer, /*!< Data type character pointer */
|
|
||||||
type_varchar, /*!< Data type varchar */
|
|
||||||
type_text, /*!< Data type text */
|
|
||||||
type_date, /*!< Data type date */
|
|
||||||
type_time, /*!< Data type time */
|
|
||||||
type_blob, /*!< Data type blob */
|
|
||||||
type_null, /*!< Data type null */
|
|
||||||
type_unknown /*!< Data type unknown */
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class sql_function_t {
|
enum class sql_function_t {
|
||||||
NONE,
|
NONE,
|
||||||
|
|
@ -79,146 +62,130 @@ struct data_type_traits;
|
||||||
/// @cond MATADOR_DEV
|
/// @cond MATADOR_DEV
|
||||||
template <> struct data_type_traits<char, void>
|
template <> struct data_type_traits<char, void>
|
||||||
{
|
{
|
||||||
// inline static database_type_t type(std::size_t /*size*/) { return database_type_t::type_char; }
|
|
||||||
inline static data_type_t builtin_type(std::size_t /*size*/) { return data_type_t::type_char; }
|
inline static data_type_t builtin_type(std::size_t /*size*/) { return data_type_t::type_char; }
|
||||||
static void read_value(query_result_reader &reader, const char *id, size_t index, char &value);
|
static void read_value(query_result_reader &reader, const char *id, size_t index, char &value);
|
||||||
// inline static unsigned long size() { return sizeof(char); }
|
static void bind_value(parameter_binder &binder, size_t index, char &value);
|
||||||
// inline static const char* name() { return "char"; }
|
inline static any_type create_value(char &value) { return value; }
|
||||||
};
|
};
|
||||||
|
|
||||||
template <> struct data_type_traits<short, void>
|
template <> struct data_type_traits<short, void>
|
||||||
{
|
{
|
||||||
// inline static database_type_t type(std::size_t /*size*/) { return database_type_t::type_smallint; }
|
|
||||||
inline static data_type_t builtin_type(std::size_t /*size*/) { return data_type_t::type_short; }
|
inline static data_type_t builtin_type(std::size_t /*size*/) { return data_type_t::type_short; }
|
||||||
static void read_value(query_result_reader &reader, const char *id, size_t index, short &value);
|
static void read_value(query_result_reader &reader, const char *id, size_t index, short &value);
|
||||||
// inline static unsigned long size() { return sizeof(short); }
|
static void bind_value(parameter_binder &binder, size_t index, short &value);
|
||||||
// inline static const char* name() { return "short"; }
|
inline static any_type create_value(short &value) { return value; }
|
||||||
};
|
};
|
||||||
|
|
||||||
template <> struct data_type_traits<int, void>
|
template <> struct data_type_traits<int, void>
|
||||||
{
|
{
|
||||||
// inline static database_type_t type(std::size_t /*size*/) { return database_type_t::type_int; }
|
|
||||||
inline static data_type_t builtin_type(std::size_t /*size*/) { return data_type_t::type_int; }
|
inline static data_type_t builtin_type(std::size_t /*size*/) { return data_type_t::type_int; }
|
||||||
static void read_value(query_result_reader &reader, const char *id, size_t index, int &value);
|
static void read_value(query_result_reader &reader, const char *id, size_t index, int &value);
|
||||||
// inline static unsigned long size() { return sizeof(int); }
|
static void bind_value(parameter_binder &binder, size_t index, int &value);
|
||||||
// inline static const char* name() { return "int"; }
|
inline static any_type create_value(int &value) { return value; }
|
||||||
};
|
};
|
||||||
|
|
||||||
template <> struct data_type_traits<long, void>
|
template <> struct data_type_traits<long, void>
|
||||||
{
|
{
|
||||||
// inline static database_type_t type(std::size_t /*size*/) { return database_type_t::type_bigint; }
|
|
||||||
inline static data_type_t builtin_type(std::size_t /*size*/) { return data_type_t::type_long; }
|
inline static data_type_t builtin_type(std::size_t /*size*/) { return data_type_t::type_long; }
|
||||||
static void read_value(query_result_reader &reader, const char *id, size_t index, long &value);
|
static void read_value(query_result_reader &reader, const char *id, size_t index, long &value);
|
||||||
// inline static unsigned long size() { return sizeof(long); }
|
static void bind_value(parameter_binder &binder, size_t index, long &value);
|
||||||
// inline static const char* name() { return "long"; }
|
inline static any_type create_value(long &value) { return value; }
|
||||||
};
|
};
|
||||||
|
|
||||||
template <> struct data_type_traits<long long, void>
|
template <> struct data_type_traits<long long, void>
|
||||||
{
|
{
|
||||||
// inline static database_type_t type(std::size_t /*size*/) { return database_type_t::type_bigint; }
|
|
||||||
inline static data_type_t builtin_type(std::size_t /*size*/) { return data_type_t::type_long_long; }
|
inline static data_type_t builtin_type(std::size_t /*size*/) { return data_type_t::type_long_long; }
|
||||||
static void read_value(query_result_reader &reader, const char *id, size_t index, long long &value);
|
static void read_value(query_result_reader &reader, const char *id, size_t index, long long &value);
|
||||||
// inline static unsigned long size() { return sizeof(long long); }
|
static void bind_value(parameter_binder &binder, size_t index, long long &value);
|
||||||
// inline static const char* name() { return "long long"; }
|
inline static any_type create_value(long long &value) { return value; }
|
||||||
};
|
};
|
||||||
|
|
||||||
template <> struct data_type_traits<unsigned char, void>
|
template <> struct data_type_traits<unsigned char, void>
|
||||||
{
|
{
|
||||||
// inline static database_type_t type(std::size_t /*size*/) { return database_type_t::type_char; }
|
|
||||||
inline static data_type_t builtin_type(std::size_t /*size*/) { return data_type_t::type_unsigned_char; }
|
inline static data_type_t builtin_type(std::size_t /*size*/) { return data_type_t::type_unsigned_char; }
|
||||||
static void read_value(query_result_reader &reader, const char *id, size_t index, unsigned char &value);
|
static void read_value(query_result_reader &reader, const char *id, size_t index, unsigned char &value);
|
||||||
// inline static unsigned long size() { return sizeof(unsigned char); }
|
static void bind_value(parameter_binder &binder, size_t index, unsigned char &value);
|
||||||
// inline static const char* name() { return "unsigned char"; }
|
inline static any_type create_value(unsigned char &value) { return value; }
|
||||||
};
|
};
|
||||||
|
|
||||||
template <> struct data_type_traits<unsigned short, void>
|
template <> struct data_type_traits<unsigned short, void>
|
||||||
{
|
{
|
||||||
// inline static database_type_t type(std::size_t /*size*/) { return database_type_t::type_smallint; }
|
|
||||||
inline static data_type_t builtin_type(std::size_t /*size*/) { return data_type_t::type_unsigned_short; }
|
inline static data_type_t builtin_type(std::size_t /*size*/) { return data_type_t::type_unsigned_short; }
|
||||||
static void read_value(query_result_reader &reader, const char *id, size_t index, unsigned short &value);
|
static void read_value(query_result_reader &reader, const char *id, size_t index, unsigned short &value);
|
||||||
// inline static unsigned long size() { return sizeof(unsigned short); }
|
static void bind_value(parameter_binder &binder, size_t index, unsigned short &value);
|
||||||
// inline static const char* name() { return "unsigned short"; }
|
inline static any_type create_value(unsigned short &value) { return value; }
|
||||||
};
|
};
|
||||||
|
|
||||||
template <> struct data_type_traits<unsigned int, void>
|
template <> struct data_type_traits<unsigned int, void>
|
||||||
{
|
{
|
||||||
// inline static database_type_t type(std::size_t /*size*/) { return database_type_t::type_int; }
|
|
||||||
inline static data_type_t builtin_type(std::size_t /*size*/) { return data_type_t::type_unsigned_int; }
|
inline static data_type_t builtin_type(std::size_t /*size*/) { return data_type_t::type_unsigned_int; }
|
||||||
static void read_value(query_result_reader &reader, const char *id, size_t index, unsigned int &value);
|
static void read_value(query_result_reader &reader, const char *id, size_t index, unsigned int &value);
|
||||||
// inline static unsigned long size() { return sizeof(unsigned int); }
|
static void bind_value(parameter_binder &binder, size_t index, unsigned int &value);
|
||||||
// inline static const char* name() { return "unsigned int"; }
|
inline static any_type create_value(unsigned int &value) { return value; }
|
||||||
};
|
};
|
||||||
|
|
||||||
template <> struct data_type_traits<unsigned long, void>
|
template <> struct data_type_traits<unsigned long, void>
|
||||||
{
|
{
|
||||||
// inline static database_type_t type(std::size_t /*size*/ = 0) { return database_type_t::type_bigint; }
|
|
||||||
inline static data_type_t builtin_type(std::size_t /*size*/ = 0) { return data_type_t::type_unsigned_long; }
|
inline static data_type_t builtin_type(std::size_t /*size*/ = 0) { return data_type_t::type_unsigned_long; }
|
||||||
static void read_value(query_result_reader &reader, const char *id, size_t index, unsigned long &value);
|
static void read_value(query_result_reader &reader, const char *id, size_t index, unsigned long &value);
|
||||||
// inline static unsigned long size() { return sizeof(unsigned long); }
|
static void bind_value(parameter_binder &binder, size_t index, unsigned long &value);
|
||||||
// inline static const char* name() { return "unsigned long"; }
|
inline static any_type create_value(unsigned long &value) { return value; }
|
||||||
};
|
};
|
||||||
|
|
||||||
template <> struct data_type_traits<unsigned long long, void>
|
template <> struct data_type_traits<unsigned long long, void>
|
||||||
{
|
{
|
||||||
// inline static database_type_t type(std::size_t /*size*/) { return database_type_t::type_bigint; }
|
|
||||||
inline static data_type_t builtin_type(std::size_t /*size*/) { return data_type_t::type_unsigned_long_long; }
|
inline static data_type_t builtin_type(std::size_t /*size*/) { return data_type_t::type_unsigned_long_long; }
|
||||||
static void read_value(query_result_reader &reader, const char *id, size_t index, unsigned long long &value);
|
static void read_value(query_result_reader &reader, const char *id, size_t index, unsigned long long &value);
|
||||||
// inline static unsigned long size() { return sizeof(unsigned long long); }
|
static void bind_value(parameter_binder &binder, size_t index, unsigned long long &value);
|
||||||
// inline static const char* name() { return "unsigned long long"; }
|
inline static any_type create_value(unsigned long long &value) { return value; }
|
||||||
};
|
};
|
||||||
|
|
||||||
template <> struct data_type_traits<bool, void>
|
template <> struct data_type_traits<bool, void>
|
||||||
{
|
{
|
||||||
// inline static database_type_t type(std::size_t /*size*/) { return database_type_t::type_bool; }
|
|
||||||
inline static data_type_t builtin_type(std::size_t /*size*/) { return data_type_t::type_bool; }
|
inline static data_type_t builtin_type(std::size_t /*size*/) { return data_type_t::type_bool; }
|
||||||
static void read_value(query_result_reader &reader, const char *id, size_t index, bool &value);
|
static void read_value(query_result_reader &reader, const char *id, size_t index, bool &value);
|
||||||
// inline static unsigned long size() { return sizeof(bool); }
|
static void bind_value(parameter_binder &binder, size_t index, bool &value);
|
||||||
// inline static const char* name() { return "bool"; }
|
inline static any_type create_value(bool &value) { return value; }
|
||||||
};
|
};
|
||||||
|
|
||||||
template <> struct data_type_traits<float, void>
|
template <> struct data_type_traits<float, void>
|
||||||
{
|
{
|
||||||
// inline static database_type_t type(std::size_t /*size*/) { return database_type_t::type_float; }
|
|
||||||
inline static data_type_t builtin_type(std::size_t /*size*/) { return data_type_t::type_float; }
|
inline static data_type_t builtin_type(std::size_t /*size*/) { return data_type_t::type_float; }
|
||||||
static void read_value(query_result_reader &reader, const char *id, size_t index, float &value);
|
static void read_value(query_result_reader &reader, const char *id, size_t index, float &value);
|
||||||
// inline static unsigned long size() { return sizeof(float); }
|
static void bind_value(parameter_binder &binder, size_t index, float &value);
|
||||||
// inline static const char* name() { return "float"; }
|
inline static any_type create_value(float &value) { return value; }
|
||||||
};
|
};
|
||||||
|
|
||||||
template <> struct data_type_traits<double, void>
|
template <> struct data_type_traits<double, void>
|
||||||
{
|
{
|
||||||
// inline static database_type_t type(std::size_t /*size*/) { return database_type_t::type_double; }
|
|
||||||
inline static data_type_t builtin_type(std::size_t /*size*/) { return data_type_t::type_double; }
|
inline static data_type_t builtin_type(std::size_t /*size*/) { return data_type_t::type_double; }
|
||||||
static void read_value(query_result_reader &reader, const char *id, size_t index, double &value);
|
static void read_value(query_result_reader &reader, const char *id, size_t index, double &value);
|
||||||
// inline static unsigned long size() { return sizeof(double); }
|
static void bind_value(parameter_binder &binder, size_t index, double &value);
|
||||||
// inline static const char* name() { return "double"; }
|
inline static any_type create_value(double &value) { return value; }
|
||||||
};
|
};
|
||||||
|
|
||||||
template <> struct data_type_traits<const char*, void>
|
template <> struct data_type_traits<const char*, void>
|
||||||
{
|
{
|
||||||
// inline static database_type_t type(std::size_t size) { return size == 0 ? database_type_t::type_text : database_type_t::type_varchar; }
|
|
||||||
inline static data_type_t builtin_type(std::size_t size) { return size == 0 ? data_type_t::type_text : data_type_t::type_char_pointer; }
|
inline static data_type_t builtin_type(std::size_t size) { return size == 0 ? data_type_t::type_text : data_type_t::type_char_pointer; }
|
||||||
static void read_value(query_result_reader &reader, const char *id, size_t index, const char* value, size_t size);
|
static void read_value(query_result_reader &reader, const char *id, size_t index, const char* value, size_t size);
|
||||||
// inline static unsigned long size() { return sizeof(const char*); }
|
static void bind_value(parameter_binder &binder, size_t index, const char *value, size_t size = 0);
|
||||||
// inline static const char* name() { return "const char*"; }
|
inline static any_type create_value(const char *value) { return value; }
|
||||||
};
|
};
|
||||||
|
|
||||||
template <> struct data_type_traits<char*, void>
|
template <> struct data_type_traits<char*, void>
|
||||||
{
|
{
|
||||||
// inline static database_type_t type(std::size_t size) { return size == 0 ? database_type_t::type_text : database_type_t::type_varchar; }
|
|
||||||
inline static data_type_t builtin_type(std::size_t size) { return size == 0 ? data_type_t::type_text : data_type_t::type_varchar; }
|
inline static data_type_t builtin_type(std::size_t size) { return size == 0 ? data_type_t::type_text : data_type_t::type_varchar; }
|
||||||
static void read_value(query_result_reader &reader, const char *id, size_t index, char *value, size_t size);
|
static void read_value(query_result_reader &reader, const char *id, size_t index, char *value, size_t size);
|
||||||
// inline static unsigned long size() { return sizeof(char*); }
|
static void bind_value(parameter_binder &binder, size_t index, char *value, size_t size = 0);
|
||||||
// inline static const char* name() { return "char*"; }
|
inline static any_type create_value(const char *value) { return value; }
|
||||||
};
|
};
|
||||||
|
|
||||||
template <> struct data_type_traits<std::string, void>
|
template <> struct data_type_traits<std::string, void>
|
||||||
{
|
{
|
||||||
// inline static database_type_t type(std::size_t size) { return size == 0 ? database_type_t::type_text : database_type_t::type_varchar; }
|
|
||||||
inline static data_type_t builtin_type(std::size_t size) { return size == 0 ? data_type_t::type_text : data_type_t::type_varchar; }
|
inline static data_type_t builtin_type(std::size_t size) { return size == 0 ? data_type_t::type_text : data_type_t::type_varchar; }
|
||||||
static void read_value(query_result_reader &reader, const char *id, size_t index, std::string &value, size_t size);
|
static void read_value(query_result_reader &reader, const char *id, size_t index, std::string &value, size_t size);
|
||||||
// inline static unsigned long size() { return 1023; }
|
static void bind_value(parameter_binder &binder, size_t index, std::string &value, size_t size = 0);
|
||||||
// inline static const char* name() { return "std::string"; }
|
inline static any_type create_value(std::string &value) { return value; }
|
||||||
};
|
};
|
||||||
|
|
||||||
//template <> struct data_type_traits<matador::date>
|
//template <> struct data_type_traits<matador::date>
|
||||||
|
|
@ -240,14 +207,16 @@ template <> struct data_type_traits<std::string, void>
|
||||||
template < typename EnumType >
|
template < typename EnumType >
|
||||||
struct data_type_traits<EnumType, typename std::enable_if<std::is_enum<EnumType>::value>::type>
|
struct data_type_traits<EnumType, typename std::enable_if<std::is_enum<EnumType>::value>::type>
|
||||||
{
|
{
|
||||||
// inline static database_type_t type(std::size_t /*size*/) { return database_type_t::type_int; }
|
|
||||||
inline static data_type_t builtin_type(std::size_t /*size*/) { return data_type_t::type_int; }
|
inline static data_type_t builtin_type(std::size_t /*size*/) { return data_type_t::type_int; }
|
||||||
static void read_value(query_result_reader &reader, const char *id, size_t index, EnumType &value)
|
static void read_value(query_result_reader &reader, const char *id, size_t index, EnumType &value)
|
||||||
{
|
{
|
||||||
data_type_traits<int>::read_value(reader, id, index, reinterpret_cast<int&>(value));
|
data_type_traits<int>::read_value(reader, id, index, reinterpret_cast<int&>(value));
|
||||||
}
|
}
|
||||||
// inline static unsigned long size() { return sizeof(int); }
|
static void bind_value(parameter_binder &binder, size_t index, EnumType &value)
|
||||||
// inline static const char* name() { return "int"; }
|
{
|
||||||
|
data_type_traits<int>::bind_value(binder, index, (int&)value);
|
||||||
|
}
|
||||||
|
inline static any_type create_value(EnumType &value) { return (int)value; }
|
||||||
};
|
};
|
||||||
/// @endcond
|
/// @endcond
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
#define QUERY_VALUE_EXTRACTOR_HPP
|
#define QUERY_VALUE_EXTRACTOR_HPP
|
||||||
|
|
||||||
#include "matador/sql/fk_value_extractor.hpp"
|
#include "matador/sql/fk_value_extractor.hpp"
|
||||||
|
#include "matador/sql/types.hpp"
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
|
@ -56,14 +57,9 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template<typename Type>
|
template<typename Type>
|
||||||
void append(Type &value, typename std::enable_if<!std::is_enum<Type>::value>::type* = 0)
|
void append(Type &value)
|
||||||
{
|
{
|
||||||
values_.emplace_back(value);
|
values_.emplace_back(data_type_traits<Type>::create_value(value));
|
||||||
}
|
|
||||||
template<typename Type>
|
|
||||||
void append(Type &value, typename std::enable_if<std::is_enum<Type>::value>::type* = 0)
|
|
||||||
{
|
|
||||||
values_.emplace_back((int)value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,50 @@
|
||||||
|
#ifndef QUERY_ENUM_MAPPER_HPP
|
||||||
|
#define QUERY_ENUM_MAPPER_HPP
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
namespace matador::utils {
|
||||||
|
|
||||||
|
template < typename EnumType, class Enable = void >
|
||||||
|
class enum_mapper;
|
||||||
|
|
||||||
|
template < typename EnumType>
|
||||||
|
class enum_mapper<EnumType, typename std::enable_if<std::is_enum<EnumType>::value>::type>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using enum_to_string_map = std::unordered_map<EnumType, std::string>;
|
||||||
|
using string_to_enum_map = std::unordered_map<std::string, EnumType>;
|
||||||
|
|
||||||
|
explicit enum_mapper(enum_to_string_map enum_map)
|
||||||
|
: enum_to_string_map_(std::move(enum_map))
|
||||||
|
{
|
||||||
|
for (const auto &elem : enum_to_string_map_) {
|
||||||
|
string_to_enum_map_.emplace(elem.second, elem.first);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<EnumType> to_enum(const std::string &enum_string) const {
|
||||||
|
if (const auto it = string_to_enum_map_.find(enum_string); it != string_to_enum_map_.end()) {
|
||||||
|
return { it->second };
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string to_string(EnumType enum_value) const {
|
||||||
|
if (const auto it = enum_to_string_map_.find(enum_value); it != enum_to_string_map_.end()) {
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
enum_to_string_map enum_to_string_map_;
|
||||||
|
string_to_enum_map string_to_enum_map_;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif //QUERY_ENUM_MAPPER_HPP
|
||||||
|
|
@ -77,7 +77,8 @@ set(UTILS_HEADER
|
||||||
../include/matador/utils/access.hpp
|
../include/matador/utils/access.hpp
|
||||||
../include/matador/utils/identifier.hpp
|
../include/matador/utils/identifier.hpp
|
||||||
../include/matador/utils/cascade_type.hpp
|
../include/matador/utils/cascade_type.hpp
|
||||||
../include/matador/utils/logger.hpp)
|
../include/matador/utils/logger.hpp
|
||||||
|
../include/matador/utils/enum_mapper.hpp)
|
||||||
|
|
||||||
set(UTILS_SOURCES
|
set(UTILS_SOURCES
|
||||||
utils/field_attributes.cpp
|
utils/field_attributes.cpp
|
||||||
|
|
|
||||||
|
|
@ -3,22 +3,35 @@
|
||||||
|
|
||||||
namespace matador::sql {
|
namespace matador::sql {
|
||||||
|
|
||||||
object_binder::object_binder(parameter_binder &binder)
|
namespace detail {
|
||||||
|
|
||||||
|
fk_binder::fk_binder(parameter_binder &binder)
|
||||||
: binder_(binder) {}
|
: binder_(binder) {}
|
||||||
|
|
||||||
|
void fk_binder::on_primary_key(const char *id, std::string &value, size_t size)
|
||||||
|
{
|
||||||
|
data_type_traits<std::string>::bind_value(binder_, index_++, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
object_binder::object_binder(parameter_binder &binder)
|
||||||
|
: binder_(binder)
|
||||||
|
, fk_binder_(binder) {}
|
||||||
|
|
||||||
void object_binder::reset()
|
void object_binder::reset()
|
||||||
{
|
{
|
||||||
index_ = 0;
|
index_ = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void object_binder::on_primary_key(const char *id, std::string &val, size_t)
|
void object_binder::on_primary_key(const char *id, std::string &val, size_t size)
|
||||||
{
|
{
|
||||||
binder_.bind(index_++, val);
|
data_type_traits<std::string>::bind_value(binder_, index_++, val, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void object_binder::on_revision(const char *id, unsigned long long int &rev)
|
void object_binder::on_revision(const char *id, unsigned long long int &rev)
|
||||||
{
|
{
|
||||||
binder_.bind(index_++, rev);
|
data_type_traits<unsigned long long>::bind_value(binder_, index_++, rev);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -6,8 +6,9 @@ namespace matador::sql {
|
||||||
detail::pk_reader::pk_reader(query_result_reader &reader)
|
detail::pk_reader::pk_reader(query_result_reader &reader)
|
||||||
: reader_(reader) {}
|
: reader_(reader) {}
|
||||||
|
|
||||||
void detail::pk_reader::on_primary_key(const char *id, std::string &value, size_t size) {
|
void detail::pk_reader::on_primary_key(const char *id, std::string &value, size_t size)
|
||||||
reader_.read_value(id, column_index_, value, size);
|
{
|
||||||
|
data_type_traits<std::string>::read_value(reader_, id, column_index_++, value, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
query_result_impl::query_result_impl(std::unique_ptr<query_result_reader> &&reader, record prototype)
|
query_result_impl::query_result_impl(std::unique_ptr<query_result_reader> &&reader, record prototype)
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,12 @@ statement::statement(std::unique_ptr<statement_impl> impl, const utils::logger &
|
||||||
, object_binder_(statement_->binder())
|
, object_binder_(statement_->binder())
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
statement &statement::bind(size_t pos, const char *value)
|
||||||
|
{
|
||||||
|
statement_->bind(pos, value, 0);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
statement &statement::bind(size_t pos, std::string &val, size_t size)
|
statement &statement::bind(size_t pos, std::string &val, size_t size)
|
||||||
{
|
{
|
||||||
statement_->bind(pos, val, size);
|
statement_->bind(pos, val, size);
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,16 @@
|
||||||
|
#include "matador/sql/connection.hpp"
|
||||||
#include "matador/sql/statement_cache.hpp"
|
#include "matador/sql/statement_cache.hpp"
|
||||||
|
|
||||||
namespace matador::sql {
|
namespace matador::sql {
|
||||||
statement &statement_cache::acquire(const std::string &stmt, const connection &conn) {
|
statement &statement_cache::acquire(query_context &&context, const connection &conn) {
|
||||||
std::lock_guard<std::mutex> guard(mutex_);
|
std::lock_guard<std::mutex> guard(mutex_);
|
||||||
auto key = hash_(stmt);
|
auto key = hash_(context.sql);
|
||||||
auto it = statement_map_.find(key);
|
auto it = statement_map_.find(key);
|
||||||
if (it == statement_map_.end()) {
|
if (it == statement_map_.end()) {
|
||||||
|
cache_info info {conn.prepare(std::move(context)), 1};
|
||||||
|
// it = statement_map_.emplace(key, {conn.prepare(std::move(context))});
|
||||||
}
|
}
|
||||||
return *it->second.statement_;
|
return it->second.statement_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void statement_cache::release(const statement &stmt) {
|
void statement_cache::release(const statement &stmt) {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
#include "matador/sql/types.hpp"
|
#include "matador/sql/types.hpp"
|
||||||
|
|
||||||
|
#include "matador/sql/parameter_binder.hpp"
|
||||||
#include "matador/sql/query_result_reader.hpp"
|
#include "matador/sql/query_result_reader.hpp"
|
||||||
|
|
||||||
namespace matador::sql {
|
namespace matador::sql {
|
||||||
|
|
@ -9,77 +10,159 @@ void data_type_traits<char>::read_value(query_result_reader &reader, const char
|
||||||
reader.read_value(id, index, value);
|
reader.read_value(id, index, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void data_type_traits<char>::bind_value(parameter_binder &binder, size_t index, char &value)
|
||||||
|
{
|
||||||
|
binder.bind(index, value);
|
||||||
|
}
|
||||||
|
|
||||||
void data_type_traits<short>::read_value(query_result_reader &reader, const char *id, size_t index, short &value)
|
void data_type_traits<short>::read_value(query_result_reader &reader, const char *id, size_t index, short &value)
|
||||||
{
|
{
|
||||||
reader.read_value(id, index, value);
|
reader.read_value(id, index, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void data_type_traits<short>::bind_value(parameter_binder &binder, size_t index, short &value)
|
||||||
|
{
|
||||||
|
binder.bind(index, value);
|
||||||
|
}
|
||||||
|
|
||||||
void data_type_traits<int>::read_value(query_result_reader &reader, const char *id, size_t index, int &value)
|
void data_type_traits<int>::read_value(query_result_reader &reader, const char *id, size_t index, int &value)
|
||||||
{
|
{
|
||||||
reader.read_value(id, index, value);
|
reader.read_value(id, index, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void data_type_traits<int>::bind_value(parameter_binder &binder, size_t index, int &value)
|
||||||
|
{
|
||||||
|
binder.bind(index, value);
|
||||||
|
}
|
||||||
|
|
||||||
void data_type_traits<long>::read_value(query_result_reader &reader, const char *id, size_t index, long &value)
|
void data_type_traits<long>::read_value(query_result_reader &reader, const char *id, size_t index, long &value)
|
||||||
{
|
{
|
||||||
reader.read_value(id, index, value);
|
reader.read_value(id, index, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void data_type_traits<long>::bind_value(parameter_binder &binder, size_t index, long &value)
|
||||||
|
{
|
||||||
|
binder.bind(index, value);
|
||||||
|
}
|
||||||
|
|
||||||
void data_type_traits<long long>::read_value(query_result_reader &reader, const char *id, size_t index, long long &value)
|
void data_type_traits<long long>::read_value(query_result_reader &reader, const char *id, size_t index, long long &value)
|
||||||
{
|
{
|
||||||
reader.read_value(id, index, value);
|
reader.read_value(id, index, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void data_type_traits<long long int>::bind_value(parameter_binder &binder, size_t index, long long int &value)
|
||||||
|
{
|
||||||
|
binder.bind(index, value);
|
||||||
|
}
|
||||||
|
|
||||||
void data_type_traits<unsigned char>::read_value(query_result_reader &reader, const char *id, size_t index, unsigned char &value)
|
void data_type_traits<unsigned char>::read_value(query_result_reader &reader, const char *id, size_t index, unsigned char &value)
|
||||||
{
|
{
|
||||||
reader.read_value(id, index, value);
|
reader.read_value(id, index, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void data_type_traits<unsigned char>::bind_value(parameter_binder &binder, size_t index, unsigned char &value)
|
||||||
|
{
|
||||||
|
binder.bind(index, value);
|
||||||
|
}
|
||||||
|
|
||||||
void data_type_traits<unsigned short>::read_value(query_result_reader &reader, const char *id, size_t index, unsigned short &value)
|
void data_type_traits<unsigned short>::read_value(query_result_reader &reader, const char *id, size_t index, unsigned short &value)
|
||||||
{
|
{
|
||||||
reader.read_value(id, index, value);
|
reader.read_value(id, index, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void data_type_traits<unsigned short>::bind_value(parameter_binder &binder, size_t index, unsigned short &value)
|
||||||
|
{
|
||||||
|
binder.bind(index, value);
|
||||||
|
}
|
||||||
|
|
||||||
void data_type_traits<unsigned int>::read_value(query_result_reader &reader, const char *id, size_t index, unsigned int &value)
|
void data_type_traits<unsigned int>::read_value(query_result_reader &reader, const char *id, size_t index, unsigned int &value)
|
||||||
{
|
{
|
||||||
reader.read_value(id, index, value);
|
reader.read_value(id, index, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void data_type_traits<unsigned int>::bind_value(parameter_binder &binder, size_t index, unsigned int &value)
|
||||||
|
{
|
||||||
|
binder.bind(index, value);
|
||||||
|
}
|
||||||
|
|
||||||
void data_type_traits<unsigned long>::read_value(query_result_reader &reader, const char *id, size_t index, unsigned long &value)
|
void data_type_traits<unsigned long>::read_value(query_result_reader &reader, const char *id, size_t index, unsigned long &value)
|
||||||
{
|
{
|
||||||
reader.read_value(id, index, value);
|
reader.read_value(id, index, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void data_type_traits<unsigned long>::bind_value(parameter_binder &binder, size_t index, unsigned long &value)
|
||||||
|
{
|
||||||
|
binder.bind(index, value);
|
||||||
|
}
|
||||||
|
|
||||||
void data_type_traits<unsigned long long>::read_value(query_result_reader &reader, const char *id, size_t index, unsigned long long &value)
|
void data_type_traits<unsigned long long>::read_value(query_result_reader &reader, const char *id, size_t index, unsigned long long &value)
|
||||||
{
|
{
|
||||||
reader.read_value(id, index, value);
|
reader.read_value(id, index, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void data_type_traits<unsigned long long int>::bind_value(parameter_binder &binder, size_t index, unsigned long long int &value)
|
||||||
|
{
|
||||||
|
binder.bind(index, value);
|
||||||
|
}
|
||||||
|
|
||||||
void data_type_traits<bool>::read_value(query_result_reader &reader, const char *id, size_t index, bool &value)
|
void data_type_traits<bool>::read_value(query_result_reader &reader, const char *id, size_t index, bool &value)
|
||||||
{
|
{
|
||||||
reader.read_value(id, index, value);
|
reader.read_value(id, index, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void data_type_traits<bool>::bind_value(parameter_binder &binder, size_t index, bool &value)
|
||||||
|
{
|
||||||
|
binder.bind(index, value);
|
||||||
|
}
|
||||||
|
|
||||||
void data_type_traits<float>::read_value(query_result_reader &reader, const char *id, size_t index, float &value)
|
void data_type_traits<float>::read_value(query_result_reader &reader, const char *id, size_t index, float &value)
|
||||||
{
|
{
|
||||||
reader.read_value(id, index, value);
|
reader.read_value(id, index, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void data_type_traits<float>::bind_value(parameter_binder &binder, size_t index, float &value)
|
||||||
|
{
|
||||||
|
binder.bind(index, value);
|
||||||
|
}
|
||||||
|
|
||||||
void data_type_traits<double>::read_value(query_result_reader &reader, const char *id, size_t index, double &value)
|
void data_type_traits<double>::read_value(query_result_reader &reader, const char *id, size_t index, double &value)
|
||||||
{
|
{
|
||||||
reader.read_value(id, index, value);
|
reader.read_value(id, index, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void data_type_traits<double>::bind_value(parameter_binder &binder, size_t index, double &value)
|
||||||
|
{
|
||||||
|
binder.bind(index, value);
|
||||||
|
}
|
||||||
|
|
||||||
void data_type_traits<const char*>::read_value(query_result_reader &reader, const char *id, size_t index, const char* value, size_t size)
|
void data_type_traits<const char*>::read_value(query_result_reader &reader, const char *id, size_t index, const char* value, size_t size)
|
||||||
{
|
{
|
||||||
reader.read_value(id, index, const_cast<char*>(value), size);
|
reader.read_value(id, index, const_cast<char*>(value), size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void data_type_traits<const char *>::bind_value(parameter_binder &binder, size_t index, const char *value, size_t size)
|
||||||
|
{
|
||||||
|
binder.bind(index, value, size);
|
||||||
|
}
|
||||||
|
|
||||||
void data_type_traits<char*>::read_value(query_result_reader &reader, const char *id, size_t index, char* value, size_t size)
|
void data_type_traits<char*>::read_value(query_result_reader &reader, const char *id, size_t index, char* value, size_t size)
|
||||||
{
|
{
|
||||||
reader.read_value(id, index, value, size);
|
reader.read_value(id, index, value, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void data_type_traits<char *>::bind_value(parameter_binder &binder, size_t index, char *value, size_t size)
|
||||||
|
{
|
||||||
|
binder.bind(index, value, size);
|
||||||
|
}
|
||||||
|
|
||||||
void data_type_traits<std::string>::read_value(query_result_reader &reader, const char *id, size_t index, std::string &value, size_t size)
|
void data_type_traits<std::string>::read_value(query_result_reader &reader, const char *id, size_t index, std::string &value, size_t size)
|
||||||
{
|
{
|
||||||
reader.read_value(id, index, value, size);
|
reader.read_value(id, index, value, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void data_type_traits<std::string>::bind_value(parameter_binder &binder, size_t index, std::string &value, size_t size)
|
||||||
|
{
|
||||||
|
binder.bind(index, value, size);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -7,25 +7,16 @@
|
||||||
|
|
||||||
using namespace matador;
|
using namespace matador;
|
||||||
|
|
||||||
class TestConnection
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
explicit TestConnection(sql::connection_info info)
|
|
||||||
: info_(std::move(info)) {}
|
|
||||||
void open() {}
|
|
||||||
|
|
||||||
private:
|
|
||||||
sql::connection_info info_;
|
|
||||||
};
|
|
||||||
|
|
||||||
TEST_CASE("Acquire prepared statement", "[statement cache]") {
|
TEST_CASE("Acquire prepared statement", "[statement cache]") {
|
||||||
sql::statement_cache cache;
|
sql::statement_cache cache;
|
||||||
sql::connection_pool<TestConnection> pool("sqlite://sqlite.db", 4);
|
sql::connection_pool<sql::connection> pool("sqlite://sqlite.db", 4);
|
||||||
|
|
||||||
// sql::session s(pool);
|
sql::session s(pool);
|
||||||
// auto conn = pool.acquire();
|
auto conn = pool.acquire();
|
||||||
|
|
||||||
std::string sql = R"(SELECT * FROM person WHERE name = 'george')";
|
std::string sql = R"(SELECT * FROM person WHERE name = 'george')";
|
||||||
// auto stmt = cache.acquire(sql, conn);
|
// auto &stmt = cache.acquire(sql, *conn);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -4,6 +4,8 @@
|
||||||
#include "matador/sql/connection_pool.hpp"
|
#include "matador/sql/connection_pool.hpp"
|
||||||
#include "matador/sql/session.hpp"
|
#include "matador/sql/session.hpp"
|
||||||
|
|
||||||
|
#include "matador/utils/enum_mapper.hpp"
|
||||||
|
|
||||||
#include "Databases.hpp"
|
#include "Databases.hpp"
|
||||||
|
|
||||||
#include "models/location.hpp"
|
#include "models/location.hpp"
|
||||||
|
|
@ -25,7 +27,7 @@ public:
|
||||||
.table<location>("location")
|
.table<location>("location")
|
||||||
.execute();
|
.execute();
|
||||||
REQUIRE(res.first == 0);
|
REQUIRE(res.first == 0);
|
||||||
REQUIRE(res.second == R"(CREATE TABLE "location" ("id" BIGINT, "name" VARCHAR(255), "coordinate_x" INTEGER, "coordinate_y" INTEGER, "coordinate_z" INTEGER, "color" INTEGER, CONSTRAINT PK_location PRIMARY KEY (id)))");
|
REQUIRE(res.second == R"(CREATE TABLE "location" ("id" BIGINT, "name" VARCHAR(255), "coordinate_x" INTEGER, "coordinate_y" INTEGER, "coordinate_z" INTEGER, "color" TEXT, CONSTRAINT PK_location PRIMARY KEY (id)))");
|
||||||
}
|
}
|
||||||
|
|
||||||
~TypeTraitsTestFixture()
|
~TypeTraitsTestFixture()
|
||||||
|
|
@ -41,19 +43,78 @@ private:
|
||||||
matador::sql::session session_;
|
matador::sql::session session_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const matador::utils::enum_mapper<Color> color_enum({
|
||||||
|
{Color::Green, "green"},
|
||||||
|
{Color::Red, "red"},
|
||||||
|
{Color::Blue, "blue"},
|
||||||
|
{Color::Yellow, "yellow"},
|
||||||
|
{Color::Black, "black"},
|
||||||
|
{Color::White, "white"},
|
||||||
|
{Color::Brown, "brown"}
|
||||||
|
});
|
||||||
|
|
||||||
|
namespace matador::sql {
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct data_type_traits<Color, void>
|
||||||
|
{
|
||||||
|
inline static data_type_t builtin_type(std::size_t size)
|
||||||
|
{ return data_type_traits<std::string>::builtin_type(size); }
|
||||||
|
|
||||||
|
static void read_value(query_result_reader &reader, const char *id, size_t index, Color &value)
|
||||||
|
{
|
||||||
|
std::string enum_string;
|
||||||
|
reader.read_value(id, index, enum_string, 64);
|
||||||
|
auto enum_opt = color_enum.to_enum(enum_string);
|
||||||
|
if (enum_opt) {
|
||||||
|
value = enum_opt.value();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static any_type create_value(Color &value)
|
||||||
|
{
|
||||||
|
return color_enum.to_string(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void bind_value(parameter_binder &binder, size_t index, Color &value)
|
||||||
|
{
|
||||||
|
binder.bind(index, color_enum.to_string(value));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
TEMPLATE_TEST_CASE_METHOD(TypeTraitsTestFixture, "Special handling of attributes with type traits", "[typetraits]", Sqlite, Postgres)
|
TEMPLATE_TEST_CASE_METHOD(TypeTraitsTestFixture, "Special handling of attributes with type traits", "[typetraits]", Sqlite, Postgres)
|
||||||
{
|
{
|
||||||
auto &s = TypeTraitsTestFixture<TestType>::session();
|
auto &s = TypeTraitsTestFixture<TestType>::session();
|
||||||
|
|
||||||
|
SECTION("Insert and select with direct execution") {
|
||||||
location loc{1, "center", {1, 2, 3}, Color::Black};
|
location loc{1, "center", {1, 2, 3}, Color::Black};
|
||||||
|
|
||||||
auto res = s.insert().template into<location>("location").values(loc).execute();
|
auto res = s.insert().template into<location>("location").values(loc).execute();
|
||||||
REQUIRE(res.first == 1);
|
REQUIRE(res.first == 1);
|
||||||
|
|
||||||
auto result = s.template select<location>().from("location").template fetch_all<location>();
|
auto result = s.template select<location>().from("location").
|
||||||
|
template fetch_all<location>();
|
||||||
|
|
||||||
for (const auto &l : result) {
|
for (const auto &l: result) {
|
||||||
REQUIRE(l.name == "center");
|
REQUIRE(l.name == "center");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("Insert and select with prepared statement") {
|
||||||
|
location loc{1, "center", {1, 2, 3}, Color::Black};
|
||||||
|
|
||||||
|
auto stmt = s.insert().template into<location>("location").template values<location>().prepare();
|
||||||
|
auto res = stmt.bind(loc).execute();
|
||||||
|
REQUIRE(res == 1);
|
||||||
|
|
||||||
|
auto result = s.template select<location>().from("location").
|
||||||
|
template fetch_all<location>();
|
||||||
|
|
||||||
|
for (const auto &l: result) {
|
||||||
|
REQUIRE(l.name == "center");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -23,4 +23,5 @@ void attribute(Operator &op, const char *id, test::coordinate &value, const fiel
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif //QUERY_COORDINATE_HPP
|
#endif //QUERY_COORDINATE_HPP
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue