@@ -1626,6 +1626,75 @@ pg_re_throw(void)
16261626}
16271627
16281628
1629+ /*
1630+ * GetErrorContextStack - Return the error context stack
1631+ *
1632+ * Returns a pstrdup'd string in the caller's context which includes the full
1633+ * call stack. It is the caller's responsibility to ensure this string is
1634+ * pfree'd (or its context cleaned up) when done.
1635+ *
1636+ * This information is collected by traversing the error contexts and calling
1637+ * each context's callback function, each of which is expected to call
1638+ * errcontext() to return a string which can be presented to the user.
1639+ */
1640+ char *
1641+ GetErrorContextStack (void )
1642+ {
1643+ char * result = NULL ;
1644+ ErrorData * edata ;
1645+ ErrorContextCallback * econtext ;
1646+ MemoryContext oldcontext = CurrentMemoryContext ;
1647+
1648+ /* this function should not be called from an exception handler */
1649+ Assert (recursion_depth == 0 );
1650+
1651+ /* Check that we have enough room on the stack for ourselves */
1652+ if (++ errordata_stack_depth >=ERRORDATA_STACK_SIZE )
1653+ {
1654+ /*
1655+ * Stack not big enough..Something bad has happened, therefore
1656+ * PANIC as we may be in an infinite loop.
1657+ */
1658+ errordata_stack_depth = -1 ;/* make room on stack */
1659+ ereport (PANIC , (errmsg_internal ("ERRORDATA_STACK_SIZE exceeded" )));
1660+ }
1661+
1662+ /* Initialize data for this error frame */
1663+ edata = & errordata [errordata_stack_depth ];
1664+ MemSet (edata ,0 ,sizeof (ErrorData ));
1665+
1666+ /* Use ErrorContext as a short lived context for the callbacks */
1667+ MemoryContextSwitchTo (ErrorContext );
1668+
1669+ /*
1670+ * Call any context callback functions to collect the context information
1671+ * into edata->context.
1672+ *
1673+ * Errors occurring in callback functions should go through the regular
1674+ * error handling code which should handle any recursive errors.
1675+ */
1676+ for (econtext = error_context_stack ;
1677+ econtext != NULL ;
1678+ econtext = econtext -> previous )
1679+ (* econtext -> callback ) (econtext -> arg );
1680+
1681+ MemoryContextSwitchTo (oldcontext );
1682+
1683+ /*
1684+ * Copy out the string into the caller's context, so we can free our
1685+ * error context and reset the error stack. Caller is expected to
1686+ * pfree() the result or throw away the context.
1687+ */
1688+ if (edata -> context )
1689+ result = pstrdup (edata -> context );
1690+
1691+ /* Reset error stack */
1692+ FlushErrorState ();
1693+
1694+ return result ;
1695+ }
1696+
1697+
16291698/*
16301699 * Initialization of error output file
16311700 */