@@ -1626,6 +1626,75 @@ pg_re_throw(void)
1626
1626
}
1627
1627
1628
1628
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
+
1629
1698
/*
1630
1699
* Initialization of error output file
1631
1700
*/
0 commit comments