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)
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