userver: userver/storages/postgres/io/interval.hpp Source File
Loading...
Searching...
No Matches
interval.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file userver/storages/postgres/io/interval.hpp
4/// @brief Time intervals I/O support
5/// @ingroup userver_postgres_parse_and_format
6
7#include <chrono>
8
9#include <userver/storages/postgres/exceptions.hpp>
10#include <userver/storages/postgres/io/buffer_io.hpp>
11#include <userver/storages/postgres/io/buffer_io_base.hpp>
12#include <userver/storages/postgres/io/integral_types.hpp>
13#include <userver/storages/postgres/io/traits.hpp>
14#include <userver/storages/postgres/io/type_mapping.hpp>
15
16USERVER_NAMESPACE_BEGIN
17
18namespace storages::postgres::io {
19
20namespace detail {
21
22/// Internal structure for representing PostgreSQL interval type
23struct Interval {
24 using DurationType = std::chrono::microseconds;
25
26 Integer months = 0;
27 Integer days = 0;
28 Bigint microseconds = 0;
29
30 constexpr Interval() = default;
31 constexpr Interval(Integer months, Integer days, Bigint microseconds)
32 : months{months},
33 days{days},
34 microseconds{microseconds}
35 {}
36 constexpr explicit Interval(DurationType ms)
37 : microseconds{ms.count()}
38 {}
39
40 constexpr bool operator==(const Interval& rhs) const {
41 return months == rhs.months && days == rhs.days && microseconds == rhs.microseconds;
42 }
43 constexpr bool operator!=(const Interval& rhs) const { return !(*this == rhs); }
44
45 constexpr DurationType GetDuration() const {
46 if (months != 0) {
47 throw UnsupportedInterval{};
48 }
49 return std::chrono::duration_cast<
50 DurationType>(std::chrono::microseconds{microseconds} + std::chrono::hours{days * 24});
51 }
52};
53
54} // namespace detail
55
56template <>
57struct BufferParser<detail::Interval> : detail::BufferParserBase<detail::Interval> {
58 using BaseType = detail::BufferParserBase<detail::Interval>;
59 using ValueType = typename BaseType::ValueType;
60
61 using BaseType::BaseType;
62
63 void operator()(const FieldBuffer& buffer) {
64 ValueType tmp;
65 std::size_t offset = 0;
66 io::ReadBuffer(buffer.GetSubBuffer(offset, sizeof(Bigint), BufferCategory::kPlainBuffer), tmp.microseconds);
67 offset += sizeof(Bigint);
68 io::ReadBuffer(buffer.GetSubBuffer(offset, sizeof(Integer), BufferCategory::kPlainBuffer), tmp.days);
69 offset += sizeof(Integer);
70 io::ReadBuffer(buffer.GetSubBuffer(offset, sizeof(Integer), BufferCategory::kPlainBuffer), tmp.months);
71
72 std::swap(this->value, tmp);
73 }
74};
75
76template <>
77struct BufferFormatter<detail::Interval> : detail::BufferFormatterBase<detail::Interval> {
78 using BaseType = detail::BufferFormatterBase<detail::Interval>;
79
80 using BaseType::BaseType;
81
82 template <typename Buffer>
83 void operator()(const UserTypes& types, Buffer& buffer) const {
84 io::WriteBuffer(types, buffer, this->value.microseconds);
85 io::WriteBuffer(types, buffer, this->value.days);
86 io::WriteBuffer(types, buffer, this->value.months);
87 }
88};
89
90template <>
91struct CppToSystemPg<detail::Interval> : PredefinedOid<PredefinedOids::kInterval> {};
92
93} // namespace storages::postgres::io
94
95USERVER_NAMESPACE_END