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