Skip to content

Commit 1b67e0c

Browse files
committed
Fix core dump in duration logging for a V3-protocol Execute message
when what's being executed is a COMMIT or ROLLBACK. Per report from Sergey Koposov. Backpatch to 8.1; 8.0 and before don't have the bug due to lack of any logging at all here.
1 parent b475d25 commit 1b67e0c

File tree

1 file changed

+65
-47
lines changed

1 file changed

+65
-47
lines changed

src/backend/tcop/postgres.c

Lines changed: 65 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.497 2006/08/10 00:44:01 momjian Exp $
11+
* $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.498 2006/08/13 22:18:08 tgl Exp $
1212
*
1313
* NOTES
1414
* this is the "main" module of the postgres backend and
@@ -1368,7 +1368,7 @@ exec_bind_message(StringInfo input_message)
13681368
PreparedStatement *pstmt;
13691369
Portal portal;
13701370
ParamListInfo params;
1371-
StringInfoData str;
1371+
StringInfoData bind_values_str;
13721372

13731373
pgstat_report_activity("<BIND>");
13741374

@@ -1385,7 +1385,7 @@ exec_bind_message(StringInfo input_message)
13851385
MemoryContextSwitchTo(MessageContext);
13861386

13871387
if (log_statement == LOGSTMT_ALL)
1388-
initStringInfo(&str);
1388+
initStringInfo(&bind_values_str);
13891389

13901390
/* Get the fixed part of the message */
13911391
portal_name = pq_getmsgstring(input_message);
@@ -1534,14 +1534,18 @@ exec_bind_message(StringInfo input_message)
15341534
else
15351535
pstring = pg_client_to_server(pbuf.data, plength);
15361536

1537-
params->params[paramno].value = OidInputFunctionCall(typinput,
1538-
pstring,
1539-
typioparam,
1540-
-1);
1537+
params->params[paramno].value =
1538+
OidInputFunctionCall(typinput,
1539+
pstring,
1540+
typioparam,
1541+
-1);
15411542

1543+
/* Log the parameter value if needed */
15421544
if (log_statement == LOGSTMT_ALL)
1543-
appendStringInfo(&str, "%s$%d = \"%s\"",
1544-
*str.data ? ", " : "", paramno + 1, pstring);
1545+
appendStringInfo(&bind_values_str, "%s$%d = \"%s\"",
1546+
bind_values_str.len ? ", " : "",
1547+
paramno + 1,
1548+
pstring);
15451549

15461550
/* Free result of encoding conversion, if any */
15471551
if (pstring && pstring != pbuf.data)
@@ -1574,6 +1578,8 @@ exec_bind_message(StringInfo input_message)
15741578
(errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
15751579
errmsg("incorrect binary data format in bind parameter %d",
15761580
paramno + 1)));
1581+
1582+
/* XXX TODO: convert value to text and log it */
15771583
}
15781584
else
15791585
{
@@ -1600,22 +1606,14 @@ exec_bind_message(StringInfo input_message)
16001606

16011607
if (log_statement == LOGSTMT_ALL)
16021608
{
1603-
if (*str.data)
1604-
ereport(LOG,
1605-
(errmsg("bind %s%s%s: %s",
1606-
*stmt_name ? stmt_name : "<unnamed>",
1607-
*portal->name ? "/" : "",
1608-
*portal->name ? portal->name : "",
1609-
pstmt->query_string ? pstmt->query_string : ""),
1610-
errdetail(str.data)));
1611-
else
1612-
ereport(LOG,
1613-
(errmsg("bind %s%s%s: %s",
1614-
*stmt_name ? stmt_name : "<unnamed>",
1615-
*portal->name ? "/" : "",
1616-
*portal->name ? portal->name : "",
1617-
pstmt->query_string ? pstmt->query_string : "")));
1618-
pfree(str.data);
1609+
ereport(LOG,
1610+
(errmsg("bind %s%s%s: %s",
1611+
*stmt_name ? stmt_name : "<unnamed>",
1612+
*portal->name ? "/" : "",
1613+
*portal->name ? portal->name : "",
1614+
pstmt->query_string ? pstmt->query_string : ""),
1615+
bind_values_str.len ? errdetail(bind_values_str.data) : 0));
1616+
pfree(bind_values_str.data);
16191617
}
16201618

16211619
/* Get the result format codes */
@@ -1685,8 +1683,11 @@ exec_execute_message(const char *portal_name, long max_rows)
16851683
Portal portal;
16861684
bool completed;
16871685
char completionTag[COMPLETION_TAG_BUFSIZE];
1686+
const char *sourceText = NULL;
1687+
const char *prepStmtName;
16881688
bool save_log_statement_stats = log_statement_stats;
1689-
bool execute_is_fetch = false;
1689+
bool is_xact_command;
1690+
bool execute_is_fetch;
16901691

16911692
/* Adjust destination to tell printtup.c what to do */
16921693
dest = whereToSendOutput;
@@ -1699,15 +1700,6 @@ exec_execute_message(const char *portal_name, long max_rows)
16991700
(errcode(ERRCODE_UNDEFINED_CURSOR),
17001701
errmsg("portal \"%s\" does not exist", portal_name)));
17011702

1702-
/*
1703-
* If we re-issue an Execute protocol request against an existing portal,
1704-
* then we are only fetching more rows rather than completely re-executing
1705-
* the query from the start. atStart is never reset for a v3 portal, so we
1706-
* are safe to use this check.
1707-
*/
1708-
if (!portal->atStart)
1709-
execute_is_fetch = true;
1710-
17111703
/*
17121704
* If the original query was a null string, just return
17131705
* EmptyQueryResponse.
@@ -1719,6 +1711,17 @@ exec_execute_message(const char *portal_name, long max_rows)
17191711
return;
17201712
}
17211713

1714+
/* Does the portal contain a transaction command? */
1715+
is_xact_command = IsTransactionStmtList(portal->parseTrees);
1716+
1717+
/*
1718+
* If we re-issue an Execute protocol request against an existing portal,
1719+
* then we are only fetching more rows rather than completely re-executing
1720+
* the query from the start. atStart is never reset for a v3 portal, so we
1721+
* are safe to use this check.
1722+
*/
1723+
execute_is_fetch = !portal->atStart;
1724+
17221725
/* Should we display the portal names here? */
17231726
if (execute_is_fetch)
17241727
{
@@ -1727,8 +1730,18 @@ exec_execute_message(const char *portal_name, long max_rows)
17271730
}
17281731
else if (portal->sourceText)
17291732
{
1730-
debug_query_string = portal->sourceText;
1731-
pgstat_report_activity(portal->sourceText);
1733+
/*
1734+
* We must copy the sourceText into MessageContext in case the
1735+
* portal is destroyed during finish_xact_command. Can avoid
1736+
* the copy if it's not an xact command, though.
1737+
*/
1738+
if (is_xact_command)
1739+
sourceText = pstrdup(portal->sourceText);
1740+
else
1741+
sourceText = portal->sourceText;
1742+
1743+
debug_query_string = sourceText;
1744+
pgstat_report_activity(sourceText);
17321745
}
17331746
else
17341747
{
@@ -1738,6 +1751,12 @@ exec_execute_message(const char *portal_name, long max_rows)
17381751

17391752
set_ps_display(portal->commandTag, false);
17401753

1754+
/* copy prepStmtName now too, in case portal is destroyed */
1755+
if (portal->prepStmtName)
1756+
prepStmtName = pstrdup(portal->prepStmtName);
1757+
else
1758+
prepStmtName = "<unnamed>";
1759+
17411760
/*
17421761
* We use save_log_statement_stats so ShowUsage doesn't report incorrect
17431762
* results because ResetUsage wasn't called.
@@ -1746,14 +1765,13 @@ exec_execute_message(const char *portal_name, long max_rows)
17461765
ResetUsage();
17471766

17481767
if (log_statement == LOGSTMT_ALL)
1749-
/* We have the portal, so output the source query. */
17501768
ereport(LOG,
17511769
(errmsg("execute %s%s%s%s: %s",
17521770
execute_is_fetch ? "fetch from " : "",
1753-
portal->prepStmtName ? portal->prepStmtName : "<unnamed>",
1754-
*portal->name ? "/" : "",
1755-
*portal->name ? portal->name : "",
1756-
portal->sourceText ? portal->sourceText : "")));
1771+
prepStmtName,
1772+
*portal_name ? "/" : "",
1773+
*portal_name ? portal_name : "",
1774+
sourceText ? sourceText : "")));
17571775

17581776
BeginCommand(portal->commandTag, dest);
17591777

@@ -1799,7 +1817,7 @@ exec_execute_message(const char *portal_name, long max_rows)
17991817

18001818
if (completed)
18011819
{
1802-
if (IsTransactionStmtList(portal->parseTrees))
1820+
if (is_xact_command)
18031821
{
18041822
/*
18051823
* If this was a transaction control statement, commit it. We
@@ -1861,10 +1879,10 @@ exec_execute_message(const char *portal_name, long max_rows)
18611879
(errmsg("duration: %ld.%03d ms execute %s%s%s%s: %s",
18621880
secs * 1000 + msecs, usecs % 1000,
18631881
execute_is_fetch ? "fetch from " : "",
1864-
portal->prepStmtName ? portal->prepStmtName : "<unnamed>",
1865-
*portal->name ? "/" : "",
1866-
*portal->name ? portal->name : "",
1867-
portal->sourceText ? portal->sourceText : "")));
1882+
prepStmtName,
1883+
*portal_name ? "/" : "",
1884+
*portal_name ? portal_name : "",
1885+
sourceText ? sourceText : "")));
18681886
}
18691887
}
18701888

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy