Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 2f96613

Browse files
committed
Represent command completion tags as structs
The backend was using strings to represent command tags and doing string comparisons in multiple places, but that's slow and unhelpful. Create a new command list with a supporting structure to use instead; this is stored in a tag-list-file that can be tailored to specific purposes with a caller-definable C macro, similar to what we do for WAL resource managers. The first first such uses are a new CommandTag enum and a CommandTagBehavior struct. Replace numerous occurrences of char *completionTag with a QueryCompletion struct so that the code no longer stores information about completed queries in a cstring. Only at the last moment, in EndCommand(), does this get converted to a string. EventTriggerCacheItem no longer holds an array of palloc’d tag strings in sorted order, but rather just a Bitmapset over the CommandTags. Author: Mark Dilger, with unsolicited help from Álvaro Herrera Reviewed-by: John Naylor, Tom Lane Discussion: https://postgr.es/m/981A9DB4-3F0C-4DA5-88AD-CB9CFF4D6CAD@enterprisedb.com
1 parent 7b425a5 commit 2f96613

39 files changed

+877
-621
lines changed

contrib/pg_stat_statements/pg_stat_statements.c

+8-12
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,7 @@ static void pgss_ExecutorEnd(QueryDesc *queryDesc);
307307
static void pgss_ProcessUtility(PlannedStmt *pstmt, const char *queryString,
308308
ProcessUtilityContext context, ParamListInfo params,
309309
QueryEnvironment *queryEnv,
310-
DestReceiver *dest, char *completionTag);
310+
DestReceiver *dest, QueryCompletion *qc);
311311
static uint64 pgss_hash_string(const char *str, int len);
312312
static void pgss_store(const char *query, uint64 queryId,
313313
int query_location, int query_len,
@@ -960,7 +960,7 @@ static void
960960
pgss_ProcessUtility(PlannedStmt *pstmt, const char *queryString,
961961
ProcessUtilityContext context,
962962
ParamListInfo params, QueryEnvironment *queryEnv,
963-
DestReceiver *dest, char *completionTag)
963+
DestReceiver *dest, QueryCompletion *qc)
964964
{
965965
Node *parsetree = pstmt->utilityStmt;
966966

@@ -998,11 +998,11 @@ pgss_ProcessUtility(PlannedStmt *pstmt, const char *queryString,
998998
if (prev_ProcessUtility)
999999
prev_ProcessUtility(pstmt, queryString,
10001000
context, params, queryEnv,
1001-
dest, completionTag);
1001+
dest, qc);
10021002
else
10031003
standard_ProcessUtility(pstmt, queryString,
10041004
context, params, queryEnv,
1005-
dest, completionTag);
1005+
dest, qc);
10061006
}
10071007
PG_FINALLY();
10081008
{
@@ -1013,12 +1013,8 @@ pgss_ProcessUtility(PlannedStmt *pstmt, const char *queryString,
10131013
INSTR_TIME_SET_CURRENT(duration);
10141014
INSTR_TIME_SUBTRACT(duration, start);
10151015

1016-
/* parse command tag to retrieve the number of affected rows. */
1017-
if (completionTag &&
1018-
strncmp(completionTag, "COPY ", 5) == 0)
1019-
rows = pg_strtouint64(completionTag + 5, NULL, 10);
1020-
else
1021-
rows = 0;
1016+
if (qc)
1017+
rows = qc->commandTag == CMDTAG_COPY ? qc->nprocessed : 0;
10221018

10231019
/* calc differences of buffer counters. */
10241020
bufusage.shared_blks_hit =
@@ -1060,11 +1056,11 @@ pgss_ProcessUtility(PlannedStmt *pstmt, const char *queryString,
10601056
if (prev_ProcessUtility)
10611057
prev_ProcessUtility(pstmt, queryString,
10621058
context, params, queryEnv,
1063-
dest, completionTag);
1059+
dest, qc);
10641060
else
10651061
standard_ProcessUtility(pstmt, queryString,
10661062
context, params, queryEnv,
1067-
dest, completionTag);
1063+
dest, qc);
10681064
}
10691065
}
10701066

contrib/sepgsql/hooks.c

+3-3
Original file line numberDiff line numberDiff line change
@@ -317,7 +317,7 @@ sepgsql_utility_command(PlannedStmt *pstmt,
317317
ParamListInfo params,
318318
QueryEnvironment *queryEnv,
319319
DestReceiver *dest,
320-
char *completionTag)
320+
QueryCompletion *qc)
321321
{
322322
Node *parsetree = pstmt->utilityStmt;
323323
sepgsql_context_info_t saved_context_info = sepgsql_context_info;
@@ -380,11 +380,11 @@ sepgsql_utility_command(PlannedStmt *pstmt,
380380
if (next_ProcessUtility_hook)
381381
(*next_ProcessUtility_hook) (pstmt, queryString,
382382
context, params, queryEnv,
383-
dest, completionTag);
383+
dest, qc);
384384
else
385385
standard_ProcessUtility(pstmt, queryString,
386386
context, params, queryEnv,
387-
dest, completionTag);
387+
dest, qc);
388388
}
389389
PG_FINALLY();
390390
{

doc/src/sgml/event-trigger.sgml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1074,7 +1074,7 @@ typedef struct EventTriggerData
10741074
NodeTag type;
10751075
const char *event; /* event name */
10761076
Node *parsetree; /* parse tree */
1077-
const char *tag; /* command tag */
1077+
CommandTag tag; /* command tag */
10781078
} EventTriggerData;
10791079
</programlisting>
10801080

src/backend/commands/createas.c

+6-8
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
*
1111
* Formerly, CTAS was implemented as a variant of SELECT, which led
1212
* to assorted legacy behaviors that we still try to preserve, notably that
13-
* we must return a tuples-processed count in the completionTag. (We no
13+
* we must return a tuples-processed count in the QueryCompletion. (We no
1414
* longer do that for CTAS ... WITH NO DATA, however.)
1515
*
1616
* Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
@@ -225,7 +225,7 @@ create_ctas_nodata(List *tlist, IntoClause *into)
225225
ObjectAddress
226226
ExecCreateTableAs(ParseState *pstate, CreateTableAsStmt *stmt,
227227
ParamListInfo params, QueryEnvironment *queryEnv,
228-
char *completionTag)
228+
QueryCompletion *qc)
229229
{
230230
Query *query = castNode(Query, stmt->query);
231231
IntoClause *into = stmt->into;
@@ -270,7 +270,7 @@ ExecCreateTableAs(ParseState *pstate, CreateTableAsStmt *stmt,
270270
ExecuteStmt *estmt = castNode(ExecuteStmt, query->utilityStmt);
271271

272272
Assert(!is_matview); /* excluded by syntax */
273-
ExecuteQuery(pstate, estmt, into, params, dest, completionTag);
273+
ExecuteQuery(pstate, estmt, into, params, dest, qc);
274274

275275
/* get object address that intorel_startup saved for us */
276276
address = ((DR_intorel *) dest)->reladdr;
@@ -352,11 +352,9 @@ ExecCreateTableAs(ParseState *pstate, CreateTableAsStmt *stmt,
352352
/* run the plan to completion */
353353
ExecutorRun(queryDesc, ForwardScanDirection, 0L, true);
354354

355-
/* save the rowcount if we're given a completionTag to fill */
356-
if (completionTag)
357-
snprintf(completionTag, COMPLETION_TAG_BUFSIZE,
358-
"SELECT " UINT64_FORMAT,
359-
queryDesc->estate->es_processed);
355+
/* save the rowcount if we're given a qc to fill */
356+
if (qc)
357+
SetQueryCompletion(qc, CMDTAG_SELECT, queryDesc->estate->es_processed);
360358

361359
/* get object address that intorel_startup saved for us */
362360
address = ((DR_intorel *) dest)->reladdr;

0 commit comments

Comments
 (0)