@@ -812,7 +812,7 @@ static void
812
812
do_sql_command_begin (PGconn * conn , const char * sql )
813
813
{
814
814
if (!PQsendQuery (conn , sql ))
815
- pgfdw_report_error (ERROR , NULL , conn , false, sql );
815
+ pgfdw_report_error (ERROR , NULL , conn , sql );
816
816
}
817
817
818
818
static void
@@ -827,10 +827,10 @@ do_sql_command_end(PGconn *conn, const char *sql, bool consume_input)
827
827
* would be large compared to the overhead of PQconsumeInput.)
828
828
*/
829
829
if (consume_input && !PQconsumeInput (conn ))
830
- pgfdw_report_error (ERROR , NULL , conn , false, sql );
830
+ pgfdw_report_error (ERROR , NULL , conn , sql );
831
831
res = pgfdw_get_result (conn );
832
832
if (PQresultStatus (res ) != PGRES_COMMAND_OK )
833
- pgfdw_report_error (ERROR , res , conn , true, sql );
833
+ pgfdw_report_error (ERROR , res , conn , sql );
834
834
PQclear (res );
835
835
}
836
836
@@ -964,62 +964,55 @@ pgfdw_get_result(PGconn *conn)
964
964
* Report an error we got from the remote server.
965
965
*
966
966
* elevel: error level to use (typically ERROR, but might be less)
967
- * res: PGresult containing the error
967
+ * res: PGresult containing the error (might be NULL)
968
968
* conn: connection we did the query on
969
- * clear: if true, PQclear the result (otherwise caller will handle it)
970
969
* sql: NULL, or text of remote command we tried to execute
971
970
*
971
+ * If "res" is not NULL, it'll be PQclear'ed here (unless we throw error,
972
+ * in which case memory context cleanup will clear it eventually).
973
+ *
972
974
* Note: callers that choose not to throw ERROR for a remote error are
973
975
* responsible for making sure that the associated ConnCacheEntry gets
974
976
* marked with have_error = true.
975
977
*/
976
978
void
977
979
pgfdw_report_error (int elevel , PGresult * res , PGconn * conn ,
978
- bool clear , const char * sql )
980
+ const char * sql )
979
981
{
980
- /* If requested, PGresult must be released before leaving this function. */
981
- PG_TRY ();
982
- {
983
- char * diag_sqlstate = PQresultErrorField (res , PG_DIAG_SQLSTATE );
984
- char * message_primary = PQresultErrorField (res , PG_DIAG_MESSAGE_PRIMARY );
985
- char * message_detail = PQresultErrorField (res , PG_DIAG_MESSAGE_DETAIL );
986
- char * message_hint = PQresultErrorField (res , PG_DIAG_MESSAGE_HINT );
987
- char * message_context = PQresultErrorField (res , PG_DIAG_CONTEXT );
988
- int sqlstate ;
989
-
990
- if (diag_sqlstate )
991
- sqlstate = MAKE_SQLSTATE (diag_sqlstate [0 ],
992
- diag_sqlstate [1 ],
993
- diag_sqlstate [2 ],
994
- diag_sqlstate [3 ],
995
- diag_sqlstate [4 ]);
996
- else
997
- sqlstate = ERRCODE_CONNECTION_FAILURE ;
982
+ char * diag_sqlstate = PQresultErrorField (res , PG_DIAG_SQLSTATE );
983
+ char * message_primary = PQresultErrorField (res , PG_DIAG_MESSAGE_PRIMARY );
984
+ char * message_detail = PQresultErrorField (res , PG_DIAG_MESSAGE_DETAIL );
985
+ char * message_hint = PQresultErrorField (res , PG_DIAG_MESSAGE_HINT );
986
+ char * message_context = PQresultErrorField (res , PG_DIAG_CONTEXT );
987
+ int sqlstate ;
988
+
989
+ if (diag_sqlstate )
990
+ sqlstate = MAKE_SQLSTATE (diag_sqlstate [0 ],
991
+ diag_sqlstate [1 ],
992
+ diag_sqlstate [2 ],
993
+ diag_sqlstate [3 ],
994
+ diag_sqlstate [4 ]);
995
+ else
996
+ sqlstate = ERRCODE_CONNECTION_FAILURE ;
998
997
999
- /*
1000
- * If we don't get a message from the PGresult, try the PGconn. This
1001
- * is needed because for connection-level failures, PQgetResult may
1002
- * just return NULL, not a PGresult at all.
1003
- */
1004
- if (message_primary == NULL )
1005
- message_primary = pchomp (PQerrorMessage (conn ));
1006
-
1007
- ereport (elevel ,
1008
- (errcode (sqlstate ),
1009
- (message_primary != NULL && message_primary [0 ] != '\0' ) ?
1010
- errmsg_internal ("%s" , message_primary ) :
1011
- errmsg ("could not obtain message string for remote error" ),
1012
- message_detail ? errdetail_internal ("%s" , message_detail ) : 0 ,
1013
- message_hint ? errhint ("%s" , message_hint ) : 0 ,
1014
- message_context ? errcontext ("%s" , message_context ) : 0 ,
1015
- sql ? errcontext ("remote SQL command: %s" , sql ) : 0 ));
1016
- }
1017
- PG_FINALLY ();
1018
- {
1019
- if (clear )
1020
- PQclear (res );
1021
- }
1022
- PG_END_TRY ();
998
+ /*
999
+ * If we don't get a message from the PGresult, try the PGconn. This is
1000
+ * needed because for connection-level failures, PQgetResult may just
1001
+ * return NULL, not a PGresult at all.
1002
+ */
1003
+ if (message_primary == NULL )
1004
+ message_primary = pchomp (PQerrorMessage (conn ));
1005
+
1006
+ ereport (elevel ,
1007
+ (errcode (sqlstate ),
1008
+ (message_primary != NULL && message_primary [0 ] != '\0' ) ?
1009
+ errmsg_internal ("%s" , message_primary ) :
1010
+ errmsg ("could not obtain message string for remote error" ),
1011
+ message_detail ? errdetail_internal ("%s" , message_detail ) : 0 ,
1012
+ message_hint ? errhint ("%s" , message_hint ) : 0 ,
1013
+ message_context ? errcontext ("%s" , message_context ) : 0 ,
1014
+ sql ? errcontext ("remote SQL command: %s" , sql ) : 0 ));
1015
+ PQclear (res );
1023
1016
}
1024
1017
1025
1018
/*
@@ -1542,7 +1535,7 @@ pgfdw_exec_cleanup_query_begin(PGconn *conn, const char *query)
1542
1535
*/
1543
1536
if (!PQsendQuery (conn , query ))
1544
1537
{
1545
- pgfdw_report_error (WARNING , NULL , conn , false, query );
1538
+ pgfdw_report_error (WARNING , NULL , conn , query );
1546
1539
return false;
1547
1540
}
1548
1541
@@ -1567,7 +1560,7 @@ pgfdw_exec_cleanup_query_end(PGconn *conn, const char *query,
1567
1560
*/
1568
1561
if (consume_input && !PQconsumeInput (conn ))
1569
1562
{
1570
- pgfdw_report_error (WARNING , NULL , conn , false, query );
1563
+ pgfdw_report_error (WARNING , NULL , conn , query );
1571
1564
return false;
1572
1565
}
1573
1566
@@ -1579,15 +1572,15 @@ pgfdw_exec_cleanup_query_end(PGconn *conn, const char *query,
1579
1572
(errmsg ("could not get query result due to timeout" ),
1580
1573
errcontext ("remote SQL command: %s" , query )));
1581
1574
else
1582
- pgfdw_report_error (WARNING , NULL , conn , false, query );
1575
+ pgfdw_report_error (WARNING , NULL , conn , query );
1583
1576
1584
1577
return false;
1585
1578
}
1586
1579
1587
1580
/* Issue a warning if not successful. */
1588
1581
if (PQresultStatus (result ) != PGRES_COMMAND_OK )
1589
1582
{
1590
- pgfdw_report_error (WARNING , result , conn , true, query );
1583
+ pgfdw_report_error (WARNING , result , conn , query );
1591
1584
return ignore_errors ;
1592
1585
}
1593
1586
PQclear (result );
@@ -1615,103 +1608,90 @@ pgfdw_get_cleanup_result(PGconn *conn, TimestampTz endtime,
1615
1608
PGresult * * result ,
1616
1609
bool * timed_out )
1617
1610
{
1618
- volatile bool failed = false;
1619
- PGresult * volatile last_res = NULL ;
1611
+ bool failed = false;
1612
+ PGresult * last_res = NULL ;
1613
+ int canceldelta = RETRY_CANCEL_TIMEOUT * 2 ;
1620
1614
1621
1615
* result = NULL ;
1622
1616
* timed_out = false;
1623
-
1624
- /* In what follows, do not leak any PGresults on an error. */
1625
- PG_TRY ();
1617
+ for (;;)
1626
1618
{
1627
- int canceldelta = RETRY_CANCEL_TIMEOUT * 2 ;
1619
+ PGresult * res ;
1628
1620
1629
- for (;; )
1621
+ while ( PQisBusy ( conn ) )
1630
1622
{
1631
- PGresult * res ;
1623
+ int wc ;
1624
+ TimestampTz now = GetCurrentTimestamp ();
1625
+ long cur_timeout ;
1632
1626
1633
- while (PQisBusy (conn ))
1627
+ /* If timeout has expired, give up. */
1628
+ if (now >= endtime )
1634
1629
{
1635
- int wc ;
1636
- TimestampTz now = GetCurrentTimestamp ();
1637
- long cur_timeout ;
1638
-
1639
- /* If timeout has expired, give up. */
1640
- if (now >= endtime )
1641
- {
1642
- * timed_out = true;
1643
- failed = true;
1644
- goto exit ;
1645
- }
1630
+ * timed_out = true;
1631
+ failed = true;
1632
+ goto exit ;
1633
+ }
1646
1634
1647
- /* If we need to re-issue the cancel request, do that. */
1648
- if (now >= retrycanceltime )
1649
- {
1650
- /* We ignore failure to issue the repeated request. */
1651
- (void ) libpqsrv_cancel (conn , endtime );
1635
+ /* If we need to re-issue the cancel request, do that. */
1636
+ if (now >= retrycanceltime )
1637
+ {
1638
+ /* We ignore failure to issue the repeated request. */
1639
+ (void ) libpqsrv_cancel (conn , endtime );
1652
1640
1653
- /* Recompute "now" in case that took measurable time. */
1654
- now = GetCurrentTimestamp ();
1641
+ /* Recompute "now" in case that took measurable time. */
1642
+ now = GetCurrentTimestamp ();
1655
1643
1656
- /* Adjust re-cancel timeout in increasing steps. */
1657
- retrycanceltime = TimestampTzPlusMilliseconds (now ,
1658
- canceldelta );
1659
- canceldelta += canceldelta ;
1660
- }
1644
+ /* Adjust re-cancel timeout in increasing steps. */
1645
+ retrycanceltime = TimestampTzPlusMilliseconds (now ,
1646
+ canceldelta );
1647
+ canceldelta += canceldelta ;
1648
+ }
1661
1649
1662
- /* If timeout has expired, give up, else get sleep time. */
1663
- cur_timeout = TimestampDifferenceMilliseconds (now ,
1664
- Min (endtime ,
1665
- retrycanceltime ));
1666
- if (cur_timeout <= 0 )
1667
- {
1668
- * timed_out = true;
1669
- failed = true;
1670
- goto exit ;
1671
- }
1650
+ /* If timeout has expired, give up, else get sleep time. */
1651
+ cur_timeout = TimestampDifferenceMilliseconds (now ,
1652
+ Min (endtime ,
1653
+ retrycanceltime ));
1654
+ if (cur_timeout <= 0 )
1655
+ {
1656
+ * timed_out = true;
1657
+ failed = true;
1658
+ goto exit ;
1659
+ }
1672
1660
1673
- /* first time, allocate or get the custom wait event */
1674
- if (pgfdw_we_cleanup_result == 0 )
1675
- pgfdw_we_cleanup_result = WaitEventExtensionNew ("PostgresFdwCleanupResult" );
1661
+ /* first time, allocate or get the custom wait event */
1662
+ if (pgfdw_we_cleanup_result == 0 )
1663
+ pgfdw_we_cleanup_result = WaitEventExtensionNew ("PostgresFdwCleanupResult" );
1676
1664
1677
- /* Sleep until there's something to do */
1678
- wc = WaitLatchOrSocket (MyLatch ,
1679
- WL_LATCH_SET | WL_SOCKET_READABLE |
1680
- WL_TIMEOUT | WL_EXIT_ON_PM_DEATH ,
1681
- PQsocket (conn ),
1682
- cur_timeout , pgfdw_we_cleanup_result );
1683
- ResetLatch (MyLatch );
1665
+ /* Sleep until there's something to do */
1666
+ wc = WaitLatchOrSocket (MyLatch ,
1667
+ WL_LATCH_SET | WL_SOCKET_READABLE |
1668
+ WL_TIMEOUT | WL_EXIT_ON_PM_DEATH ,
1669
+ PQsocket (conn ),
1670
+ cur_timeout , pgfdw_we_cleanup_result );
1671
+ ResetLatch (MyLatch );
1684
1672
1685
- CHECK_FOR_INTERRUPTS ();
1673
+ CHECK_FOR_INTERRUPTS ();
1686
1674
1687
- /* Data available in socket? */
1688
- if (wc & WL_SOCKET_READABLE )
1675
+ /* Data available in socket? */
1676
+ if (wc & WL_SOCKET_READABLE )
1677
+ {
1678
+ if (!PQconsumeInput (conn ))
1689
1679
{
1690
- if (!PQconsumeInput (conn ))
1691
- {
1692
- /* connection trouble */
1693
- failed = true;
1694
- goto exit ;
1695
- }
1680
+ /* connection trouble */
1681
+ failed = true;
1682
+ goto exit ;
1696
1683
}
1697
1684
}
1685
+ }
1698
1686
1699
- res = PQgetResult (conn );
1700
- if (res == NULL )
1701
- break ; /* query is complete */
1687
+ res = PQgetResult (conn );
1688
+ if (res == NULL )
1689
+ break ; /* query is complete */
1702
1690
1703
- PQclear (last_res );
1704
- last_res = res ;
1705
- }
1706
- exit : ;
1707
- }
1708
- PG_CATCH ();
1709
- {
1710
1691
PQclear (last_res );
1711
- PG_RE_THROW () ;
1692
+ last_res = res ;
1712
1693
}
1713
- PG_END_TRY ();
1714
-
1694
+ exit :
1715
1695
if (failed )
1716
1696
PQclear (last_res );
1717
1697
else
0 commit comments