query/backends/postgres/src/postgres_result_reader.cpp

238 lines
6.9 KiB
C++

#include "postgres_result_reader.hpp"
#include "matador/utils/convert.hpp"
#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_))
{}
postgres_result_reader::~postgres_result_reader()
{
if (result_) {
PQclear(result_);
}
}
size_t postgres_result_reader::column_count() const
{
return column_count_;
}
const char *postgres_result_reader::column( const size_t index) const
{
return PQgetvalue(result_, static_cast<int>(row_index_), static_cast<int>(index));
}
utils::result<bool, utils::error> postgres_result_reader::fetch() { return utils::ok(++row_index_ < row_count_); }
size_t postgres_result_reader::start_column_index() const {
return 0;
}
void postgres_result_reader::unshift() {
if (row_index_ > 0) {
--row_index_;
}
}
void postgres_result_reader::read_value(const char * /*id*/, const size_t index, int8_t &value) {
if (auto res = utils::to<int8_t>(column(index)); res.is_ok()) {
value = res.value();
}
}
void postgres_result_reader::read_value(const char * /*id*/, const size_t index, int16_t &value) {
if (auto res = utils::to<int16_t>(column(index)); res.is_ok()) {
value = res.value();
}
}
void postgres_result_reader::read_value(const char * /*id*/, const size_t index, int32_t &value) {
if (auto res = utils::to<int32_t>(column(index)); res.is_ok()) {
value = res.value();
}
}
void postgres_result_reader::read_value(const char * /*id*/, const size_t index, int64_t &value) {
if (auto res = utils::to<int64_t>(column(index)); res.is_ok()) {
value = res.value();
}
}
void postgres_result_reader::read_value(const char * /*id*/, const size_t index, uint8_t &value) {
if (auto res = utils::to<uint8_t>(column(index)); res.is_ok()) {
value = res.value();
}
}
void postgres_result_reader::read_value(const char * /*id*/, const size_t index, uint16_t &value) {
if (auto res = utils::to<uint16_t>(column(index)); res.is_ok()) {
value = res.value();
}
}
void postgres_result_reader::read_value(const char * /*id*/, const size_t index, uint32_t &value) {
if (auto res = utils::to<uint32_t>(column(index)); res.is_ok()) {
value = res.value();
}
}
void postgres_result_reader::read_value(const char * /*id*/, const size_t index, uint64_t &value) {
if (auto res = utils::to<uint64_t>(column(index)); res.is_ok()) {
value = res.value();
}
}
void postgres_result_reader::read_value(const char * /*id*/, const size_t index, bool &value) {
if (auto res = utils::to<bool>(column(index)); res.is_ok()) {
value = res.value();
}
}
void postgres_result_reader::read_value(const char * /*id*/, const size_t index, float &value) {
if (auto res = utils::to<float>(column(index)); res.is_ok()) {
value = res.value();
}
}
void postgres_result_reader::read_value(const char * /*id*/, const size_t index, double &value) {
if (auto res = utils::to<double>(column(index)); res.is_ok()) {
value = res.value();
}
}
void postgres_result_reader::read_value(const char * /*id*/, const size_t index, time &/*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) {
// value.set(val, matador::utils::date_format::ISO8601);
// }
}
void postgres_result_reader::read_value(const char * /*id*/, const size_t index, char *value, size_t size) {
auto val = column(index);
if (const size_t len = strlen(val); len > size) {
#ifdef _MSC_VER
strncpy_s(value, size, val, len);
#else
strncpy(value, val, size);
#endif
value[size-1] = '\n';
} else {
#ifdef _MSC_VER
strcpy_s(value, size, val);
#else
strcpy(value, val);
#endif
}
}
void postgres_result_reader::read_value(const char * /*id*/, const size_t index, std::string &value) {
value.assign(column(index));
}
void postgres_result_reader::read_value(const char * /*id*/, const size_t index, std::string &value, size_t /*s*/) {
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<const unsigned char*>(column(index));
// auto length = PQgetlength(result_, row_index_, static_cast<int>(index));
size_t length;
unsigned char* unescaped = PQunescapeBytea(data, &length);
value.assign(unescaped, unescaped+length);
}
template <typename Type>
void set_value(const char* str, utils::value& value) {
if (const auto res = utils::to<Type>(str); res.is_ok()) {
value = res.value();
}
}
template <>
void set_value<utils::blob>(const char* str, utils::value& value) {
size_t length;
unsigned char* unescaped = PQunescapeBytea(reinterpret_cast<const unsigned char*>(str), &length);
value = utils::blob(unescaped, unescaped+length);
}
void postgres_result_reader::read_value(const char * /*id*/, const size_t index, utils::value &val, size_t) {
switch (val.type()) {
case utils::basic_type::type_int8:
set_value<int8_t>(column(index), val);
break;
case utils::basic_type::type_int16:
set_value<int16_t>(column(index), val);
break;
case utils::basic_type::type_int32:
set_value<int32_t>(column(index), val);
break;
case utils::basic_type::type_int64:
set_value<int64_t>(column(index), val);
break;
case utils::basic_type::type_uint8:
set_value<uint8_t>(column(index), val);
break;
case utils::basic_type::type_uint16:
set_value<uint16_t>(column(index), val);
break;
case utils::basic_type::type_uint32:
set_value<uint32_t>(column(index), val);
break;
case utils::basic_type::type_uint64:
set_value<uint64_t>(column(index), val);
break;
case utils::basic_type::type_float:
set_value<float>(column(index), val);
break;
case utils::basic_type::type_double:
set_value<double>(column(index), val);
break;
case utils::basic_type::type_bool:
set_value<bool>(column(index), val);
break;
case utils::basic_type::type_text:
case utils::basic_type::type_varchar: {
if (const auto *column_value = column(index); column_value == nullptr) {
val = std::string{};
} else {
val = std::string{column_value};
}
break;
}
case utils::basic_type::type_time:
case utils::basic_type::type_date: {
val = std::string{column(index)};
break;
}
case utils::basic_type::type_null: {
val = nullptr_t{};
break;
}
case utils::basic_type::type_blob: {
set_value<utils::blob>(column(index), val);
break;
}
}
}
utils::attribute_reader &postgres_result_reader::result_binder() {
return empty_binder_;
}
} // namespace matador::backends::postgres