1
0
mirror of https://github.com/postgres/postgres.git synced 2025-06-17 17:02:08 +03:00

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
This commit is contained in:
Alvaro Herrera
2020-03-02 18:19:51 -03:00
parent 7b425a5283
commit 2f9661311b
39 changed files with 877 additions and 621 deletions

View File

@ -1064,8 +1064,8 @@ exec_simple_query(const char *query_string)
{
RawStmt *parsetree = lfirst_node(RawStmt, parsetree_item);
bool snapshot_set = false;
const char *commandTag;
char completionTag[COMPLETION_TAG_BUFSIZE];
CommandTag commandTag;
QueryCompletion qc;
MemoryContext per_parsetree_context = NULL;
List *querytree_list,
*plantree_list;
@ -1081,7 +1081,7 @@ exec_simple_query(const char *query_string)
*/
commandTag = CreateCommandTag(parsetree->stmt);
set_ps_display(commandTag, false);
set_ps_display(GetCommandTagName(commandTag), false);
BeginCommand(commandTag, dest);
@ -1239,7 +1239,7 @@ exec_simple_query(const char *query_string)
true,
receiver,
receiver,
completionTag);
&qc);
receiver->rDestroy(receiver);
@ -1290,7 +1290,7 @@ exec_simple_query(const char *query_string)
* command the client sent, regardless of rewriting. (But a command
* aborted by error will not send an EndCommand report at all.)
*/
EndCommand(completionTag, dest);
EndCommand(&qc, dest, false);
/* Now we may drop the per-parsetree context, if one was created. */
if (per_parsetree_context)
@ -1352,7 +1352,6 @@ exec_parse_message(const char *query_string, /* string to execute */
MemoryContext oldcontext;
List *parsetree_list;
RawStmt *raw_parse_tree;
const char *commandTag;
List *querytree_list;
CachedPlanSource *psrc;
bool is_named;
@ -1438,11 +1437,6 @@ exec_parse_message(const char *query_string, /* string to execute */
raw_parse_tree = linitial_node(RawStmt, parsetree_list);
/*
* Get the command name for possible use in status display.
*/
commandTag = CreateCommandTag(raw_parse_tree->stmt);
/*
* If we are in an aborted transaction, reject all commands except
* COMMIT/ROLLBACK. It is important that this test occur before we
@ -1463,7 +1457,8 @@ exec_parse_message(const char *query_string, /* string to execute */
* Create the CachedPlanSource before we do parse analysis, since it
* needs to see the unmodified raw parse tree.
*/
psrc = CreateCachedPlan(raw_parse_tree, query_string, commandTag);
psrc = CreateCachedPlan(raw_parse_tree, query_string,
CreateCommandTag(raw_parse_tree->stmt));
/*
* Set up a snapshot if parse analysis will need one.
@ -1514,8 +1509,8 @@ exec_parse_message(const char *query_string, /* string to execute */
{
/* Empty input string. This is legal. */
raw_parse_tree = NULL;
commandTag = NULL;
psrc = CreateCachedPlan(raw_parse_tree, query_string, commandTag);
psrc = CreateCachedPlan(raw_parse_tree, query_string,
CMDTAG_UNKNOWN);
querytree_list = NIL;
}
@ -2031,7 +2026,7 @@ exec_execute_message(const char *portal_name, long max_rows)
DestReceiver *receiver;
Portal portal;
bool completed;
char completionTag[COMPLETION_TAG_BUFSIZE];
QueryCompletion qc;
const char *sourceText;
const char *prepStmtName;
ParamListInfo portalParams;
@ -2058,7 +2053,7 @@ exec_execute_message(const char *portal_name, long max_rows)
* If the original query was a null string, just return
* EmptyQueryResponse.
*/
if (portal->commandTag == NULL)
if (portal->commandTag == CMDTAG_UNKNOWN)
{
Assert(portal->stmts == NIL);
NullCommand(dest);
@ -2104,7 +2099,7 @@ exec_execute_message(const char *portal_name, long max_rows)
pgstat_report_activity(STATE_RUNNING, sourceText);
set_ps_display(portal->commandTag, false);
set_ps_display(GetCommandTagName(portal->commandTag), false);
if (save_log_statement_stats)
ResetUsage();
@ -2185,7 +2180,7 @@ exec_execute_message(const char *portal_name, long max_rows)
!execute_is_fetch && max_rows == FETCH_ALL,
receiver,
receiver,
completionTag);
&qc);
receiver->rDestroy(receiver);
@ -2218,7 +2213,7 @@ exec_execute_message(const char *portal_name, long max_rows)
}
/* Send appropriate CommandComplete to client */
EndCommand(completionTag, dest);
EndCommand(&qc, dest, false);
}
else
{