added test for date and time, sql read and write functionality

This commit is contained in:
Sascha Kühl 2026-01-06 22:23:50 +01:00
parent 0c6b5a0a93
commit c48bd4f9d6
17 changed files with 516 additions and 360 deletions

View File

@ -9,8 +9,7 @@ namespace matador::backends::postgres {
namespace detail { namespace detail {
class empty_binder final : public utils::attribute_reader class empty_binder final : public utils::attribute_reader {
{
public: public:
void read_value(const char *, size_t, int8_t &) override {} void read_value(const char *, size_t, int8_t &) override {}
void read_value(const char *, size_t, int16_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, bool &) override {}
void read_value(const char *, size_t, float &) 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, double &) override {}
void read_value(const char *, size_t, time &) override {} void read_value(const char *, size_t, utils::date_type_t &) override {}
void read_value(const char *, size_t, date &) 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, char *, size_t) override {}
void read_value(const char *, size_t, std::string &) override {} void read_value(const char *, size_t, std::string &) override {}
void read_value(const char *, size_t, std::string &, size_t) 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: public:
explicit postgres_result_reader(PGresult *result); explicit postgres_result_reader(PGresult *result);
~postgres_result_reader() override; ~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, bool &value) override;
void read_value(const char *id, size_t index, float &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, 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, utils::date_type_t &) override;
void read_value(const char *id, size_t index, matador::date &value) 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, 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) override;
void read_value(const char *id, size_t index, std::string &value, size_t size) override; void read_value(const char *id, size_t index, std::string &value, size_t size) override;

View File

@ -178,8 +178,10 @@ utils::basic_type oid2type(const Oid oid) {
return utils::basic_type::Double; return utils::basic_type::Double;
case 1082: case 1082:
return utils::basic_type::Date; return utils::basic_type::Date;
case 1114: case 1083:
return utils::basic_type::Time; return utils::basic_type::Time;
case 1114:
return utils::basic_type::DateTime;
default: default:
return utils::basic_type::Null; return utils::basic_type::Null;
} }
@ -201,9 +203,12 @@ utils::basic_type string2type(const char *type) {
if (strcmp(type, "date") == 0) { if (strcmp(type, "date") == 0) {
return utils::basic_type::Date; return utils::basic_type::Date;
} }
if (strcmp(type, "timestamp") == 0) { if (strcmp(type, "time") == 0) {
return utils::basic_type::Time; return utils::basic_type::Time;
} }
if (strcmp(type, "timestamp") == 0) {
return utils::basic_type::DateTime;
}
if (strcmp(type, "float4") == 0) { if (strcmp(type, "float4") == 0) {
return utils::basic_type::Float; return utils::basic_type::Float;
} }

View File

@ -20,7 +20,8 @@
{matador::utils::basic_type::UInt8, "SMALLINT"}, {matador::utils::basic_type::UInt8, "SMALLINT"},
{matador::utils::basic_type::Float, "REAL"}, {matador::utils::basic_type::Float, "REAL"},
{matador::utils::basic_type::Double, "DOUBLE PRECISION"}, {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"} {matador::utils::basic_type::Blob, "BYTEA"}
}) })
.with_bool_strings("TRUE", "FALSE") .with_bool_strings("TRUE", "FALSE")

View File

@ -123,15 +123,23 @@ void postgres_parameter_binder::write_value(const size_t pos, const std::string
write_value(pos, x); write_value(pos, x);
} }
void postgres_parameter_binder::write_value(const size_t pos, const utils::date_type_t &/*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); char buf[11]; // "YYYY-MM-DD" + '\0'
std::snprintf(buf, sizeof(buf), "%04d-%02u-%02u", x.year, static_cast<unsigned>(x.month), static_cast<unsigned>(x.day));
bind_data_.strings[pos] = std::string{buf};
bind_data_.values[pos] = bind_data_.strings[pos].data(); bind_data_.values[pos] = bind_data_.strings[pos].data();
bind_data_.lengths[pos] = static_cast<int>(bind_data_.strings[pos].size()); bind_data_.lengths[pos] = static_cast<int>(bind_data_.strings[pos].size());
bind_data_.formats[pos] = 0; bind_data_.formats[pos] = 0;
} }
void postgres_parameter_binder::write_value(const size_t pos, const utils::time_type_t &/*x*/) { 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"); char buf[16]; // "HH:MM:SS.ffffff" + '\0'
std::snprintf(buf, sizeof(buf), "%02u:%02u:%02u.%06u",
static_cast<unsigned>(x.hour), static_cast<unsigned>(x.minute), static_cast<unsigned>(x.second), x.microsecond);
bind_data_.strings[pos] = std::string{buf};
bind_data_.values[pos] = bind_data_.strings[pos].data(); bind_data_.values[pos] = bind_data_.strings[pos].data();
bind_data_.lengths[pos] = static_cast<int>(bind_data_.strings[pos].size()); bind_data_.lengths[pos] = static_cast<int>(bind_data_.strings[pos].size());
bind_data_.formats[pos] = 0; bind_data_.formats[pos] = 0;

View File

@ -4,27 +4,23 @@
#include "matador/utils/value.hpp" #include "matador/utils/value.hpp"
namespace matador::backends::postgres { namespace matador::backends::postgres {
postgres_result_reader::postgres_result_reader(PGresult *result) postgres_result_reader::postgres_result_reader(PGresult *result)
: result_(result) : result_(result)
, row_count_(PQntuples(result_)) , row_count_(PQntuples(result_))
, column_count_(PQnfields(result_)) , column_count_(PQnfields(result_)) {
{} }
postgres_result_reader::~postgres_result_reader() postgres_result_reader::~postgres_result_reader() {
{
if (result_) { if (result_) {
PQclear(result_); PQclear(result_);
} }
} }
size_t postgres_result_reader::column_count() const size_t postgres_result_reader::column_count() const {
{
return column_count_; 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<int>(row_index_), static_cast<int>(index)); return PQgetvalue(result_, static_cast<int>(row_index_), static_cast<int>(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*/) { 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) { if (const auto val = column(index); strlen(val) > 0) {
// value = time::parse(val, "%Y-%m-%d %T.%f"); // value = time::parse(val, "%Y-%m-%d %T.%f");
// } }
} }
void postgres_result_reader::read_value(const char * /*id*/, const size_t /*index*/, date &/*value*/) { 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) { if (const auto val = column(index); strlen(val) > 0) {
// value.set(val, matador::utils::date_format::ISO8601); // 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) { 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 #else
strncpy(value, val, size); strncpy(value, val, size);
#endif #endif
value[size-1] = '\n'; value[size - 1] = '\n';
} else { } else {
#ifdef _MSC_VER #ifdef _MSC_VER
strcpy_s(value, size, val); 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)); value.assign(column(index));
} }
void postgres_result_reader::read_value( const char* /*id*/, const size_t index, utils::blob& value ) void postgres_result_reader::read_value(const char * /*id*/, const size_t index, utils::blob &value) {
{ const auto *data = reinterpret_cast<const unsigned char *>(column(index));
const auto *data = reinterpret_cast<const unsigned char*>(column(index));
// auto length = PQgetlength(result_, row_index_, static_cast<int>(index));
size_t length; 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); PQfreemem(unescaped);
} }
template <typename Type> template<typename Type>
void set_value(const char* str, utils::value& value) { void set_value(const char *str, utils::value &value) {
if (const auto res = utils::to<Type>(str); res.is_ok()) { if (const auto res = utils::to<Type>(str); res.is_ok()) {
value = res.value(); value = res.value();
} }
} }
template <> template<>
void set_value<utils::blob>(const char* str, utils::value& value) { void set_value<utils::blob>(const char *str, utils::value &value) {
size_t length; size_t length;
unsigned char* unescaped = PQunescapeBytea(reinterpret_cast<const unsigned char*>(str), &length); unsigned char *unescaped = PQunescapeBytea(reinterpret_cast<const unsigned char *>(str), &length);
value = utils::blob(unescaped, unescaped+length); value = utils::blob(unescaped, unescaped + length);
PQfreemem(unescaped); PQfreemem(unescaped);
} }
@ -219,8 +218,13 @@ void postgres_result_reader::read_value(const char * /*id*/, const size_t index,
break; break;
} }
case utils::basic_type::Time: case utils::basic_type::Time:
case utils::basic_type::Date: { set_value<utils::time_type_t>(column(index), val);
val = std::string{column(index)}; break;
case utils::basic_type::Date:
set_value<utils::date_type_t>(column(index), val);
break;
case utils::basic_type::DateTime: {
set_value<utils::timestamp>(column(index), val);
break; break;
} }
case utils::basic_type::Null: { case utils::basic_type::Null: {
@ -231,11 +235,12 @@ void postgres_result_reader::read_value(const char * /*id*/, const size_t index,
set_value<utils::blob>(column(index), val); set_value<utils::blob>(column(index), val);
break; break;
} }
case utils::basic_type::Unknown:
break;
} }
} }
utils::attribute_reader &postgres_result_reader::result_binder() { utils::attribute_reader &postgres_result_reader::result_binder() {
return empty_binder_; return empty_binder_;
} }
} // namespace matador::backends::postgres } // namespace matador::backends::postgres

View File

@ -69,7 +69,7 @@ public:
[[nodiscard]] std::string prepare_literal(const std::string &str) const; [[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 * @param str Identifier to put quotes around
*/ */
@ -259,7 +259,8 @@ private:
{utils::basic_type::Varchar, "VARCHAR"}, {utils::basic_type::Varchar, "VARCHAR"},
{utils::basic_type::Text, "TEXT"}, {utils::basic_type::Text, "TEXT"},
{utils::basic_type::Date, "DATE"}, {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::Blob, "BLOB"},
{utils::basic_type::Null, "NULL"} {utils::basic_type::Null, "NULL"}
}; };

View File

@ -5,10 +5,6 @@
#include <string> #include <string>
namespace matador {
class date;
class time;
}
namespace matador::utils { namespace matador::utils {
class value; 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, 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, 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, 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, time_type_t &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, 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, 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) = 0;
virtual void read_value(const char *id, size_t index, std::string &value, size_t size) = 0; virtual void read_value(const char *id, size_t index, std::string &value, size_t size) = 0;

View File

@ -256,26 +256,57 @@ template < typename DestType >
result<DestType, conversion_error> to(const std::string &source, std::enable_if_t<std::is_same_v<DestType, date_type_t>>* = nullptr) { result<DestType, conversion_error> to(const std::string &source, std::enable_if_t<std::is_same_v<DestType, date_type_t>>* = nullptr) {
std::tm result{}; std::tm result{};
std::istringstream iss(source); std::istringstream iss(source);
iss >> std::get_time(&result, "%Y-%m-%d %H:%M:%S"); iss >> std::get_time(&result, "%Y-%m-%d");
return ok(result); if (iss.fail()) {
return failure(conversion_error::NotConvertable);
}
return ok(date_type_t{result.tm_year + 1900, static_cast<uint8_t>(result.tm_mon + 1), static_cast<uint8_t>(result.tm_mday)});
}
template < typename DestType >
result<DestType, conversion_error> to(const char *source, std::enable_if_t<std::is_same_v<DestType, date_type_t>>* = nullptr) {
return to<DestType>(std::string{source});
} }
template < typename DestType > template < typename DestType >
result<DestType, conversion_error> to(const std::string &source, std::enable_if_t<std::is_same_v<DestType, time_type_t>>* = nullptr) { result<DestType, conversion_error> to(const std::string &source, std::enable_if_t<std::is_same_v<DestType, time_type_t>>* = nullptr) {
std::tm result{}; std::tm result{};
std::istringstream iss(source); std::istringstream iss(source);
iss >> std::get_time(&result, "%Y-%m-%d %H:%M:%S"); iss >> std::get_time(&result, "%H:%M:%S");
return ok(result); if (iss.fail()) {
return failure(conversion_error::NotConvertable);
}
return ok(time_type_t{static_cast<uint8_t>(result.tm_hour), static_cast<uint8_t>(result.tm_min), static_cast<uint8_t>(result.tm_sec)});
} }
template < typename DestType >
result<DestType, conversion_error> to(const char *source, std::enable_if_t<std::is_same_v<DestType, time_type_t>>* = nullptr) {
return to<DestType>(std::string{source});
}
template < typename DestType > template < typename DestType >
result<DestType, conversion_error> to(const std::string &source, std::enable_if_t<std::is_same_v<DestType, timestamp>>* = nullptr) { result<DestType, conversion_error> to(const std::string &source, std::enable_if_t<std::is_same_v<DestType, timestamp>>* = nullptr) {
std::tm result{}; std::tm result{};
std::istringstream iss(source); std::istringstream iss(source);
iss >> std::get_time(&result, "%Y-%m-%d %H:%M:%S"); 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<DestType, conversion_error> to(const char *source, std::enable_if_t<std::is_same_v<DestType, timestamp>>* = nullptr) {
return to<DestType>(std::string{source});
}
template < typename DestType, typename SourceType > template < typename DestType, typename SourceType >
result<DestType, conversion_error> to(const SourceType &/*source*/, std::enable_if_t<std::is_integral_v<DestType> && !std::is_same_v<bool, DestType> && std::is_same_v<date_type_t, SourceType>>* = nullptr) { result<DestType, conversion_error> to(const SourceType &/*source*/, std::enable_if_t<std::is_integral_v<DestType> && !std::is_same_v<bool, DestType> && std::is_same_v<date_type_t, SourceType>>* = nullptr) {
return failure(conversion_error::NotConvertable); return failure(conversion_error::NotConvertable);
@ -351,6 +382,104 @@ result<DestType, conversion_error> to(const SourceType &/*source*/, std::enable_
return failure(conversion_error::NotConvertable); return failure(conversion_error::NotConvertable);
} }
template < typename DestType, typename SourceType >
result<DestType, conversion_error> to(const SourceType &/*source*/, std::enable_if_t<std::is_integral_v<SourceType> && !std::is_same_v<bool, SourceType> && std::is_same_v<date_type_t, DestType>>* = nullptr) {
return failure(conversion_error::NotConvertable);
}
template < typename DestType, typename SourceType >
result<DestType, conversion_error> to(const SourceType &/*source*/, std::enable_if_t<std::is_integral_v<SourceType> && !std::is_same_v<bool, SourceType> && std::is_same_v<time_type_t, DestType>>* = nullptr) {
return failure(conversion_error::NotConvertable);
}
template < typename DestType, typename SourceType >
result<DestType, conversion_error> to(const SourceType &/*source*/, std::enable_if_t<std::is_integral_v<SourceType> && !std::is_same_v<bool, SourceType> && std::is_same_v<timestamp, DestType>>* = nullptr) {
return failure(conversion_error::NotConvertable);
}
template < typename DestType, typename SourceType >
result<DestType, conversion_error> to(const SourceType &/*source*/, std::enable_if_t<std::is_floating_point_v<SourceType> && std::is_same_v<date_type_t, DestType>>* = nullptr) {
return failure(conversion_error::NotConvertable);
}
template < typename DestType, typename SourceType >
result<DestType, conversion_error> to(const SourceType &/*source*/, std::enable_if_t<std::is_floating_point_v<SourceType> && std::is_same_v<time_type_t, DestType>>* = nullptr) {
return failure(conversion_error::NotConvertable);
}
template < typename DestType, typename SourceType >
result<DestType, conversion_error> to(const SourceType &/*source*/, std::enable_if_t<std::is_floating_point_v<SourceType> && std::is_same_v<timestamp, DestType>>* = nullptr) {
return failure(conversion_error::NotConvertable);
}
template < typename DestType>
result<DestType, conversion_error> to(const blob &/*source*/, std::enable_if_t<std::is_same_v<date_type_t, DestType>>* = nullptr) {
return failure(conversion_error::NotConvertable);
}
template < typename DestType>
result<DestType, conversion_error> to(const blob &/*source*/, std::enable_if_t<std::is_same_v<time_type_t, DestType>>* = nullptr) {
return failure(conversion_error::NotConvertable);
}
template < typename DestType>
result<DestType, conversion_error> to(const blob &/*source*/, std::enable_if_t<std::is_same_v<timestamp, DestType>>* = nullptr) {
return failure(conversion_error::NotConvertable);
}
template < typename DestType>
result<DestType, conversion_error> to(const bool &/*source*/, std::enable_if_t<std::is_same_v<date_type_t, DestType>>* = nullptr) {
return failure(conversion_error::NotConvertable);
}
template < typename DestType>
result<DestType, conversion_error> to(const bool &/*source*/, std::enable_if_t<std::is_same_v<time_type_t, DestType>>* = nullptr) {
return failure(conversion_error::NotConvertable);
}
template < typename DestType>
result<DestType, conversion_error> to(const bool &/*source*/, std::enable_if_t<std::is_same_v<timestamp, DestType>>* = nullptr) {
return failure(conversion_error::NotConvertable);
}
template < typename DestType>
result<DestType, conversion_error> to(const time_type_t &/*source*/, std::enable_if_t<std::is_same_v<date_type_t, DestType>>* = nullptr) {
return failure(conversion_error::NotConvertable);
}
template < typename DestType>
result<DestType, conversion_error> to(const time_type_t &source, std::enable_if_t<std::is_same_v<time_type_t, DestType>>* = nullptr) {
return ok(source);
}
template < typename DestType>
result<DestType, conversion_error> to(const date_type_t &/*source*/, std::enable_if_t<std::is_same_v<time_type_t, DestType>>* = nullptr) {
return failure(conversion_error::NotConvertable);
}
template < typename DestType>
result<DestType, conversion_error> to(const date_type_t &source, std::enable_if_t<std::is_same_v<date_type_t, DestType>>* = nullptr) {
return ok(source);
}
template < typename DestType>
result<DestType, conversion_error> to(const timestamp &source, std::enable_if_t<std::is_same_v<time_type_t, DestType>>* = 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<uint8_t>(result->tm_hour), static_cast<uint8_t>(result->tm_min), static_cast<uint8_t>(result->tm_sec)});
}
template < typename DestType>
result<DestType, conversion_error> to(const timestamp &source, std::enable_if_t<std::is_same_v<date_type_t, DestType>>* = 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<uint8_t>(result->tm_mon + 1), static_cast<uint8_t>(result->tm_mday)});
}
} }
#endif //MATADOR_CONVERT_HPP #endif //MATADOR_CONVERT_HPP

View File

@ -8,159 +8,162 @@
#include <string> #include <string>
namespace matador::utils { namespace matador::utils {
/// @cond MATADOR_DEV /// @cond MATADOR_DEV
template <> struct data_type_traits<nullptr_t, void> template<>
{ struct data_type_traits<nullptr_t, void> {
static basic_type type(std::size_t /*size*/) { return basic_type::Null; } 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 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 bind_value(attribute_writer &binder, size_t index, nullptr_t &/*value*/, size_t /*size*/ = 0);
}; };
template <> struct data_type_traits<int8_t, void> template<>
{ struct data_type_traits<int8_t, void> {
static basic_type type(std::size_t /*size*/ = 0) { return basic_type::Int8; } 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 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); static void bind_value(attribute_writer &binder, size_t index, const int8_t &value, size_t /*size*/ = 0);
}; };
template <> struct data_type_traits<int16_t, void> template<>
{ struct data_type_traits<int16_t, void> {
static basic_type type(std::size_t /*size*/ = 0) { return basic_type::Int16; } 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 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); static void bind_value(attribute_writer &binder, size_t index, const int16_t &value, size_t /*size*/ = 0);
}; };
template <> struct data_type_traits<int32_t, void> template<>
{ struct data_type_traits<int32_t, void> {
static basic_type type(std::size_t /*size*/ = 0) { return basic_type::Int32; } 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 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); static void bind_value(attribute_writer &binder, size_t index, const int32_t &value, size_t /*size*/ = 0);
}; };
template <> struct data_type_traits<int64_t, void> template<>
{ struct data_type_traits<int64_t, void> {
static basic_type type(std::size_t /*size*/ = 0) { return basic_type::Int64; } 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 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); static void bind_value(attribute_writer &binder, size_t index, const int64_t &value, size_t /*size*/ = 0);
}; };
template <> struct data_type_traits<uint8_t, void> template<>
{ struct data_type_traits<uint8_t, void> {
static basic_type type(std::size_t /*size*/ = 0) { return basic_type::UInt8; } 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 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); static void bind_value(attribute_writer &binder, size_t index, const uint8_t &value, size_t /*size*/ = 0);
}; };
template <> struct data_type_traits<uint16_t, void> template<>
{ struct data_type_traits<uint16_t, void> {
static basic_type type(std::size_t /*size*/ = 0) { return basic_type::UInt16; } 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 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); static void bind_value(attribute_writer &binder, size_t index, const uint16_t &value, size_t /*size*/ = 0);
}; };
template <> struct data_type_traits<uint32_t, void> template<>
{ struct data_type_traits<uint32_t, void> {
static basic_type type(std::size_t /*size*/ = 0) { return basic_type::UInt32; } 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 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); static void bind_value(attribute_writer &binder, size_t index, const uint32_t &value, size_t /*size*/ = 0);
}; };
template <> struct data_type_traits<uint64_t, void> template<>
{ struct data_type_traits<uint64_t, void> {
static basic_type type(std::size_t /*size*/ = 0) { return basic_type::UInt64; } 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 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); static void bind_value(attribute_writer &binder, size_t index, const uint64_t &value, size_t /*size*/ = 0);
}; };
template <> struct data_type_traits<bool, void> template<>
{ struct data_type_traits<bool, void> {
static basic_type type(std::size_t /*size*/ = 0) { return basic_type::Boolean; } 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 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); static void bind_value(attribute_writer &binder, size_t index, const bool &value, size_t /*size*/ = 0);
}; };
template <> struct data_type_traits<float, void> template<>
{ struct data_type_traits<float, void> {
static basic_type type(std::size_t /*size*/ = 0) { return basic_type::Float; } 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 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); static void bind_value(attribute_writer &binder, size_t index, const float &value, size_t /*size*/ = 0);
}; };
template <> struct data_type_traits<double, void> template<>
{ struct data_type_traits<double, void> {
static basic_type type(std::size_t /*size*/ = 0) { return basic_type::Double; } 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 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); static void bind_value(attribute_writer &binder, size_t index, const double &value, size_t /*size*/ = 0);
}; };
template <> struct data_type_traits<const char*, void> template<>
{ struct data_type_traits<const char *, void> {
static basic_type type(const std::size_t size) { return size == 0 ? basic_type::Text : basic_type::Varchar; } 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); static void bind_value(attribute_writer &binder, size_t index, const char *value, size_t size = 0);
}; };
template <> struct data_type_traits<char*, void> template<>
{ struct data_type_traits<char *, void> {
static basic_type type(const std::size_t size) { return size == 0 ? basic_type::Text : basic_type::Varchar; } 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 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); static void bind_value(attribute_writer &binder, size_t index, const char *value, size_t size = 0);
}; };
template <> struct data_type_traits<char[], void> template<>
{ struct data_type_traits<char[], void> {
static basic_type type(const std::size_t size) { return size == 0 ? basic_type::Text : basic_type::Varchar; } static basic_type type(const std::size_t size) { return size == 0 ? basic_type::Text : basic_type::Varchar; }
template < int N >
template<int N>
static void read_value(attribute_reader &reader, const char *id, const size_t index, char (&value)[N], const size_t size) { static void read_value(attribute_reader &reader, const char *id, const size_t index, char (&value)[N], const size_t size) {
data_type_traits<const char*>::read_value(reader, id, index, value, size); data_type_traits<const char *>::read_value(reader, id, index, value, size);
} }
template < int N >
template<int N>
static void bind_value(attribute_writer &binder, const size_t index, char *value, const size_t size = 0) { static void bind_value(attribute_writer &binder, const size_t index, char *value, const size_t size = 0) {
data_type_traits<const char*>::bind_value(binder, index, value, size); data_type_traits<const char *>::bind_value(binder, index, value, size);
} }
}; };
template <> struct data_type_traits<std::string, void> template<>
{ struct data_type_traits<std::string, void> {
static basic_type type(const std::size_t size) { return size == 0 ? basic_type::Text : basic_type::Varchar; } 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 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); static void bind_value(attribute_writer &binder, size_t index, std::string &value, size_t size = 0);
}; };
template <> struct data_type_traits<utils::blob, void> template<>
{ struct data_type_traits<utils::blob, void> {
static basic_type type(std::size_t /*size*/) { return basic_type::Blob; } 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 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 bind_value(attribute_writer &binder, size_t index, utils::blob &value, size_t /*size*/ = 0);
}; };
//template <> struct data_type_traits<matador::date, void> template<>
//{ struct data_type_traits<date_type_t, void> {
// static basic_type type(std::size_t /*size*/) { return basic_type::type_date; } 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, matador::date &value); 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, matador::date &value); static void bind_value(attribute_writer &binder, size_t index, date_type_t &value);
//}; };
//
//template <> struct data_type_traits<matador::time, void>
//{
// 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 < typename EnumType > template<>
struct data_type_traits<EnumType, std::enable_if_t<std::is_enum_v<EnumType>>> struct data_type_traits<time_type_t, void> {
{ 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<typename EnumType>
struct data_type_traits<EnumType, std::enable_if_t<std::is_enum_v<EnumType> > > {
static basic_type type(std::size_t /*size*/ = 0) { return basic_type::Int32; } 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) { static void read_value(attribute_reader &reader, const char *id, const size_t index, EnumType &value, const size_t size = 0) {
data_type_traits<int>::read_value(reader, id, index, reinterpret_cast<int&>(value), size); data_type_traits<int>::read_value(reader, id, index, reinterpret_cast<int &>(value), size);
} }
static void bind_value(attribute_writer &binder, const size_t index, EnumType &value, const size_t size = 0) { static void bind_value(attribute_writer &binder, const size_t index, EnumType &value, const size_t size = 0) {
data_type_traits<int>::bind_value(binder, index, static_cast<int &>(value), size); data_type_traits<int>::bind_value(binder, index, static_cast<int &>(value), size);
} }
}; };
/// @endcond
/// @endcond
} }
#endif //MATADOR_DEFAULT_TYPE_TRAITS_HPP #endif //MATADOR_DEFAULT_TYPE_TRAITS_HPP

View File

@ -19,6 +19,8 @@ namespace matador::utils {
* @return Binary data as string * @return Binary data as string
*/ */
MATADOR_UTILS_API std::string to_string(const blob &data); 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 * Splits a string by a delimiter and

View File

@ -127,28 +127,24 @@ void data_type_traits<blob>::read_value(attribute_reader &reader, const char *id
reader.read_value(id, index, value); reader.read_value(id, index, value);
} }
void data_type_traits<blob>::bind_value(attribute_writer &binder, const size_t index, utils::blob &value, const size_t /*size*/) { void data_type_traits<blob>::bind_value(attribute_writer &binder, const size_t index, blob &value, const size_t /*size*/) {
binder.write_value(index, value); binder.write_value(index, value);
} }
// void data_type_traits<matador::date>::read_value(attribute_reader &reader, const char *id, size_t index, date &value) void data_type_traits<date_type_t>::read_value(attribute_reader &reader, const char *id, size_t index, date_type_t &value) {
// { reader.read_value(id, index, value);
// reader.read_value(id, index, value); }
// }
// void data_type_traits<date_type_t>::bind_value(attribute_writer &binder, const size_t index, date_type_t &value) {
// void data_type_traits<matador::date>::bind_value(attribute_writer &binder, size_t index, date &value) binder.write_value(index, value);
// { }
// binder.write_value(index, value);
// } void data_type_traits<time_type_t>::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<matador::time>::read_value(attribute_reader &reader, const char *id, size_t index, time &value) }
// {
// reader.read_value(id, index, value); void data_type_traits<time_type_t>::bind_value(attribute_writer &binder, const size_t index, time_type_t &value) {
// } binder.write_value(index, value);
// }
// void data_type_traits<matador::time>::bind_value(attribute_writer &binder, size_t index, time &value)
// {
// binder.write_value(index, value);
// }
} }

View File

@ -18,6 +18,24 @@ std::string to_string(const blob& data) {
return str; 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<unsigned>(data.month), static_cast<unsigned>(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<unsigned>(data.hour), static_cast<unsigned>(data.minute), static_cast<unsigned>(data.second), data.microsecond);
return buf;
}
size_t split(const std::string &str, char delim, std::vector<std::string> &values) size_t split(const std::string &str, char delim, std::vector<std::string> &values)
{ {
std::stringstream ss(str); std::stringstream ss(str);

View File

@ -9,104 +9,108 @@
#include "matador/utils/string.hpp" #include "matador/utils/string.hpp"
namespace matador::query { namespace matador::query {
attribute_string_writer::attribute_string_writer(const sql::dialect &d,
attribute_string_writer::attribute_string_writer(const sql::dialect &d, const std::optional<std::reference_wrapper<const sql::connection_impl>> conn) const std::optional<std::reference_wrapper<const
sql::connection_impl> > conn)
: dialect_(d) : dialect_(d)
, conn_(conn) {} , conn_(conn) {
}
const sql::dialect& attribute_string_writer::dialect() const { const sql::dialect &attribute_string_writer::dialect() const {
return dialect_; return dialect_;
} }
void attribute_string_writer::write_value(size_t /*pos*/, const int8_t& x ) { void attribute_string_writer::write_value(size_t /*pos*/, const int8_t &x) {
result_ = std::to_string(x) ; result_ = std::to_string(x);
} }
void attribute_string_writer::write_value(size_t /*pos*/, const int16_t& x ) { void attribute_string_writer::write_value(size_t /*pos*/, const int16_t &x) {
result_ = std::to_string(x) ; result_ = std::to_string(x);
} }
void attribute_string_writer::write_value(size_t /*pos*/, const int32_t& x ) { void attribute_string_writer::write_value(size_t /*pos*/, const int32_t &x) {
result_ = std::to_string(x) ; result_ = std::to_string(x);
} }
void attribute_string_writer::write_value(size_t /*pos*/, const int64_t& x ) { void attribute_string_writer::write_value(size_t /*pos*/, const int64_t &x) {
result_ = std::to_string(x) ; result_ = std::to_string(x);
} }
void attribute_string_writer::write_value(size_t /*pos*/, const uint8_t& x ) { void attribute_string_writer::write_value(size_t /*pos*/, const uint8_t &x) {
result_ = std::to_string(x) ; result_ = std::to_string(x);
} }
void attribute_string_writer::write_value(size_t /*pos*/, const uint16_t& x ) { void attribute_string_writer::write_value(size_t /*pos*/, const uint16_t &x) {
result_ = std::to_string(x) ; result_ = std::to_string(x);
} }
void attribute_string_writer::write_value(size_t /*pos*/, const uint32_t& x ) { void attribute_string_writer::write_value(size_t /*pos*/, const uint32_t &x) {
result_ = std::to_string(x) ; result_ = std::to_string(x);
} }
void attribute_string_writer::write_value(size_t /*pos*/, const uint64_t& x ) { void attribute_string_writer::write_value(size_t /*pos*/, const uint64_t &x) {
result_ = std::to_string(x) ; result_ = std::to_string(x);
} }
void attribute_string_writer::write_value(size_t /*pos*/, const bool& x ) { void attribute_string_writer::write_value(size_t /*pos*/, const bool &x) {
// result_ = "'" + conn_->dialect().prepare_literal(x ? "true" : "false") + "'"; // result_ = "'" + conn_->dialect().prepare_literal(x ? "true" : "false") + "'";
result_ = dialect_.to_string(x); 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<std::string>(x); !res.is_error()) { if (const auto res = utils::to<std::string>(x); !res.is_error()) {
result_ = *res; 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<std::string>(x); !res.is_error()) { if (const auto res = utils::to<std::string>(x); !res.is_error()) {
result_ = *res; result_ = *res;
} }
} }
void attribute_string_writer::write_value(size_t /*pos*/, const utils::date_type_t& /*x*/ ) { void attribute_string_writer::write_value(size_t /*pos*/, const utils::date_type_t &x) {
// result_ = "'" + dialect_.prepare_literal(utils::to_string(x)) + "'"; result_ = "'" + dialect_.prepare_literal(utils::to_string(x)) + "'";
} }
void attribute_string_writer::write_value(size_t /*pos*/, const utils::time_type_t& /*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")) + "'"; 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 utils::timestamp &/*x*/) {
} }
void attribute_string_writer::write_value(size_t pos, const char* x ) { void attribute_string_writer::write_value(size_t pos, const char *x) {
write_value(pos, std::string(x) ); write_value(pos, std::string(x));
} }
void attribute_string_writer::write_value(size_t pos, const char* x, size_t /*size*/) { void attribute_string_writer::write_value(size_t pos, const char *x, size_t /*size*/) {
write_value(pos, std::string(x) ); 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) + "'"; 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) + "'"; 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: // "This is a binary Data string" as binary data:
// MySQL: X'5468697320697320612062616E617279204461746120737472696E67' // MySQL: X'5468697320697320612062616E617279204461746120737472696E67'
// Postgres: '\\x5468697320697320612062616E617279204461746120737472696E67' // Postgres: '\\x5468697320697320612062616E617279204461746120737472696E67'
// MSSQL: 0x5468697320697320612062616E617279204461746120737472696E67 // MSSQL: 0x5468697320697320612062616E617279204461746120737472696E67
// Sqlite: X'5468697320697320612062616E617279204461746120737472696E67' // Sqlite: X'5468697320697320612062616E617279204461746120737472696E67'
if (conn_.has_value()) { 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 { } 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*/) {} void attribute_string_writer::write_value(size_t /*pos*/, const utils::value &/*x*/, size_t /*size*/) {
}
} }

View File

@ -3,49 +3,47 @@
#include "matador/sql/interface/query_result_reader.hpp" #include "matador/sql/interface/query_result_reader.hpp"
namespace matador::sql { 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) {
}
query_result_impl::query_result_impl(std::unique_ptr<query_result_reader> &&reader, std::vector<object::attribute> &&prototype, const size_t column_index) query_result_impl::query_result_impl(std::unique_ptr<query_result_reader> &&reader,
std::vector<object::attribute> &&prototype,
const size_t column_index)
: column_index_(column_index) : column_index_(column_index)
, prototype_(std::move(prototype)) , prototype_(std::move(prototype))
, reader_(std::move(reader)) , reader_(std::move(reader))
, pk_reader_(*reader_) , pk_reader_(*reader_) {
{} }
query_result_impl::query_result_impl(std::unique_ptr<query_result_reader> &&reader, const std::vector<object::attribute> &prototype, const size_t column_index) query_result_impl::query_result_impl(std::unique_ptr<query_result_reader> &&reader,
const std::vector<object::attribute> &prototype,
const size_t column_index)
: column_index_(column_index) : column_index_(column_index)
, prototype_(prototype) , prototype_(prototype)
, reader_(std::move(reader)) , reader_(std::move(reader))
, pk_reader_(*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<uint64_t>::read_value(*reader_, id, column_index_++, rev); utils::data_type_traits<uint64_t>::read_value(*reader_, id, column_index_++, rev);
reader_->read_value(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) void query_result_impl::on_attribute(const char *id, char *value, const utils::field_attributes &attr) {
{ utils::data_type_traits<char *>::read_value(*reader_, id, column_index_++, value, attr.size());
utils::data_type_traits<char*>::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<std::string>::read_value(*reader_, id, column_index_++, value, attr.size()); utils::data_type_traits<std::string>::read_value(*reader_, id, column_index_++, value, attr.size());
} }
void 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()); reader_->read_value(id, column_index_++, val, attr.size());
} }
const std::vector<object::attribute>& query_result_impl::prototype() const const std::vector<object::attribute> &query_result_impl::prototype() const {
{
return prototype_; return prototype_;
} }
} }

View File

@ -61,15 +61,16 @@ void value_extractor::write_value(size_t /*pos*/, const double &x) {
values_.emplace_back(x); values_.emplace_back(x);
} }
void value_extractor::write_value(size_t /*pos*/, const utils::date_type_t &/*x*/) { void value_extractor::write_value(size_t /*pos*/, const utils::date_type_t &x) {
// values_.emplace_back(x); values_.emplace_back(x);
} }
void value_extractor::write_value(size_t /*pos*/, const utils::time_type_t &/*x*/) { void value_extractor::write_value(size_t /*pos*/, const utils::time_type_t &x) {
// values_.emplace_back(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) { void value_extractor::write_value(size_t /*pos*/, const char *x) {

View File

@ -6,8 +6,7 @@
#include "matador/utils/value.hpp" #include "matador/utils/value.hpp"
namespace matador::sql { 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); 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); 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); return sql_func_map_.at(func);
} }
std::string dialect::table_name( const std::string& table, const std::string& schema_name ) const { std::string dialect::table_name(const std::string &table, const std::string &schema_name) const {
if ( schema_name.empty() && default_schema_name_.empty()) { if (schema_name.empty() && default_schema_name_.empty()) {
return prepare_identifier_string( table ); return prepare_identifier_string(table);
} }
if ( schema_name.empty() ) { if (schema_name.empty()) {
return prepare_identifier_string( default_schema_name_ ) + "." + prepare_identifier_string( table ); return prepare_identifier_string(default_schema_name_) + "." + prepare_identifier_string(table);
} }
return prepare_identifier_string( 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<int>(val)]; return bool_strings_[static_cast<int>(val)];
} }
@ -45,38 +43,33 @@ std::string dialect::to_sql_string(const utils::value &val) const {
return val.str(); 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_[0] = false_string;
bool_strings_[1] = true_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, '.'); auto parts = utils::split(col, '.');
for (auto &part : parts) { for (auto &part: parts) {
escape_quotes_in_identifier(part); escape_quotes_in_identifier(part);
quote_identifier(part); quote_identifier(part);
} }
return utils::join(parts, "."); 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); std::string result(str);
escape_quotes_in_literals(result); escape_quotes_in_literals(result);
return 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.insert(0, token_at(dialect_token::StartQuote));
str += token_at(dialect_token::EndQuote); 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 open_char(token_at(dialect_token::StartQuote));
const std::string close_char(token_at(dialect_token::EndQuote)); const std::string close_char(token_at(dialect_token::EndQuote));
if (identifier_escape_type() == escape_identifier_t::ESCAPE_CLOSING_BRACKET) { 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 single_quote(token_at(dialect_token::StringQuote));
const std::string double_quote(token_at(dialect_token::StringQuote) + 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); 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; identifier_escape_type_ = escape_identifier;
} }
std::string dialect::next_placeholder(const std::vector<std::string> &bind_vars) const std::string dialect::next_placeholder(const std::vector<std::string> &bind_vars) const {
{
return placeholder_func_(bind_vars.size()); 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) { if (conn != nullptr) {
return conn->to_escaped_string(value); 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); return to_escaped_string_func_(value);
} }
std::string dialect::default_schema_name() const std::string dialect::default_schema_name() const {
{
return default_schema_name_; return default_schema_name_;
} }
const std::string& dialect::add_constraint() const { const std::string &dialect::add_constraint() const {
return token_at(dialect_token::AddConstraint); return token_at(dialect_token::AddConstraint);
} }
const std::string& dialect::alter() const { const std::string &dialect::alter() const {
return token_at(dialect_token::Alter); return token_at(dialect_token::Alter);
} }
const std::string& dialect::and_() const { const std::string &dialect::and_() const {
return token_at(dialect_token::And); return token_at(dialect_token::And);
} }
const std::string& dialect::as() const { const std::string &dialect::as() const {
return token_at(dialect_token::As); return token_at(dialect_token::As);
} }
const std::string& dialect::asc() const { const std::string &dialect::asc() const {
return token_at(dialect_token::Asc); return token_at(dialect_token::Asc);
} }
const std::string& dialect::begin() const { const std::string &dialect::begin() const {
return token_at(dialect_token::Begin); return token_at(dialect_token::Begin);
} }
const std::string& dialect::asterisk() const { const std::string &dialect::asterisk() const {
return token_at(dialect_token::Asterisk); 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); 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); return token_at(dialect_token::BeginStringData);
} }
const std::string& dialect::between() const { const std::string &dialect::between() const {
return token_at(dialect_token::Between); return token_at(dialect_token::Between);
} }
const std::string& dialect::column() const { const std::string &dialect::column() const {
return token_at(dialect_token::Column); return token_at(dialect_token::Column);
} }
const std::string& dialect::columns() const { const std::string &dialect::columns() const {
return token_at(dialect_token::Columns); return token_at(dialect_token::Columns);
} }
const std::string& dialect::commit() const { const std::string &dialect::commit() const {
return token_at(dialect_token::Commit); return token_at(dialect_token::Commit);
} }
const std::string& dialect::constraint() const { const std::string &dialect::constraint() const {
return token_at(dialect_token::Constraint); return token_at(dialect_token::Constraint);
} }
const std::string& dialect::create() const { const std::string &dialect::create() const {
return token_at(dialect_token::Create); return token_at(dialect_token::Create);
} }
const std::string& dialect::drop() const { const std::string &dialect::drop() const {
return token_at(dialect_token::Drop); 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); 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); return token_at(dialect_token::EndStringData);
} }
const std::string& dialect::from() const { const std::string &dialect::from() const {
return token_at(dialect_token::From); return token_at(dialect_token::From);
} }
const std::string& dialect::in() const { const std::string &dialect::in() const {
return token_at(dialect_token::In); return token_at(dialect_token::In);
} }
const std::string& dialect::desc() const { const std::string &dialect::desc() const {
return token_at(dialect_token::Desc); return token_at(dialect_token::Desc);
} }
const std::string& dialect::distinct() const { const std::string &dialect::distinct() const {
return token_at(dialect_token::Distinct); 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); 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); 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); 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); return token_at(dialect_token::GroupBy);
} }
const std::string& dialect::insert() const { const std::string &dialect::insert() const {
return token_at(dialect_token::Insert); return token_at(dialect_token::Insert);
} }
const std::string& dialect::into() const { const std::string &dialect::into() const {
return token_at(dialect_token::Into); return token_at(dialect_token::Into);
} }
const std::string& dialect::join() const { const std::string &dialect::join() const {
return token_at(dialect_token::Join); return token_at(dialect_token::Join);
} }
const std::string& dialect::like() const { const std::string &dialect::like() const {
return token_at(dialect_token::Like); return token_at(dialect_token::Like);
} }
const std::string& dialect::limit() const { const std::string &dialect::limit() const {
return token_at(dialect_token::Limit); return token_at(dialect_token::Limit);
} }
const std::string& dialect::not_() const { const std::string &dialect::not_() const {
return token_at(dialect_token::Not); 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); return token_at(dialect_token::NotNull);
} }
const std::string& dialect::offset() const { const std::string &dialect::offset() const {
return token_at(dialect_token::Offset); return token_at(dialect_token::Offset);
} }
const std::string& dialect::on() const { const std::string &dialect::on() const {
return token_at(dialect_token::On); return token_at(dialect_token::On);
} }
const std::string& dialect::or_() const { const std::string &dialect::or_() const {
return token_at(dialect_token::Or); 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); 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); return token_at(dialect_token::PrimaryKey);
} }
const std::string& dialect::references() const { const std::string &dialect::references() const {
return token_at(dialect_token::References); return token_at(dialect_token::References);
} }
const std::string& dialect::remove() const { const std::string &dialect::remove() const {
return token_at(dialect_token::Remove); return token_at(dialect_token::Remove);
} }
const std::string& dialect::rollback() const { const std::string &dialect::rollback() const {
return token_at(dialect_token::Rollback); return token_at(dialect_token::Rollback);
} }
const std::string& dialect::schema() const { const std::string &dialect::schema() const {
return token_at(dialect_token::Schema); return token_at(dialect_token::Schema);
} }
const std::string& dialect::select() const { const std::string &dialect::select() const {
return token_at(dialect_token::Select); return token_at(dialect_token::Select);
} }
const std::string& dialect::set() const { const std::string &dialect::set() const {
return token_at(dialect_token::Set); 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); 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); return token_at(dialect_token::StringQuote);
} }
const std::string& dialect::table() const { const std::string &dialect::table() const {
return token_at(dialect_token::Table); return token_at(dialect_token::Table);
} }
const std::string & dialect::unique() const { const std::string &dialect::unique() const {
return token_at(dialect_token::Unique); return token_at(dialect_token::Unique);
} }
const std::string& dialect::update() const { const std::string &dialect::update() const {
return token_at(dialect_token::Update); return token_at(dialect_token::Update);
} }
const std::string& dialect::values() const { const std::string &dialect::values() const {
return token_at(dialect_token::Values); return token_at(dialect_token::Values);
} }
const std::string& dialect::where() const { const std::string &dialect::where() const {
return token_at(dialect_token::Where); return token_at(dialect_token::Where);
} }
} }

View File

@ -26,9 +26,6 @@ TEST_CASE_METHOD(QueryFixture, "Test all data types for record", "[query][record
const table tab("types"); const table tab("types");
// auto r = query::create().table(tab).columns({
// column("id", basic_type::UInt32)
// });
auto res = query::create() auto res = query::create()
.table(tab) .table(tab)
.columns({ .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_double", basic_type::Double),
column("val_string", basic_type::Text), column("val_string", basic_type::Text),
column("val_varchar", basic_type::Varchar, 63), column("val_varchar", basic_type::Varchar, 63),
// column("val_date", basic_type::type_date), column("val_date", basic_type::Date),
// column("val_time", basic_type::type_time), column("val_time", basic_type::Time),
column("val_blob", basic_type::Blob), column("val_blob", basic_type::Blob),
}) })
.constraints({ .constraints({
@ -66,7 +63,7 @@ TEST_CASE_METHOD(QueryFixture, "Test all data types for record", "[query][record
"val_bool", "val_bool",
"val_float", "val_double", "val_float", "val_double",
"val_string", "val_varchar", "val_string", "val_varchar",
// "val_date", "val_time", "val_date", "val_time",
"val_blob"}; "val_blob"};
const auto fields = db.describe("types"); 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}; double d{2.71828};
std::string str{"long text"}; std::string str{"long text"};
std::string varchar{"good day"}; std::string varchar{"good day"};
// auto md{matador::date()}; date_type_t md{2025, 11, 27};
// auto mt{matador::time::now()}; time_type_t mt{12, 34, 56};
blob bin{0x01,0x02,0x03,0x04}; blob bin{0x01,0x02,0x03,0x04};
res = query::insert() res = query::insert()
.into("types", cols) .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); .execute(db);
REQUIRE(res.is_ok()); REQUIRE(res.is_ok());
REQUIRE(res.value() == 1); REQUIRE(res.value() == 1);
auto row = query::select(cols) auto result = query::select(cols)
.from("types") .from("types")
.fetch_one(db); .fetch_one(db);
REQUIRE(row.is_ok()); REQUIRE(result.is_ok());
REQUIRE(row.value().has_value()); REQUIRE(result.value().has_value());
REQUIRE(id == (*row)->at<uint32_t>("id")); const auto &row = result.value().value();
REQUIRE(c == (*row)->at<int8_t>("val_char")); REQUIRE(id == row.at<uint32_t>("id"));
REQUIRE(s == (*row)->at<int16_t>("val_short")); REQUIRE(c == row.at<int8_t>("val_char"));
REQUIRE(i == (*row)->at<int32_t>("val_int")); REQUIRE(s == row.at<int16_t>("val_short"));
REQUIRE(ll == (*row)->at<int64_t>("val_long_long")); REQUIRE(i == row.at<int32_t>("val_int"));
REQUIRE(uc == (*row)->at<uint8_t>("val_uchar")); REQUIRE(ll == row.at<int64_t>("val_long_long"));
REQUIRE(us == (*row)->at<unsigned short>("val_ushort")); REQUIRE(uc == row.at<uint8_t>("val_uchar"));
REQUIRE(ui == (*row)->at<unsigned int>("val_uint")); REQUIRE(us == row.at<unsigned short>("val_ushort"));
REQUIRE(ull == (*row)->at<uint64_t>("val_ulong_long")); REQUIRE(ui == row.at<unsigned int>("val_uint"));
REQUIRE((*row)->at<bool>("val_bool")); REQUIRE(ull == row.at<uint64_t>("val_ulong_long"));
REQUIRE(f == (*row)->at<float>("val_float")); REQUIRE(row.at<bool>("val_bool"));
REQUIRE(d == (*row)->at<double>("val_double")); REQUIRE(f == row.at<float>("val_float"));
REQUIRE(str == (*row)->at<std::string>("val_string")); REQUIRE(d == row.at<double>("val_double"));
REQUIRE(varchar == (*row)->at<std::string>("val_varchar")); REQUIRE(str == row.at<std::string>("val_string"));
// REQUIRE(md == (*row)->at<matador::date>("val_date")); REQUIRE(varchar == row.at<std::string>("val_varchar"));
// REQUIRE(mt == (*row)->at<matador::time>("val_time")); REQUIRE(md == row.at<date_type_t>("val_date"));
REQUIRE(bin == (*row)->at<blob>("val_blob")); const auto mtres = row.at<time_type_t>("val_time");
REQUIRE(mt == row.at<time_type_t>("val_time"));
REQUIRE(bin == row.at<blob>("val_blob"));
} }
TEST_CASE_METHOD(QueryFixture, "Create and drop table statement", "[query][record]") TEST_CASE_METHOD(QueryFixture, "Create and drop table statement", "[query][record]")