summaryrefslogtreecommitdiff
path: root/lib/output/pq/pqRecordSet.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/output/pq/pqRecordSet.cpp')
-rw-r--r--lib/output/pq/pqRecordSet.cpp86
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};
+ }
+ }
+}