diff options
author | Dan Goodliffe <dan@randomdan.homeip.net> | 2021-05-31 13:18:17 +0100 |
---|---|---|
committer | Dan Goodliffe <dan@randomdan.homeip.net> | 2021-05-31 13:18:17 +0100 |
commit | 63b2ca0dbdae190941d60a55c9cff99d4a75a0e1 (patch) | |
tree | d3766bcbc98fb5fb0fb2d8dddf2f194bedcb0325 /lib/output/pq/pqRecordSet.cpp | |
parent | Map std::size_t to a sensible header (diff) | |
download | mygrate-63b2ca0dbdae190941d60a55c9cff99d4a75a0e1.tar.bz2 mygrate-63b2ca0dbdae190941d60a55c9cff99d4a75a0e1.tar.xz mygrate-63b2ca0dbdae190941d60a55c9cff99d4a75a0e1.zip |
Initial commit of prepstmt, selects, record sets
This is full of holes, but all the basics are covered.
Diffstat (limited to 'lib/output/pq/pqRecordSet.cpp')
-rw-r--r-- | lib/output/pq/pqRecordSet.cpp | 86 |
1 files changed, 86 insertions, 0 deletions
diff --git a/lib/output/pq/pqRecordSet.cpp b/lib/output/pq/pqRecordSet.cpp new file mode 100644 index 0000000..71ddee4 --- /dev/null +++ b/lib/output/pq/pqRecordSet.cpp @@ -0,0 +1,86 @@ +#include "pqRecordSet.h" +#include "dbTypes.h" +#include "pqStmt.h" +#include <cstddef> +#include <cstdint> +#include <cstdlib> +#include <ctime> +#include <helpers.h> +#include <libpq-fe.h> +#include <server/catalog/pg_type_d.h> +#include <stdexcept> +#include <string_view> +#include <utility> + +namespace MyGrate::Output::Pq { + PqRecordSet::PqRecordSet(ResPtr r) : res {std::move(r)} { } + + std::size_t + PqRecordSet::rows() const + { + return PQntuples(res.get()); + } + + std::size_t + PqRecordSet::columns() const + { + return PQnfields(res.get()); + } + + DbValue + PqRecordSet::at(std::size_t row, std::size_t col) const + { + if (PQgetisnull(res.get(), (int)row, (int)col)) { + return nullptr; + } + const auto value {PQgetvalue(res.get(), (int)row, (int)col)}; + const auto size {static_cast<size_t>(PQgetlength(res.get(), (int)row, (int)col))}; + const auto type {PQftype(res.get(), (int)col)}; + switch (type) { + // case BITOID: TODO bool + // case BOOLOID: TODO bool + // case BOOLARRAYOID: + case VARBITOID: + case BYTEAOID: + // This is wrong :) + return Blob {reinterpret_cast<const std::byte *>(value), size}; + case INT2OID: + return static_cast<int16_t>(std::strtol(value, nullptr, 10)); + case INT4OID: + return static_cast<int32_t>(std::strtol(value, nullptr, 10)); + case INT8OID: + return std::strtol(value, nullptr, 10); + case FLOAT4OID: + return std::strtof(value, nullptr); + case FLOAT8OID: + case CASHOID: + case NUMERICOID: + return std::strtod(value, nullptr); + case DATEOID: { + tm tm {}; + const auto end = strptime(value, "%F", &tm); + verify<std::runtime_error>(end && !*end, "Invalid date string"); + return Date {tm}; + } + case TIMEOID: { + tm tm {}; + const auto end = strptime(value, "%T", &tm); + verify<std::runtime_error>(end && !*end, "Invalid time string"); + return Time {tm}; + } + case TIMESTAMPOID: { + tm tm {}; + const auto end = strptime(value, "%FT%T", &tm); + verify<std::runtime_error>(end && !*end, "Invalid timestamp string"); + return DateTime {tm}; + } + // case TIMESTAMPTZOID: Maybe add TZ support? + // case INTERVALOID: Maybe add interval support? + // case TIMETZOID: Maybe add TZ support? + case VOIDOID: + return nullptr; + default: + return std::string_view {value, size}; + } + } +} |