Skip to content

Commit

Permalink
Add infrastucture for "soft" error handle
Browse files Browse the repository at this point in the history
  • Loading branch information
robozmey committed Dec 11, 2024
1 parent 0c941b3 commit af4e4bf
Show file tree
Hide file tree
Showing 6 changed files with 169 additions and 0 deletions.
25 changes: 25 additions & 0 deletions src/backend/utils/error/elog.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@
#include "libpq/pqformat.h"
#include "libpq/pqsignal.h"
#include "mb/pg_wchar.h"
#include "nodes/miscnodes.h"
#include "miscadmin.h"
#include "postmaster/postmaster.h"
#include "postmaster/syslogger.h"
Expand Down Expand Up @@ -830,6 +831,30 @@ errfinish_and_return(int dummy __attribute__((unused)),...)
return edata_copy;
}

/*
* errsave_start
*/
bool
errsave_start(struct Node *context,
const char *filename, int lineno,
const char *funcname, const char *domain)
{
ErrorSaveContext *escontext;

/*
* Do we have a context for soft error reporting? If not, just punt to
* errstart().
*/
if (context == NULL || !IsA(context, ErrorSaveContext))
return errstart(ERROR, filename, lineno, funcname, domain);

/* Report that a soft error was detected */
escontext = (ErrorSaveContext *) context;
escontext->error_occurred = true;

return false;
}


/*
* errcode --- add SQLSTATE error code to the current error
Expand Down
82 changes: 82 additions & 0 deletions src/backend/utils/fmgr/fmgr.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "lib/stringinfo.h"
#include "miscadmin.h"
#include "nodes/nodeFuncs.h"
#include "nodes/miscnodes.h"
#include "pgstat.h"
#include "utils/acl.h"
#include "utils/builtins.h"
Expand Down Expand Up @@ -1887,6 +1888,41 @@ OidFunctionCall9Coll(Oid functionId, Oid collation, Datum arg1, Datum arg2,
return result;
}

/*
*/
Datum
OidFunctionCall3CollSafe(Oid functionId, Oid collation, Datum arg1, Datum arg2,
Datum arg3, fmNodePtr escontext)
{
FmgrInfo flinfo;
FunctionCallInfoData fcinfo;
Datum result;

fmgr_info(functionId, &flinfo);

InitFunctionCallInfoData(fcinfo, &flinfo, 3, collation, escontext, NULL);

fcinfo.arg[0] = arg1;
fcinfo.arg[1] = arg2;
fcinfo.arg[2] = arg3;
fcinfo.argnull[0] = false;
fcinfo.argnull[1] = false;
fcinfo.argnull[2] = false;

result = FunctionCallInvoke(&fcinfo);

/* Result value is garbage, and could be null, if an error was reported */
if (SOFT_ERROR_OCCURRED(escontext))
return (Datum) 0;

/* Check for null result, since caller is clearly not expecting one */
if (fcinfo.isnull)
elog(ERROR, "function %u returned NULL", flinfo.fn_oid);

return result;
}


/*
* Special cases for convenient invocation of datatype I/O functions.
Expand Down Expand Up @@ -1948,6 +1984,52 @@ InputFunctionCall(FmgrInfo *flinfo, char *str, Oid typioparam, int32 typmod)
return result;
}

Datum
InputFunctionCallSafe(FmgrInfo *flinfo, char *str, Oid typioparam, int32 typmod, fmNodePtr escontext)
{
FunctionCallInfoData fcinfo;
Datum result;
bool pushed;

if (str == NULL && flinfo->fn_strict)
return (Datum) 0; /* just return null result */

pushed = SPI_push_conditional();

InitFunctionCallInfoData(fcinfo, flinfo, 3, InvalidOid, escontext, NULL);

fcinfo.arg[0] = CStringGetDatum(str);
fcinfo.arg[1] = ObjectIdGetDatum(typioparam);
fcinfo.arg[2] = Int32GetDatum(typmod);
fcinfo.argnull[0] = (str == NULL);
fcinfo.argnull[1] = false;
fcinfo.argnull[2] = false;

result = FunctionCallInvoke(&fcinfo);

/* Result value is garbage, and could be null, if an error was reported */
if (SOFT_ERROR_OCCURRED(escontext))
return (Datum) 0;

/* Should get null result if and only if str is NULL */
if (str == NULL)
{
if (!fcinfo.isnull)
elog(ERROR, "input function %u returned non-NULL",
fcinfo.flinfo->fn_oid);
}
else
{
if (fcinfo.isnull)
elog(ERROR, "input function %u returned NULL",
fcinfo.flinfo->fn_oid);
}

SPI_pop_conditional(pushed);

return result;
}

/*
* Call a previously-looked-up datatype output function.
*
Expand Down
11 changes: 11 additions & 0 deletions src/include/fmgr.h
Original file line number Diff line number Diff line change
Expand Up @@ -579,6 +579,11 @@ extern Datum OidFunctionCall9Coll(Oid functionId, Oid collation,
Datum arg6, Datum arg7, Datum arg8,
Datum arg9);


extern Datum OidFunctionCall3CollSafe(Oid functionId, Oid collation,
Datum arg1, Datum arg2,
Datum arg3, fmNodePtr escontext);

/* These macros allow the collation argument to be omitted (with a default of
* InvalidOid, ie, no collation). They exist mostly for backwards
* compatibility of source code.
Expand Down Expand Up @@ -641,9 +646,15 @@ extern Datum OidFunctionCall9Coll(Oid functionId, Oid collation,
OidFunctionCall9Coll(functionId, InvalidOid, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9)


#define OidFunctionCall3Safe(functionId, arg1, arg2, arg3, escontext) \
OidFunctionCall3CollSafe(functionId, InvalidOid, arg1, arg2, arg3, escontext)


/* Special cases for convenient invocation of datatype I/O functions. */
extern Datum InputFunctionCall(FmgrInfo *flinfo, char *str,
Oid typioparam, int32 typmod);
extern Datum InputFunctionCallSafe(FmgrInfo *flinfo, char *str,
Oid typioparam, int32 typmod, fmNodePtr escontext);
extern Datum OidInputFunctionCall(Oid functionId, char *str,
Oid typioparam, int32 typmod);
extern char *OutputFunctionCall(FmgrInfo *flinfo, Datum val);
Expand Down
26 changes: 26 additions & 0 deletions src/include/nodes/miscnodes.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*-------------------------------------------------------------------------
*
* miscnodes.h
* Definitions for hard-to-classify node types.
*
* src/include/nodes/miscnodes.h
*
*-------------------------------------------------------------------------
*/

#ifndef MISCNODES_H
#define MISCNODES_H
#include "nodes/nodes.h"

typedef struct ErrorSaveContext
{
NodeTag type;
bool error_occurred; /* set to true if we detect a soft error */
} 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
2 changes: 2 additions & 0 deletions src/include/nodes/nodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -571,6 +571,8 @@ typedef enum NodeTag
T_GpPolicy, /* in catalog/gp_policy.h */
T_RetrieveStmt,

T_ErrorSaveContext,

} NodeTag;

/*
Expand Down
23 changes: 23 additions & 0 deletions src/include/utils/elog.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@
#include <sys/time.h>
#include <setjmp.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. */
Expand Down Expand Up @@ -204,6 +207,26 @@ extern bool errstart(int elevel, const char *filename, int lineno,
const char *funcname, const char *domain);
extern void errfinish(int dummy,...);

#define errsave_domain(context, domain, rest) \
do { \
struct Node *context_ = (context); \
if (errsave_start(context_, __FILE__, __LINE__, __func__, domain)) \
errfinish rest; \
} while(0)
#define errsave(context, rest) \
errsave_domain(context, TEXTDOMAIN, rest)

#define ereturn_domain(context, dummy_value, domain, rest) \
do { \
errsave_domain(context, domain, rest); \
return dummy_value; \
} while(0)
#define ereturn(context, dummy_value, rest) \
ereturn_domain(context, dummy_value, TEXTDOMAIN, rest)

extern bool errsave_start(struct Node* context, const char *filename, int lineno,
const char *funcname, const char *domain);

extern int errcode(int sqlerrcode);

extern int errcode_for_file_access(void);
Expand Down

0 comments on commit af4e4bf

Please sign in to comment.