diff --git a/backends/postgres/include/postgres_result_reader.hpp b/backends/postgres/include/postgres_result_reader.hpp index 9d3675d..0ee6004 100644 --- a/backends/postgres/include/postgres_result_reader.hpp +++ b/backends/postgres/include/postgres_result_reader.hpp @@ -9,8 +9,7 @@ namespace matador::backends::postgres { namespace detail { -class empty_binder final : public utils::attribute_reader -{ +class empty_binder final : public utils::attribute_reader { public: void read_value(const char *, size_t, int8_t &) override {} void read_value(const char *, size_t, int16_t &) override {} @@ -23,8 +22,9 @@ public: void read_value(const char *, size_t, bool &) override {} void read_value(const char *, size_t, float &) override {} void read_value(const char *, size_t, double &) override {} - void read_value(const char *, size_t, time &) override {} - void read_value(const char *, size_t, date &) override {} + void read_value(const char *, size_t, utils::date_type_t &) override {} + void read_value(const char *, size_t, utils::time_type_t &) override {} + void read_value(const char *, size_t, utils::timestamp &) override {} void read_value(const char *, size_t, char *, size_t) override {} void read_value(const char *, size_t, std::string &) override {} void read_value(const char *, size_t, std::string &, size_t) override {} @@ -34,8 +34,7 @@ public: } -class postgres_result_reader final : public sql::query_result_reader -{ +class postgres_result_reader final : public sql::query_result_reader { public: explicit postgres_result_reader(PGresult *result); ~postgres_result_reader() override; @@ -57,8 +56,9 @@ public: void read_value(const char *id, size_t index, bool &value) override; void read_value(const char *id, size_t index, float &value) override; void read_value(const char *id, size_t index, double &value) override; - void read_value(const char *id, size_t index, matador::time &value) override; - void read_value(const char *id, size_t index, matador::date &value) override; + void read_value(const char *id, size_t index, utils::date_type_t &) override; + void read_value(const char *id, size_t index, utils::time_type_t &) override; + void read_value(const char *id, size_t index, utils::timestamp &) override; void read_value(const char *id, size_t index, char *value, size_t size) override; void read_value(const char *id, size_t index, std::string &value) override; void read_value(const char *id, size_t index, std::string &value, size_t size) override; diff --git a/backends/postgres/src/postgres_connection.cpp b/backends/postgres/src/postgres_connection.cpp index 4f31837..4f09cf9 100644 --- a/backends/postgres/src/postgres_connection.cpp +++ b/backends/postgres/src/postgres_connection.cpp @@ -178,8 +178,10 @@ utils::basic_type oid2type(const Oid oid) { return utils::basic_type::Double; case 1082: return utils::basic_type::Date; - case 1114: + case 1083: return utils::basic_type::Time; + case 1114: + return utils::basic_type::DateTime; default: return utils::basic_type::Null; } @@ -201,9 +203,12 @@ utils::basic_type string2type(const char *type) { if (strcmp(type, "date") == 0) { return utils::basic_type::Date; } - if (strcmp(type, "timestamp") == 0) { + if (strcmp(type, "time") == 0) { return utils::basic_type::Time; } + if (strcmp(type, "timestamp") == 0) { + return utils::basic_type::DateTime; + } if (strcmp(type, "float4") == 0) { return utils::basic_type::Float; } diff --git a/backends/postgres/src/postgres_dialect.cpp b/backends/postgres/src/postgres_dialect.cpp index a8caca2..0a7a957 100644 --- a/backends/postgres/src/postgres_dialect.cpp +++ b/backends/postgres/src/postgres_dialect.cpp @@ -20,7 +20,8 @@ {matador::utils::basic_type::UInt8, "SMALLINT"}, {matador::utils::basic_type::Float, "REAL"}, {matador::utils::basic_type::Double, "DOUBLE PRECISION"}, - {matador::utils::basic_type::Time, "TIMESTAMP"}, + {matador::utils::basic_type::Time, "TIME(6)"}, + {matador::utils::basic_type::DateTime, "TIMESTAMPTZ(6)"}, {matador::utils::basic_type::Blob, "BYTEA"} }) .with_bool_strings("TRUE", "FALSE") diff --git a/backends/postgres/src/postgres_parameter_binder.cpp b/backends/postgres/src/postgres_parameter_binder.cpp index 5bb4083..8dd8a02 100644 --- a/backends/postgres/src/postgres_parameter_binder.cpp +++ b/backends/postgres/src/postgres_parameter_binder.cpp @@ -123,15 +123,23 @@ void postgres_parameter_binder::write_value(const size_t pos, const std::string write_value(pos, x); } -void postgres_parameter_binder::write_value(const size_t pos, const utils::date_type_t &/*x*/) { - // bind_data_.strings[pos] = utils::to_string(x, utils::date_format::ISO8601); +void postgres_parameter_binder::write_value(const size_t pos, const utils::date_type_t &x) { + char buf[11]; // "YYYY-MM-DD" + '\0' + + std::snprintf(buf, sizeof(buf), "%04d-%02u-%02u", x.year, static_cast(x.month), static_cast(x.day)); + bind_data_.strings[pos] = std::string{buf}; bind_data_.values[pos] = bind_data_.strings[pos].data(); bind_data_.lengths[pos] = static_cast(bind_data_.strings[pos].size()); bind_data_.formats[pos] = 0; } -void postgres_parameter_binder::write_value(const size_t pos, const utils::time_type_t &/*x*/) { - // bind_data_.strings[pos] = utils::to_string(x, "%Y-%m-%d %T.%f"); +void postgres_parameter_binder::write_value(const size_t pos, const utils::time_type_t &x) { + char buf[16]; // "HH:MM:SS.ffffff" + '\0' + + std::snprintf(buf, sizeof(buf), "%02u:%02u:%02u.%06u", + static_cast(x.hour), static_cast(x.minute), static_cast(x.second), x.microsecond); + + bind_data_.strings[pos] = std::string{buf}; bind_data_.values[pos] = bind_data_.strings[pos].data(); bind_data_.lengths[pos] = static_cast(bind_data_.strings[pos].size()); bind_data_.formats[pos] = 0; diff --git a/backends/postgres/src/postgres_result_reader.cpp b/backends/postgres/src/postgres_result_reader.cpp index e390e54..5a0b43b 100644 --- a/backends/postgres/src/postgres_result_reader.cpp +++ b/backends/postgres/src/postgres_result_reader.cpp @@ -4,27 +4,23 @@ #include "matador/utils/value.hpp" namespace matador::backends::postgres { - postgres_result_reader::postgres_result_reader(PGresult *result) : result_(result) -, row_count_(PQntuples(result_)) -, column_count_(PQnfields(result_)) -{} + , row_count_(PQntuples(result_)) + , column_count_(PQnfields(result_)) { +} -postgres_result_reader::~postgres_result_reader() -{ +postgres_result_reader::~postgres_result_reader() { if (result_) { PQclear(result_); } } -size_t postgres_result_reader::column_count() const -{ +size_t postgres_result_reader::column_count() const { return column_count_; } -const char *postgres_result_reader::column( const size_t index) const -{ +const char *postgres_result_reader::column(const size_t index) const { return PQgetvalue(result_, static_cast(row_index_), static_cast(index)); } @@ -106,16 +102,21 @@ void postgres_result_reader::read_value(const char * /*id*/, const size_t index, } } -void postgres_result_reader::read_value(const char * /*id*/, const size_t /*index*/, time &/*value*/) { - // if (const auto val = column(index); strlen(val) > 0) { +void postgres_result_reader::read_value(const char * /*id*/, const size_t index, utils::date_type_t &value) { + if (const auto val = column(index); strlen(val) > 0) { // value = time::parse(val, "%Y-%m-%d %T.%f"); - // } + } } -void postgres_result_reader::read_value(const char * /*id*/, const size_t /*index*/, date &/*value*/) { - // if (const auto val = column(index); strlen(val) > 0) { +void postgres_result_reader::read_value(const char * /*id*/, const size_t index, utils::time_type_t &value) { + if (const auto val = column(index); strlen(val) > 0) { // value.set(val, matador::utils::date_format::ISO8601); - // } + } +} + +void postgres_result_reader::read_value(const char * /*id*/, size_t index, utils::timestamp &value) { + if (const auto val = column(index); strlen(val) > 0) { + } } void postgres_result_reader::read_value(const char * /*id*/, const size_t index, char *value, size_t size) { @@ -126,7 +127,7 @@ void postgres_result_reader::read_value(const char * /*id*/, const size_t index, #else strncpy(value, val, size); #endif - value[size-1] = '\n'; + value[size - 1] = '\n'; } else { #ifdef _MSC_VER strcpy_s(value, size, val); @@ -144,32 +145,30 @@ void postgres_result_reader::read_value(const char * /*id*/, const size_t index, value.assign(column(index)); } -void postgres_result_reader::read_value( const char* /*id*/, const size_t index, utils::blob& value ) -{ - const auto *data = reinterpret_cast(column(index)); - // auto length = PQgetlength(result_, row_index_, static_cast(index)); +void postgres_result_reader::read_value(const char * /*id*/, const size_t index, utils::blob &value) { + const auto *data = reinterpret_cast(column(index)); size_t length; - unsigned char* unescaped = PQunescapeBytea(data, &length); + unsigned char *unescaped = PQunescapeBytea(data, &length); - value.assign(unescaped, unescaped+length); + value.assign(unescaped, unescaped + length); PQfreemem(unescaped); } -template -void set_value(const char* str, utils::value& value) { +template +void set_value(const char *str, utils::value &value) { if (const auto res = utils::to(str); res.is_ok()) { value = res.value(); } } -template <> -void set_value(const char* str, utils::value& value) { +template<> +void set_value(const char *str, utils::value &value) { size_t length; - unsigned char* unescaped = PQunescapeBytea(reinterpret_cast(str), &length); + unsigned char *unescaped = PQunescapeBytea(reinterpret_cast(str), &length); - value = utils::blob(unescaped, unescaped+length); + value = utils::blob(unescaped, unescaped + length); PQfreemem(unescaped); } @@ -219,8 +218,13 @@ void postgres_result_reader::read_value(const char * /*id*/, const size_t index, break; } case utils::basic_type::Time: - case utils::basic_type::Date: { - val = std::string{column(index)}; + set_value(column(index), val); + break; + case utils::basic_type::Date: + set_value(column(index), val); + break; + case utils::basic_type::DateTime: { + set_value(column(index), val); break; } case utils::basic_type::Null: { @@ -231,11 +235,12 @@ void postgres_result_reader::read_value(const char * /*id*/, const size_t index, set_value(column(index), val); break; } + case utils::basic_type::Unknown: + break; } } utils::attribute_reader &postgres_result_reader::result_binder() { return empty_binder_; } - } // namespace matador::backends::postgres diff --git a/include/matador/sql/dialect.hpp b/include/matador/sql/dialect.hpp index 53277a6..a1bea6d 100644 --- a/include/matador/sql/dialect.hpp +++ b/include/matador/sql/dialect.hpp @@ -69,7 +69,7 @@ public: [[nodiscard]] std::string prepare_literal(const std::string &str) const; /** - * Wrap identifier quotes around a sql identifier keyword + * Wrap identifier quotes around a SQL identifier keyword * * @param str Identifier to put quotes around */ @@ -259,7 +259,8 @@ private: {utils::basic_type::Varchar, "VARCHAR"}, {utils::basic_type::Text, "TEXT"}, {utils::basic_type::Date, "DATE"}, - {utils::basic_type::Time, "DATETIME"}, + {utils::basic_type::Time, "TIME"}, + {utils::basic_type::DateTime, "DATETIME"}, {utils::basic_type::Blob, "BLOB"}, {utils::basic_type::Null, "NULL"} }; diff --git a/include/matador/utils/attribute_reader.hpp b/include/matador/utils/attribute_reader.hpp index 02fa451..6f0ef94 100644 --- a/include/matador/utils/attribute_reader.hpp +++ b/include/matador/utils/attribute_reader.hpp @@ -5,10 +5,6 @@ #include -namespace matador { -class date; -class time; -} namespace matador::utils { class value; @@ -29,8 +25,9 @@ public: virtual void read_value(const char *id, size_t index, bool &value) = 0; virtual void read_value(const char *id, size_t index, float &value) = 0; virtual void read_value(const char *id, size_t index, double &value) = 0; - virtual void read_value(const char *id, size_t index, time &value) = 0; - virtual void read_value(const char *id, size_t index, date &value) = 0; + virtual void read_value(const char *id, size_t index, time_type_t &value) = 0; + virtual void read_value(const char *id, size_t index, date_type_t &value) = 0; + virtual void read_value(const char *id, size_t index, timestamp &value) = 0; virtual void read_value(const char *id, size_t index, char *value, size_t size) = 0; virtual void read_value(const char *id, size_t index, std::string &value) = 0; virtual void read_value(const char *id, size_t index, std::string &value, size_t size) = 0; diff --git a/include/matador/utils/convert.hpp b/include/matador/utils/convert.hpp index fa5e98c..aa1db64 100644 --- a/include/matador/utils/convert.hpp +++ b/include/matador/utils/convert.hpp @@ -256,26 +256,57 @@ template < typename DestType > result to(const std::string &source, std::enable_if_t>* = nullptr) { std::tm result{}; std::istringstream iss(source); - iss >> std::get_time(&result, "%Y-%m-%d %H:%M:%S"); - return ok(result); + iss >> std::get_time(&result, "%Y-%m-%d"); + if (iss.fail()) { + return failure(conversion_error::NotConvertable); + } + return ok(date_type_t{result.tm_year + 1900, static_cast(result.tm_mon + 1), static_cast(result.tm_mday)}); +} + +template < typename DestType > +result to(const char *source, std::enable_if_t>* = nullptr) { + return to(std::string{source}); } template < typename DestType > result to(const std::string &source, std::enable_if_t>* = nullptr) { std::tm result{}; std::istringstream iss(source); - iss >> std::get_time(&result, "%Y-%m-%d %H:%M:%S"); - return ok(result); + iss >> std::get_time(&result, "%H:%M:%S"); + if (iss.fail()) { + return failure(conversion_error::NotConvertable); + } + return ok(time_type_t{static_cast(result.tm_hour), static_cast(result.tm_min), static_cast(result.tm_sec)}); } +template < typename DestType > +result to(const char *source, std::enable_if_t>* = nullptr) { + return to(std::string{source}); +} + + template < typename DestType > result to(const std::string &source, std::enable_if_t>* = nullptr) { std::tm result{}; std::istringstream iss(source); iss >> std::get_time(&result, "%Y-%m-%d %H:%M:%S"); - return ok(result); + if (iss.fail()) { + return failure(conversion_error::NotConvertable); + } + + const std::time_t tt = std::mktime(&result); + if (tt == -1) { + return failure(conversion_error::NotConvertable); + } + return ok(std::chrono::system_clock::from_time_t(tt)); } +template < typename DestType > +result to(const char *source, std::enable_if_t>* = nullptr) { + return to(std::string{source}); +} + + template < typename DestType, typename SourceType > result to(const SourceType &/*source*/, std::enable_if_t && !std::is_same_v && std::is_same_v>* = nullptr) { return failure(conversion_error::NotConvertable); @@ -351,6 +382,104 @@ result to(const SourceType &/*source*/, std::enable_ return failure(conversion_error::NotConvertable); } +template < typename DestType, typename SourceType > +result to(const SourceType &/*source*/, std::enable_if_t && !std::is_same_v && std::is_same_v>* = nullptr) { + return failure(conversion_error::NotConvertable); +} + +template < typename DestType, typename SourceType > +result to(const SourceType &/*source*/, std::enable_if_t && !std::is_same_v && std::is_same_v>* = nullptr) { + return failure(conversion_error::NotConvertable); +} + +template < typename DestType, typename SourceType > +result to(const SourceType &/*source*/, std::enable_if_t && !std::is_same_v && std::is_same_v>* = nullptr) { + return failure(conversion_error::NotConvertable); +} + +template < typename DestType, typename SourceType > +result to(const SourceType &/*source*/, std::enable_if_t && std::is_same_v>* = nullptr) { + return failure(conversion_error::NotConvertable); +} + +template < typename DestType, typename SourceType > +result to(const SourceType &/*source*/, std::enable_if_t && std::is_same_v>* = nullptr) { + return failure(conversion_error::NotConvertable); +} + +template < typename DestType, typename SourceType > +result to(const SourceType &/*source*/, std::enable_if_t && std::is_same_v>* = nullptr) { + return failure(conversion_error::NotConvertable); +} + +template < typename DestType> +result to(const blob &/*source*/, std::enable_if_t>* = nullptr) { + return failure(conversion_error::NotConvertable); +} + +template < typename DestType> +result to(const blob &/*source*/, std::enable_if_t>* = nullptr) { + return failure(conversion_error::NotConvertable); +} + +template < typename DestType> +result to(const blob &/*source*/, std::enable_if_t>* = nullptr) { + return failure(conversion_error::NotConvertable); +} + +template < typename DestType> +result to(const bool &/*source*/, std::enable_if_t>* = nullptr) { + return failure(conversion_error::NotConvertable); +} + +template < typename DestType> +result to(const bool &/*source*/, std::enable_if_t>* = nullptr) { + return failure(conversion_error::NotConvertable); +} + +template < typename DestType> +result to(const bool &/*source*/, std::enable_if_t>* = nullptr) { + return failure(conversion_error::NotConvertable); +} + +template < typename DestType> +result to(const time_type_t &/*source*/, std::enable_if_t>* = nullptr) { + return failure(conversion_error::NotConvertable); +} + +template < typename DestType> +result to(const time_type_t &source, std::enable_if_t>* = nullptr) { + return ok(source); +} + +template < typename DestType> +result to(const date_type_t &/*source*/, std::enable_if_t>* = nullptr) { + return failure(conversion_error::NotConvertable); +} + +template < typename DestType> +result to(const date_type_t &source, std::enable_if_t>* = nullptr) { + return ok(source); +} + +template < typename DestType> +result to(const timestamp &source, std::enable_if_t>* = nullptr) { + const std::time_t tt = std::chrono::system_clock::to_time_t(source); + + const std::tm* result = std::localtime(&tt); + + return ok(time_type_t{static_cast(result->tm_hour), static_cast(result->tm_min), static_cast(result->tm_sec)}); +} + +template < typename DestType> +result to(const timestamp &source, std::enable_if_t>* = nullptr) { + const std::time_t tt = std::chrono::system_clock::to_time_t(source); + + const std::tm* result = std::localtime(&tt); + + return ok(date_type_t{result->tm_year + 1900, static_cast(result->tm_mon + 1), static_cast(result->tm_mday)}); +} + } #endif //MATADOR_CONVERT_HPP diff --git a/include/matador/utils/default_type_traits.hpp b/include/matador/utils/default_type_traits.hpp index d3584e1..36f76c0 100644 --- a/include/matador/utils/default_type_traits.hpp +++ b/include/matador/utils/default_type_traits.hpp @@ -8,159 +8,162 @@ #include namespace matador::utils { - /// @cond MATADOR_DEV -template <> struct data_type_traits -{ +template<> +struct data_type_traits { static basic_type type(std::size_t /*size*/) { return basic_type::Null; } - static void read_value(attribute_reader &reader, const char *id, size_t index, nullptr_t &/*value*/, size_t /*size*/ = 0); - static void bind_value(attribute_writer &binder, size_t index, nullptr_t &/*value*/, size_t /*size*/ = 0); + static void read_value(attribute_reader &reader, const char *id, size_t index, nullptr_t &/*value*/, + size_t /*size*/ = 0); + static void bind_value(attribute_writer &binder, size_t index, nullptr_t &/*value*/, size_t /*size*/ = 0); }; -template <> struct data_type_traits -{ - static basic_type type(std::size_t /*size*/ = 0) { return basic_type::Int8; } - static void read_value(attribute_reader &reader, const char *id, size_t index, int8_t &value, size_t /*size*/ = 0); - static void bind_value(attribute_writer &binder, size_t index, const int8_t &value, size_t /*size*/ = 0); +template<> +struct data_type_traits { + static basic_type type(std::size_t /*size*/ = 0) { return basic_type::Int8; } + static void read_value(attribute_reader &reader, const char *id, size_t index, int8_t &value, size_t /*size*/ = 0); + static void bind_value(attribute_writer &binder, size_t index, const int8_t &value, size_t /*size*/ = 0); }; -template <> struct data_type_traits -{ - static basic_type type(std::size_t /*size*/ = 0) { return basic_type::Int16; } - static void read_value(attribute_reader &reader, const char *id, size_t index, int16_t &value, size_t /*size*/ = 0); - static void bind_value(attribute_writer &binder, size_t index, const int16_t &value, size_t /*size*/ = 0); +template<> +struct data_type_traits { + static basic_type type(std::size_t /*size*/ = 0) { return basic_type::Int16; } + static void read_value(attribute_reader &reader, const char *id, size_t index, int16_t &value, size_t /*size*/ = 0); + static void bind_value(attribute_writer &binder, size_t index, const int16_t &value, size_t /*size*/ = 0); }; -template <> struct data_type_traits -{ - static basic_type type(std::size_t /*size*/ = 0) { return basic_type::Int32; } - static void read_value(attribute_reader &reader, const char *id, size_t index, int32_t &value, size_t /*size*/ = 0); - static void bind_value(attribute_writer &binder, size_t index, const int32_t &value, size_t /*size*/ = 0); +template<> +struct data_type_traits { + static basic_type type(std::size_t /*size*/ = 0) { return basic_type::Int32; } + static void read_value(attribute_reader &reader, const char *id, size_t index, int32_t &value, size_t /*size*/ = 0); + static void bind_value(attribute_writer &binder, size_t index, const int32_t &value, size_t /*size*/ = 0); }; -template <> struct data_type_traits -{ - static basic_type type(std::size_t /*size*/ = 0) { return basic_type::Int64; } - static void read_value(attribute_reader &reader, const char *id, size_t index, int64_t &value, size_t /*size*/ = 0); - static void bind_value(attribute_writer &binder, size_t index, const int64_t &value, size_t /*size*/ = 0); +template<> +struct data_type_traits { + static basic_type type(std::size_t /*size*/ = 0) { return basic_type::Int64; } + static void read_value(attribute_reader &reader, const char *id, size_t index, int64_t &value, size_t /*size*/ = 0); + static void bind_value(attribute_writer &binder, size_t index, const int64_t &value, size_t /*size*/ = 0); }; -template <> struct data_type_traits -{ - static basic_type type(std::size_t /*size*/ = 0) { return basic_type::UInt8; } - static void read_value(attribute_reader &reader, const char *id, size_t index, uint8_t &value, size_t /*size*/ = 0); - static void bind_value(attribute_writer &binder, size_t index, const uint8_t &value, size_t /*size*/ = 0); +template<> +struct data_type_traits { + static basic_type type(std::size_t /*size*/ = 0) { return basic_type::UInt8; } + static void read_value(attribute_reader &reader, const char *id, size_t index, uint8_t &value, size_t /*size*/ = 0); + static void bind_value(attribute_writer &binder, size_t index, const uint8_t &value, size_t /*size*/ = 0); }; -template <> struct data_type_traits -{ - static basic_type type(std::size_t /*size*/ = 0) { return basic_type::UInt16; } - static void read_value(attribute_reader &reader, const char *id, size_t index, uint16_t &value, size_t /*size*/ = 0); - static void bind_value(attribute_writer &binder, size_t index, const uint16_t &value, size_t /*size*/ = 0); +template<> +struct data_type_traits { + static basic_type type(std::size_t /*size*/ = 0) { return basic_type::UInt16; } + static void read_value(attribute_reader &reader, const char *id, size_t index, uint16_t &value, size_t /*size*/ = 0); + static void bind_value(attribute_writer &binder, size_t index, const uint16_t &value, size_t /*size*/ = 0); }; -template <> struct data_type_traits -{ - static basic_type type(std::size_t /*size*/ = 0) { return basic_type::UInt32; } - static void read_value(attribute_reader &reader, const char *id, size_t index, uint32_t &value, size_t /*size*/ = 0); - static void bind_value(attribute_writer &binder, size_t index, const uint32_t &value, size_t /*size*/ = 0); +template<> +struct data_type_traits { + static basic_type type(std::size_t /*size*/ = 0) { return basic_type::UInt32; } + static void read_value(attribute_reader &reader, const char *id, size_t index, uint32_t &value, size_t /*size*/ = 0); + static void bind_value(attribute_writer &binder, size_t index, const uint32_t &value, size_t /*size*/ = 0); }; -template <> struct data_type_traits -{ - static basic_type type(std::size_t /*size*/ = 0) { return basic_type::UInt64; } - static void read_value(attribute_reader &reader, const char *id, size_t index, uint64_t &value, size_t /*size*/ = 0); - static void bind_value(attribute_writer &binder, size_t index, const uint64_t &value, size_t /*size*/ = 0); +template<> +struct data_type_traits { + static basic_type type(std::size_t /*size*/ = 0) { return basic_type::UInt64; } + static void read_value(attribute_reader &reader, const char *id, size_t index, uint64_t &value, size_t /*size*/ = 0); + static void bind_value(attribute_writer &binder, size_t index, const uint64_t &value, size_t /*size*/ = 0); }; -template <> struct data_type_traits -{ - static basic_type type(std::size_t /*size*/ = 0) { return basic_type::Boolean; } - static void read_value(attribute_reader &reader, const char *id, size_t index, bool &value, size_t /*size*/ = 0); - static void bind_value(attribute_writer &binder, size_t index, const bool &value, size_t /*size*/ = 0); +template<> +struct data_type_traits { + static basic_type type(std::size_t /*size*/ = 0) { return basic_type::Boolean; } + static void read_value(attribute_reader &reader, const char *id, size_t index, bool &value, size_t /*size*/ = 0); + static void bind_value(attribute_writer &binder, size_t index, const bool &value, size_t /*size*/ = 0); }; -template <> struct data_type_traits -{ - static basic_type type(std::size_t /*size*/ = 0) { return basic_type::Float; } - static void read_value(attribute_reader &reader, const char *id, size_t index, float &value, size_t /*size*/ = 0); - static void bind_value(attribute_writer &binder, size_t index, const float &value, size_t /*size*/ = 0); +template<> +struct data_type_traits { + static basic_type type(std::size_t /*size*/ = 0) { return basic_type::Float; } + static void read_value(attribute_reader &reader, const char *id, size_t index, float &value, size_t /*size*/ = 0); + static void bind_value(attribute_writer &binder, size_t index, const float &value, size_t /*size*/ = 0); }; -template <> struct data_type_traits -{ - static basic_type type(std::size_t /*size*/ = 0) { return basic_type::Double; } - static void read_value(attribute_reader &reader, const char *id, size_t index, double &value, size_t /*size*/ = 0); - static void bind_value(attribute_writer &binder, size_t index, const double &value, size_t /*size*/ = 0); +template<> +struct data_type_traits { + static basic_type type(std::size_t /*size*/ = 0) { return basic_type::Double; } + static void read_value(attribute_reader &reader, const char *id, size_t index, double &value, size_t /*size*/ = 0); + static void bind_value(attribute_writer &binder, size_t index, const double &value, size_t /*size*/ = 0); }; -template <> struct data_type_traits -{ +template<> +struct data_type_traits { static basic_type type(const std::size_t size) { return size == 0 ? basic_type::Text : basic_type::Varchar; } - static void read_value(attribute_reader &reader, const char *id, size_t index, const char* value, size_t size); + static void read_value(attribute_reader &reader, const char *id, size_t index, const char *value, size_t size); static void bind_value(attribute_writer &binder, size_t index, const char *value, size_t size = 0); }; -template <> struct data_type_traits -{ +template<> +struct data_type_traits { static basic_type type(const std::size_t size) { return size == 0 ? basic_type::Text : basic_type::Varchar; } static void read_value(attribute_reader &reader, const char *id, size_t index, char *value, size_t size); static void bind_value(attribute_writer &binder, size_t index, const char *value, size_t size = 0); }; -template <> struct data_type_traits -{ +template<> +struct data_type_traits { static basic_type type(const std::size_t size) { return size == 0 ? basic_type::Text : basic_type::Varchar; } - template < int N > + + template static void read_value(attribute_reader &reader, const char *id, const size_t index, char (&value)[N], const size_t size) { - data_type_traits::read_value(reader, id, index, value, size); + data_type_traits::read_value(reader, id, index, value, size); } - template < int N > + + template static void bind_value(attribute_writer &binder, const size_t index, char *value, const size_t size = 0) { - data_type_traits::bind_value(binder, index, value, size); + data_type_traits::bind_value(binder, index, value, size); } }; -template <> struct data_type_traits -{ +template<> +struct data_type_traits { static basic_type type(const std::size_t size) { return size == 0 ? basic_type::Text : basic_type::Varchar; } static void read_value(attribute_reader &reader, const char *id, size_t index, std::string &value, size_t size); static void bind_value(attribute_writer &binder, size_t index, std::string &value, size_t size = 0); }; -template <> struct data_type_traits -{ +template<> +struct data_type_traits { static basic_type type(std::size_t /*size*/) { return basic_type::Blob; } - static void read_value(attribute_reader &reader, const char *id, size_t index, utils::blob &value, size_t /*size*/ = 0); - static void bind_value(attribute_writer &binder, size_t index, utils::blob &value, size_t /*size*/ = 0); + static void read_value(attribute_reader &reader, const char *id, size_t index, utils::blob &value, size_t /*size*/ = 0); + static void bind_value(attribute_writer &binder, size_t index, utils::blob &value, size_t /*size*/ = 0); }; -//template <> struct data_type_traits -//{ -// static basic_type type(std::size_t /*size*/) { return basic_type::type_date; } -// static void read_value(attribute_reader &reader, const char *id, size_t index, matador::date &value); -// static void bind_value(attribute_writer &binder, size_t index, matador::date &value); -//}; -// -//template <> struct data_type_traits -//{ -// static basic_type type(std::size_t /*size*/) { return basic_type::type_time; } -// static void read_value(attribute_reader &reader, const char *id, size_t index, matador::time &value); -// static void bind_value(attribute_writer &binder, size_t index, matador::time &value); -//}; +template<> +struct data_type_traits { + static basic_type type(std::size_t /*size*/) { return basic_type::Date; } + static void read_value(attribute_reader &reader, const char *id, size_t index, date_type_t &value); + static void bind_value(attribute_writer &binder, size_t index, date_type_t &value); +}; + +template<> +struct data_type_traits { + static basic_type type(std::size_t /*size*/) { return basic_type::Time; } + static void read_value(attribute_reader &reader, const char *id, size_t index, time_type_t &value); + static void bind_value(attribute_writer &binder, size_t index, time_type_t &value); +}; + +template +struct data_type_traits > > { + static basic_type type(std::size_t /*size*/ = 0) { return basic_type::Int32; } -template < typename EnumType > -struct data_type_traits>> -{ - static basic_type type(std::size_t /*size*/ = 0) { return basic_type::Int32; } static void read_value(attribute_reader &reader, const char *id, const size_t index, EnumType &value, const size_t size = 0) { - data_type_traits::read_value(reader, id, index, reinterpret_cast(value), size); + data_type_traits::read_value(reader, id, index, reinterpret_cast(value), size); } + static void bind_value(attribute_writer &binder, const size_t index, EnumType &value, const size_t size = 0) { data_type_traits::bind_value(binder, index, static_cast(value), size); } }; -/// @endcond +/// @endcond } #endif //MATADOR_DEFAULT_TYPE_TRAITS_HPP diff --git a/include/matador/utils/string.hpp b/include/matador/utils/string.hpp index a4301a4..5f18ace 100644 --- a/include/matador/utils/string.hpp +++ b/include/matador/utils/string.hpp @@ -19,6 +19,8 @@ namespace matador::utils { * @return Binary data as string */ MATADOR_UTILS_API std::string to_string(const blob &data); +MATADOR_UTILS_API std::string to_string(const date_type_t &data); +MATADOR_UTILS_API std::string to_string(const time_type_t &data); /** * Splits a string by a delimiter and diff --git a/source/core/utils/default_type_traits.cpp b/source/core/utils/default_type_traits.cpp index 1db2c22..27c8a4d 100644 --- a/source/core/utils/default_type_traits.cpp +++ b/source/core/utils/default_type_traits.cpp @@ -127,28 +127,24 @@ void data_type_traits::read_value(attribute_reader &reader, const char *id reader.read_value(id, index, value); } -void data_type_traits::bind_value(attribute_writer &binder, const size_t index, utils::blob &value, const size_t /*size*/) { +void data_type_traits::bind_value(attribute_writer &binder, const size_t index, blob &value, const size_t /*size*/) { binder.write_value(index, value); } -// void data_type_traits::read_value(attribute_reader &reader, const char *id, size_t index, date &value) -// { -// reader.read_value(id, index, value); -// } -// -// void data_type_traits::bind_value(attribute_writer &binder, size_t index, date &value) -// { -// binder.write_value(index, value); -// } -// -// void data_type_traits::read_value(attribute_reader &reader, const char *id, size_t index, time &value) -// { -// reader.read_value(id, index, value); -// } -// -// void data_type_traits::bind_value(attribute_writer &binder, size_t index, time &value) -// { -// binder.write_value(index, value); -// } +void data_type_traits::read_value(attribute_reader &reader, const char *id, size_t index, date_type_t &value) { + reader.read_value(id, index, value); +} + +void data_type_traits::bind_value(attribute_writer &binder, const size_t index, date_type_t &value) { + binder.write_value(index, value); +} + +void data_type_traits::read_value(attribute_reader &reader, const char *id, size_t index, time_type_t &value) { + reader.read_value(id, index, value); +} + +void data_type_traits::bind_value(attribute_writer &binder, const size_t index, time_type_t &value) { + binder.write_value(index, value); +} } \ No newline at end of file diff --git a/source/core/utils/string.cpp b/source/core/utils/string.cpp index 1bd247c..8f62474 100644 --- a/source/core/utils/string.cpp +++ b/source/core/utils/string.cpp @@ -18,6 +18,24 @@ std::string to_string(const blob& data) { return str; } +std::string to_string(const date_type_t &data) { + char buf[11]; // "YYYY-MM-DD" + '\0' + + std::snprintf(buf, sizeof(buf), "%04d-%02u-%02u", + data.year, static_cast(data.month), static_cast(data.day)); + + return buf; +} + +std::string to_string(const time_type_t &data) { + char buf[16]; // "HH:MM:SS.ffffff" + '\0' + + std::snprintf(buf, sizeof(buf), "%02u:%02u:%02u.%06u", + static_cast(data.hour), static_cast(data.minute), static_cast(data.second), data.microsecond); + + return buf; +} + size_t split(const std::string &str, char delim, std::vector &values) { std::stringstream ss(str); diff --git a/source/orm/query/attribute_string_writer.cpp b/source/orm/query/attribute_string_writer.cpp index 7d1ae54..28fbe1e 100644 --- a/source/orm/query/attribute_string_writer.cpp +++ b/source/orm/query/attribute_string_writer.cpp @@ -9,104 +9,108 @@ #include "matador/utils/string.hpp" namespace matador::query { - -attribute_string_writer::attribute_string_writer(const sql::dialect &d, const std::optional> conn) +attribute_string_writer::attribute_string_writer(const sql::dialect &d, + const std::optional > conn) : dialect_(d) -, conn_(conn) {} - -const sql::dialect& attribute_string_writer::dialect() const { - return dialect_; + , conn_(conn) { } -void attribute_string_writer::write_value(size_t /*pos*/, const int8_t& x ) { - result_ = std::to_string(x) ; +const sql::dialect &attribute_string_writer::dialect() const { + return dialect_; } -void attribute_string_writer::write_value(size_t /*pos*/, const int16_t& x ) { - result_ = std::to_string(x) ; +void attribute_string_writer::write_value(size_t /*pos*/, const int8_t &x) { + result_ = std::to_string(x); } -void attribute_string_writer::write_value(size_t /*pos*/, const int32_t& x ) { - result_ = std::to_string(x) ; +void attribute_string_writer::write_value(size_t /*pos*/, const int16_t &x) { + result_ = std::to_string(x); } -void attribute_string_writer::write_value(size_t /*pos*/, const int64_t& x ) { - result_ = std::to_string(x) ; +void attribute_string_writer::write_value(size_t /*pos*/, const int32_t &x) { + result_ = std::to_string(x); } -void attribute_string_writer::write_value(size_t /*pos*/, const uint8_t& x ) { - result_ = std::to_string(x) ; +void attribute_string_writer::write_value(size_t /*pos*/, const int64_t &x) { + result_ = std::to_string(x); } -void attribute_string_writer::write_value(size_t /*pos*/, const uint16_t& x ) { - result_ = std::to_string(x) ; +void attribute_string_writer::write_value(size_t /*pos*/, const uint8_t &x) { + result_ = std::to_string(x); } -void attribute_string_writer::write_value(size_t /*pos*/, const uint32_t& x ) { - result_ = std::to_string(x) ; +void attribute_string_writer::write_value(size_t /*pos*/, const uint16_t &x) { + result_ = std::to_string(x); } -void attribute_string_writer::write_value(size_t /*pos*/, const uint64_t& x ) { - result_ = std::to_string(x) ; +void attribute_string_writer::write_value(size_t /*pos*/, const uint32_t &x) { + result_ = std::to_string(x); } -void attribute_string_writer::write_value(size_t /*pos*/, const bool& x ) { -// result_ = "'" + conn_->dialect().prepare_literal(x ? "true" : "false") + "'"; +void attribute_string_writer::write_value(size_t /*pos*/, const uint64_t &x) { + result_ = std::to_string(x); +} + +void attribute_string_writer::write_value(size_t /*pos*/, const bool &x) { + // result_ = "'" + conn_->dialect().prepare_literal(x ? "true" : "false") + "'"; result_ = dialect_.to_string(x); } -void attribute_string_writer::write_value(size_t /*pos*/, const float& x ) { +void attribute_string_writer::write_value(size_t /*pos*/, const float &x) { if (const auto res = utils::to(x); !res.is_error()) { result_ = *res; } } -void attribute_string_writer::write_value(size_t /*pos*/, const double& x ) { +void attribute_string_writer::write_value(size_t /*pos*/, const double &x) { if (const auto res = utils::to(x); !res.is_error()) { result_ = *res; } } -void attribute_string_writer::write_value(size_t /*pos*/, const utils::date_type_t& /*x*/ ) { - // result_ = "'" + dialect_.prepare_literal(utils::to_string(x)) + "'"; +void attribute_string_writer::write_value(size_t /*pos*/, const utils::date_type_t &x) { + result_ = "'" + dialect_.prepare_literal(utils::to_string(x)) + "'"; } -void attribute_string_writer::write_value(size_t /*pos*/, const utils::time_type_t& /*x*/ ) { -// result_ = "'" + dialect_.prepare_literal(utils::to_string(x, "%F %T.%f")) + "'"; +void attribute_string_writer::write_value(size_t /*pos*/, const utils::time_type_t &x) { + result_ = "'" + dialect_.prepare_literal(utils::to_string(x)) + "'"; } void attribute_string_writer::write_value(size_t /*pos*/, const utils::timestamp &/*x*/) { } -void attribute_string_writer::write_value(size_t pos, const char* x ) { - write_value(pos, std::string(x) ); +void attribute_string_writer::write_value(size_t pos, const char *x) { + write_value(pos, std::string(x)); } -void attribute_string_writer::write_value(size_t pos, const char* x, size_t /*size*/) { - write_value(pos, std::string(x) ); +void attribute_string_writer::write_value(size_t pos, const char *x, size_t /*size*/) { + write_value(pos, std::string(x)); } -void attribute_string_writer::write_value(size_t /*pos*/, const std::string& x ) { +void attribute_string_writer::write_value(size_t /*pos*/, const std::string &x) { result_ = "'" + dialect_.prepare_literal(x) + "'"; } -void attribute_string_writer::write_value(size_t /*pos*/, const std::string& x, size_t /*size*/) { +void attribute_string_writer::write_value(size_t /*pos*/, const std::string &x, size_t /*size*/) { result_ = "'" + dialect_.prepare_literal(x) + "'"; } -void attribute_string_writer::write_value(size_t /*pos*/, const utils::blob& x ) { +void attribute_string_writer::write_value(size_t /*pos*/, const utils::blob &x) { // "This is a binary Data string" as binary data: // MySQL: X'5468697320697320612062616E617279204461746120737472696E67' // Postgres: '\\x5468697320697320612062616E617279204461746120737472696E67' // MSSQL: 0x5468697320697320612062616E617279204461746120737472696E67 // Sqlite: X'5468697320697320612062616E617279204461746120737472696E67' if (conn_.has_value()) { - result_ = dialect_.token_at(sql::dialect_token::BeginBinaryData) + conn_.value().get().to_escaped_string(x) + dialect_.token_at(sql::dialect_token::EndBinaryData); + result_ = dialect_.token_at(sql::dialect_token::BeginBinaryData) + conn_.value().get().to_escaped_string(x) + + dialect_.token_at(sql::dialect_token::EndBinaryData); } else { - result_ = dialect_.token_at(sql::dialect_token::BeginBinaryData) + dialect_.to_escaped_string(x) + dialect_.token_at(sql::dialect_token::EndBinaryData); + result_ = dialect_.token_at(sql::dialect_token::BeginBinaryData) + dialect_.to_escaped_string(x) + dialect_. + token_at(sql::dialect_token::EndBinaryData); } } -void attribute_string_writer::write_value(size_t /*pos*/, const utils::value &/*x*/, size_t /*size*/) {} - -} \ No newline at end of file +void attribute_string_writer::write_value(size_t /*pos*/, const utils::value &/*x*/, size_t /*size*/) { +} +} diff --git a/source/orm/query/internal/query_result_impl.cpp b/source/orm/query/internal/query_result_impl.cpp index bbfbb7b..f985bbe 100644 --- a/source/orm/query/internal/query_result_impl.cpp +++ b/source/orm/query/internal/query_result_impl.cpp @@ -3,49 +3,47 @@ #include "matador/sql/interface/query_result_reader.hpp" namespace matador::sql { - detail::pk_reader::pk_reader(query_result_reader &reader) -: reader_(reader) {} +: reader_(reader) { +} -query_result_impl::query_result_impl(std::unique_ptr &&reader, std::vector &&prototype, const size_t column_index) +query_result_impl::query_result_impl(std::unique_ptr &&reader, + std::vector &&prototype, + const size_t column_index) : column_index_(column_index) -, prototype_(std::move(prototype)) -, reader_(std::move(reader)) -, pk_reader_(*reader_) -{} + , prototype_(std::move(prototype)) + , reader_(std::move(reader)) + , pk_reader_(*reader_) { +} -query_result_impl::query_result_impl(std::unique_ptr &&reader, const std::vector &prototype, const size_t column_index) +query_result_impl::query_result_impl(std::unique_ptr &&reader, + const std::vector &prototype, + const size_t column_index) : column_index_(column_index) -, prototype_(prototype) -, reader_(std::move(reader)) -, pk_reader_(*reader_) -{} + , prototype_(prototype) + , reader_(std::move(reader)) + , pk_reader_(*reader_) { +} -void query_result_impl::on_revision(const char *id, uint64_t &rev) -{ +void query_result_impl::on_revision(const char *id, uint64_t &rev) { utils::data_type_traits::read_value(*reader_, id, column_index_++, rev); reader_->read_value(id, column_index_++, rev); } -void query_result_impl::on_attribute(const char *id, char *value, const utils::field_attributes &attr) -{ - utils::data_type_traits::read_value(*reader_, id, column_index_++, value, attr.size()); +void query_result_impl::on_attribute(const char *id, char *value, const utils::field_attributes &attr) { + utils::data_type_traits::read_value(*reader_, id, column_index_++, value, attr.size()); } -void query_result_impl::on_attribute(const char *id, std::string &value, const utils::field_attributes &attr) -{ +void query_result_impl::on_attribute(const char *id, std::string &value, const utils::field_attributes &attr) { utils::data_type_traits::read_value(*reader_, id, column_index_++, value, attr.size()); } void -query_result_impl::on_attribute(const char *id, utils::value &val, const utils::field_attributes &attr) -{ +query_result_impl::on_attribute(const char *id, utils::value &val, const utils::field_attributes &attr) { reader_->read_value(id, column_index_++, val, attr.size()); } -const std::vector& query_result_impl::prototype() const -{ +const std::vector &query_result_impl::prototype() const { return prototype_; } - -} \ No newline at end of file +} diff --git a/source/orm/query/value_extractor.cpp b/source/orm/query/value_extractor.cpp index 71ca649..23322ff 100644 --- a/source/orm/query/value_extractor.cpp +++ b/source/orm/query/value_extractor.cpp @@ -61,15 +61,16 @@ void value_extractor::write_value(size_t /*pos*/, const double &x) { values_.emplace_back(x); } -void value_extractor::write_value(size_t /*pos*/, const utils::date_type_t &/*x*/) { - // values_.emplace_back(x); +void value_extractor::write_value(size_t /*pos*/, const utils::date_type_t &x) { + values_.emplace_back(x); } -void value_extractor::write_value(size_t /*pos*/, const utils::time_type_t &/*x*/) { - // values_.emplace_back(x); +void value_extractor::write_value(size_t /*pos*/, const utils::time_type_t &x) { + values_.emplace_back(x); } -void value_extractor::write_value(size_t /*pos*/, const utils::timestamp &/*x*/) { +void value_extractor::write_value(size_t /*pos*/, const utils::timestamp &x) { + values_.emplace_back(x); } void value_extractor::write_value(size_t /*pos*/, const char *x) { diff --git a/source/orm/sql/dialect.cpp b/source/orm/sql/dialect.cpp index ede0d4b..8f25d66 100644 --- a/source/orm/sql/dialect.cpp +++ b/source/orm/sql/dialect.cpp @@ -6,8 +6,7 @@ #include "matador/utils/value.hpp" namespace matador::sql { - -const std::string& dialect::token_at(const dialect_token token) const { +const std::string &dialect::token_at(const dialect_token token) const { return tokens_.at(token); } @@ -15,22 +14,21 @@ const std::string &dialect::data_type_at(const utils::basic_type type) const { return data_types_.at(type); } -const std::string& dialect::sql_function_at(const sql_function_t func) const { +const std::string &dialect::sql_function_at(const sql_function_t func) const { return sql_func_map_.at(func); } -std::string dialect::table_name( const std::string& table, const std::string& schema_name ) const { - if ( schema_name.empty() && default_schema_name_.empty()) { - return prepare_identifier_string( table ); - } - if ( schema_name.empty() ) { - return prepare_identifier_string( default_schema_name_ ) + "." + prepare_identifier_string( table ); - } - return prepare_identifier_string( schema_name ) + "." + prepare_identifier_string( table ); +std::string dialect::table_name(const std::string &table, const std::string &schema_name) const { + if (schema_name.empty() && default_schema_name_.empty()) { + return prepare_identifier_string(table); + } + if (schema_name.empty()) { + return prepare_identifier_string(default_schema_name_) + "." + prepare_identifier_string(table); + } + return prepare_identifier_string(schema_name) + "." + prepare_identifier_string(table); } -const std::string& dialect::to_string(const bool val) const -{ +const std::string &dialect::to_string(const bool val) const { return bool_strings_[static_cast(val)]; } @@ -45,38 +43,33 @@ std::string dialect::to_sql_string(const utils::value &val) const { return val.str(); } -void dialect::bool_strings(const std::string &true_string, const std::string &false_string) -{ +void dialect::bool_strings(const std::string &true_string, const std::string &false_string) { bool_strings_[0] = false_string; bool_strings_[1] = true_string; } -std::string dialect::prepare_identifier_string(const std::string &col) const -{ +std::string dialect::prepare_identifier_string(const std::string &col) const { auto parts = utils::split(col, '.'); - for (auto &part : parts) { + for (auto &part: parts) { escape_quotes_in_identifier(part); quote_identifier(part); } return utils::join(parts, "."); } -std::string dialect::prepare_literal(const std::string &str) const -{ +std::string dialect::prepare_literal(const std::string &str) const { std::string result(str); escape_quotes_in_literals(result); return result; } -void dialect::quote_identifier(std::string &str) const -{ +void dialect::quote_identifier(std::string &str) const { str.insert(0, token_at(dialect_token::StartQuote)); str += token_at(dialect_token::EndQuote); } -void dialect::escape_quotes_in_identifier(std::string &str) const -{ +void dialect::escape_quotes_in_identifier(std::string &str) const { const std::string open_char(token_at(dialect_token::StartQuote)); const std::string close_char(token_at(dialect_token::EndQuote)); if (identifier_escape_type() == escape_identifier_t::ESCAPE_CLOSING_BRACKET) { @@ -86,8 +79,7 @@ void dialect::escape_quotes_in_identifier(std::string &str) const } } -void dialect::escape_quotes_in_literals(std::string &str) const -{ +void dialect::escape_quotes_in_literals(std::string &str) const { const std::string single_quote(token_at(dialect_token::StringQuote)); const std::string double_quote(token_at(dialect_token::StringQuote) + token_at(dialect_token::StringQuote)); utils::replace_all(str, single_quote, double_quote); @@ -101,13 +93,11 @@ void dialect::identifier_escape_type(escape_identifier_t escape_identifier) { identifier_escape_type_ = escape_identifier; } -std::string dialect::next_placeholder(const std::vector &bind_vars) const -{ +std::string dialect::next_placeholder(const std::vector &bind_vars) const { return placeholder_func_(bind_vars.size()); } -std::string dialect::to_escaped_string(const utils::blob &value, const connection_impl *conn) const -{ +std::string dialect::to_escaped_string(const utils::blob &value, const connection_impl *conn) const { if (conn != nullptr) { return conn->to_escaped_string(value); } @@ -115,212 +105,211 @@ std::string dialect::to_escaped_string(const utils::blob &value, const connectio return to_escaped_string_func_(value); } -std::string dialect::default_schema_name() const -{ +std::string dialect::default_schema_name() const { return default_schema_name_; } -const std::string& dialect::add_constraint() const { +const std::string &dialect::add_constraint() const { return token_at(dialect_token::AddConstraint); } -const std::string& dialect::alter() const { +const std::string &dialect::alter() const { return token_at(dialect_token::Alter); } -const std::string& dialect::and_() const { +const std::string &dialect::and_() const { return token_at(dialect_token::And); } -const std::string& dialect::as() const { +const std::string &dialect::as() const { return token_at(dialect_token::As); } -const std::string& dialect::asc() const { +const std::string &dialect::asc() const { return token_at(dialect_token::Asc); } -const std::string& dialect::begin() const { +const std::string &dialect::begin() const { return token_at(dialect_token::Begin); } -const std::string& dialect::asterisk() const { +const std::string &dialect::asterisk() const { return token_at(dialect_token::Asterisk); } -const std::string& dialect::begin_binary_data() const { +const std::string &dialect::begin_binary_data() const { return token_at(dialect_token::BeginBinaryData); } -const std::string& dialect::begin_string_data() const { +const std::string &dialect::begin_string_data() const { return token_at(dialect_token::BeginStringData); } -const std::string& dialect::between() const { +const std::string &dialect::between() const { return token_at(dialect_token::Between); } -const std::string& dialect::column() const { +const std::string &dialect::column() const { return token_at(dialect_token::Column); } -const std::string& dialect::columns() const { +const std::string &dialect::columns() const { return token_at(dialect_token::Columns); } -const std::string& dialect::commit() const { +const std::string &dialect::commit() const { return token_at(dialect_token::Commit); } -const std::string& dialect::constraint() const { +const std::string &dialect::constraint() const { return token_at(dialect_token::Constraint); } -const std::string& dialect::create() const { +const std::string &dialect::create() const { return token_at(dialect_token::Create); } -const std::string& dialect::drop() const { +const std::string &dialect::drop() const { return token_at(dialect_token::Drop); } -const std::string& dialect::end_binary_data() const { +const std::string &dialect::end_binary_data() const { return token_at(dialect_token::EndBinaryData); } -const std::string& dialect::end_string_data() const { +const std::string &dialect::end_string_data() const { return token_at(dialect_token::EndStringData); } -const std::string& dialect::from() const { +const std::string &dialect::from() const { return token_at(dialect_token::From); } -const std::string& dialect::in() const { +const std::string &dialect::in() const { return token_at(dialect_token::In); } -const std::string& dialect::desc() const { +const std::string &dialect::desc() const { return token_at(dialect_token::Desc); } -const std::string& dialect::distinct() const { +const std::string &dialect::distinct() const { return token_at(dialect_token::Distinct); } -const std::string& dialect::drop_constraint() const { +const std::string &dialect::drop_constraint() const { return token_at(dialect_token::DropConstraint); } -const std::string& dialect::end_quote() const { +const std::string &dialect::end_quote() const { return token_at(dialect_token::EndQuote); } -const std::string& dialect::foreign_key() const { +const std::string &dialect::foreign_key() const { return token_at(dialect_token::ForeignKey); } -const std::string& dialect::group_by() const { +const std::string &dialect::group_by() const { return token_at(dialect_token::GroupBy); } -const std::string& dialect::insert() const { +const std::string &dialect::insert() const { return token_at(dialect_token::Insert); } -const std::string& dialect::into() const { +const std::string &dialect::into() const { return token_at(dialect_token::Into); } -const std::string& dialect::join() const { +const std::string &dialect::join() const { return token_at(dialect_token::Join); } -const std::string& dialect::like() const { +const std::string &dialect::like() const { return token_at(dialect_token::Like); } -const std::string& dialect::limit() const { +const std::string &dialect::limit() const { return token_at(dialect_token::Limit); } -const std::string& dialect::not_() const { +const std::string &dialect::not_() const { return token_at(dialect_token::Not); } -const std::string& dialect::not_null() const { +const std::string &dialect::not_null() const { return token_at(dialect_token::NotNull); } -const std::string& dialect::offset() const { +const std::string &dialect::offset() const { return token_at(dialect_token::Offset); } -const std::string& dialect::on() const { +const std::string &dialect::on() const { return token_at(dialect_token::On); } -const std::string& dialect::or_() const { +const std::string &dialect::or_() const { return token_at(dialect_token::Or); } -const std::string& dialect::order_by() const { +const std::string &dialect::order_by() const { return token_at(dialect_token::OrderBy); } -const std::string& dialect::primary_key() const { +const std::string &dialect::primary_key() const { return token_at(dialect_token::PrimaryKey); } -const std::string& dialect::references() const { +const std::string &dialect::references() const { return token_at(dialect_token::References); } -const std::string& dialect::remove() const { +const std::string &dialect::remove() const { return token_at(dialect_token::Remove); } -const std::string& dialect::rollback() const { +const std::string &dialect::rollback() const { return token_at(dialect_token::Rollback); } -const std::string& dialect::schema() const { +const std::string &dialect::schema() const { return token_at(dialect_token::Schema); } -const std::string& dialect::select() const { +const std::string &dialect::select() const { return token_at(dialect_token::Select); } -const std::string& dialect::set() const { +const std::string &dialect::set() const { return token_at(dialect_token::Set); } -const std::string& dialect::start_quote() const { +const std::string &dialect::start_quote() const { return token_at(dialect_token::StartQuote); } -const std::string& dialect::string_quote() const { +const std::string &dialect::string_quote() const { return token_at(dialect_token::StringQuote); } -const std::string& dialect::table() const { +const std::string &dialect::table() const { return token_at(dialect_token::Table); } -const std::string & dialect::unique() const { +const std::string &dialect::unique() const { return token_at(dialect_token::Unique); } -const std::string& dialect::update() const { +const std::string &dialect::update() const { return token_at(dialect_token::Update); } -const std::string& dialect::values() const { +const std::string &dialect::values() const { return token_at(dialect_token::Values); } -const std::string& dialect::where() const { +const std::string &dialect::where() const { return token_at(dialect_token::Where); } } diff --git a/test/backends/QueryRecordTest.cpp b/test/backends/QueryRecordTest.cpp index 04c8996..e75fd4a 100644 --- a/test/backends/QueryRecordTest.cpp +++ b/test/backends/QueryRecordTest.cpp @@ -26,9 +26,6 @@ TEST_CASE_METHOD(QueryFixture, "Test all data types for record", "[query][record const table tab("types"); - // auto r = query::create().table(tab).columns({ - // column("id", basic_type::UInt32) - // }); auto res = query::create() .table(tab) .columns({ @@ -46,8 +43,8 @@ TEST_CASE_METHOD(QueryFixture, "Test all data types for record", "[query][record column("val_double", basic_type::Double), column("val_string", basic_type::Text), column("val_varchar", basic_type::Varchar, 63), - // column("val_date", basic_type::type_date), - // column("val_time", basic_type::type_time), + column("val_date", basic_type::Date), + column("val_time", basic_type::Time), column("val_blob", basic_type::Blob), }) .constraints({ @@ -66,7 +63,7 @@ TEST_CASE_METHOD(QueryFixture, "Test all data types for record", "[query][record "val_bool", "val_float", "val_double", "val_string", "val_varchar", - // "val_date", "val_time", + "val_date", "val_time", "val_blob"}; const auto fields = db.describe("types"); @@ -89,41 +86,43 @@ TEST_CASE_METHOD(QueryFixture, "Test all data types for record", "[query][record double d{2.71828}; std::string str{"long text"}; std::string varchar{"good day"}; - // auto md{matador::date()}; - // auto mt{matador::time::now()}; + date_type_t md{2025, 11, 27}; + time_type_t mt{12, 34, 56}; blob bin{0x01,0x02,0x03,0x04}; res = query::insert() .into("types", cols) - .values({id, c, s, i, ll, uc, us, ui, ull, b, f, d, str, varchar, /*md, mt, */bin}) + .values({id, c, s, i, ll, uc, us, ui, ull, b, f, d, str, varchar, md, mt, bin}) .execute(db); REQUIRE(res.is_ok()); REQUIRE(res.value() == 1); - auto row = query::select(cols) + auto result = query::select(cols) .from("types") .fetch_one(db); - REQUIRE(row.is_ok()); - REQUIRE(row.value().has_value()); + REQUIRE(result.is_ok()); + REQUIRE(result.value().has_value()); - REQUIRE(id == (*row)->at("id")); - REQUIRE(c == (*row)->at("val_char")); - REQUIRE(s == (*row)->at("val_short")); - REQUIRE(i == (*row)->at("val_int")); - REQUIRE(ll == (*row)->at("val_long_long")); - REQUIRE(uc == (*row)->at("val_uchar")); - REQUIRE(us == (*row)->at("val_ushort")); - REQUIRE(ui == (*row)->at("val_uint")); - REQUIRE(ull == (*row)->at("val_ulong_long")); - REQUIRE((*row)->at("val_bool")); - REQUIRE(f == (*row)->at("val_float")); - REQUIRE(d == (*row)->at("val_double")); - REQUIRE(str == (*row)->at("val_string")); - REQUIRE(varchar == (*row)->at("val_varchar")); - // REQUIRE(md == (*row)->at("val_date")); - // REQUIRE(mt == (*row)->at("val_time")); - REQUIRE(bin == (*row)->at("val_blob")); + const auto &row = result.value().value(); + REQUIRE(id == row.at("id")); + REQUIRE(c == row.at("val_char")); + REQUIRE(s == row.at("val_short")); + REQUIRE(i == row.at("val_int")); + REQUIRE(ll == row.at("val_long_long")); + REQUIRE(uc == row.at("val_uchar")); + REQUIRE(us == row.at("val_ushort")); + REQUIRE(ui == row.at("val_uint")); + REQUIRE(ull == row.at("val_ulong_long")); + REQUIRE(row.at("val_bool")); + REQUIRE(f == row.at("val_float")); + REQUIRE(d == row.at("val_double")); + REQUIRE(str == row.at("val_string")); + REQUIRE(varchar == row.at("val_varchar")); + REQUIRE(md == row.at("val_date")); + const auto mtres = row.at("val_time"); + REQUIRE(mt == row.at("val_time")); + REQUIRE(bin == row.at("val_blob")); } TEST_CASE_METHOD(QueryFixture, "Create and drop table statement", "[query][record]")