summaryrefslogtreecommitdiff
path: root/src/backend/utils
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/utils')
-rw-r--r--src/backend/utils/activity/backend_status.c68
-rw-r--r--src/backend/utils/adt/pgstatfuncs.c7
-rw-r--r--src/backend/utils/error/elog.c8
-rw-r--r--src/backend/utils/misc/postgresql.conf.sample1
-rw-r--r--src/backend/utils/misc/queryjumble.c27
5 files changed, 96 insertions, 15 deletions
diff --git a/src/backend/utils/activity/backend_status.c b/src/backend/utils/activity/backend_status.c
index a25ec0ee3c1..6110113e56a 100644
--- a/src/backend/utils/activity/backend_status.c
+++ b/src/backend/utils/activity/backend_status.c
@@ -544,6 +544,7 @@ pgstat_report_activity(BackendState state, const char *cmd_str)
beentry->st_activity_start_timestamp = 0;
/* st_xact_start_timestamp and wait_event_info are also disabled */
beentry->st_xact_start_timestamp = 0;
+ beentry->st_queryid = UINT64CONST(0);
proc->wait_event_info = 0;
PGSTAT_END_WRITE_ACTIVITY(beentry);
}
@@ -598,6 +599,14 @@ pgstat_report_activity(BackendState state, const char *cmd_str)
beentry->st_state = state;
beentry->st_state_start_timestamp = current_timestamp;
+ /*
+ * If a new query is started, we reset the query identifier as it'll only
+ * be known after parse analysis, to avoid reporting last query's
+ * identifier.
+ */
+ if (state == STATE_RUNNING)
+ beentry->st_queryid = UINT64CONST(0);
+
if (cmd_str != NULL)
{
memcpy((char *) beentry->st_activity_raw, cmd_str, len);
@@ -608,6 +617,46 @@ pgstat_report_activity(BackendState state, const char *cmd_str)
PGSTAT_END_WRITE_ACTIVITY(beentry);
}
+/* --------
+ * pgstat_report_queryid() -
+ *
+ * Called to update top-level query identifier.
+ * --------
+ */
+void
+pgstat_report_queryid(uint64 queryId, bool force)
+{
+ volatile PgBackendStatus *beentry = MyBEEntry;
+
+ /*
+ * if track_activities is disabled, st_queryid should already have been
+ * reset
+ */
+ if (!beentry || !pgstat_track_activities)
+ return;
+
+ /*
+ * We only report the top-level query identifiers. The stored queryid is
+ * reset when a backend calls pgstat_report_activity(STATE_RUNNING), or
+ * with an explicit call to this function using the force flag. If the
+ * saved query identifier is not zero it means that it's not a top-level
+ * command, so ignore the one provided unless it's an explicit call to
+ * reset the identifier.
+ */
+ if (beentry->st_queryid != 0 && !force)
+ return;
+
+ /*
+ * Update my status entry, following the protocol of bumping
+ * st_changecount before and after. We use a volatile pointer here to
+ * ensure the compiler doesn't try to get cute.
+ */
+ PGSTAT_BEGIN_WRITE_ACTIVITY(beentry);
+ beentry->st_queryid = queryId;
+ PGSTAT_END_WRITE_ACTIVITY(beentry);
+}
+
+
/* ----------
* pgstat_report_appname() -
*
@@ -972,6 +1021,25 @@ pgstat_get_crashed_backend_activity(int pid, char *buffer, int buflen)
return NULL;
}
+/* ----------
+ * pgstat_get_my_queryid() -
+ *
+ * Return current backend's query identifier.
+ */
+uint64
+pgstat_get_my_queryid(void)
+{
+ if (!MyBEEntry)
+ return 0;
+
+ /* There's no need for a look around pgstat_begin_read_activity /
+ * pgstat_end_read_activity here as it's only called from
+ * pg_stat_get_activity which is already protected, or from the same
+ * backend which mean that there won't be concurrent write.
+ */
+ return MyBEEntry->st_queryid;
+}
+
/* ----------
* pgstat_fetch_stat_beentry() -
diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c
index 9ffbca685cd..9fa4a93162f 100644
--- a/src/backend/utils/adt/pgstatfuncs.c
+++ b/src/backend/utils/adt/pgstatfuncs.c
@@ -569,7 +569,7 @@ pg_stat_get_progress_info(PG_FUNCTION_ARGS)
Datum
pg_stat_get_activity(PG_FUNCTION_ARGS)
{
-#define PG_STAT_GET_ACTIVITY_COLS 29
+#define PG_STAT_GET_ACTIVITY_COLS 30
int num_backends = pgstat_fetch_stat_numbackends();
int curr_backend;
int pid = PG_ARGISNULL(0) ? -1 : PG_GETARG_INT32(0);
@@ -914,6 +914,10 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
values[27] = BoolGetDatum(false); /* GSS Encryption not in
* use */
}
+ if (beentry->st_queryid == 0)
+ nulls[29] = true;
+ else
+ values[29] = DatumGetUInt64(beentry->st_queryid);
}
else
{
@@ -941,6 +945,7 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
nulls[26] = true;
nulls[27] = true;
nulls[28] = true;
+ nulls[29] = true;
}
tuplestore_putvalues(tupstore, tupdesc, values, nulls);
diff --git a/src/backend/utils/error/elog.c b/src/backend/utils/error/elog.c
index 12de4b38cba..1cf71a649b3 100644
--- a/src/backend/utils/error/elog.c
+++ b/src/backend/utils/error/elog.c
@@ -2714,6 +2714,14 @@ log_line_prefix(StringInfo buf, ErrorData *edata)
else
appendStringInfoString(buf, unpack_sql_state(edata->sqlerrcode));
break;
+ case 'Q':
+ if (padding != 0)
+ appendStringInfo(buf, "%*ld", padding,
+ pgstat_get_my_queryid());
+ else
+ appendStringInfo(buf, "%ld",
+ pgstat_get_my_queryid());
+ break;
default:
/* format error - ignore it */
break;
diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample
index 192577a02e5..65f61869663 100644
--- a/src/backend/utils/misc/postgresql.conf.sample
+++ b/src/backend/utils/misc/postgresql.conf.sample
@@ -543,6 +543,7 @@
# %t = timestamp without milliseconds
# %m = timestamp with milliseconds
# %n = timestamp with milliseconds (as a Unix epoch)
+ # %Q = query ID (0 if none or not computed)
# %i = command tag
# %e = SQL state
# %c = session ID
diff --git a/src/backend/utils/misc/queryjumble.c b/src/backend/utils/misc/queryjumble.c
index 2a47688fd63..53286bb333f 100644
--- a/src/backend/utils/misc/queryjumble.c
+++ b/src/backend/utils/misc/queryjumble.c
@@ -39,7 +39,7 @@
#define JUMBLE_SIZE 1024 /* query serialization buffer size */
-static uint64 compute_utility_queryid(const char *str, int query_len);
+static uint64 compute_utility_queryid(const char *str, int query_location, int query_len);
static void AppendJumble(JumbleState *jstate,
const unsigned char *item, Size size);
static void JumbleQueryInternal(JumbleState *jstate, Query *query);
@@ -97,17 +97,9 @@ JumbleQuery(Query *query, const char *querytext)
JumbleState *jstate = NULL;
if (query->utilityStmt)
{
- const char *sql;
- int query_location = query->stmt_location;
- int query_len = query->stmt_len;
-
- /*
- * Confine our attention to the relevant part of the string, if the
- * query is a portion of a multi-statement source string.
- */
- sql = CleanQuerytext(querytext, &query_location, &query_len);
-
- query->queryId = compute_utility_queryid(sql, query_len);
+ query->queryId = compute_utility_queryid(querytext,
+ query->stmt_location,
+ query->stmt_len);
}
else
{
@@ -143,11 +135,18 @@ JumbleQuery(Query *query, const char *querytext)
* Compute a query identifier for the given utility query string.
*/
static uint64
-compute_utility_queryid(const char *str, int query_len)
+compute_utility_queryid(const char *query_text, int query_location, int query_len)
{
uint64 queryId;
+ const char *sql;
+
+ /*
+ * Confine our attention to the relevant part of the string, if the
+ * query is a portion of a multi-statement source string.
+ */
+ sql = CleanQuerytext(query_text, &query_location, &query_len);
- queryId = DatumGetUInt64(hash_any_extended((const unsigned char *) str,
+ queryId = DatumGetUInt64(hash_any_extended((const unsigned char *) sql,
query_len, 0));
/*