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