userver: userver/storages/postgres/exceptions.hpp Source File
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages Concepts
exceptions.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file userver/storages/postgres/exceptions.hpp
4/// @brief Postgres errors
5
6#include <stdexcept>
7#include <string_view>
8
9#include <fmt/format.h>
10
11#include <userver/storages/postgres/dsn.hpp>
12#include <userver/storages/postgres/io/traits.hpp>
13#include <userver/storages/postgres/message.hpp>
14
15#include <userver/compiler/demangle.hpp>
16#include <userver/utils/underlying_value.hpp>
17
18USERVER_NAMESPACE_BEGIN
19
20namespace storages::postgres {
21
22namespace impl {
23
24// Provides nice to read messages for pattern strings that end on 'type'. For example:
25// fmt::format("Unexpected database type {}", OidPrettyPrint(oid));
26std::string OidPrettyPrint(Oid oid);
27
28} // namespace impl
29
30/**
31 * @page pg_errors uPg: Postgres errors
32 *
33 * Base class for all PostgreSQL errors is Error which is derived from
34 * std::runtime_error. This is done to simplify exception handling.
35 *
36 * There are two base types of errors: runtime (RuntimeError) and logic
37 * (LogicError).
38 *
39 * **Logic errors** are a consequence of faulty logic within the program such as
40 * violating logical preconditions or invariants and may be preventable by
41 * correcting the program.
42 *
43 * **Runtime errors** are due to events beyond the scope of the program, such as
44 * network failure, faulty configuration file, unique index violation etc. A
45 * user can catch such an error and recover from it by reconnecting, providing
46 * a decent default for configuration or modifying the key value.
47 *
48 * Both logic and runtime errors can contain a postgres server message
49 * (Message). Those are ServerLogicError and ServerRuntimeError
50 * respectively. These errors occur on the server side and are translated into
51 * exceptions by the driver. Server errors are descendants of either
52 * ServerLogicError or ServerRuntimeError and their hierarchy corresponds to SQL
53 * error classes.
54 *
55 * Some server errors, such as IntegrityConstraintViolation, have a more
56 * detailed hierarchy to distinguish errors in catch clauses.
57 *
58 * Server errors have the following hierarchy:
59 * - ServerLogicError
60 * - SqlStatementNotYetComplete
61 * - FeatureNotSupported
62 * - InvalidRoleSpecification
63 * - CardinalityViolation
64 * - InvalidObjectName
65 * - InvalidAuthorizationSpecification
66 * - SyntaxError
67 * - AccessRuleViolation
68 * - ServerRuntimeError
69 * - TriggeredActionException
70 * - LocatorException
71 * - InvalidGrantor
72 * - DiagnosticsException
73 * - DataException
74 * - DuplicatePreparedStatement
75 * - IntegrityConstraintViolation
76 * - RestrictViolation
77 * - NotNullViolation (TODO Make it a logic error)
78 * - ForeignKeyViolation
79 * - UniqueViolation
80 * - CheckViolation
81 * - ExclusionViolation
82 * - TriggeredDataChangeViolation
83 * - WithCheckOptionViolation
84 * - InvalidCursorState
85 * - InvalidSqlStatementName
86 * - InvalidTransactionState
87 * - DependentPrivilegeDescriptorsStillExist
88 * - InvalidTransactionTermination
89 * - ExternalRoutineException
90 * - ExternalRoutineInvocationException
91 * - SavepointException
92 * - SqlRoutineException
93 * - TransactionRollback
94 * - InsufficientResources
95 * - ProgramLimitExceeded
96 * - ObjectNotInPrerequisiteState
97 * - OperatorIntervention
98 * - QueryCancelled
99 * - AdminShutdown
100 * - CrashShutdown
101 * - CannotConnectNow
102 * - DatabaseDropped
103 * - SystemError
104 * - SnapshotFailure
105 * - ConfigurationFileError
106 * - FdwError
107 * - PlPgSqlError
108 * - InternalServerError
109 *
110 * Besides server errors there are exceptions thrown by the driver itself,
111 * those are:
112 * - LogicError
113 * - ResultSetError
114 * - FieldIndexOutOfBounds
115 * - FieldNameDoesntExist
116 * - FieldTupleMismatch
117 * - FieldValueIsNull
118 * - InvalidBinaryBuffer
119 * - InvalidInputBufferSize
120 * - InvalidParserCategory
121 * - InvalidTupleSizeRequested
122 * - NonSingleColumnResultSet
123 * - NonSingleRowResultSet
124 * - NoBinaryParser
125 * - RowIndexOutOfBounds
126 * - TypeCannotBeNull
127 * - UnknownBufferCategory
128 * - UserTypeError
129 * - CompositeSizeMismatch
130 * - CompositeMemberTypeMismatch
131 * - ArrayError
132 * - DimensionMismatch
133 * - InvalidDimensions
134 * - NumericError
135 * - NumericOverflow
136 * - ValueIsNaN
137 * - InvalidRepresentation
138 * - InvalidInputFormat
139 * - EnumerationError
140 * - InvalidEnumerationLiteral
141 * - InvalidEnumerationValue
142 * - TransactionError
143 * - AlreadyInTransaction
144 * - NotInTransaction
145 * - UnsupportedInterval
146 * - BoundedRangeError
147 * - BitStringError
148 * - BitStringOverflow
149 * - InvalidBitStringRepresentation
150 * - RuntimeError
151 * - ConnectionError
152 * - ClusterUnavailable
153 * - CommandError
154 * - ConnectionFailed
155 * - ServerConnectionError (contains a message from server)
156 * - ConnectionTimeoutError
157 * - ConnectionBusy
158 * - ConnectionInterrupted
159 * - PoolError
160 * - ClusterError
161 * - InvalidConfig
162 * - InvalidDSN
163 *
164 *
165 * ----------
166 *
167 * @htmlonly <div class="bottom-nav"> @endhtmlonly
168 * ⇦ @ref pg_user_row_types | @ref pg_topology ⇨
169 * @htmlonly </div> @endhtmlonly
170 */
171
172//@{
173/** @name Generic driver errors */
174
175/// @brief Base class for all exceptions that may be thrown by the driver.
176class Error : public std::runtime_error {
177 using runtime_error::runtime_error;
178};
179
180/// @brief Base Postgres logic error.
181/// Reports errors that are consequences of erroneous driver usage,
182/// such as invalid query syntax, absence of appropriate parsers, out of range
183/// errors etc.
184/// These can be avoided by fixing code.
185class LogicError : public Error {
186 using Error::Error;
187};
188
189/// @brief Base Postgres runtime error.
190/// Reports errors that are consequences of erroneous data, misconfiguration,
191/// network errors etc.
192class RuntimeError : public Error {
193 using Error::Error;
194};
195
196/// @brief Error that was reported by PosgtreSQL server
197/// Contains the message sent by the server.
198/// Templated class because the errors can be both runtime and logic.
199template <typename Base>
200class ServerError : public Base {
201public:
202 explicit ServerError(const Message& msg) : Base(msg.GetMessage()), msg_{msg} {}
203
204 const Message& GetServerMessage() const { return msg_; }
205
206 Message::Severity GetSeverity() const { return msg_.GetSeverity(); }
207 SqlState GetSqlState() const { return msg_.GetSqlState(); }
208
209private:
210 Message msg_;
211};
212
213using ServerLogicError = ServerError<LogicError>;
214using ServerRuntimeError = ServerError<RuntimeError>;
215//@}
216
217//@{
218/** @name Connection errors */
220 using RuntimeError::RuntimeError;
221};
222
223/// @brief Exception is thrown when a single connection fails to connect
225public:
226 explicit ConnectionFailed(const Dsn& dsn);
227 ConnectionFailed(const Dsn& dsn, std::string_view message);
228};
229
230/// @brief Connection error reported by PostgreSQL server.
231/// Doc: https://www.postgresql.org/docs/12/static/errcodes-appendix.html
232/// Class 08 - Connection exception
234 using ServerError::ServerError;
235};
236
237/// @brief Indicates errors during pool operation
238class PoolError : public RuntimeError {
239public:
240 PoolError(std::string_view msg, std::string_view db_name);
241 PoolError(std::string_view msg);
242};
243
245 using ConnectionError::ConnectionError;
246};
247
248/// @brief Error when invoking a libpq function
250 using ConnectionError::ConnectionError;
251};
252
253/// @brief A network operation on a connection has timed out
255 using ConnectionError::ConnectionError;
256};
257
259 using RuntimeError::RuntimeError;
260};
261
262/// @brief An attempt to make a query to server was made while there is another
263/// query in flight.
265 using RuntimeError::RuntimeError;
266};
267
268/// @brief A network operation was interrupted by task cancellation.
270 using RuntimeError::RuntimeError;
271};
272
273//@}
274
275//@{
276/** @name SQL errors */
277//@{
278/** @name Class 03 — SQL Statement Not Yet Complete */
279/// A programming error, a statement is sent before other statement's results
280/// are processed.
281class SqlStatementNotYetComplete : public ServerLogicError {
282 using ServerLogicError::ServerLogicError;
283};
284//@}
285
286//@{
287/** @name Class 09 — Triggered Action Exception */
288class TriggeredActionException : public ServerRuntimeError {
289 using ServerRuntimeError::ServerRuntimeError;
290};
291//@}
292
293//@{
294/** @name Class 0A — Feature Not Supported */
295class FeatureNotSupported : public ServerLogicError {
296 using ServerLogicError::ServerLogicError;
297};
298//@}
299
300//@{
301/** @name Class 0F - Locator Exception */
302class LocatorException : public ServerRuntimeError {
303 using ServerRuntimeError::ServerRuntimeError;
304};
305//@}
306
307//@{
308/** @name Class 0L - Invalid Grantor */
309class InvalidGrantor : public ServerRuntimeError {
310 using ServerRuntimeError::ServerRuntimeError;
311};
312//@}
313
314//@{
315/** @name Class 0P - Invalid Role Specification */
316class InvalidRoleSpecification : public ServerLogicError {
317 using ServerLogicError::ServerLogicError;
318};
319//@}
320
321//@{
322/** @name Class 0Z - Diagnostics Exception */
323class DiagnosticsException : public ServerRuntimeError {
324 using ServerRuntimeError::ServerRuntimeError;
325};
326//@}
327
328//@{
329/** @name Class 21 - Cardinality Violation */
330class CardinalityViolation : public ServerLogicError {
331 using ServerLogicError::ServerLogicError;
332};
333//@}
334
335//@{
336/** @name Class 22 — Data Exception */
337/// @brief Base class for data exceptions
338/// Doc: https://www.postgresql.org/docs/12/static/errcodes-appendix.html
339class DataException : public ServerRuntimeError {
340 using ServerRuntimeError::ServerRuntimeError;
341};
342//@}
343
344//@{
345/** @name Class 23 — Integrity Constraint Violation */
346// TODO Shortcut accessors to respective message fields
347/// @brief Base class for integrity constraint violation errors.
348/// Doc: https://www.postgresql.org/docs/12/static/errcodes-appendix.html
349class IntegrityConstraintViolation : public ServerRuntimeError {
350public:
351 using ServerRuntimeError::ServerRuntimeError;
352
353 std::string GetSchema() const;
354 std::string GetTable() const;
355 std::string GetConstraint() const;
356};
357
359 using IntegrityConstraintViolation::IntegrityConstraintViolation;
360};
361
363 using IntegrityConstraintViolation::IntegrityConstraintViolation;
364};
365
367 using IntegrityConstraintViolation::IntegrityConstraintViolation;
368};
369
371 using IntegrityConstraintViolation::IntegrityConstraintViolation;
372};
373
375 using IntegrityConstraintViolation::IntegrityConstraintViolation;
376};
377
379 using IntegrityConstraintViolation::IntegrityConstraintViolation;
380};
381
382/// Class 27 - Triggered Data Change Violation
384 using IntegrityConstraintViolation::IntegrityConstraintViolation;
385};
386
387/// Class 44 - WITH CHECK OPTION Violation
389 using IntegrityConstraintViolation::IntegrityConstraintViolation;
390};
391//@}
392
393//@{
394/** @name Class 24 - Invalid Cursor State */
395class InvalidCursorState : public ServerRuntimeError {
396 using ServerRuntimeError::ServerRuntimeError;
397};
398//@}
399
400//@{
401/** @name Class 25 — Invalid Transaction State */
402class InvalidTransactionState : public ServerRuntimeError {
403 using ServerRuntimeError::ServerRuntimeError;
404};
405//@}
406
407//@{
408/** @name Class 26 - Invalid SQL Statement Name */
409/// This exception is thrown in case a prepared statement doesn't exist
410class InvalidSqlStatementName : public ServerRuntimeError {
411 using ServerRuntimeError::ServerRuntimeError;
412};
413//@}
414
415//@{
416/** @name Invalid object name, several classes */
417/// @brief Exception class for several Invalid * Name classes.
418/// Class 34 - Invalid Cursor Name
419/// Class 3D - Invalid Catalogue Name
420/// Class 3F - Invalid Schema Name
421/// TODO Add documentation (links) on the error classes
422/// TODO Split exception classes if needed based on documentation
423class InvalidObjectName : public ServerLogicError {
424 using ServerLogicError::ServerLogicError;
425};
426//@}
427
428//@{
429/** @name Class 28 - Invalid Authorisation Specification */
430class InvalidAuthorizationSpecification : public ServerLogicError {
431 using ServerLogicError::ServerLogicError;
432};
433//@}
434
435//@{
436/** @name Class 2B - Dependent Privilege Descriptors Still Exist */
437class DependentPrivilegeDescriptorsStillExist : public ServerRuntimeError {
438 using ServerRuntimeError::ServerRuntimeError;
439};
440//@}
441
442//@{
443/** @name Class 2D - Invalid Transaction Termination */
444class InvalidTransactionTermination : public ServerRuntimeError {
445 using ServerRuntimeError::ServerRuntimeError;
446};
447//@}
448
449//@{
450/** @name Class 38 - External Routine Exception */
451class ExternalRoutineException : public ServerRuntimeError {
452 using ServerRuntimeError::ServerRuntimeError;
453};
454//@}
455
456//@{
457/** @name Class 39 - External Routine Invocation Exception */
458class ExternalRoutineInvocationException : public ServerRuntimeError {
459 using ServerRuntimeError::ServerRuntimeError;
460};
461//@}
462
463//@{
464/** @name Class 3B - Savepoint Exception */
465class SavepointException : public ServerRuntimeError {
466 using ServerRuntimeError::ServerRuntimeError;
467};
468//@}
469
470//@{
471/** @name Class 2F — SQL Routine Exception */
472class SqlRoutineException : public ServerRuntimeError {
473 using ServerRuntimeError::ServerRuntimeError;
474};
475//@}
476
477//@{
478/** @name Class 40 — Transaction Rollback */
479class TransactionRollback : public ServerRuntimeError {
480 using ServerRuntimeError::ServerRuntimeError;
481};
482//@}
483
484//@{
485/** @name Class 42 — Syntax Error or Access Rule Violation */
486class SyntaxError : public ServerLogicError {
487 using ServerLogicError::ServerLogicError;
488};
489
490class AccessRuleViolation : public ServerLogicError {
491 using ServerLogicError::ServerLogicError;
492};
493
494class DuplicatePreparedStatement : public ServerLogicError {
495 using ServerLogicError::ServerLogicError;
496};
497
498//@}
499
500//@{
501/** @name Class 53 - Insufficient Resources */
502class InsufficientResources : public ServerRuntimeError {
503 using ServerRuntimeError::ServerRuntimeError;
504};
505//@}
506
507//@{
508/** @name Class 54 - Program Limit Exceeded */
509class ProgramLimitExceeded : public ServerRuntimeError {
510 using ServerRuntimeError::ServerRuntimeError;
511};
512//@}
513
514//@{
515/** @name Class 55 - Object Not In Prerequisite State */
516class ObjectNotInPrerequisiteState : public ServerRuntimeError {
517 using ServerRuntimeError::ServerRuntimeError;
518};
519//@}
520
521//@{
522/** @name Class 57 - Operator Intervention */
523class OperatorIntervention : public ServerRuntimeError {
524 using ServerRuntimeError::ServerRuntimeError;
525};
526
528 using OperatorIntervention::OperatorIntervention;
529};
530
532 using OperatorIntervention::OperatorIntervention;
533};
534
536 using OperatorIntervention::OperatorIntervention;
537};
538
540 using OperatorIntervention::OperatorIntervention;
541};
542
544 using OperatorIntervention::OperatorIntervention;
545};
546//@}
547
548//@{
549/** @name Class 58 - System Error (errors external to PostgreSQL itself) */
550class SystemError : public ServerRuntimeError {
551 using ServerRuntimeError::ServerRuntimeError;
552};
553//@}
554
555//@{
556/** @name Class 72 — Snapshot Failure */
557class SnapshotFailure : public ServerRuntimeError {
558 using ServerRuntimeError::ServerRuntimeError;
559};
560//@}
561
562//@{
563/** @name Class F0 — Configuration File Error */
564class ConfigurationFileError : public ServerRuntimeError {
565 using ServerRuntimeError::ServerRuntimeError;
566};
567//@}
568
569//@{
570/** @name Class HV — Foreign Data Wrapper Error (SQL/MED) */
571class FdwError : public ServerRuntimeError {
572 using ServerRuntimeError::ServerRuntimeError;
573};
574//@}
575
576//@{
577/** @name Class P0 — PL/pgSQL Error */
578class PlPgSqlError : public ServerRuntimeError {
579 using ServerRuntimeError::ServerRuntimeError;
580};
581//@}
582
583//@{
584/** @name Class XX — Internal Error */
585class InternalServerError : public ServerRuntimeError {
586 using ServerRuntimeError::ServerRuntimeError;
587};
588//@}
589//@}
590
591//@{
592/** @name Transaction errors */
594 using LogicError::LogicError;
595};
596
598public:
599 AlreadyInTransaction();
600};
601
603public:
604 NotInTransaction();
605 NotInTransaction(const std::string& msg);
606};
607
609public:
610 TransactionForceRollback();
611 TransactionForceRollback(const std::string& msg);
612};
613
614//@}
615
616//@{
617/** @name Result set usage errors */
618
620public:
621 ResultSetError(std::string msg);
622
623 void AddMsgSuffix(std::string_view str);
624 void AddMsgPrefix(std::string_view str);
625
626 const char* what() const noexcept override;
627
628private:
629 std::string msg_;
630};
631
632/// @brief Result set has less rows than the requested row index.
634public:
635 RowIndexOutOfBounds(std::size_t index);
636};
637
638/// @brief Result set has less columns that the requested index.
640public:
641 FieldIndexOutOfBounds(std::size_t index);
642};
643
644/// @brief Result set doesn't have field with the requested name.
646public:
647 FieldNameDoesntExist(std::string_view name);
648};
649
650/// @brief Data extraction from a null field value to a non-nullable type
651/// requested.
653public:
654 template <typename T>
655 FieldValueIsNull(std::size_t field_index, std::string_view field_name, const T&)
656 : ResultSetError(fmt::format(
657 "Field #{} name `{}` C++ type `{}` value is null, forgot `std::optional`?",
658 field_index,
659 field_name,
660 compiler::GetTypeName<T>()
661 )) {}
662};
663
664/// @brief A value of a non-nullable type requested to be set null.
665/// Can occur if io::traits::IsNullable for the type is specialised as
666/// true_type, but io::traits::GetSetNull is not specialized appropriately.
668public:
669 TypeCannotBeNull(std::string_view type);
670};
671
672/// @brief Field buffer contains different category of data than expected by
673/// data parser.
675public:
676 InvalidParserCategory(std::string_view type, io::BufferCategory parser, io::BufferCategory buffer);
677};
678
679/// @brief While checking result set types, failed to determine the buffer
680/// category for a type oid.
681/// The context string is formed by the ResultSet and will have the form
682/// of 'result set field `foo` type `my_schema.bar` field `baz` array element'
684public:
685 UnknownBufferCategory(std::string_view context, Oid type_oid);
686 UnknownBufferCategory(Oid type_oid, std::string_view cpp_field_type, std::string_view cpp_composite_type);
687
688 const Oid type_oid;
689};
690
691/// @brief A field in a result set doesn't have a binary parser.
693 using ResultSetError::ResultSetError;
694};
695
696/// @brief Buffer size is invalid for a fixed-size type.
697/// Can occur when a wrong field type is requested for reply.
699 using ResultSetError::ResultSetError;
700};
701
702/// @brief Binary buffer contains invalid data.
703/// Can occur when parsing binary buffers containing multiple fields.
705public:
706 InvalidBinaryBuffer(const std::string& message);
707};
708
709/// @brief A tuple was requested to be parsed out of a row that doesn't have
710/// enough fields.
712public:
713 InvalidTupleSizeRequested(std::size_t field_count, std::size_t tuple_size);
714};
715
716/// @brief A row or result set requested to be treated as a single column, but
717/// contains more than one column.
719public:
720 NonSingleColumnResultSet(std::size_t actual_size, std::string_view type_name, std::string_view func);
721};
722
723/// @brief A result set containing a single row was expected
725public:
726 explicit NonSingleRowResultSet(std::size_t actual_size);
727};
728
729/// @brief A row was requested to be parsed based on field names/indexed,
730/// the count of names/indexes doesn't match the tuple size.
732public:
733 FieldTupleMismatch(std::size_t field_count, std::size_t tuple_size);
734};
735
736//@}
737
738//@{
739/// @brief Base error when working with mapped types
740class UserTypeError : public LogicError {
741 using LogicError::LogicError;
742};
743
744/// @brief PostgreSQL composite type has different count of members from
745/// the C++ counterpart.
747public:
748 CompositeSizeMismatch(std::size_t pg_size, std::size_t cpp_size, std::string_view cpp_type);
749};
750
751/// @brief PostgreSQL composite type has different member type that the C++
752/// mapping suggests.
754public:
755 CompositeMemberTypeMismatch(
756 std::string_view pg_type_schema,
757 std::string_view pg_type_name,
758 std::string_view field_name,
759 Oid pg_oid,
760 Oid user_oid
761 );
762};
763
764//@}
765
766//@{
767/** @name Array errors */
768/// @brief Base error when working with array types.
769class ArrayError : public LogicError {
770 using LogicError::LogicError;
771};
772
773/// @brief Array received from postgres has different dimensions from those of
774/// C++ container.
776public:
777 DimensionMismatch();
778};
779
781public:
782 InvalidDimensions(std::size_t expected, std::size_t actual);
783};
784
785//@}
786
787//@{
788/** @name Numeric/decimal datatype errors */
789class NumericError : public LogicError {
790 using LogicError::LogicError;
791};
792
793/// Value in PostgreSQL binary buffer cannot be represented by a given C++ type
795 using NumericError::NumericError;
796};
797
798/// PostgreSQL binary buffer contains NaN value, but the given C++ type doesn't
799/// support NaN value
800class ValueIsNaN : public NumericError {
801 using NumericError::NumericError;
802};
803
804/// Integral representation for a numeric contains invalid data
806 using NumericError::NumericError;
807};
808//@}
809
810/// @brief Invalid format for input data.
811///
812/// Can occur when a numeric string representation cannot be parsed for sending
813/// in binary buffers
815 using LogicError::LogicError;
816};
817
818//@{
819/** @name Enumeration type errors */
821 using LogicError::LogicError;
822};
823
825public:
826 InvalidEnumerationLiteral(std::string_view type_name, std::string_view literal);
827};
828
830public:
831 template <typename Enum>
832 explicit InvalidEnumerationValue(Enum val)
833 : EnumerationError(fmt::format(
834 "Invalid enumeration value '{}' for enum type '{}'",
835 USERVER_NAMESPACE::utils::UnderlyingValue(val),
836 compiler::GetTypeName<Enum>()
837 )) {}
838};
839//@}
840
841/// PostgreSQL interval datatype contains months field, which cannot be
842/// converted to microseconds unambiguously
844public:
845 UnsupportedInterval();
846};
847
848/// PostgreSQL range type has at least one end unbound
850public:
851 BoundedRangeError(std::string_view message);
852};
853
854//@{
855/** @name bit/bit varying type errors */
856
857/// @brief Base error when working with bit string types.
859public:
860 using LogicError::LogicError;
861};
862
863/// Value in PostgreSQL binary buffer cannot be represented by a given C++ type
865public:
866 BitStringOverflow(std::size_t actual, std::size_t expected);
867};
868
869/// Value in PostgreSQL binary buffer cannot be represented as bit string type
871public:
872 InvalidBitStringRepresentation();
873};
874//@}
875
876//@{
877/** @name Misc exceptions */
878class InvalidDSN : public RuntimeError {
879public:
880 InvalidDSN(std::string_view dsn, std::string_view err);
881};
882
884 using RuntimeError::RuntimeError;
885};
886
888 using LogicError::LogicError;
889};
890
891//@}
892
893//@{
894/** @name ip type errors */
896public:
897 using LogicError::LogicError;
898};
899
901public:
902 explicit IpAddressInvalidFormat(std::string_view str);
903};
904//@}
905
906} // namespace storages::postgres
907
908USERVER_NAMESPACE_END