userver: userver/storages/postgres/io/user_types.hpp Source File
Loading...
Searching...
No Matches
user_types.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file userver/storages/postgres/io/user_types.hpp
4/// @brief User types I/O support
5/// @ingroup userver_postgres_parse_and_format
6
7#include <unordered_map>
8#include <unordered_set>
9
10#include <userver/storages/postgres/exceptions.hpp>
11#include <userver/storages/postgres/io/pg_types.hpp>
12#include <userver/storages/postgres/io/type_mapping.hpp>
13
14USERVER_NAMESPACE_BEGIN
15
16namespace storages::postgres {
17
18/// @brief PostgreSQL composite type description
20public:
21 using CompositeFieldDefs = std::vector<CompositeFieldDef>;
22 CompositeTypeDescription(CompositeFieldDefs::const_iterator begin, CompositeFieldDefs::const_iterator end)
23 : attributes_{begin, end}
24 {}
25 std::size_t Size() const { return attributes_.size(); }
26 bool Empty() const { return attributes_.empty(); }
27 const CompositeFieldDef& operator[](std::size_t index) const {
28 if (index >= Size()) {
29 throw FieldIndexOutOfBounds{index};
30 }
31 return attributes_[index];
32 }
33
34private:
35 CompositeFieldDefs attributes_;
36};
37
38/// @brief Container for connection-specific user data types.
39class UserTypes {
40public:
41 using CompositeFieldDefs = std::vector<CompositeFieldDef>;
42
43 UserTypes() = default;
44 UserTypes(const UserTypes&) = delete;
45 UserTypes(UserTypes&&) noexcept = default;
46
47 UserTypes& operator=(const UserTypes&) = delete;
48 UserTypes& operator=(UserTypes&&) noexcept = default;
49
50 void Reset();
51
52 Oid FindOid(DBTypeName) const;
53 Oid FindArrayOid(DBTypeName) const;
54 /// Find element type oid for an array type.
55 /// Returns invalid oid if the type is not an array or the type is not found
56 Oid FindElementOid(Oid) const;
57 DBTypeName FindName(Oid) const;
58 /// Find name of the base type for a domain or element type for an array.
59 /// For the rest of types returns the name for the oid if found.
61 /// Find base oid for a domain or element type for an array.
62 /// For the rest of types returns the oid itself.
63 Oid FindBaseOid(Oid) const;
64 Oid FindBaseOid(DBTypeName) const;
65 /// Find base oid for a domain.
66 /// For the rest of types returns the oid itself.
67 Oid FindDomainBaseOid(Oid) const;
68
69 bool HasParser(Oid) const;
70 io::BufferCategory GetBufferCategory(Oid) const;
71 const io::TypeBufferCategory& GetTypeBufferCategories() const;
72
73 void AddType(DBTypeDescription&& desc);
74 void AddCompositeFields(CompositeFieldDefs&& defs);
75
76 const CompositeTypeDescription& GetCompositeDescription(Oid) const;
77 /// Get type description by oid.
78 /// May return nullptr if the type was not loaded from the database
80
81 /// @throws UserTypeError if not all registered cpp types are added
83
84private:
85 using DescriptionSet =
87 using DescriptionIterator = DescriptionSet::const_iterator;
88 using MapByOid = std::unordered_map<Oid, DescriptionIterator>;
89 using MapByName = std::unordered_map<DBTypeName, DescriptionIterator>;
90 using CompositeTypes = std::unordered_map<Oid, CompositeTypeDescription>;
91
92 DescriptionSet types_;
93 MapByOid by_oid_;
94 MapByName by_name_;
95 io::TypeBufferCategory buffer_categories_;
96 CompositeTypes composite_types_;
97};
98
99namespace io::detail {
100
101template <typename T>
102inline constexpr DBTypeName kPgUserTypeName = CppToUserPg<T>::postgres_name;
103
104template <typename T>
105struct CppToUserPgImpl {
106 static_assert(io::traits::CheckParser<T>());
107
108 using Type = T;
109 using Mapping = CppToUserPg<T>;
110 static constexpr DBTypeName postgres_name = kPgUserTypeName<T>;
111 static const detail::RegisterUserTypeParser init;
112 static Oid GetOid(const UserTypes& user_types) {
113 // TODO Handle oid not found
114 return user_types.FindOid(init.postgres_name);
115 }
116 static Oid GetArrayOid(const UserTypes& user_types) {
117 // TODO Handle oid not found
118 return user_types.FindArrayOid(init.postgres_name);
119 }
120};
121
122template <typename T>
123const RegisterUserTypeParser CppToUserPgImpl<
124 T>::init = RegisterUserTypeParser::Register(kPgUserTypeName<T>, std::string{compiler::GetTypeName<T>()});
125
126} // namespace io::detail
127
128void LogRegisteredTypesOnce();
129
130} // namespace storages::postgres
131
132USERVER_NAMESPACE_END