static int datumstreamwrite_context_callback(void *arg) { DatumStreamWrite *acc = (DatumStreamWrite *) arg; char *str; /* * Append-Only Storage Write's context. */ if (acc->need_close_file) { str = AppendOnlyStorageWrite_ContextStr(&acc->ao_write); errcontext("%s", str); pfree(str); } else { errcontext("%s", acc->title); } return 0; }
/* * Report an error we got from the remote server. * * elevel: error level to use (typically ERROR, but might be less) * res: PGresult containing the error * conn: connection we did the query on * clear: if true, PQclear the result (otherwise caller will handle it) * sql: NULL, or text of remote command we tried to execute * * Note: callers that choose not to throw ERROR for a remote error are * responsible for making sure that the associated ConnCacheEntry gets * marked with have_error = true. */ void pgfdw_report_error(int elevel, PGresult *res, PGconn *conn, bool clear, const char *sql) { /* If requested, PGresult must be released before leaving this function. */ PG_TRY(); { char *diag_sqlstate = PQresultErrorField(res, PG_DIAG_SQLSTATE); char *message_primary = PQresultErrorField(res, PG_DIAG_MESSAGE_PRIMARY); char *message_detail = PQresultErrorField(res, PG_DIAG_MESSAGE_DETAIL); char *message_hint = PQresultErrorField(res, PG_DIAG_MESSAGE_HINT); char *message_context = PQresultErrorField(res, PG_DIAG_CONTEXT); int sqlstate; if (diag_sqlstate) sqlstate = MAKE_SQLSTATE(diag_sqlstate[0], diag_sqlstate[1], diag_sqlstate[2], diag_sqlstate[3], diag_sqlstate[4]); else sqlstate = ERRCODE_CONNECTION_FAILURE; /* * If we don't get a message from the PGresult, try the PGconn. This * is needed because for connection-level failures, PQexec may just * return NULL, not a PGresult at all. */ if (message_primary == NULL) message_primary = PQerrorMessage(conn); ereport(elevel, (errcode(sqlstate), message_primary ? errmsg_internal("%s", message_primary) : errmsg("unknown error"), message_detail ? errdetail_internal("%s", message_detail) : 0, message_hint ? errhint("%s", message_hint) : 0, message_context ? errcontext("%s", message_context) : 0, sql ? errcontext("Remote SQL command: %s", sql) : 0)); } PG_CATCH(); { if (clear) PQclear(res); PG_RE_THROW(); } PG_END_TRY(); if (clear) PQclear(res); }
static int datumstreamread_context_callback(void *arg) { DatumStreamRead *acc = (DatumStreamRead *) arg; if (Debug_appendonly_print_datumstream) elog(LOG, "datumstream_advance filePathName %s nth %u ndatum %u datump %p ", acc->ao_read.bufferedRead.filePathName, acc->blockRead.nth, acc->blockRead.logical_row_count, acc->blockRead.datump); /* * Append-Only Storage Read's context. */ if (acc->need_close_file) { errcontext_appendonly_read_storage_block(&acc->ao_read); } else { errcontext("%s", acc->title); } return 0; }
/* * Error callback to give more context info about type conversion failure. */ static void slot_store_error_callback(void *arg) { SlotErrCallbackArg *errarg = (SlotErrCallbackArg *) arg; LogicalRepRelMapEntry *rel; char *remotetypname; Oid remotetypoid, localtypoid; /* Nothing to do if remote attribute number is not set */ if (errarg->remote_attnum < 0) return; rel = errarg->rel; remotetypoid = rel->remoterel.atttyps[errarg->remote_attnum]; /* Fetch remote type name from the LogicalRepTypMap cache */ remotetypname = logicalrep_typmap_gettypname(remotetypoid); /* Fetch local type OID from the local sys cache */ localtypoid = get_atttype(rel->localreloid, errarg->local_attnum + 1); errcontext("processing remote data for replication target relation \"%s.%s\" column \"%s\", " "remote type %s, local type %s", rel->remoterel.nspname, rel->remoterel.relname, rel->remoterel.attnames[errarg->remote_attnum], remotetypname, format_type_be(localtypoid)); }
/* * Pass remote error/notice/warning through. */ void plproxy_remote_error(ProxyFunction *func, ProxyConnection *conn, const PGresult *res, bool iserr) { const char *ss = PQresultErrorField(res, PG_DIAG_SQLSTATE); const char *sev = PQresultErrorField(res, PG_DIAG_SEVERITY); const char *msg = PQresultErrorField(res, PG_DIAG_MESSAGE_PRIMARY); const char *det = PQresultErrorField(res, PG_DIAG_MESSAGE_DETAIL); const char *hint = PQresultErrorField(res, PG_DIAG_MESSAGE_HINT); const char *spos = PQresultErrorField(res, PG_DIAG_STATEMENT_POSITION); const char *ipos = PQresultErrorField(res, PG_DIAG_INTERNAL_POSITION); const char *iquery = PQresultErrorField(res, PG_DIAG_INTERNAL_QUERY); const char *ctx = PQresultErrorField(res, PG_DIAG_CONTEXT); int elevel; /* libpq errors may not have sqlstate */ if (!ss) ss = "XX000"; if (iserr) /* must ignore remote level, as it may be FATAL/PANIC */ elevel = ERROR; else /* cannot look at sev here, as it may be localized */ elevel = !strncmp(ss, "00", 2) ? NOTICE : WARNING; ereport(elevel, ( errcode(MAKE_SQLSTATE(ss[0], ss[1], ss[2], ss[3], ss[4])), errmsg("%s(%d): [%s] REMOTE %s: %s", func->name, func->arg_count, PQdb(conn->cur->db), sev, msg), det ? errdetail("Remote detail: %s", det) : 0, hint ? errhint("Remote hint: %s", hint) : 0, spos ? errposition(atoi(spos)) : 0, ipos ? internalerrposition(atoi(ipos)) : 0, iquery ? internalerrquery(iquery) : 0, ctx ? errcontext("Remote context: %s", ctx) : 0)); }
static void pg_result_error(PGresult *pg_result) { const char *diag_sqlstate = PQresultErrorField(pg_result, PG_DIAG_SQLSTATE); const char *diag_primary = PQresultErrorField(pg_result, PG_DIAG_MESSAGE_PRIMARY); const char *diag_detail = PQresultErrorField(pg_result, PG_DIAG_MESSAGE_DETAIL); const char *diag_context = PQresultErrorField(pg_result, PG_DIAG_CONTEXT); const char *diag_hint = PQresultErrorField(pg_result, PG_DIAG_MESSAGE_HINT); int sqlstate; if (diag_sqlstate) sqlstate = MAKE_SQLSTATE(diag_sqlstate[0], diag_sqlstate[1], diag_sqlstate[2], diag_sqlstate[3], diag_sqlstate[4]); else sqlstate = ERRCODE_CONNECTION_FAILURE; PQclear(pg_result); ereport(ERROR, (errcode(sqlstate), errmsg("Remote error: %s", diag_primary), diag_detail ? errdetail("Remote detail: %s", diag_detail) : 0, diag_hint ? errhint("Remote hint: %s", diag_hint) : 0, diag_context ? errcontext("Remote context: %s", diag_context) : 0)); }
static void plpython_return_error_callback(void *arg) { PLyExecutionContext *exec_ctx = PLy_current_execution_context(); if (exec_ctx->curr_proc) errcontext("while creating return value"); }
static void plpython_trigger_error_callback(void *arg) { PLyExecutionContext *exec_ctx = PLy_current_execution_context(); if (exec_ctx->curr_proc) errcontext("while modifying trigger row"); }
static void plpython_error_callback(void *arg) { PLyExecutionContext *exec_ctx = (PLyExecutionContext *) arg; if (exec_ctx->curr_proc) errcontext("PL/Python function \"%s\"", PLy_procedure_name(exec_ctx->curr_proc)); }
/* * errcontext_appendonly_read_storage_block * * Add an errcontext() line showing the table, segment file, offset in file, * block count of the storage block being read. */ int errcontext_appendonly_read_storage_block(AppendOnlyStorageRead *storageRead) { char *str; str = AppendOnlyStorageRead_ContextStr(storageRead); errcontext("%s", str); pfree(str); return 0; }
/* * Report an error we got from the remote server. * * elevel: error level to use (typically ERROR, but might be less) * res: PGresult containing the error * clear: if true, PQclear the result (otherwise caller will handle it) * sql: NULL, or text of remote command we tried to execute * * Note: callers that choose not to throw ERROR for a remote error are * responsible for making sure that the associated ConnCacheEntry gets * marked with have_error = true. */ void pgfdw_report_error(int elevel, PGresult *res, bool clear, const char *sql) { /* If requested, PGresult must be released before leaving this function. */ PG_TRY(); { char *diag_sqlstate = PQresultErrorField(res, PG_DIAG_SQLSTATE); char *message_primary = PQresultErrorField(res, PG_DIAG_MESSAGE_PRIMARY); char *message_detail = PQresultErrorField(res, PG_DIAG_MESSAGE_DETAIL); char *message_hint = PQresultErrorField(res, PG_DIAG_MESSAGE_HINT); char *message_context = PQresultErrorField(res, PG_DIAG_CONTEXT); int sqlstate; if (diag_sqlstate) sqlstate = MAKE_SQLSTATE(diag_sqlstate[0], diag_sqlstate[1], diag_sqlstate[2], diag_sqlstate[3], diag_sqlstate[4]); else sqlstate = ERRCODE_CONNECTION_FAILURE; ereport(elevel, (errcode(sqlstate), message_primary ? errmsg_internal("%s", message_primary) : errmsg("unknown error"), message_detail ? errdetail_internal("%s", message_detail) : 0, message_hint ? errhint("%s", message_hint) : 0, message_context ? errcontext("%s", message_context) : 0, sql ? errcontext("Remote SQL command: %s", sql) : 0)); } PG_CATCH(); { if (clear) PQclear(res); PG_RE_THROW(); } PG_END_TRY(); if (clear) PQclear(res); }
/* * Error context callback for errors occurring while reading a tsearch * configuration file. */ static void tsearch_readline_callback(void *arg) { tsearch_readline_state *stp = (tsearch_readline_state *) arg; /* * We can't include the text of the config line for errors that occur * during t_readline() itself. This is only partly a consequence of our * arms-length use of that routine: the major cause of such errors is * encoding violations, and we daren't try to print error messages * containing badly-encoded data. */ if (stp->curline) errcontext("line %d of configuration file \"%s\": \"%s\"", stp->lineno, stp->filename, stp->curline); else errcontext("line %d of configuration file \"%s\"", stp->lineno, stp->filename); }
/* * XactLockTableWaitErrorContextCb * Error context callback for transaction lock waits. */ static void XactLockTableWaitErrorCb(void *arg) { XactLockTableWaitInfo *info = (XactLockTableWaitInfo *) arg; /* * We would like to print schema name too, but that would require a * syscache lookup. */ if (info->oper != XLTW_None && ItemPointerIsValid(info->ctid) && RelationIsValid(info->rel)) { const char *cxt; switch (info->oper) { case XLTW_Update: cxt = gettext_noop("while updating tuple (%u,%u) in relation \"%s\""); break; case XLTW_Delete: cxt = gettext_noop("while deleting tuple (%u,%u) in relation \"%s\""); break; case XLTW_Lock: cxt = gettext_noop("while locking tuple (%u,%u) in relation \"%s\""); break; case XLTW_LockUpdated: cxt = gettext_noop("while locking updated version (%u,%u) of tuple in relation \"%s\""); break; case XLTW_InsertIndex: cxt = gettext_noop("while inserting index tuple (%u,%u) in relation \"%s\""); break; case XLTW_InsertIndexUnique: cxt = gettext_noop("while checking uniqueness of tuple (%u,%u) in relation \"%s\""); break; case XLTW_FetchUpdated: cxt = gettext_noop("while rechecking updated tuple (%u,%u) in relation \"%s\""); break; case XLTW_RecheckExclusionConstr: cxt = gettext_noop("while checking exclusion constraint on tuple (%u,%u) in relation \"%s\""); break; default: return; } errcontext(cxt, ItemPointerGetBlockNumber(info->ctid), ItemPointerGetOffsetNumber(info->ctid), RelationGetRelationName(info->rel)); } }
/* * Error context callback for handling errors in SQL function definitions */ static void sql_function_parse_error_callback(void *arg) { HeapTuple tuple = (HeapTuple) arg; Form_pg_proc proc = (Form_pg_proc) GETSTRUCT(tuple); bool isnull; Datum tmp; char *prosrc; /* See if it's a syntax error; if so, transpose to CREATE FUNCTION */ tmp = SysCacheGetAttr(PROCOID, tuple, Anum_pg_proc_prosrc, &isnull); if (isnull) elog(ERROR, "null prosrc"); prosrc = DatumGetCString(DirectFunctionCall1(textout, tmp)); if (!function_parse_error_transpose(prosrc)) { /* If it's not a syntax error, push info onto context stack */ errcontext("SQL function \"%s\"", NameStr(proc->proname)); } pfree(prosrc); }
/* * Emit a PG error or notice, together with any available info about * the current Python error, previously set by PLy_exception_set(). * This should be used to propagate Python errors into PG. If fmt is * NULL, the Python error becomes the primary error message, otherwise * it becomes the detail. If there is a Python traceback, it is put * in the context. */ void PLy_elog(int elevel, const char *fmt,...) { char *xmsg; char *tbmsg; int tb_depth; StringInfoData emsg; PyObject *exc, *val, *tb; const char *primary = NULL; int sqlerrcode = 0; char *detail = NULL; char *hint = NULL; char *query = NULL; int position = 0; PyErr_Fetch(&exc, &val, &tb); if (exc != NULL) { if (PyErr_GivenExceptionMatches(val, PLy_exc_spi_error)) PLy_get_spi_error_data(val, &sqlerrcode, &detail, &hint, &query, &position); else if (PyErr_GivenExceptionMatches(val, PLy_exc_fatal)) elevel = FATAL; } PyErr_Restore(exc, val, tb); PLy_traceback(&xmsg, &tbmsg, &tb_depth); if (fmt) { initStringInfo(&emsg); for (;;) { va_list ap; bool success; va_start(ap, fmt); success = appendStringInfoVA(&emsg, dgettext(TEXTDOMAIN, fmt), ap); va_end(ap); if (success) break; enlargeStringInfo(&emsg, emsg.maxlen); } primary = emsg.data; /* Since we have a format string, we cannot have a SPI detail. */ Assert(detail == NULL); /* If there's an exception message, it goes in the detail. */ if (xmsg) detail = xmsg; } else { if (xmsg) primary = xmsg; } PG_TRY(); { ereport(elevel, (errcode(sqlerrcode ? sqlerrcode : ERRCODE_INTERNAL_ERROR), errmsg_internal("%s", primary ? primary : "no exception data"), (detail) ? errdetail_internal("%s", detail) : 0, (tb_depth > 0 && tbmsg) ? errcontext("%s", tbmsg) : 0, (hint) ? errhint("%s", hint) : 0, (query) ? internalerrquery(query) : 0, (position) ? internalerrposition(position) : 0)); } PG_CATCH(); { if (fmt) pfree(emsg.data); if (xmsg) pfree(xmsg); if (tbmsg) pfree(tbmsg); PG_RE_THROW(); } PG_END_TRY(); if (fmt) pfree(emsg.data); if (xmsg) pfree(xmsg); if (tbmsg) pfree(tbmsg); }
/* * ReportRemoteError is an internal helper function which implements logic * needed by both WarnRemoteError and ReraiseRemoteError. They wrap this * function to provide explicit names for the possible behaviors. */ static void ReportRemoteError(PGconn *connection, PGresult *result, bool raiseError) { char *sqlStateString = PQresultErrorField(result, PG_DIAG_SQLSTATE); char *messagePrimary = PQresultErrorField(result, PG_DIAG_MESSAGE_PRIMARY); char *messageDetail = PQresultErrorField(result, PG_DIAG_MESSAGE_DETAIL); char *messageHint = PQresultErrorField(result, PG_DIAG_MESSAGE_HINT); char *messageContext = PQresultErrorField(result, PG_DIAG_CONTEXT); char *nodeName = ConnectionGetOptionValue(connection, "host"); char *nodePort = ConnectionGetOptionValue(connection, "port"); int sqlState = ERRCODE_CONNECTION_FAILURE; int errorLevel = WARNING; if (sqlStateString != NULL) { sqlState = MAKE_SQLSTATE(sqlStateString[0], sqlStateString[1], sqlStateString[2], sqlStateString[3], sqlStateString[4]); } /* * If the PGresult did not contain a message, the connection may provide a * suitable top level one. At worst, this is an empty string. */ if (messagePrimary == NULL) { char *lastNewlineIndex = NULL; messagePrimary = PQerrorMessage(connection); lastNewlineIndex = strrchr(messagePrimary, '\n'); /* trim trailing newline, if any */ if (lastNewlineIndex != NULL) { *lastNewlineIndex = '\0'; } } /* * If requested, actually raise an error. This necessitates purging the * connection so it doesn't remain in the hash in an invalid state. */ if (raiseError) { errorLevel = ERROR; PurgeConnection(connection); } if (sqlState == ERRCODE_CONNECTION_FAILURE) { ereport(errorLevel, (errcode(sqlState), errmsg("connection failed to %s:%s", nodeName, nodePort), errdetail("%s", messagePrimary))); } else { ereport(errorLevel, (errcode(sqlState), errmsg("%s", messagePrimary), messageDetail ? errdetail("%s", messageDetail) : 0, messageHint ? errhint("%s", messageHint) : 0, messageContext ? errcontext("%s", messageContext) : 0, errcontext("while executing command on %s:%s", nodeName, nodePort))); } }
/* * A function having everything to do with logging, which ought to be factored * out one day to make a start on the Thoughts-on-logging wiki ideas. */ static void reLogWithChangedLevel(int level) { ErrorData *edata = CopyErrorData(); int sqlstate = edata->sqlerrcode; int category = ERRCODE_TO_CATEGORY(sqlstate); FlushErrorState(); if ( WARNING > level ) { if ( ERRCODE_SUCCESSFUL_COMPLETION != category ) sqlstate = ERRCODE_SUCCESSFUL_COMPLETION; } else if ( WARNING == level ) { if ( ERRCODE_WARNING != category && ERRCODE_NO_DATA != category ) sqlstate = ERRCODE_WARNING; } else if ( ERRCODE_WARNING == category || ERRCODE_NO_DATA == category || ERRCODE_SUCCESSFUL_COMPLETION == category ) sqlstate = ERRCODE_INTERNAL_ERROR; #if PG_VERSION_NUM >= 90500 edata->elevel = level; edata->sqlerrcode = sqlstate; PG_TRY(); { ThrowErrorData(edata); } PG_CATCH(); { FreeErrorData(edata); /* otherwise this wouldn't happen in ERROR case */ PG_RE_THROW(); } PG_END_TRY(); FreeErrorData(edata); #else if (!errstart(level, edata->filename, edata->lineno, edata->funcname, NULL)) { FreeErrorData(edata); return; } errcode(sqlstate); if (edata->message) errmsg("%s", edata->message); if (edata->detail) errdetail("%s", edata->detail); if (edata->detail_log) errdetail_log("%s", edata->detail_log); if (edata->hint) errhint("%s", edata->hint); if (edata->context) errcontext("%s", edata->context); /* this may need to be trimmed */ #if PG_VERSION_NUM >= 90300 if (edata->schema_name) err_generic_string(PG_DIAG_SCHEMA_NAME, edata->schema_name); if (edata->table_name) err_generic_string(PG_DIAG_TABLE_NAME, edata->table_name); if (edata->column_name) err_generic_string(PG_DIAG_COLUMN_NAME, edata->column_name); if (edata->datatype_name) err_generic_string(PG_DIAG_DATATYPE_NAME, edata->datatype_name); if (edata->constraint_name) err_generic_string(PG_DIAG_CONSTRAINT_NAME, edata->constraint_name); #endif if (edata->internalquery) internalerrquery(edata->internalquery); FreeErrorData(edata); errfinish(0); #endif }
/* * error context callback to let us supply a call-stack traceback */ static void rsupport_error_callback(void *arg) { if (arg) errcontext("In R support function %s", (char *) arg); }
/* * Report a CONTEXT line for bogus JSON input. * * lex->token_terminator must be set to identify the spot where we detected * the error. Note that lex->token_start might be NULL, in case we recognized * error at EOF. * * The return value isn't meaningful, but we make it non-void so that this * can be invoked inside ereport(). */ static int report_json_context(JsonLexContext *lex) { const char *context_start; const char *context_end; const char *line_start; int line_number; char *ctxt; int ctxtlen; const char *prefix; const char *suffix; /* Choose boundaries for the part of the input we will display */ context_start = lex->input; context_end = lex->token_terminator; line_start = context_start; line_number = 1; for (;;) { /* Always advance over newlines */ if (context_start < context_end && *context_start == '\n') { context_start++; line_start = context_start; line_number++; continue; } /* Otherwise, done as soon as we are close enough to context_end */ if (context_end - context_start < 50) break; /* Advance to next multibyte character */ if (IS_HIGHBIT_SET(*context_start)) context_start += pg_mblen(context_start); else context_start++; } /* * We add "..." to indicate that the excerpt doesn't start at the * beginning of the line ... but if we're within 3 characters of the * beginning of the line, we might as well just show the whole line. */ if (context_start - line_start <= 3) context_start = line_start; /* Get a null-terminated copy of the data to present */ ctxtlen = context_end - context_start; ctxt = palloc(ctxtlen + 1); memcpy(ctxt, context_start, ctxtlen); ctxt[ctxtlen] = '\0'; /* * Show the context, prefixing "..." if not starting at start of line, and * suffixing "..." if not ending at end of line. */ prefix = (context_start > line_start) ? "..." : ""; suffix = (lex->token_type != JSON_TOKEN_END && context_end - lex->input < lex->input_length && *context_end != '\n' && *context_end != '\r') ? "..." : ""; return errcontext("JSON data, line %d: %s%s%s", line_number, prefix, ctxt, suffix); }
/* * Emit a PG error or notice, together with any available info about * the current Python error, previously set by PLy_exception_set(). * This should be used to propagate Python errors into PG. If fmt is * NULL, the Python error becomes the primary error message, otherwise * it becomes the detail. If there is a Python traceback, it is put * in the context. */ void PLy_elog(int elevel, const char *fmt,...) { char *xmsg; char *tbmsg; int tb_depth; StringInfoData emsg; PyObject *exc, *val, *tb; const char *primary = NULL; int sqlerrcode = 0; char *detail = NULL; char *hint = NULL; char *query = NULL; int position = 0; char *schema_name = NULL; char *table_name = NULL; char *column_name = NULL; char *datatype_name = NULL; char *constraint_name = NULL; PyErr_Fetch(&exc, &val, &tb); if (exc != NULL) { PyErr_NormalizeException(&exc, &val, &tb); if (PyErr_GivenExceptionMatches(val, PLy_exc_spi_error)) PLy_get_spi_error_data(val, &sqlerrcode, &detail, &hint, &query, &position, &schema_name, &table_name, &column_name, &datatype_name, &constraint_name); else if (PyErr_GivenExceptionMatches(val, PLy_exc_error)) PLy_get_error_data(val, &sqlerrcode, &detail, &hint, &schema_name, &table_name, &column_name, &datatype_name, &constraint_name); else if (PyErr_GivenExceptionMatches(val, PLy_exc_fatal)) elevel = FATAL; } /* this releases our refcount on tb! */ PLy_traceback(exc, val, tb, &xmsg, &tbmsg, &tb_depth); if (fmt) { initStringInfo(&emsg); for (;;) { va_list ap; int needed; va_start(ap, fmt); needed = appendStringInfoVA(&emsg, dgettext(TEXTDOMAIN, fmt), ap); va_end(ap); if (needed == 0) break; enlargeStringInfo(&emsg, needed); } primary = emsg.data; /* Since we have a format string, we cannot have a SPI detail. */ Assert(detail == NULL); /* If there's an exception message, it goes in the detail. */ if (xmsg) detail = xmsg; } else { if (xmsg) primary = xmsg; } PG_TRY(); { ereport(elevel, (errcode(sqlerrcode ? sqlerrcode : ERRCODE_EXTERNAL_ROUTINE_EXCEPTION), errmsg_internal("%s", primary ? primary : "no exception data"), (detail) ? errdetail_internal("%s", detail) : 0, (tb_depth > 0 && tbmsg) ? errcontext("%s", tbmsg) : 0, (hint) ? errhint("%s", hint) : 0, (query) ? internalerrquery(query) : 0, (position) ? internalerrposition(position) : 0, (schema_name) ? err_generic_string(PG_DIAG_SCHEMA_NAME, schema_name) : 0, (table_name) ? err_generic_string(PG_DIAG_TABLE_NAME, table_name) : 0, (column_name) ? err_generic_string(PG_DIAG_COLUMN_NAME, column_name) : 0, (datatype_name) ? err_generic_string(PG_DIAG_DATATYPE_NAME, datatype_name) : 0, (constraint_name) ? err_generic_string(PG_DIAG_CONSTRAINT_NAME, constraint_name) : 0)); } PG_CATCH(); { if (fmt) pfree(emsg.data); if (xmsg) pfree(xmsg); if (tbmsg) pfree(tbmsg); Py_XDECREF(exc); Py_XDECREF(val); PG_RE_THROW(); } PG_END_TRY(); if (fmt) pfree(emsg.data); if (xmsg) pfree(xmsg); if (tbmsg) pfree(tbmsg); Py_XDECREF(exc); Py_XDECREF(val); }
static void plpython_inline_error_callback(void *arg) { errcontext("PL/Python anonymous code block"); }