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
44 Register(PredefinedOids type_oid, PredefinedOids array_oid, BufferCategory category, std::string cpp_name);
45};
46
47// note: implementation is in user_types.cpp
48struct RegisterUserTypeParser {
49 static RegisterUserTypeParser Register(const DBTypeName&, std::string cpp_name);
50 const DBTypeName postgres_name;
51};
52
53/// @brief Declare a mapping of a C++ type to a PostgreSQL type oid.
54/// Also mark available parsers
55template <typename T>
56struct CppToSystemPgImpl {
57 using Type = T;
58 using Mapping = CppToSystemPg<T>;
59 static constexpr auto type_oid = Mapping::value;
60 static_assert(type_oid != PredefinedOids::kInvalid, "Type oid is invalid");
61
62 using ArrayMapping = ArrayType<type_oid>;
63 static constexpr auto array_oid = ArrayMapping::value;
64 static_assert(array_oid != PredefinedOids::kInvalid, "Array type oid is invalid");
65
66 // We cannot perform a static check for parser presence here as there are
67 // types that should not have one, e.g. char[N]. All parser checks will be
68 // performed at runtime.
69
70 static const inline RegisterPredefinedOidParser init_ = RegisterPredefinedOidParser::Register(
71 type_oid,
72 array_oid,
73 io::traits::kTypeBufferCategory<T>,
74 compiler::GetTypeName<T>()
75 );
76
77 static constexpr Oid GetOid(const UserTypes&) {
78 ForceReference(init_);
79 return static_cast<Oid>(type_oid);
80 }
81 static constexpr Oid GetArrayOid(const UserTypes&) {
82 ForceReference(init_);
83 return static_cast<Oid>(array_oid);
84 }
85};
86
87template <typename T>
88struct CppToUserPgImpl;
89
90/// @brief Declare a mapping of a PostgreSQL predefined type oid to a C++ type.
91/// Available parsers will be marked after referencing the init_
92/// somewhere in the code.
93template <PredefinedOids TypeOid, typename T>
94struct PgToCppPredefined {
95 static constexpr auto type_oid = TypeOid;
96 static_assert(type_oid != PredefinedOids::kInvalid, "Type oid is invalid");
97
98 using ArrayMapping = ArrayType<type_oid>;
99 static constexpr auto array_oid = ArrayMapping::value;
100 static_assert(array_oid != PredefinedOids::kInvalid, "Array type oid is invalid");
101
102 // See above on parser presence checks.
103
104 static const inline RegisterPredefinedOidParser init_ = RegisterPredefinedOidParser::Register(
105 type_oid,
106 array_oid,
107 io::traits::kTypeBufferCategory<T>,
108 compiler::GetTypeName<T>()
109 );
110};
111
112} // namespace detail
113
114template <typename T>
115struct CppToPg<
116 T,
117 std::enable_if_t<!traits::kIsSpecialMapping<T> && traits::kIsMappedToPg<T> && !traits::kIsMappedToArray<T>>>
118 : std::conditional_t<traits::kIsMappedToSystemType<T>, detail::CppToSystemPgImpl<T>, detail::CppToUserPgImpl<T>> {};
119
120template <typename T>
121constexpr bool IsTypeMappedToSystem() {
122 return traits::kIsMappedToPg<T> &&
123 std::is_same<typename CppToPg<T>::Mapping, CppToSystemPg<typename CppToPg<T>::Type>>::value;
124}
125
126void LogRegisteredTypes();
127
128} // namespace storages::postgres::io
129
130USERVER_NAMESPACE_END