summaryrefslogtreecommitdiff
path: root/src/include
diff options
context:
space:
mode:
Diffstat (limited to 'src/include')
-rw-r--r--src/include/fmgr.h4
-rw-r--r--src/include/nodes/meson.build1
-rw-r--r--src/include/nodes/miscnodes.h56
-rw-r--r--src/include/utils/elog.h61
4 files changed, 122 insertions, 0 deletions
diff --git a/src/include/fmgr.h b/src/include/fmgr.h
index 380a82b9de..b7832d0aa2 100644
--- a/src/include/fmgr.h
+++ b/src/include/fmgr.h
@@ -700,6 +700,10 @@ extern Datum OidFunctionCall9Coll(Oid functionId, Oid collation,
/* Special cases for convenient invocation of datatype I/O functions. */
extern Datum InputFunctionCall(FmgrInfo *flinfo, char *str,
Oid typioparam, int32 typmod);
+extern bool InputFunctionCallSafe(FmgrInfo *flinfo, char *str,
+ Oid typioparam, int32 typmod,
+ fmNodePtr escontext,
+ Datum *result);
extern Datum OidInputFunctionCall(Oid functionId, char *str,
Oid typioparam, int32 typmod);
extern char *OutputFunctionCall(FmgrInfo *flinfo, Datum val);
diff --git a/src/include/nodes/meson.build b/src/include/nodes/meson.build
index e63881086e..f0e60935b6 100644
--- a/src/include/nodes/meson.build
+++ b/src/include/nodes/meson.build
@@ -16,6 +16,7 @@ node_support_input_i = [
'nodes/bitmapset.h',
'nodes/extensible.h',
'nodes/lockoptions.h',
+ 'nodes/miscnodes.h',
'nodes/replnodes.h',
'nodes/supportnodes.h',
'nodes/value.h',
diff --git a/src/include/nodes/miscnodes.h b/src/include/nodes/miscnodes.h
new file mode 100644
index 0000000000..b50ee60352
--- /dev/null
+++ b/src/include/nodes/miscnodes.h
@@ -0,0 +1,56 @@
+/*-------------------------------------------------------------------------
+ *
+ * miscnodes.h
+ * Definitions for hard-to-classify node types.
+ *
+ * Node types declared here are not part of parse trees, plan trees,
+ * or execution state trees. We only assign them NodeTag values because
+ * IsA() tests provide a convenient way to disambiguate what kind of
+ * structure is being passed through assorted APIs, such as function
+ * "context" pointers.
+ *
+ *
+ * Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/nodes/miscnodes.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef MISCNODES_H
+#define MISCNODES_H
+
+#include "nodes/nodes.h"
+
+/*
+ * ErrorSaveContext -
+ * function call context node for handling of "soft" errors
+ *
+ * A caller wishing to trap soft errors must initialize a struct like this
+ * with all fields zero/NULL except for the NodeTag. Optionally, set
+ * details_wanted = true if more than the bare knowledge that a soft error
+ * occurred is required. The struct is then passed to a SQL-callable function
+ * via the FunctionCallInfo.context field; or below the level of SQL calls,
+ * it could be passed to a subroutine directly.
+ *
+ * After calling code that might report an error this way, check
+ * error_occurred to see if an error happened. If so, and if details_wanted
+ * is true, error_data has been filled with error details (stored in the
+ * callee's memory context!). FreeErrorData() can be called to release
+ * error_data, although that step is typically not necessary if the called
+ * code was run in a short-lived context.
+ */
+typedef struct ErrorSaveContext
+{
+ NodeTag type;
+ bool error_occurred; /* set to true if we detect a soft error */
+ bool details_wanted; /* does caller want more info than that? */
+ ErrorData *error_data; /* details of error, if so */
+} ErrorSaveContext;
+
+/* Often-useful macro for checking if a soft error was reported */
+#define SOFT_ERROR_OCCURRED(escontext) \
+ ((escontext) != NULL && IsA(escontext, ErrorSaveContext) && \
+ ((ErrorSaveContext *) (escontext))->error_occurred)
+
+#endif /* MISCNODES_H */
diff --git a/src/include/utils/elog.h b/src/include/utils/elog.h
index f107a818e8..8025dce335 100644
--- a/src/include/utils/elog.h
+++ b/src/include/utils/elog.h
@@ -18,6 +18,10 @@
#include "lib/stringinfo.h"
+/* We cannot include nodes.h yet, so forward-declare struct Node */
+struct Node;
+
+
/* Error level codes */
#define DEBUG5 10 /* Debugging messages, in categories of
* decreasing detail. */
@@ -235,6 +239,63 @@ extern int getinternalerrposition(void);
ereport(elevel, errmsg_internal(__VA_ARGS__))
+/*----------
+ * Support for reporting "soft" errors that don't require a full transaction
+ * abort to clean up. This is to be used in this way:
+ * errsave(context,
+ * errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
+ * errmsg("invalid input syntax for type %s: \"%s\"",
+ * "boolean", in_str),
+ * ... other errxxx() fields as needed ...);
+ *
+ * "context" is a node pointer or NULL, and the remaining auxiliary calls
+ * provide the same error details as in ereport(). If context is not a
+ * pointer to an ErrorSaveContext node, then errsave(context, ...)
+ * behaves identically to ereport(ERROR, ...). If context is a pointer
+ * to an ErrorSaveContext node, then the information provided by the
+ * auxiliary calls is stored in the context node and control returns
+ * normally. The caller of errsave() must then do any required cleanup
+ * and return control back to its caller. That caller must check the
+ * ErrorSaveContext node to see whether an error occurred before
+ * it can trust the function's result to be meaningful.
+ *
+ * errsave_domain() allows a message domain to be specified; it is
+ * precisely analogous to ereport_domain().
+ *----------
+ */
+#define errsave_domain(context, domain, ...) \
+ do { \
+ struct Node *context_ = (context); \
+ pg_prevent_errno_in_scope(); \
+ if (errsave_start(context_, domain)) \
+ __VA_ARGS__, errsave_finish(context_, __FILE__, __LINE__, __func__); \
+ } while(0)
+
+#define errsave(context, ...) \
+ errsave_domain(context, TEXTDOMAIN, __VA_ARGS__)
+
+/*
+ * "ereturn(context, dummy_value, ...);" is exactly the same as
+ * "errsave(context, ...); return dummy_value;". This saves a bit
+ * of typing in the common case where a function has no cleanup
+ * actions to take after reporting a soft error. "dummy_value"
+ * can be empty if the function returns void.
+ */
+#define ereturn_domain(context, dummy_value, domain, ...) \
+ do { \
+ errsave_domain(context, domain, __VA_ARGS__); \
+ return dummy_value; \
+ } while(0)
+
+#define ereturn(context, dummy_value, ...) \
+ ereturn_domain(context, dummy_value, TEXTDOMAIN, __VA_ARGS__)
+
+extern bool errsave_start(struct Node *context, const char *domain);
+extern void errsave_finish(struct Node *context,
+ const char *filename, int lineno,
+ const char *funcname);
+
+
/* Support for constructing error strings separately from ereport() calls */
extern void pre_format_elog_string(int errnumber, const char *domain);