userver: userver/storages/postgres/io/type_mapping.hpp Source File
Loading...
Searching...
No Matches
type_mapping.hpp
1#pragma once
2
3#include <string>
4#include <type_traits>
5
6#include <userver/compiler/demangle.hpp>
7#include <userver/storages/postgres/detail/is_decl_complete.hpp>
8#include <userver/storages/postgres/io/pg_types.hpp>
9#include <userver/storages/postgres/io/traits.hpp>
10#include <userver/storages/postgres/io/type_traits.hpp>
11
12USERVER_NAMESPACE_BEGIN
13
14namespace storages::postgres::io {
15
16/// @brief Detect mapping of a C++ type to Postgres type.
17template <typename T, typename Enable = USERVER_NAMESPACE::utils::void_t<>>
18struct CppToPg;
19
20template <PredefinedOids Oid, typename T>
21struct PgToCpp;
22
23/// Find out if a parser for a predefined Postgres type was registered.
25/// Find out if predefined Postgres types are mapped to the same cpp type
27/// Get array element oid for a predefined type
29/// Get the buffer category for a predefined type
31
32bool HasParser(DBTypeName);
33
34namespace detail {
35
36/// Works as boost::ignore_unused, but returning a value.
37template <typename... T>
38inline bool ForceReference(const T&...) {
39 return true;
40}
41
42struct RegisterPredefinedOidParser {
43 static RegisterPredefinedOidParser Register(
44 PredefinedOids type_oid,
45 PredefinedOids array_oid,
46 BufferCategory category,
47 std::string cpp_name
48 );
49};
50
51// note: implementation is in user_types.cpp
52struct RegisterUserTypeParser {
53 static RegisterUserTypeParser Register(const DBTypeName&, std::string cpp_name);
54 const DBTypeName postgres_name;
55};
56
57/// @brief Declare a mapping of a C++ type to a PostgreSQL type oid.
58/// Also mark available parsers
59template <typename T>
60struct CppToSystemPgImpl {
61 using Type = T;
62 using Mapping = CppToSystemPg<T>;
63 static constexpr auto type_oid = Mapping::value;
64 static_assert(type_oid != PredefinedOids::kInvalid, "Type oid is invalid");
65
66 using ArrayMapping = ArrayType<type_oid>;
67 static constexpr auto array_oid = ArrayMapping::value;
68 static_assert(array_oid != PredefinedOids::kInvalid, "Array type oid is invalid");
69
70 // We cannot perform a static check for parser presence here as there are
71 // types that should not have one, e.g. char[N]. All parser checks will be
72 // performed at runtime.
73
74 static const inline RegisterPredefinedOidParser init = RegisterPredefinedOidParser::Register(
75 type_oid,
76 array_oid,
77 io::traits::kTypeBufferCategory<T>,
78 std::string{compiler::GetTypeName<T>()}
79 );
80
81 static constexpr Oid GetOid(const UserTypes&) {
82 ForceReference(init);
83 return static_cast<Oid>(type_oid);
84 }
85 static constexpr Oid GetArrayOid(const UserTypes&) {
86 ForceReference(init);
87 return static_cast<Oid>(array_oid);
88 }
89};
90
91template <typename T>
92struct CppToUserPgImpl;
93
94/// @brief Declare a mapping of a PostgreSQL predefined type oid to a C++ type.
95/// Available parsers will be marked after referencing the init somewhere in the code.
96template <PredefinedOids TypeOid, typename T>
97struct PgToCppPredefined {
98 static constexpr auto type_oid = TypeOid;
99 static_assert(type_oid != PredefinedOids::kInvalid, "Type oid is invalid");
100
101 using ArrayMapping = ArrayType<type_oid>;
102 static constexpr auto array_oid = ArrayMapping::value;
103 static_assert(array_oid != PredefinedOids::kInvalid, "Array type oid is invalid");
104
105 // See above on parser presence checks.
106
107 static const inline RegisterPredefinedOidParser init = RegisterPredefinedOidParser::Register(
108 type_oid,
109 array_oid,
110 io::traits::kTypeBufferCategory<T>,
111 std::string{compiler::GetTypeName<T>()}
112 );
113};
114
115} // namespace detail
116
117template <typename T>
118struct CppToPg<
119 T,
120 std::enable_if_t<!traits::kIsSpecialMapping<T> && traits::kIsMappedToPg<T> && !traits::kIsMappedToArray<T>>>
121 : std::conditional_t<traits::kIsMappedToSystemType<T>, detail::CppToSystemPgImpl<T>, detail::CppToUserPgImpl<T>> {};
122
123template <typename T>
124constexpr bool IsTypeMappedToSystem() {
125 return traits::kIsMappedToPg<T> &&
126 std::is_same<typename CppToPg<T>::Mapping, CppToSystemPg<typename CppToPg<T>::Type>>::value;
127}
128
129void LogRegisteredTypes();
130
131} // namespace storages::postgres::io
132
133USERVER_NAMESPACE_END