userver: userver/storages/postgres/io/pg_types.hpp Source File
Loading...
Searching...
No Matches
pg_types.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file userver/storages/postgres/io/pg_types.hpp
4/// @brief Postgres-specific types I/O support
5
6#include <cstdint>
7#include <string>
8#include <string_view>
9
10#include <userver/storages/postgres/detail/db_data_type_name.hpp>
11
12USERVER_NAMESPACE_BEGIN
13
14namespace storages::postgres {
15
16/// PostgreSQL Oid type.
17// Aliased to unsigned int to match the type used in libpq.
18using Oid = unsigned int;
19inline constexpr Oid kInvalidOid = 0;
20
21//@{
22/** @name Type aliases for integral types */
23using Smallint = std::int16_t;
24using Integer = std::int32_t;
25using Bigint = std::int64_t;
26//@}
27
28//@{
29using Float4 = float;
30using Float8 = double;
31//@}
32
33/// @brief Identity for a PostgreSQL type name
34struct DBTypeName {
35 const std::string_view schema;
36 const std::string_view name;
37
38 constexpr DBTypeName() : schema{}, name{} {}
39 explicit constexpr DBTypeName(std::pair<std::string_view, std::string_view> n) : schema(n.first), name(n.second) {}
40 /// Implicit constructor from a string literal, to enable declarations like
41 /// @code
42 /// DBTypeName my_type = "my_schema.my_type";
43 /// @endcode
44 /* implicit */ constexpr DBTypeName(const char* name) : DBTypeName(utils::ParseDBName(name)) {}
45 constexpr DBTypeName(std::string_view s, std::string_view n) : schema(s), name(n) {}
46
47 bool operator==(const DBTypeName& rhs) const { return name == rhs.name && schema == rhs.schema; }
48 bool operator<(const DBTypeName& rhs) const {
49 auto schema_cmp = schema.compare(rhs.schema);
50 if (schema_cmp < 0) {
51 return true;
52 } else if (schema_cmp == 0) {
53 return name < rhs.name;
54 }
55 return false;
56 }
57
58 bool Empty() const { return name.empty(); }
59 std::size_t GetHash() const;
60 std::string ToString() const;
61};
62
63/// @brief Description of a PostgreSQL type.
64/// The structure is selected from the pg_catalog.pg_type table (not all, only
65/// appropriate fields).
66/// See https://www.postgresql.org/docs/12/catalog-pg-type.html
68 enum class TypeClass : char {
69 kUnknown = 'X',
70 kBase = 'b',
71 kComposite = 'c',
72 kDomain = 'd',
73 kEnum = 'e',
74 kPseudo = 'p',
75 kRange = 'r'
76 };
77 /// @brief PosgtreSQL type category.
78 /// See
79 /// https://www.postgresql.org/docs/12/catalog-pg-type.html#CATALOG-TYPCATEGORY-TABLE
80 enum class TypeCategory : char {
81 kInvalid = 0, //!< Invalid type category
82 kArray = 'A', //!< https://www.postgresql.org/docs/12/arrays.html
83 kBoolean = 'B', //!< https://www.postgresql.org/docs/12/datatype-boolean.html
84 kComposite = 'C', //!< https://www.postgresql.org/docs/12/rowtypes.html
85 kDatetime = 'D', //!< https://www.postgresql.org/docs/12/datatype-datetime.html
86 kEnumeration = 'E', //!< https://www.postgresql.org/docs/12/datatype-enum.html
87 kGeometric = 'G', //!< https://www.postgresql.org/docs/12/datatype-geometric.html
88 kNetwork = 'I', //!< https://www.postgresql.org/docs/12/datatype-net-types.html
89 kNumeric = 'N', //!< https://www.postgresql.org/docs/12/datatype-numeric.html
90 kPseudotype = 'P', //!< https://www.postgresql.org/docs/12/datatype-pseudo.html
91 kRange = 'R', //!< https://www.postgresql.org/docs/12/rangetypes.html
92 kString = 'S', //!< https://www.postgresql.org/docs/12/datatype-character.html
93 kTimespan = 'T', //!< https://www.postgresql.org/docs/12/datatype-datetime.html
94 kUser = 'U', //!< User types, created by fourth form of create type
95 /// statement
96 /// https://www.postgresql.org/docs/12/sql-createtype.html
97 kBitstring = 'V', //!< https://www.postgresql.org/docs/12/datatype-bit.html
98 kUnknown = 'X' //!< Unknown type category
99 };
100
101 /// pg_type.oid
102 Oid oid{kInvalidOid};
103 /// pg_namespace.nspname
104 std::string schema;
105 /// pg_type.typname
106 std::string name;
107 /// pg_type.typlen
108 Integer length{0};
109 /// pg_type.typtype
110 TypeClass type_class{TypeClass::kUnknown};
111 /// pg_type.typcategory
113 /// pg_type.typrelid
114 Oid relation_id{kInvalidOid};
115 /// pg_type.typelem
116 /// If not zero, this type is an array
117 Oid element_type{kInvalidOid};
118 /// pg_type.typarray
119 Oid array_type{kInvalidOid};
120 /// pg_type.typbasetype
121 /// Base type for domains
122 Oid base_type{kInvalidOid};
123 /// pg_type.typnotnull
124 /// Used only with domains
125 bool not_null{false};
126 // TODO rest of domain fields. or eliminate them if they are not needed
127
128 DBTypeName GetName() const { return {schema.c_str(), name.c_str()}; }
129 std::size_t GetNameHash() const;
130
131 struct NameHash {
132 std::size_t operator()(const DBTypeDescription& type) const { return type.GetNameHash(); }
133 };
134 struct NamesEqual {
135 bool operator()(const DBTypeDescription& lhs, const DBTypeDescription& rhs) const {
136 return lhs.name == rhs.name && lhs.schema == rhs.schema;
137 }
138 };
141 auto operator()(TypeCategory val) const { return std::hash<IntegralType>{}(static_cast<IntegralType>(val)); }
142 };
143};
144
145/// Description of a field in a user-defined composite type, for type checking
147 Oid owner{kInvalidOid};
148 std::string name;
149 Oid type{kInvalidOid};
150
151 static CompositeFieldDef EmptyDef() { return {kInvalidOid, {}, kInvalidOid}; }
152};
153
154std::string ToString(DBTypeDescription::TypeClass);
155
156namespace io {
157/// Oids are predefined for postgres fundamental types
158/// Constants can be found here
159/// https://github.com/postgres/postgres/blob/master/src/include/catalog/pg_type.dat
160/// Oid values can also be retrieved from PostgreSQL instance by running query
161/// @code
162/// select t.oid as "Oid", pg_catalog.format_type(t.oid, null) as "Name"
163/// from pg_catalog.pg_type t
164/// left join pg_catalog.pg_namespace n on n.oid = t.typnamespace
165/// where (t.typrelid = 0 or (select c.relkind = 'c' from pg_catalog.pg_class c
166/// where c.oid = t.typrelid))
167/// and not exists(select 1 from pg_catalog.pg_type el where el.oid =
168/// t.typelem and el.typarray = t.oid) and n.nspname = 'pg_catalog'
169/// order by 1, 2
170/// @endcode
171enum class PredefinedOids {
172 kInvalid = kInvalidOid,
173 kBoolean = 16,
174 kBytea = 17,
175 kChar = 18,
176 kName = 19,
177 kInt8 = 20,
178 kInt2 = 21,
179 kInt2Vector = 22,
180 kInt4 = 23,
181 kRegproc = 24,
182 kText = 25,
183 kOid = 26,
184 kTid = 27,
185 kXid = 28,
186 kCid = 29,
187 kOidVector = 30,
188 kJson = 114,
189 kJsonArray = 199, // Not in documentation
190 kXml = 142,
191 kPgNodeTree = 194,
192 kPgDdlCommand = 32,
193 kPoint = 600,
194 kLseg = 601,
195 kPath = 602,
196 kBox = 603,
197 kPolygon = 604,
198 kLine = 628,
199 kLineArray = 629,
200 kFloat4 = 700,
201 kFloat8 = 701,
202 kAbstime = 702,
203 kReltime = 703,
204 kTinterval = 704,
205 kUnknown = 705,
206 kCircle = 718,
207 kCircleArray = 719, // Not in documentation
208 kCash = 790,
209 kMacaddr = 829,
210 kMacaddrArray = 1040,
211 kMacaddr8 = 774,
212 kMacaddr8Array = 775,
213 kInet = 869,
214 kInetArray = 1041,
215 kCidr = 650,
216 kCidrArray = 651,
217 kBooleanArray = 1000, // Not in documentation
218 kByteaArray = 1001, // Not in documentation
219 kCharArray = 1002, // Not in documentation
220 kNameArray = 1003, // Not in documentation
221 kInt2Array = 1005,
222 kInt4Array = 1007,
223 kTextArray = 1009,
224 kTidArray = 1010, // Not in documentation
225 kXidArray = 1011, // Not in documentation
226 kCidArray = 1012, // Not in documentation
227 kBphcarArray = 1014, // Not in documentation
228 kVarcharArray = 1015, // Not in documentation
229 kInt8Array = 1016, // Not in documentation
230 kPointArray = 1017, // Not in documentation
231 kLsegArray = 1018, // Not in documentation
232 kPathArray = 1019, // Not in documentation
233 kBoxArray = 1020, // Not in documentation
234 kFloat4Array = 1021,
235 kFloat8Array = 1022, // Not in documentation
236 kPolygonArray = 1027, // Not in documentation
237 kOidArray = 1028,
238 kAclItem = 1033,
239 kCstringArray = 1263,
240 kBpchar = 1042,
241 kVarchar = 1043,
242 kDate = 1082,
243 kTime = 1083,
244 kDateArray = 1182, // Not in documentation
245 kTimeArray = 1183, // Not in documentation
246 kTimestamp = 1114,
247 kTimestampArray = 1115, // Not in documentation
248 kTimestamptz = 1184,
249 kTimestamptzArray = 1185, // Not in documentation
250 kInterval = 1186,
251 kIntervalArray = 1187, // Not in documentation
252 kNumericArray = 1231, // Not in documentation
253 kTimetz = 1266,
254 kBit = 1560,
255 kBitArray = 1561,
256 kVarbit = 1562,
257 kVarbitArray = 1563,
258 kNumeric = 1700,
259 kRefcursor = 1790,
260 kRegprocedure = 2202,
261 kRegoper = 2203,
262 kRegoperator = 2204,
263 kRegclass = 2205,
264 kRegtype = 2206,
265 kRegrole = 4096,
266 kRegtypearray = 2211,
267 kUuid = 2950,
268 kUuidArray = 2951, // Not in documentation
269 kLsn = 3220,
270 kLsnArray = 3221,
271 kTsvector = 3614,
272 kGtsvector = 3642,
273 kTsquery = 3615,
274 kRegconfig = 3734,
275 kRegdictionary = 3769,
276 kJsonb = 3802,
277 kJsonbArray = 3807, // Not in documentation
278 kRecord = 2249,
279 kRecordArray = 2287,
280 kCstring = 2275,
281 kAny = 2276,
282 kAnyArray = 2277,
283 kVoid = 2278,
284 kTrigger = 2279,
285 kEvttrigger = 3838,
286 kLanguageHandler = 2280,
287 kInternal = 2281,
288 kOpaque = 2282,
289 kAnyElement = 2283,
290 kAnyNonArray = 2776,
291 kAnyEnum = 3500,
292 kFdwHandler = 3115,
293 kAnyRange = 3831,
294 kInt4Range = 3904,
295 kInt4RangeArray = 3905, // Not in documentation
296 kNumRange = 3906, // Not in documentation
297 kNumRangeArray = 3907, // Not in documentation
298 kTimestampRange = 3908, // Not in documentation
299 kTimestampRangeArray = 3909, // Not in documentation
300 kTimestamptzRange = 3910, // Not in documentation
301 kTimestamptzRangeArray = 3911, // Not in documentation
302 kDateRange = 3912, // Not in documentation
303 kDateRangeArray = 3913, // Not in documentation
304 kInt8Range = 3926, // Not in documentation
305 kInt8RangeArray = 3927, // Not in documentation
306};
307
308template <PredefinedOids TypeOid>
310
311//@{
312/** @name Array types for predefined oids */
313template <PredefinedOids TypeOid>
315
316template <>
318template <>
320template <>
322template <>
324template <>
326template <>
328template <>
330template <>
332template <>
334template <>
336template <>
338template <>
340template <>
342template <>
344template <>
346
347template <>
349template <>
351
352template <>
354template <>
356
357template <>
359
360template <>
362
363template <>
365template <>
367
368template <>
370
371template <>
373
374template <>
376
377template <>
379
380template <>
382
383template <>
385
386template <>
388
389template <>
391
392template <>
394
395template <>
397
398template <>
400
401template <>
403template <>
405template <>
407template <>
409template <>
411template <>
413template <>
415
416template <>
418template <>
420
421template <>
423
424template <>
426
427template <>
429
430//@}
431
432} // namespace io
433} // namespace storages::postgres
434
435USERVER_NAMESPACE_END
436
437namespace std {
438
439template <>
440struct hash<USERVER_NAMESPACE::storages::postgres::io::PredefinedOids> {
441 std::size_t operator()(USERVER_NAMESPACE::storages::postgres::io::PredefinedOids value) const {
442 return static_cast<std::size_t>(value);
443 }
444};
445
446template <>
447struct hash<USERVER_NAMESPACE::storages::postgres::DBTypeName> {
448 std::size_t operator()(const USERVER_NAMESPACE::storages::postgres::DBTypeName& value) const {
449 return value.GetHash();
450 }
451};
452
453} // namespace std