Commit 2f966131 authored by Alvaro Herrera's avatar Alvaro Herrera

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
parent 7b425a52
...@@ -307,7 +307,7 @@ static void pgss_ExecutorEnd(QueryDesc *queryDesc); ...@@ -307,7 +307,7 @@ static void pgss_ExecutorEnd(QueryDesc *queryDesc);
static void pgss_ProcessUtility(PlannedStmt *pstmt, const char *queryString, static void pgss_ProcessUtility(PlannedStmt *pstmt, const char *queryString,
ProcessUtilityContext context, ParamListInfo params, ProcessUtilityContext context, ParamListInfo params,
QueryEnvironment *queryEnv, QueryEnvironment *queryEnv,
DestReceiver *dest, char *completionTag); DestReceiver *dest, QueryCompletion *qc);
static uint64 pgss_hash_string(const char *str, int len); static uint64 pgss_hash_string(const char *str, int len);
static void pgss_store(const char *query, uint64 queryId, static void pgss_store(const char *query, uint64 queryId,
int query_location, int query_len, int query_location, int query_len,
...@@ -960,7 +960,7 @@ static void ...@@ -960,7 +960,7 @@ static void
pgss_ProcessUtility(PlannedStmt *pstmt, const char *queryString, pgss_ProcessUtility(PlannedStmt *pstmt, const char *queryString,
ProcessUtilityContext context, ProcessUtilityContext context,
ParamListInfo params, QueryEnvironment *queryEnv, ParamListInfo params, QueryEnvironment *queryEnv,
DestReceiver *dest, char *completionTag) DestReceiver *dest, QueryCompletion *qc)
{ {
Node *parsetree = pstmt->utilityStmt; Node *parsetree = pstmt->utilityStmt;
...@@ -998,11 +998,11 @@ pgss_ProcessUtility(PlannedStmt *pstmt, const char *queryString, ...@@ -998,11 +998,11 @@ pgss_ProcessUtility(PlannedStmt *pstmt, const char *queryString,
if (prev_ProcessUtility) if (prev_ProcessUtility)
prev_ProcessUtility(pstmt, queryString, prev_ProcessUtility(pstmt, queryString,
context, params, queryEnv, context, params, queryEnv,
dest, completionTag); dest, qc);
else else
standard_ProcessUtility(pstmt, queryString, standard_ProcessUtility(pstmt, queryString,
context, params, queryEnv, context, params, queryEnv,
dest, completionTag); dest, qc);
} }
PG_FINALLY(); PG_FINALLY();
{ {
...@@ -1013,12 +1013,8 @@ pgss_ProcessUtility(PlannedStmt *pstmt, const char *queryString, ...@@ -1013,12 +1013,8 @@ pgss_ProcessUtility(PlannedStmt *pstmt, const char *queryString,
INSTR_TIME_SET_CURRENT(duration); INSTR_TIME_SET_CURRENT(duration);
INSTR_TIME_SUBTRACT(duration, start); INSTR_TIME_SUBTRACT(duration, start);
/* parse command tag to retrieve the number of affected rows. */ if (qc)
if (completionTag && rows = qc->commandTag == CMDTAG_COPY ? qc->nprocessed : 0;
strncmp(completionTag, "COPY ", 5) == 0)
rows = pg_strtouint64(completionTag + 5, NULL, 10);
else
rows = 0;
/* calc differences of buffer counters. */ /* calc differences of buffer counters. */
bufusage.shared_blks_hit = bufusage.shared_blks_hit =
...@@ -1060,11 +1056,11 @@ pgss_ProcessUtility(PlannedStmt *pstmt, const char *queryString, ...@@ -1060,11 +1056,11 @@ pgss_ProcessUtility(PlannedStmt *pstmt, const char *queryString,
if (prev_ProcessUtility) if (prev_ProcessUtility)
prev_ProcessUtility(pstmt, queryString, prev_ProcessUtility(pstmt, queryString,
context, params, queryEnv, context, params, queryEnv,
dest, completionTag); dest, qc);
else else
standard_ProcessUtility(pstmt, queryString, standard_ProcessUtility(pstmt, queryString,
context, params, queryEnv, context, params, queryEnv,
dest, completionTag); dest, qc);
} }
} }
......
...@@ -317,7 +317,7 @@ sepgsql_utility_command(PlannedStmt *pstmt, ...@@ -317,7 +317,7 @@ sepgsql_utility_command(PlannedStmt *pstmt,
ParamListInfo params, ParamListInfo params,
QueryEnvironment *queryEnv, QueryEnvironment *queryEnv,
DestReceiver *dest, DestReceiver *dest,
char *completionTag) QueryCompletion *qc)
{ {
Node *parsetree = pstmt->utilityStmt; Node *parsetree = pstmt->utilityStmt;
sepgsql_context_info_t saved_context_info = sepgsql_context_info; sepgsql_context_info_t saved_context_info = sepgsql_context_info;
...@@ -380,11 +380,11 @@ sepgsql_utility_command(PlannedStmt *pstmt, ...@@ -380,11 +380,11 @@ sepgsql_utility_command(PlannedStmt *pstmt,
if (next_ProcessUtility_hook) if (next_ProcessUtility_hook)
(*next_ProcessUtility_hook) (pstmt, queryString, (*next_ProcessUtility_hook) (pstmt, queryString,
context, params, queryEnv, context, params, queryEnv,
dest, completionTag); dest, qc);
else else
standard_ProcessUtility(pstmt, queryString, standard_ProcessUtility(pstmt, queryString,
context, params, queryEnv, context, params, queryEnv,
dest, completionTag); dest, qc);
} }
PG_FINALLY(); PG_FINALLY();
{ {
......
...@@ -1074,7 +1074,7 @@ typedef struct EventTriggerData ...@@ -1074,7 +1074,7 @@ typedef struct EventTriggerData
NodeTag type; NodeTag type;
const char *event; /* event name */ const char *event; /* event name */
Node *parsetree; /* parse tree */ Node *parsetree; /* parse tree */
const char *tag; /* command tag */ CommandTag tag; /* command tag */
} EventTriggerData; } EventTriggerData;
</programlisting> </programlisting>
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
* *
* Formerly, CTAS was implemented as a variant of SELECT, which led * Formerly, CTAS was implemented as a variant of SELECT, which led
* to assorted legacy behaviors that we still try to preserve, notably that * to assorted legacy behaviors that we still try to preserve, notably that
* we must return a tuples-processed count in the completionTag. (We no * we must return a tuples-processed count in the QueryCompletion. (We no
* longer do that for CTAS ... WITH NO DATA, however.) * longer do that for CTAS ... WITH NO DATA, however.)
* *
* Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
...@@ -225,7 +225,7 @@ create_ctas_nodata(List *tlist, IntoClause *into) ...@@ -225,7 +225,7 @@ create_ctas_nodata(List *tlist, IntoClause *into)
ObjectAddress ObjectAddress
ExecCreateTableAs(ParseState *pstate, CreateTableAsStmt *stmt, ExecCreateTableAs(ParseState *pstate, CreateTableAsStmt *stmt,
ParamListInfo params, QueryEnvironment *queryEnv, ParamListInfo params, QueryEnvironment *queryEnv,
char *completionTag) QueryCompletion *qc)
{ {
Query *query = castNode(Query, stmt->query); Query *query = castNode(Query, stmt->query);
IntoClause *into = stmt->into; IntoClause *into = stmt->into;
...@@ -270,7 +270,7 @@ ExecCreateTableAs(ParseState *pstate, CreateTableAsStmt *stmt, ...@@ -270,7 +270,7 @@ ExecCreateTableAs(ParseState *pstate, CreateTableAsStmt *stmt,
ExecuteStmt *estmt = castNode(ExecuteStmt, query->utilityStmt); ExecuteStmt *estmt = castNode(ExecuteStmt, query->utilityStmt);
Assert(!is_matview); /* excluded by syntax */ Assert(!is_matview); /* excluded by syntax */
ExecuteQuery(pstate, estmt, into, params, dest, completionTag); ExecuteQuery(pstate, estmt, into, params, dest, qc);
/* get object address that intorel_startup saved for us */ /* get object address that intorel_startup saved for us */
address = ((DR_intorel *) dest)->reladdr; address = ((DR_intorel *) dest)->reladdr;
...@@ -352,11 +352,9 @@ ExecCreateTableAs(ParseState *pstate, CreateTableAsStmt *stmt, ...@@ -352,11 +352,9 @@ ExecCreateTableAs(ParseState *pstate, CreateTableAsStmt *stmt,
/* run the plan to completion */ /* run the plan to completion */
ExecutorRun(queryDesc, ForwardScanDirection, 0L, true); ExecutorRun(queryDesc, ForwardScanDirection, 0L, true);
/* save the rowcount if we're given a completionTag to fill */ /* save the rowcount if we're given a qc to fill */
if (completionTag) if (qc)
snprintf(completionTag, COMPLETION_TAG_BUFSIZE, SetQueryCompletion(qc, CMDTAG_SELECT, queryDesc->estate->es_processed);
"SELECT " UINT64_FORMAT,
queryDesc->estate->es_processed);
/* get object address that intorel_startup saved for us */ /* get object address that intorel_startup saved for us */
address = ((DR_intorel *) dest)->reladdr; address = ((DR_intorel *) dest)->reladdr;
......
...@@ -78,59 +78,6 @@ typedef struct ...@@ -78,59 +78,6 @@ typedef struct
bool supported; bool supported;
} event_trigger_support_data; } event_trigger_support_data;
typedef enum
{
EVENT_TRIGGER_COMMAND_TAG_OK,
EVENT_TRIGGER_COMMAND_TAG_NOT_SUPPORTED,
EVENT_TRIGGER_COMMAND_TAG_NOT_RECOGNIZED
} event_trigger_command_tag_check_result;
/* XXX merge this with ObjectTypeMap? */
static const event_trigger_support_data event_trigger_support[] = {
{"ACCESS METHOD", true},
{"AGGREGATE", true},
{"CAST", true},
{"CONSTRAINT", true},
{"COLLATION", true},
{"CONVERSION", true},
{"DATABASE", false},
{"DOMAIN", true},
{"EXTENSION", true},
{"EVENT TRIGGER", false},
{"FOREIGN DATA WRAPPER", true},
{"FOREIGN TABLE", true},
{"FUNCTION", true},
{"INDEX", true},
{"LANGUAGE", true},
{"MATERIALIZED VIEW", true},
{"OPERATOR", true},
{"OPERATOR CLASS", true},
{"OPERATOR FAMILY", true},
{"POLICY", true},
{"PROCEDURE", true},
{"PUBLICATION", true},
{"ROLE", false},
{"ROUTINE", true},
{"RULE", true},
{"SCHEMA", true},
{"SEQUENCE", true},
{"SERVER", true},
{"STATISTICS", true},
{"SUBSCRIPTION", true},
{"TABLE", true},
{"TABLESPACE", false},
{"TRANSFORM", true},
{"TRIGGER", true},
{"TEXT SEARCH CONFIGURATION", true},
{"TEXT SEARCH DICTIONARY", true},
{"TEXT SEARCH PARSER", true},
{"TEXT SEARCH TEMPLATE", true},
{"TYPE", true},
{"USER MAPPING", true},
{"VIEW", true},
{NULL, false}
};
/* Support for dropped objects */ /* Support for dropped objects */
typedef struct SQLDropObject typedef struct SQLDropObject
{ {
...@@ -150,8 +97,6 @@ typedef struct SQLDropObject ...@@ -150,8 +97,6 @@ typedef struct SQLDropObject
static void AlterEventTriggerOwner_internal(Relation rel, static void AlterEventTriggerOwner_internal(Relation rel,
HeapTuple tup, HeapTuple tup,
Oid newOwnerId); Oid newOwnerId);
static event_trigger_command_tag_check_result check_ddl_tag(const char *tag);
static event_trigger_command_tag_check_result check_table_rewrite_ddl_tag(const char *tag);
static void error_duplicate_filter_variable(const char *defname); static void error_duplicate_filter_variable(const char *defname);
static Datum filter_list_to_array(List *filterlist); static Datum filter_list_to_array(List *filterlist);
static Oid insert_event_trigger_tuple(const char *trigname, const char *eventname, static Oid insert_event_trigger_tuple(const char *trigname, const char *eventname,
...@@ -259,71 +204,23 @@ validate_ddl_tags(const char *filtervar, List *taglist) ...@@ -259,71 +204,23 @@ validate_ddl_tags(const char *filtervar, List *taglist)
foreach(lc, taglist) foreach(lc, taglist)
{ {
const char *tag = strVal(lfirst(lc)); const char *tagstr = strVal(lfirst(lc));
event_trigger_command_tag_check_result result; CommandTag commandTag = GetCommandTagEnum(tagstr);
result = check_ddl_tag(tag); if (commandTag == CMDTAG_UNKNOWN)
if (result == EVENT_TRIGGER_COMMAND_TAG_NOT_RECOGNIZED)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR), (errcode(ERRCODE_SYNTAX_ERROR),
errmsg("filter value \"%s\" not recognized for filter variable \"%s\"", errmsg("filter value \"%s\" not recognized for filter variable \"%s\"",
tag, filtervar))); tagstr, filtervar)));
if (result == EVENT_TRIGGER_COMMAND_TAG_NOT_SUPPORTED) if (!command_tag_event_trigger_ok(commandTag))
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED), (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
/* translator: %s represents an SQL statement name */ /* translator: %s represents an SQL statement name */
errmsg("event triggers are not supported for %s", errmsg("event triggers are not supported for %s",
tag))); tagstr)));
} }
} }
static event_trigger_command_tag_check_result
check_ddl_tag(const char *tag)
{
const char *obtypename;
const event_trigger_support_data *etsd;
/*
* Handle some idiosyncratic special cases.
*/
if (pg_strcasecmp(tag, "CREATE TABLE AS") == 0 ||
pg_strcasecmp(tag, "SELECT INTO") == 0 ||
pg_strcasecmp(tag, "REFRESH MATERIALIZED VIEW") == 0 ||
pg_strcasecmp(tag, "ALTER DEFAULT PRIVILEGES") == 0 ||
pg_strcasecmp(tag, "ALTER LARGE OBJECT") == 0 ||
pg_strcasecmp(tag, "COMMENT") == 0 ||
pg_strcasecmp(tag, "GRANT") == 0 ||
pg_strcasecmp(tag, "REVOKE") == 0 ||
pg_strcasecmp(tag, "DROP OWNED") == 0 ||
pg_strcasecmp(tag, "IMPORT FOREIGN SCHEMA") == 0 ||
pg_strcasecmp(tag, "SECURITY LABEL") == 0)
return EVENT_TRIGGER_COMMAND_TAG_OK;
/*
* Otherwise, command should be CREATE, ALTER, or DROP.
*/
if (pg_strncasecmp(tag, "CREATE ", 7) == 0)
obtypename = tag + 7;
else if (pg_strncasecmp(tag, "ALTER ", 6) == 0)
obtypename = tag + 6;
else if (pg_strncasecmp(tag, "DROP ", 5) == 0)
obtypename = tag + 5;
else
return EVENT_TRIGGER_COMMAND_TAG_NOT_RECOGNIZED;
/*
* ...and the object type should be something recognizable.
*/
for (etsd = event_trigger_support; etsd->obtypename != NULL; etsd++)
if (pg_strcasecmp(etsd->obtypename, obtypename) == 0)
break;
if (etsd->obtypename == NULL)
return EVENT_TRIGGER_COMMAND_TAG_NOT_RECOGNIZED;
if (!etsd->supported)
return EVENT_TRIGGER_COMMAND_TAG_NOT_SUPPORTED;
return EVENT_TRIGGER_COMMAND_TAG_OK;
}
/* /*
* Validate DDL command tags for event table_rewrite. * Validate DDL command tags for event table_rewrite.
*/ */
...@@ -334,29 +231,18 @@ validate_table_rewrite_tags(const char *filtervar, List *taglist) ...@@ -334,29 +231,18 @@ validate_table_rewrite_tags(const char *filtervar, List *taglist)
foreach(lc, taglist) foreach(lc, taglist)
{ {
const char *tag = strVal(lfirst(lc)); const char *tagstr = strVal(lfirst(lc));
event_trigger_command_tag_check_result result; CommandTag commandTag = GetCommandTagEnum(tagstr);
result = check_table_rewrite_ddl_tag(tag); if (!command_tag_table_rewrite_ok(commandTag))
if (result == EVENT_TRIGGER_COMMAND_TAG_NOT_SUPPORTED)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED), (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
/* translator: %s represents an SQL statement name */ /* translator: %s represents an SQL statement name */
errmsg("event triggers are not supported for %s", errmsg("event triggers are not supported for %s",
tag))); tagstr)));
} }
} }
static event_trigger_command_tag_check_result
check_table_rewrite_ddl_tag(const char *tag)
{
if (pg_strcasecmp(tag, "ALTER TABLE") == 0 ||
pg_strcasecmp(tag, "ALTER TYPE") == 0)
return EVENT_TRIGGER_COMMAND_TAG_OK;
return EVENT_TRIGGER_COMMAND_TAG_NOT_SUPPORTED;
}
/* /*
* Complain about a duplicate filter variable. * Complain about a duplicate filter variable.
*/ */
...@@ -663,7 +549,7 @@ get_event_trigger_oid(const char *trigname, bool missing_ok) ...@@ -663,7 +549,7 @@ get_event_trigger_oid(const char *trigname, bool missing_ok)
* tags matching. * tags matching.
*/ */
static bool static bool
filter_event_trigger(const char **tag, EventTriggerCacheItem *item) filter_event_trigger(CommandTag tag, EventTriggerCacheItem *item)
{ {
/* /*
* Filter by session replication role, knowing that we never see disabled * Filter by session replication role, knowing that we never see disabled
...@@ -681,9 +567,7 @@ filter_event_trigger(const char **tag, EventTriggerCacheItem *item) ...@@ -681,9 +567,7 @@ filter_event_trigger(const char **tag, EventTriggerCacheItem *item)
} }
/* Filter by tags, if any were specified. */ /* Filter by tags, if any were specified. */
if (item->ntags != 0 && bsearch(tag, item->tag, if (!bms_is_empty(item->tagset) && !bms_is_member(tag, item->tagset))
item->ntags, sizeof(char *),
pg_qsort_strcmp) == NULL)
return false; return false;
/* if we reach that point, we're not filtering out this item */ /* if we reach that point, we're not filtering out this item */
...@@ -700,7 +584,7 @@ EventTriggerCommonSetup(Node *parsetree, ...@@ -700,7 +584,7 @@ EventTriggerCommonSetup(Node *parsetree,
EventTriggerEvent event, const char *eventstr, EventTriggerEvent event, const char *eventstr,
EventTriggerData *trigdata) EventTriggerData *trigdata)
{ {
const char *tag; CommandTag tag;
List *cachelist; List *cachelist;
ListCell *lc; ListCell *lc;
List *runlist = NIL; List *runlist = NIL;
...@@ -716,25 +600,25 @@ EventTriggerCommonSetup(Node *parsetree, ...@@ -716,25 +600,25 @@ EventTriggerCommonSetup(Node *parsetree,
* *
* If this cross-check fails for you, you probably need to either adjust * If this cross-check fails for you, you probably need to either adjust
* standard_ProcessUtility() not to invoke event triggers for the command * standard_ProcessUtility() not to invoke event triggers for the command
* type in question, or you need to adjust check_ddl_tag to accept the * type in question, or you need to adjust event_trigger_ok to accept the
* relevant command tag. * relevant command tag.
*/ */
#ifdef USE_ASSERT_CHECKING #ifdef USE_ASSERT_CHECKING
{ {
const char *dbgtag; CommandTag dbgtag;
dbgtag = CreateCommandTag(parsetree); dbgtag = CreateCommandTag(parsetree);
if (event == EVT_DDLCommandStart || if (event == EVT_DDLCommandStart ||
event == EVT_DDLCommandEnd || event == EVT_DDLCommandEnd ||
event == EVT_SQLDrop) event == EVT_SQLDrop)
{ {
if (check_ddl_tag(dbgtag) != EVENT_TRIGGER_COMMAND_TAG_OK) if (!command_tag_event_trigger_ok(dbgtag))
elog(ERROR, "unexpected command tag \"%s\"", dbgtag); elog(ERROR, "unexpected command tag \"%s\"", GetCommandTagName(dbgtag));
} }
else if (event == EVT_TableRewrite) else if (event == EVT_TableRewrite)
{ {
if (check_table_rewrite_ddl_tag(dbgtag) != EVENT_TRIGGER_COMMAND_TAG_OK) if (!command_tag_table_rewrite_ok(dbgtag))
elog(ERROR, "unexpected command tag \"%s\"", dbgtag); elog(ERROR, "unexpected command tag \"%s\"", GetCommandTagName(dbgtag));
} }
} }
#endif #endif
...@@ -758,7 +642,7 @@ EventTriggerCommonSetup(Node *parsetree, ...@@ -758,7 +642,7 @@ EventTriggerCommonSetup(Node *parsetree,
{ {
EventTriggerCacheItem *item = lfirst(lc); EventTriggerCacheItem *item = lfirst(lc);
if (filter_event_trigger(&tag, item)) if (filter_event_trigger(tag, item))
{ {
/* We must plan to fire this trigger. */ /* We must plan to fire this trigger. */
runlist = lappend_oid(runlist, item->fnoid); runlist = lappend_oid(runlist, item->fnoid);
...@@ -2136,7 +2020,7 @@ pg_event_trigger_ddl_commands(PG_FUNCTION_ARGS) ...@@ -2136,7 +2020,7 @@ pg_event_trigger_ddl_commands(PG_FUNCTION_ARGS)
/* objsubid */ /* objsubid */
values[i++] = Int32GetDatum(addr.objectSubId); values[i++] = Int32GetDatum(addr.objectSubId);
/* command tag */ /* command tag */
values[i++] = CStringGetTextDatum(CreateCommandTag(cmd->parsetree)); values[i++] = CStringGetTextDatum(CreateCommandName(cmd->parsetree));
/* object_type */ /* object_type */
values[i++] = CStringGetTextDatum(type); values[i++] = CStringGetTextDatum(type);
/* schema */ /* schema */
...@@ -2161,7 +2045,7 @@ pg_event_trigger_ddl_commands(PG_FUNCTION_ARGS) ...@@ -2161,7 +2045,7 @@ pg_event_trigger_ddl_commands(PG_FUNCTION_ARGS)
/* objsubid */ /* objsubid */
nulls[i++] = true; nulls[i++] = true;
/* command tag */ /* command tag */
values[i++] = CStringGetTextDatum(CreateCommandTag(cmd->parsetree)); values[i++] = CStringGetTextDatum(CreateCommandName(cmd->parsetree));
/* object_type */ /* object_type */
values[i++] = CStringGetTextDatum(stringify_adefprivs_objtype(cmd->d.defprivs.objtype)); values[i++] = CStringGetTextDatum(stringify_adefprivs_objtype(cmd->d.defprivs.objtype));
/* schema */ /* schema */
......
...@@ -136,7 +136,7 @@ SetMatViewPopulatedState(Relation relation, bool newstate) ...@@ -136,7 +136,7 @@ SetMatViewPopulatedState(Relation relation, bool newstate)
*/ */
ObjectAddress ObjectAddress
ExecRefreshMatView(RefreshMatViewStmt *stmt, const char *queryString, ExecRefreshMatView(RefreshMatViewStmt *stmt, const char *queryString,
ParamListInfo params, char *completionTag) ParamListInfo params, QueryCompletion *qc)
{ {
Oid matviewOid; Oid matviewOid;
Relation matviewRel; Relation matviewRel;
......
...@@ -106,7 +106,7 @@ PerformCursorOpen(ParseState *pstate, DeclareCursorStmt *cstmt, ParamListInfo pa ...@@ -106,7 +106,7 @@ PerformCursorOpen(ParseState *pstate, DeclareCursorStmt *cstmt, ParamListInfo pa
PortalDefineQuery(portal, PortalDefineQuery(portal,
NULL, NULL,
queryString, queryString,
"SELECT", /* cursor's query is always a SELECT */ CMDTAG_SELECT, /* cursor's query is always a SELECT */
list_make1(plan), list_make1(plan),
NULL); NULL);
...@@ -160,15 +160,14 @@ PerformCursorOpen(ParseState *pstate, DeclareCursorStmt *cstmt, ParamListInfo pa ...@@ -160,15 +160,14 @@ PerformCursorOpen(ParseState *pstate, DeclareCursorStmt *cstmt, ParamListInfo pa
* *
* stmt: parsetree node for command * stmt: parsetree node for command
* dest: where to send results * dest: where to send results
* completionTag: points to a buffer of size COMPLETION_TAG_BUFSIZE * qc: where to store a command completion status data.
* in which to store a command completion status string.
* *
* completionTag may be NULL if caller doesn't want a status string. * qc may be NULL if caller doesn't want status data.
*/ */
void void
PerformPortalFetch(FetchStmt *stmt, PerformPortalFetch(FetchStmt *stmt,
DestReceiver *dest, DestReceiver *dest,
char *completionTag) QueryCompletion *qc)
{ {
Portal portal; Portal portal;
uint64 nprocessed; uint64 nprocessed;
...@@ -203,10 +202,9 @@ PerformPortalFetch(FetchStmt *stmt, ...@@ -203,10 +202,9 @@ PerformPortalFetch(FetchStmt *stmt,
dest); dest);
/* Return command status if wanted */ /* Return command status if wanted */
if (completionTag) if (qc)
snprintf(completionTag, COMPLETION_TAG_BUFSIZE, "%s " UINT64_FORMAT, SetQueryCompletion(qc, stmt->ismove ? CMDTAG_MOVE : CMDTAG_FETCH,
stmt->ismove ? "MOVE" : "FETCH", nprocessed);
nprocessed);
} }
/* /*
......
...@@ -187,7 +187,7 @@ void ...@@ -187,7 +187,7 @@ void
ExecuteQuery(ParseState *pstate, ExecuteQuery(ParseState *pstate,
ExecuteStmt *stmt, IntoClause *intoClause, ExecuteStmt *stmt, IntoClause *intoClause,
ParamListInfo params, ParamListInfo params,
DestReceiver *dest, char *completionTag) DestReceiver *dest, QueryCompletion *qc)
{ {
PreparedStatement *entry; PreparedStatement *entry;
CachedPlan *cplan; CachedPlan *cplan;
...@@ -288,7 +288,7 @@ ExecuteQuery(ParseState *pstate, ...@@ -288,7 +288,7 @@ ExecuteQuery(ParseState *pstate,
*/ */
PortalStart(portal, paramLI, eflags, GetActiveSnapshot()); PortalStart(portal, paramLI, eflags, GetActiveSnapshot());
(void) PortalRun(portal, count, false, true, dest, dest, completionTag); (void) PortalRun(portal, count, false, true, dest, dest, qc);
PortalDrop(portal, false); PortalDrop(portal, false);
......
...@@ -787,11 +787,11 @@ ExecCheckXactReadOnly(PlannedStmt *plannedstmt) ...@@ -787,11 +787,11 @@ ExecCheckXactReadOnly(PlannedStmt *plannedstmt)
if (isTempNamespace(get_rel_namespace(rte->relid))) if (isTempNamespace(get_rel_namespace(rte->relid)))
continue; continue;
PreventCommandIfReadOnly(CreateCommandTag((Node *) plannedstmt)); PreventCommandIfReadOnly(CreateCommandName((Node *) plannedstmt));
} }
if (plannedstmt->commandType != CMD_SELECT || plannedstmt->hasModifyingCTE) if (plannedstmt->commandType != CMD_SELECT || plannedstmt->hasModifyingCTE)
PreventCommandIfParallelMode(CreateCommandTag((Node *) plannedstmt)); PreventCommandIfParallelMode(CreateCommandName((Node *) plannedstmt));
} }
......
...@@ -530,7 +530,7 @@ init_execution_state(List *queryTree_list, ...@@ -530,7 +530,7 @@ init_execution_state(List *queryTree_list,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED), (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
/* translator: %s is a SQL statement name */ /* translator: %s is a SQL statement name */
errmsg("%s is not allowed in a SQL function", errmsg("%s is not allowed in a SQL function",
CreateCommandTag(stmt->utilityStmt)))); CreateCommandName(stmt->utilityStmt))));
} }
if (fcache->readonly_func && !CommandIsReadOnly(stmt)) if (fcache->readonly_func && !CommandIsReadOnly(stmt))
...@@ -538,7 +538,7 @@ init_execution_state(List *queryTree_list, ...@@ -538,7 +538,7 @@ init_execution_state(List *queryTree_list,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED), (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
/* translator: %s is a SQL statement name */ /* translator: %s is a SQL statement name */
errmsg("%s is not allowed in a non-volatile function", errmsg("%s is not allowed in a non-volatile function",
CreateCommandTag((Node *) stmt)))); CreateCommandName((Node *) stmt))));
/* OK, build the execution_state for this query */ /* OK, build the execution_state for this query */
newes = (execution_state *) palloc(sizeof(execution_state)); newes = (execution_state *) palloc(sizeof(execution_state));
......
...@@ -1338,7 +1338,7 @@ SPI_cursor_open_internal(const char *name, SPIPlanPtr plan, ...@@ -1338,7 +1338,7 @@ SPI_cursor_open_internal(const char *name, SPIPlanPtr plan,
(errcode(ERRCODE_INVALID_CURSOR_DEFINITION), (errcode(ERRCODE_INVALID_CURSOR_DEFINITION),
/* translator: %s is name of a SQL command, eg INSERT */ /* translator: %s is name of a SQL command, eg INSERT */
errmsg("cannot open %s query as cursor", errmsg("cannot open %s query as cursor",
plansource->commandTag))); GetCommandTagName(plansource->commandTag))));
} }
Assert(list_length(plan->plancache_list) == 1); Assert(list_length(plan->plancache_list) == 1);
...@@ -1469,7 +1469,7 @@ SPI_cursor_open_internal(const char *name, SPIPlanPtr plan, ...@@ -1469,7 +1469,7 @@ SPI_cursor_open_internal(const char *name, SPIPlanPtr plan,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED), (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
/* translator: %s is a SQL statement name */ /* translator: %s is a SQL statement name */
errmsg("%s is not allowed in a non-volatile function", errmsg("%s is not allowed in a non-volatile function",
CreateCommandTag((Node *) pstmt)))); CreateCommandName((Node *) pstmt))));
} }
} }
...@@ -2255,7 +2255,7 @@ _SPI_execute_plan(SPIPlanPtr plan, ParamListInfo paramLI, ...@@ -2255,7 +2255,7 @@ _SPI_execute_plan(SPIPlanPtr plan, ParamListInfo paramLI,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED), (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
/* translator: %s is a SQL statement name */ /* translator: %s is a SQL statement name */
errmsg("%s is not allowed in a non-volatile function", errmsg("%s is not allowed in a non-volatile function",
CreateCommandTag((Node *) stmt)))); CreateCommandName((Node *) stmt))));
/* /*
* If not read-only mode, advance the command counter before each * If not read-only mode, advance the command counter before each
...@@ -2291,8 +2291,8 @@ _SPI_execute_plan(SPIPlanPtr plan, ParamListInfo paramLI, ...@@ -2291,8 +2291,8 @@ _SPI_execute_plan(SPIPlanPtr plan, ParamListInfo paramLI,
} }
else else
{ {
char completionTag[COMPLETION_TAG_BUFSIZE];
ProcessUtilityContext context; ProcessUtilityContext context;
QueryCompletion qc;
/* /*
* If the SPI context is atomic, or we are asked to manage * If the SPI context is atomic, or we are asked to manage
...@@ -2306,13 +2306,14 @@ _SPI_execute_plan(SPIPlanPtr plan, ParamListInfo paramLI, ...@@ -2306,13 +2306,14 @@ _SPI_execute_plan(SPIPlanPtr plan, ParamListInfo paramLI,
else else
context = PROCESS_UTILITY_QUERY_NONATOMIC; context = PROCESS_UTILITY_QUERY_NONATOMIC;
InitializeQueryCompletion(&qc);
ProcessUtility(stmt, ProcessUtility(stmt,
plansource->query_string, plansource->query_string,
context, context,
paramLI, paramLI,
_SPI_current->queryEnv, _SPI_current->queryEnv,
dest, dest,
completionTag); &qc);
/* Update "processed" if stmt returned tuples */ /* Update "processed" if stmt returned tuples */
if (_SPI_current->tuptable) if (_SPI_current->tuptable)
...@@ -2328,9 +2329,8 @@ _SPI_execute_plan(SPIPlanPtr plan, ParamListInfo paramLI, ...@@ -2328,9 +2329,8 @@ _SPI_execute_plan(SPIPlanPtr plan, ParamListInfo paramLI,
{ {
CreateTableAsStmt *ctastmt = (CreateTableAsStmt *) stmt->utilityStmt; CreateTableAsStmt *ctastmt = (CreateTableAsStmt *) stmt->utilityStmt;
if (strncmp(completionTag, "SELECT ", 7) == 0) if (qc.commandTag == CMDTAG_SELECT)
_SPI_current->processed = _SPI_current->processed = qc.nprocessed;
pg_strtouint64(completionTag + 7, NULL, 10);
else else
{ {
/* /*
...@@ -2351,9 +2351,8 @@ _SPI_execute_plan(SPIPlanPtr plan, ParamListInfo paramLI, ...@@ -2351,9 +2351,8 @@ _SPI_execute_plan(SPIPlanPtr plan, ParamListInfo paramLI,
} }
else if (IsA(stmt->utilityStmt, CopyStmt)) else if (IsA(stmt->utilityStmt, CopyStmt))
{ {
Assert(strncmp(completionTag, "COPY ", 5) == 0); Assert(qc.commandTag == CMDTAG_COPY);
_SPI_current->processed = pg_strtouint64(completionTag + 5, _SPI_current->processed = qc.nprocessed;
NULL, 10);
} }
} }
......
...@@ -100,7 +100,7 @@ LogicalDecodingProcessRecord(LogicalDecodingContext *ctx, XLogReaderState *recor ...@@ -100,7 +100,7 @@ LogicalDecodingProcessRecord(LogicalDecodingContext *ctx, XLogReaderState *recor
buf.record = record; buf.record = record;
/* cast so we get a warning when new rmgrs are added */ /* cast so we get a warning when new rmgrs are added */
switch ((RmgrIds) XLogRecGetRmid(record)) switch ((RmgrId) XLogRecGetRmid(record))
{ {
/* /*
* Rmgrs we care about for logical decoding. Add new rmgrs in * Rmgrs we care about for logical decoding. Add new rmgrs in
......
...@@ -1074,8 +1074,11 @@ CreateReplicationSlot(CreateReplicationSlotCmd *cmd) ...@@ -1074,8 +1074,11 @@ CreateReplicationSlot(CreateReplicationSlotCmd *cmd)
static void static void
DropReplicationSlot(DropReplicationSlotCmd *cmd) DropReplicationSlot(DropReplicationSlotCmd *cmd)
{ {
QueryCompletion qc;
ReplicationSlotDrop(cmd->slotname, !cmd->wait); ReplicationSlotDrop(cmd->slotname, !cmd->wait);
EndCommand("DROP_REPLICATION_SLOT", DestRemote); SetQueryCompletion(&qc, CMDTAG_DROP_REPLICATION_SLOT, 0);
EndCommand(&qc, DestRemote, false);
} }
/* /*
...@@ -1086,6 +1089,7 @@ static void ...@@ -1086,6 +1089,7 @@ static void
StartLogicalReplication(StartReplicationCmd *cmd) StartLogicalReplication(StartReplicationCmd *cmd)
{ {
StringInfoData buf; StringInfoData buf;
QueryCompletion qc;
/* make sure that our requirements are still fulfilled */ /* make sure that our requirements are still fulfilled */
CheckLogicalDecodingRequirements(); CheckLogicalDecodingRequirements();
...@@ -1160,7 +1164,8 @@ StartLogicalReplication(StartReplicationCmd *cmd) ...@@ -1160,7 +1164,8 @@ StartLogicalReplication(StartReplicationCmd *cmd)
WalSndSetState(WALSNDSTATE_STARTUP); WalSndSetState(WALSNDSTATE_STARTUP);
/* Get out of COPY mode (CommandComplete). */ /* Get out of COPY mode (CommandComplete). */
EndCommand("COPY 0", DestRemote); SetQueryCompletion(&qc, CMDTAG_COPY, 0);
EndCommand(&qc, DestRemote, false);
} }
/* /*
...@@ -1464,6 +1469,7 @@ exec_replication_command(const char *cmd_string) ...@@ -1464,6 +1469,7 @@ exec_replication_command(const char *cmd_string)
Node *cmd_node; Node *cmd_node;
MemoryContext cmd_context; MemoryContext cmd_context;
MemoryContext old_context; MemoryContext old_context;
QueryCompletion qc;
/* /*
* If WAL sender has been told that shutdown is getting close, switch its * If WAL sender has been told that shutdown is getting close, switch its
...@@ -1614,7 +1620,8 @@ exec_replication_command(const char *cmd_string) ...@@ -1614,7 +1620,8 @@ exec_replication_command(const char *cmd_string)
MemoryContextDelete(cmd_context); MemoryContextDelete(cmd_context);
/* Send CommandComplete message */ /* Send CommandComplete message */
EndCommand("SELECT", DestRemote); SetQueryCompletion(&qc, CMDTAG_SELECT, 0);
EndCommand(&qc, DestRemote, true);
/* Report to pgstat that this process is now idle */ /* Report to pgstat that this process is now idle */
pgstat_report_activity(STATE_IDLE, NULL); pgstat_report_activity(STATE_IDLE, NULL);
...@@ -2867,8 +2874,11 @@ WalSndDone(WalSndSendDataCallback send_data) ...@@ -2867,8 +2874,11 @@ WalSndDone(WalSndSendDataCallback send_data)
if (WalSndCaughtUp && sentPtr == replicatedPtr && if (WalSndCaughtUp && sentPtr == replicatedPtr &&
!pq_is_send_pending()) !pq_is_send_pending())
{ {
QueryCompletion qc;
/* Inform the standby that XLOG streaming is done */ /* Inform the standby that XLOG streaming is done */
EndCommand("COPY 0", DestRemote); SetQueryCompletion(&qc, CMDTAG_COPY, 0);
EndCommand(&qc, DestRemote, false);
pq_flush(); pq_flush();
proc_exit(0); proc_exit(0);
......
...@@ -13,6 +13,7 @@ top_builddir = ../../.. ...@@ -13,6 +13,7 @@ top_builddir = ../../..
include $(top_builddir)/src/Makefile.global include $(top_builddir)/src/Makefile.global
OBJS = \ OBJS = \
cmdtag.o \
dest.o \ dest.o \
fastpath.o \ fastpath.o \
postgres.o \ postgres.o \
......
/*-------------------------------------------------------------------------
*
* cmdtag.c
* Data and routines for commandtag names and enumeration.
*
* Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* src/backend/tcop/cmdtag.c
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
#include "miscadmin.h"
#include "tcop/cmdtag.h"
typedef struct CommandTagBehavior
{
const char *name;
const bool event_trigger_ok;
const bool table_rewrite_ok;
const bool display_rowcount;
} CommandTagBehavior;
#define PG_CMDTAG(tag, name, evtrgok, rwrok, rowcnt) \
{ name, evtrgok, rwrok, rowcnt },
const CommandTagBehavior tag_behavior[COMMAND_TAG_NEXTTAG] = {
#include "tcop/cmdtaglist.h"
};
#undef PG_CMDTAG
void
InitializeQueryCompletion(QueryCompletion *qc)
{
qc->commandTag = CMDTAG_UNKNOWN;
qc->nprocessed = 0;
}
const char *
GetCommandTagName(CommandTag commandTag)
{
return tag_behavior[commandTag].name;
}
bool
command_tag_display_rowcount(CommandTag commandTag)
{
return tag_behavior[commandTag].display_rowcount;
}
bool
command_tag_event_trigger_ok(CommandTag commandTag)
{
return tag_behavior[commandTag].event_trigger_ok;
}
bool
command_tag_table_rewrite_ok(CommandTag commandTag)
{
return tag_behavior[commandTag].table_rewrite_ok;
}
/*
* Search CommandTag by name
*
* Returns CommandTag, or CMDTAG_UNKNOWN if not recognized
*/
CommandTag
GetCommandTagEnum(const char *commandname)
{
const CommandTagBehavior *base,
*last,
*position;
int result;
if (commandname == NULL || *commandname == '\0')
return CMDTAG_UNKNOWN;
base = tag_behavior;
last = tag_behavior + lengthof(tag_behavior) - 1;
while (last >= base)
{
position = base + ((last - base) >> 1);
result = pg_strcasecmp(commandname, position->name);
if (result == 0)
return (CommandTag) (position - tag_behavior);
else if (result < 0)
last = position - 1;
else
base = position + 1;
}
return CMDTAG_UNKNOWN;
}
...@@ -100,7 +100,7 @@ DestReceiver *None_Receiver = (DestReceiver *) &donothingDR; ...@@ -100,7 +100,7 @@ DestReceiver *None_Receiver = (DestReceiver *) &donothingDR;
* ---------------- * ----------------
*/ */
void void
BeginCommand(const char *commandTag, CommandDest dest) BeginCommand(CommandTag commandTag, CommandDest dest)
{ {
/* Nothing to do at present */ /* Nothing to do at present */
} }
...@@ -163,8 +163,12 @@ CreateDestReceiver(CommandDest dest) ...@@ -163,8 +163,12 @@ CreateDestReceiver(CommandDest dest)
* ---------------- * ----------------
*/ */
void void
EndCommand(const char *commandTag, CommandDest dest) EndCommand(const QueryCompletion *qc, CommandDest dest, bool force_undecorated_output)
{ {
char completionTag[COMPLETION_TAG_BUFSIZE];
CommandTag tag;
const char *tagname;
switch (dest) switch (dest)
{ {
case DestRemote: case DestRemote:
...@@ -172,11 +176,27 @@ EndCommand(const char *commandTag, CommandDest dest) ...@@ -172,11 +176,27 @@ EndCommand(const char *commandTag, CommandDest dest)
case DestRemoteSimple: case DestRemoteSimple:
/* /*
* We assume the commandTag is plain ASCII and therefore requires * We assume the tagname is plain ASCII and therefore requires no
* no encoding conversion. * encoding conversion.
*
* We no longer display LastOid, but to preserve the wire
* protocol, we write InvalidOid where the LastOid used to be
* written.
*
* All cases where LastOid was written also write nprocessed
* count, so just Assert that rather than having an extra test.
*/ */
pq_putmessage('C', commandTag, strlen(commandTag) + 1); tag = qc->commandTag;
break; tagname = GetCommandTagName(tag);
if (command_tag_display_rowcount(tag) && !force_undecorated_output)
snprintf(completionTag, COMPLETION_TAG_BUFSIZE,
tag == CMDTAG_INSERT ?
"%s 0 " UINT64_FORMAT : "%s " UINT64_FORMAT,
tagname, qc->nprocessed);
else
snprintf(completionTag, COMPLETION_TAG_BUFSIZE, "%s", tagname);
pq_putmessage('C', completionTag, strlen(completionTag) + 1);
case DestNone: case DestNone:
case DestDebug: case DestDebug:
......
...@@ -1064,8 +1064,8 @@ exec_simple_query(const char *query_string) ...@@ -1064,8 +1064,8 @@ exec_simple_query(const char *query_string)
{ {
RawStmt *parsetree = lfirst_node(RawStmt, parsetree_item); RawStmt *parsetree = lfirst_node(RawStmt, parsetree_item);
bool snapshot_set = false; bool snapshot_set = false;
const char *commandTag; CommandTag commandTag;
char completionTag[COMPLETION_TAG_BUFSIZE]; QueryCompletion qc;
MemoryContext per_parsetree_context = NULL; MemoryContext per_parsetree_context = NULL;
List *querytree_list, List *querytree_list,
*plantree_list; *plantree_list;
...@@ -1081,7 +1081,7 @@ exec_simple_query(const char *query_string) ...@@ -1081,7 +1081,7 @@ exec_simple_query(const char *query_string)
*/ */
commandTag = CreateCommandTag(parsetree->stmt); commandTag = CreateCommandTag(parsetree->stmt);
set_ps_display(commandTag, false); set_ps_display(GetCommandTagName(commandTag), false);
BeginCommand(commandTag, dest); BeginCommand(commandTag, dest);
...@@ -1239,7 +1239,7 @@ exec_simple_query(const char *query_string) ...@@ -1239,7 +1239,7 @@ exec_simple_query(const char *query_string)
true, true,
receiver, receiver,
receiver, receiver,
completionTag); &qc);
receiver->rDestroy(receiver); receiver->rDestroy(receiver);
...@@ -1290,7 +1290,7 @@ exec_simple_query(const char *query_string) ...@@ -1290,7 +1290,7 @@ exec_simple_query(const char *query_string)
* command the client sent, regardless of rewriting. (But a command * command the client sent, regardless of rewriting. (But a command
* aborted by error will not send an EndCommand report at all.) * 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. */ /* Now we may drop the per-parsetree context, if one was created. */
if (per_parsetree_context) if (per_parsetree_context)
...@@ -1352,7 +1352,6 @@ exec_parse_message(const char *query_string, /* string to execute */ ...@@ -1352,7 +1352,6 @@ exec_parse_message(const char *query_string, /* string to execute */
MemoryContext oldcontext; MemoryContext oldcontext;
List *parsetree_list; List *parsetree_list;
RawStmt *raw_parse_tree; RawStmt *raw_parse_tree;
const char *commandTag;
List *querytree_list; List *querytree_list;
CachedPlanSource *psrc; CachedPlanSource *psrc;
bool is_named; bool is_named;
...@@ -1438,11 +1437,6 @@ exec_parse_message(const char *query_string, /* string to execute */ ...@@ -1438,11 +1437,6 @@ exec_parse_message(const char *query_string, /* string to execute */
raw_parse_tree = linitial_node(RawStmt, parsetree_list); 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 * If we are in an aborted transaction, reject all commands except
* COMMIT/ROLLBACK. It is important that this test occur before we * 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 */ ...@@ -1463,7 +1457,8 @@ exec_parse_message(const char *query_string, /* string to execute */
* Create the CachedPlanSource before we do parse analysis, since it * Create the CachedPlanSource before we do parse analysis, since it
* needs to see the unmodified raw parse tree. * 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. * Set up a snapshot if parse analysis will need one.
...@@ -1514,8 +1509,8 @@ exec_parse_message(const char *query_string, /* string to execute */ ...@@ -1514,8 +1509,8 @@ exec_parse_message(const char *query_string, /* string to execute */
{ {
/* Empty input string. This is legal. */ /* Empty input string. This is legal. */
raw_parse_tree = NULL; raw_parse_tree = NULL;
commandTag = NULL; psrc = CreateCachedPlan(raw_parse_tree, query_string,
psrc = CreateCachedPlan(raw_parse_tree, query_string, commandTag); CMDTAG_UNKNOWN);
querytree_list = NIL; querytree_list = NIL;
} }
...@@ -2031,7 +2026,7 @@ exec_execute_message(const char *portal_name, long max_rows) ...@@ -2031,7 +2026,7 @@ exec_execute_message(const char *portal_name, long max_rows)
DestReceiver *receiver; DestReceiver *receiver;
Portal portal; Portal portal;
bool completed; bool completed;
char completionTag[COMPLETION_TAG_BUFSIZE]; QueryCompletion qc;
const char *sourceText; const char *sourceText;
const char *prepStmtName; const char *prepStmtName;
ParamListInfo portalParams; ParamListInfo portalParams;
...@@ -2058,7 +2053,7 @@ exec_execute_message(const char *portal_name, long max_rows) ...@@ -2058,7 +2053,7 @@ exec_execute_message(const char *portal_name, long max_rows)
* If the original query was a null string, just return * If the original query was a null string, just return
* EmptyQueryResponse. * EmptyQueryResponse.
*/ */
if (portal->commandTag == NULL) if (portal->commandTag == CMDTAG_UNKNOWN)
{ {
Assert(portal->stmts == NIL); Assert(portal->stmts == NIL);
NullCommand(dest); NullCommand(dest);
...@@ -2104,7 +2099,7 @@ exec_execute_message(const char *portal_name, long max_rows) ...@@ -2104,7 +2099,7 @@ exec_execute_message(const char *portal_name, long max_rows)
pgstat_report_activity(STATE_RUNNING, sourceText); pgstat_report_activity(STATE_RUNNING, sourceText);
set_ps_display(portal->commandTag, false); set_ps_display(GetCommandTagName(portal->commandTag), false);
if (save_log_statement_stats) if (save_log_statement_stats)
ResetUsage(); ResetUsage();
...@@ -2185,7 +2180,7 @@ exec_execute_message(const char *portal_name, long max_rows) ...@@ -2185,7 +2180,7 @@ exec_execute_message(const char *portal_name, long max_rows)
!execute_is_fetch && max_rows == FETCH_ALL, !execute_is_fetch && max_rows == FETCH_ALL,
receiver, receiver,
receiver, receiver,
completionTag); &qc);
receiver->rDestroy(receiver); receiver->rDestroy(receiver);
...@@ -2218,7 +2213,7 @@ exec_execute_message(const char *portal_name, long max_rows) ...@@ -2218,7 +2213,7 @@ exec_execute_message(const char *portal_name, long max_rows)
} }
/* Send appropriate CommandComplete to client */ /* Send appropriate CommandComplete to client */
EndCommand(completionTag, dest); EndCommand(&qc, dest, false);
} }
else else
{ {
......
...@@ -40,7 +40,7 @@ static void ProcessQuery(PlannedStmt *plan, ...@@ -40,7 +40,7 @@ static void ProcessQuery(PlannedStmt *plan,
ParamListInfo params, ParamListInfo params,
QueryEnvironment *queryEnv, QueryEnvironment *queryEnv,
DestReceiver *dest, DestReceiver *dest,
char *completionTag); QueryCompletion *qc);
static void FillPortalStore(Portal portal, bool isTopLevel); static void FillPortalStore(Portal portal, bool isTopLevel);
static uint64 RunFromStore(Portal portal, ScanDirection direction, uint64 count, static uint64 RunFromStore(Portal portal, ScanDirection direction, uint64 count,
DestReceiver *dest); DestReceiver *dest);
...@@ -48,11 +48,11 @@ static uint64 PortalRunSelect(Portal portal, bool forward, long count, ...@@ -48,11 +48,11 @@ static uint64 PortalRunSelect(Portal portal, bool forward, long count,
DestReceiver *dest); DestReceiver *dest);
static void PortalRunUtility(Portal portal, PlannedStmt *pstmt, static void PortalRunUtility(Portal portal, PlannedStmt *pstmt,
bool isTopLevel, bool setHoldSnapshot, bool isTopLevel, bool setHoldSnapshot,
DestReceiver *dest, char *completionTag); DestReceiver *dest, QueryCompletion *qc);
static void PortalRunMulti(Portal portal, static void PortalRunMulti(Portal portal,
bool isTopLevel, bool setHoldSnapshot, bool isTopLevel, bool setHoldSnapshot,
DestReceiver *dest, DestReceiver *altdest, DestReceiver *dest, DestReceiver *altdest,
char *completionTag); QueryCompletion *qc);
static uint64 DoPortalRunFetch(Portal portal, static uint64 DoPortalRunFetch(Portal portal,
FetchDirection fdirection, FetchDirection fdirection,
long count, long count,
...@@ -125,10 +125,9 @@ FreeQueryDesc(QueryDesc *qdesc) ...@@ -125,10 +125,9 @@ FreeQueryDesc(QueryDesc *qdesc)
* sourceText: the source text of the query * sourceText: the source text of the query
* params: any parameters needed * params: any parameters needed
* dest: where to send results * dest: where to send results
* completionTag: points to a buffer of size COMPLETION_TAG_BUFSIZE * qc: where to store the command completion status data.
* in which to store a command completion status string.
* *
* completionTag may be NULL if caller doesn't want a status string. * qc may be NULL if caller doesn't want a status string.
* *
* Must be called in a memory context that will be reset or deleted on * Must be called in a memory context that will be reset or deleted on
* error; otherwise the executor's memory usage will be leaked. * error; otherwise the executor's memory usage will be leaked.
...@@ -139,7 +138,7 @@ ProcessQuery(PlannedStmt *plan, ...@@ -139,7 +138,7 @@ ProcessQuery(PlannedStmt *plan,
ParamListInfo params, ParamListInfo params,
QueryEnvironment *queryEnv, QueryEnvironment *queryEnv,
DestReceiver *dest, DestReceiver *dest,
char *completionTag) QueryCompletion *qc)
{ {
QueryDesc *queryDesc; QueryDesc *queryDesc;
...@@ -161,38 +160,26 @@ ProcessQuery(PlannedStmt *plan, ...@@ -161,38 +160,26 @@ ProcessQuery(PlannedStmt *plan,
ExecutorRun(queryDesc, ForwardScanDirection, 0L, true); ExecutorRun(queryDesc, ForwardScanDirection, 0L, true);
/* /*
* Build command completion status string, if caller wants one. * Build command completion status data, if caller wants one.
*/ */
if (completionTag) if (qc)
{ {
Oid lastOid;
switch (queryDesc->operation) switch (queryDesc->operation)
{ {
case CMD_SELECT: case CMD_SELECT:
snprintf(completionTag, COMPLETION_TAG_BUFSIZE, SetQueryCompletion(qc, CMDTAG_SELECT, queryDesc->estate->es_processed);
"SELECT " UINT64_FORMAT,
queryDesc->estate->es_processed);
break; break;
case CMD_INSERT: case CMD_INSERT:
/* lastoid doesn't exist anymore */ SetQueryCompletion(qc, CMDTAG_INSERT, queryDesc->estate->es_processed);
lastOid = InvalidOid;
snprintf(completionTag, COMPLETION_TAG_BUFSIZE,
"INSERT %u " UINT64_FORMAT,
lastOid, queryDesc->estate->es_processed);
break; break;
case CMD_UPDATE: case CMD_UPDATE:
snprintf(completionTag, COMPLETION_TAG_BUFSIZE, SetQueryCompletion(qc, CMDTAG_UPDATE, queryDesc->estate->es_processed);
"UPDATE " UINT64_FORMAT,
queryDesc->estate->es_processed);
break; break;
case CMD_DELETE: case CMD_DELETE:
snprintf(completionTag, COMPLETION_TAG_BUFSIZE, SetQueryCompletion(qc, CMDTAG_DELETE, queryDesc->estate->es_processed);
"DELETE " UINT64_FORMAT,
queryDesc->estate->es_processed);
break; break;
default: default:
strcpy(completionTag, "???"); SetQueryCompletion(qc, CMDTAG_UNKNOWN, queryDesc->estate->es_processed);
break; break;
} }
} }
...@@ -675,9 +662,8 @@ PortalSetResultFormat(Portal portal, int nFormats, int16 *formats) ...@@ -675,9 +662,8 @@ PortalSetResultFormat(Portal portal, int nFormats, int16 *formats)
* *
* altdest: where to send output of non-primary queries * altdest: where to send output of non-primary queries
* *
* completionTag: points to a buffer of size COMPLETION_TAG_BUFSIZE * qc: where to store command completion status data.
* in which to store a command completion status string. * May be NULL if caller doesn't want status data.
* May be NULL if caller doesn't want a status string.
* *
* Returns true if the portal's execution is complete, false if it was * Returns true if the portal's execution is complete, false if it was
* suspended due to exhaustion of the count parameter. * suspended due to exhaustion of the count parameter.
...@@ -685,7 +671,7 @@ PortalSetResultFormat(Portal portal, int nFormats, int16 *formats) ...@@ -685,7 +671,7 @@ PortalSetResultFormat(Portal portal, int nFormats, int16 *formats)
bool bool
PortalRun(Portal portal, long count, bool isTopLevel, bool run_once, PortalRun(Portal portal, long count, bool isTopLevel, bool run_once,
DestReceiver *dest, DestReceiver *altdest, DestReceiver *dest, DestReceiver *altdest,
char *completionTag) QueryCompletion *qc)
{ {
bool result; bool result;
uint64 nprocessed; uint64 nprocessed;
...@@ -700,9 +686,9 @@ PortalRun(Portal portal, long count, bool isTopLevel, bool run_once, ...@@ -700,9 +686,9 @@ PortalRun(Portal portal, long count, bool isTopLevel, bool run_once,
TRACE_POSTGRESQL_QUERY_EXECUTE_START(); TRACE_POSTGRESQL_QUERY_EXECUTE_START();
/* Initialize completion tag to empty string */ /* Initialize empty completion data */
if (completionTag) if (qc)
completionTag[0] = '\0'; InitializeQueryCompletion(qc);
if (log_executor_stats && portal->strategy != PORTAL_MULTI_QUERY) if (log_executor_stats && portal->strategy != PORTAL_MULTI_QUERY)
{ {
...@@ -771,16 +757,13 @@ PortalRun(Portal portal, long count, bool isTopLevel, bool run_once, ...@@ -771,16 +757,13 @@ PortalRun(Portal portal, long count, bool isTopLevel, bool run_once,
/* /*
* If the portal result contains a command tag and the caller * If the portal result contains a command tag and the caller
* gave us a pointer to store it, copy it. Patch the "SELECT" * gave us a pointer to store it, copy it and update the
* tag to also provide the rowcount. * rowcount.
*/ */
if (completionTag && portal->commandTag) if (qc && portal->qc.commandTag != CMDTAG_UNKNOWN)
{ {
if (strcmp(portal->commandTag, "SELECT") == 0) CopyQueryCompletion(qc, &portal->qc);
snprintf(completionTag, COMPLETION_TAG_BUFSIZE, qc->nprocessed = nprocessed;
"SELECT " UINT64_FORMAT, nprocessed);
else
strcpy(completionTag, portal->commandTag);
} }
/* Mark portal not active */ /* Mark portal not active */
...@@ -794,7 +777,7 @@ PortalRun(Portal portal, long count, bool isTopLevel, bool run_once, ...@@ -794,7 +777,7 @@ PortalRun(Portal portal, long count, bool isTopLevel, bool run_once,
case PORTAL_MULTI_QUERY: case PORTAL_MULTI_QUERY:
PortalRunMulti(portal, isTopLevel, false, PortalRunMulti(portal, isTopLevel, false,
dest, altdest, completionTag); dest, altdest, qc);
/* Prevent portal's commands from being re-executed */ /* Prevent portal's commands from being re-executed */
MarkPortalDone(portal); MarkPortalDone(portal);
...@@ -1005,8 +988,9 @@ static void ...@@ -1005,8 +988,9 @@ static void
FillPortalStore(Portal portal, bool isTopLevel) FillPortalStore(Portal portal, bool isTopLevel)
{ {
DestReceiver *treceiver; DestReceiver *treceiver;
char completionTag[COMPLETION_TAG_BUFSIZE]; QueryCompletion qc;
InitializeQueryCompletion(&qc);
PortalCreateHoldStore(portal); PortalCreateHoldStore(portal);
treceiver = CreateDestReceiver(DestTuplestore); treceiver = CreateDestReceiver(DestTuplestore);
SetTuplestoreDestReceiverParams(treceiver, SetTuplestoreDestReceiverParams(treceiver,
...@@ -1014,8 +998,6 @@ FillPortalStore(Portal portal, bool isTopLevel) ...@@ -1014,8 +998,6 @@ FillPortalStore(Portal portal, bool isTopLevel)
portal->holdContext, portal->holdContext,
false); false);
completionTag[0] = '\0';
switch (portal->strategy) switch (portal->strategy)
{ {
case PORTAL_ONE_RETURNING: case PORTAL_ONE_RETURNING:
...@@ -1028,12 +1010,12 @@ FillPortalStore(Portal portal, bool isTopLevel) ...@@ -1028,12 +1010,12 @@ FillPortalStore(Portal portal, bool isTopLevel)
* portal's holdSnapshot to the snapshot used (or a copy of it). * portal's holdSnapshot to the snapshot used (or a copy of it).
*/ */
PortalRunMulti(portal, isTopLevel, true, PortalRunMulti(portal, isTopLevel, true,
treceiver, None_Receiver, completionTag); treceiver, None_Receiver, &qc);
break; break;
case PORTAL_UTIL_SELECT: case PORTAL_UTIL_SELECT:
PortalRunUtility(portal, linitial_node(PlannedStmt, portal->stmts), PortalRunUtility(portal, linitial_node(PlannedStmt, portal->stmts),
isTopLevel, true, treceiver, completionTag); isTopLevel, true, treceiver, &qc);
break; break;
default: default:
...@@ -1042,9 +1024,9 @@ FillPortalStore(Portal portal, bool isTopLevel) ...@@ -1042,9 +1024,9 @@ FillPortalStore(Portal portal, bool isTopLevel)
break; break;
} }
/* Override default completion tag with actual command result */ /* Override portal completion data with actual command results */
if (completionTag[0] != '\0') if (qc.commandTag != CMDTAG_UNKNOWN)
portal->commandTag = pstrdup(completionTag); CopyQueryCompletion(&portal->qc, &qc);
treceiver->rDestroy(treceiver); treceiver->rDestroy(treceiver);
} }
...@@ -1130,7 +1112,7 @@ RunFromStore(Portal portal, ScanDirection direction, uint64 count, ...@@ -1130,7 +1112,7 @@ RunFromStore(Portal portal, ScanDirection direction, uint64 count,
static void static void
PortalRunUtility(Portal portal, PlannedStmt *pstmt, PortalRunUtility(Portal portal, PlannedStmt *pstmt,
bool isTopLevel, bool setHoldSnapshot, bool isTopLevel, bool setHoldSnapshot,
DestReceiver *dest, char *completionTag) DestReceiver *dest, QueryCompletion *qc)
{ {
Node *utilityStmt = pstmt->utilityStmt; Node *utilityStmt = pstmt->utilityStmt;
Snapshot snapshot; Snapshot snapshot;
...@@ -1178,7 +1160,7 @@ PortalRunUtility(Portal portal, PlannedStmt *pstmt, ...@@ -1178,7 +1160,7 @@ PortalRunUtility(Portal portal, PlannedStmt *pstmt,
portal->portalParams, portal->portalParams,
portal->queryEnv, portal->queryEnv,
dest, dest,
completionTag); qc);
/* Some utility statements may change context on us */ /* Some utility statements may change context on us */
MemoryContextSwitchTo(portal->portalContext); MemoryContextSwitchTo(portal->portalContext);
...@@ -1202,7 +1184,7 @@ static void ...@@ -1202,7 +1184,7 @@ static void
PortalRunMulti(Portal portal, PortalRunMulti(Portal portal,
bool isTopLevel, bool setHoldSnapshot, bool isTopLevel, bool setHoldSnapshot,
DestReceiver *dest, DestReceiver *altdest, DestReceiver *dest, DestReceiver *altdest,
char *completionTag) QueryCompletion *qc)
{ {
bool active_snapshot_set = false; bool active_snapshot_set = false;
ListCell *stmtlist_item; ListCell *stmtlist_item;
...@@ -1284,7 +1266,7 @@ PortalRunMulti(Portal portal, ...@@ -1284,7 +1266,7 @@ PortalRunMulti(Portal portal,
portal->sourceText, portal->sourceText,
portal->portalParams, portal->portalParams,
portal->queryEnv, portal->queryEnv,
dest, completionTag); dest, qc);
} }
else else
{ {
...@@ -1319,7 +1301,7 @@ PortalRunMulti(Portal portal, ...@@ -1319,7 +1301,7 @@ PortalRunMulti(Portal portal,
Assert(!active_snapshot_set); Assert(!active_snapshot_set);
/* statement can set tag string */ /* statement can set tag string */
PortalRunUtility(portal, pstmt, isTopLevel, false, PortalRunUtility(portal, pstmt, isTopLevel, false,
dest, completionTag); dest, qc);
} }
else else
{ {
...@@ -1350,8 +1332,8 @@ PortalRunMulti(Portal portal, ...@@ -1350,8 +1332,8 @@ PortalRunMulti(Portal portal,
PopActiveSnapshot(); PopActiveSnapshot();
/* /*
* If a command completion tag was supplied, use it. Otherwise use the * If a query completion data was supplied, use it. Otherwise use the
* portal's commandTag as the default completion tag. * portal's query completion data.
* *
* Exception: Clients expect INSERT/UPDATE/DELETE tags to have counts, so * Exception: Clients expect INSERT/UPDATE/DELETE tags to have counts, so
* fake them with zeros. This can happen with DO INSTEAD rules if there * fake them with zeros. This can happen with DO INSTEAD rules if there
...@@ -1361,18 +1343,12 @@ PortalRunMulti(Portal portal, ...@@ -1361,18 +1343,12 @@ PortalRunMulti(Portal portal,
* e.g. an INSERT that does an UPDATE instead should not print "0 1" if * e.g. an INSERT that does an UPDATE instead should not print "0 1" if
* one row was updated. See QueryRewrite(), step 3, for details. * one row was updated. See QueryRewrite(), step 3, for details.
*/ */
if (completionTag && completionTag[0] == '\0') if (qc && qc->commandTag == CMDTAG_UNKNOWN)
{ {
if (portal->commandTag) if (portal->qc.commandTag != CMDTAG_UNKNOWN)
strcpy(completionTag, portal->commandTag); CopyQueryCompletion(qc, &portal->qc);
if (strcmp(completionTag, "SELECT") == 0) /* If the caller supplied a qc, we should have set it by now. */
sprintf(completionTag, "SELECT 0 0"); Assert(qc->commandTag != CMDTAG_UNKNOWN);
else if (strcmp(completionTag, "INSERT") == 0)
strcpy(completionTag, "INSERT 0 0");
else if (strcmp(completionTag, "UPDATE") == 0)
strcpy(completionTag, "UPDATE 0");
else if (strcmp(completionTag, "DELETE") == 0)
strcpy(completionTag, "DELETE 0");
} }
} }
......
...@@ -75,7 +75,7 @@ ...@@ -75,7 +75,7 @@
ProcessUtility_hook_type ProcessUtility_hook = NULL; ProcessUtility_hook_type ProcessUtility_hook = NULL;
/* local function declarations */ /* local function declarations */
static int ClassifyUtilityCommandAsReadOnly(Node *parsetree); static int ClassifyUtilityCommandAsReadOnly(Node *parsetree);
static void ProcessUtilitySlow(ParseState *pstate, static void ProcessUtilitySlow(ParseState *pstate,
PlannedStmt *pstmt, PlannedStmt *pstmt,
const char *queryString, const char *queryString,
...@@ -83,10 +83,9 @@ static void ProcessUtilitySlow(ParseState *pstate, ...@@ -83,10 +83,9 @@ static void ProcessUtilitySlow(ParseState *pstate,
ParamListInfo params, ParamListInfo params,
QueryEnvironment *queryEnv, QueryEnvironment *queryEnv,
DestReceiver *dest, DestReceiver *dest,
char *completionTag); QueryCompletion *qc);
static void ExecDropStmt(DropStmt *stmt, bool isTopLevel); static void ExecDropStmt(DropStmt *stmt, bool isTopLevel);
/* /*
* CommandIsReadOnly: is an executable query read-only? * CommandIsReadOnly: is an executable query read-only?
* *
...@@ -467,7 +466,6 @@ CheckRestrictedOperation(const char *cmdname) ...@@ -467,7 +466,6 @@ CheckRestrictedOperation(const char *cmdname)
cmdname))); cmdname)));
} }
/* /*
* ProcessUtility * ProcessUtility
* general utility function invoker * general utility function invoker
...@@ -480,17 +478,13 @@ CheckRestrictedOperation(const char *cmdname) ...@@ -480,17 +478,13 @@ CheckRestrictedOperation(const char *cmdname)
* queryEnv: environment for parse through execution (e.g., ephemeral named * queryEnv: environment for parse through execution (e.g., ephemeral named
* tables like trigger transition tables). May be NULL. * tables like trigger transition tables). May be NULL.
* dest: where to send results * dest: where to send results
* completionTag: points to a buffer of size COMPLETION_TAG_BUFSIZE * qc: where to store command completion status data. May be NULL,
* in which to store a command completion status string. * but if not, then caller must have initialized it.
* *
* Caller MUST supply a queryString; it is not allowed (anymore) to pass NULL. * Caller MUST supply a queryString; it is not allowed (anymore) to pass NULL.
* If you really don't have source text, you can pass a constant string, * If you really don't have source text, you can pass a constant string,
* perhaps "(query not available)". * perhaps "(query not available)".
* *
* completionTag is only set nonempty if we want to return a nondefault status.
*
* completionTag may be NULL if caller doesn't want a status string.
*
* Note for users of ProcessUtility_hook: the same queryString may be passed * Note for users of ProcessUtility_hook: the same queryString may be passed
* to multiple invocations of ProcessUtility when processing a query string * to multiple invocations of ProcessUtility when processing a query string
* containing multiple semicolon-separated statements. One should use * containing multiple semicolon-separated statements. One should use
...@@ -507,11 +501,12 @@ ProcessUtility(PlannedStmt *pstmt, ...@@ -507,11 +501,12 @@ ProcessUtility(PlannedStmt *pstmt,
ParamListInfo params, ParamListInfo params,
QueryEnvironment *queryEnv, QueryEnvironment *queryEnv,
DestReceiver *dest, DestReceiver *dest,
char *completionTag) QueryCompletion *qc)
{ {
Assert(IsA(pstmt, PlannedStmt)); Assert(IsA(pstmt, PlannedStmt));
Assert(pstmt->commandType == CMD_UTILITY); Assert(pstmt->commandType == CMD_UTILITY);
Assert(queryString != NULL); /* required as of 8.4 */ Assert(queryString != NULL); /* required as of 8.4 */
Assert(qc == NULL || qc->commandTag == CMDTAG_UNKNOWN);
/* /*
* We provide a function hook variable that lets loadable plugins get * We provide a function hook variable that lets loadable plugins get
...@@ -521,11 +516,11 @@ ProcessUtility(PlannedStmt *pstmt, ...@@ -521,11 +516,11 @@ ProcessUtility(PlannedStmt *pstmt,
if (ProcessUtility_hook) if (ProcessUtility_hook)
(*ProcessUtility_hook) (pstmt, queryString, (*ProcessUtility_hook) (pstmt, queryString,
context, params, queryEnv, context, params, queryEnv,
dest, completionTag); dest, qc);
else else
standard_ProcessUtility(pstmt, queryString, standard_ProcessUtility(pstmt, queryString,
context, params, queryEnv, context, params, queryEnv,
dest, completionTag); dest, qc);
} }
/* /*
...@@ -546,7 +541,7 @@ standard_ProcessUtility(PlannedStmt *pstmt, ...@@ -546,7 +541,7 @@ standard_ProcessUtility(PlannedStmt *pstmt,
ParamListInfo params, ParamListInfo params,
QueryEnvironment *queryEnv, QueryEnvironment *queryEnv,
DestReceiver *dest, DestReceiver *dest,
char *completionTag) QueryCompletion *qc)
{ {
Node *parsetree = pstmt->utilityStmt; Node *parsetree = pstmt->utilityStmt;
bool isTopLevel = (context == PROCESS_UTILITY_TOPLEVEL); bool isTopLevel = (context == PROCESS_UTILITY_TOPLEVEL);
...@@ -562,19 +557,16 @@ standard_ProcessUtility(PlannedStmt *pstmt, ...@@ -562,19 +557,16 @@ standard_ProcessUtility(PlannedStmt *pstmt,
if (readonly_flags != COMMAND_IS_STRICTLY_READ_ONLY && if (readonly_flags != COMMAND_IS_STRICTLY_READ_ONLY &&
(XactReadOnly || IsInParallelMode())) (XactReadOnly || IsInParallelMode()))
{ {
const char *commandtag = CreateCommandTag(parsetree); CommandTag commandtag = CreateCommandTag(parsetree);
if ((readonly_flags & COMMAND_OK_IN_READ_ONLY_TXN) == 0) if ((readonly_flags & COMMAND_OK_IN_READ_ONLY_TXN) == 0)
PreventCommandIfReadOnly(commandtag); PreventCommandIfReadOnly(GetCommandTagName(commandtag));
if ((readonly_flags & COMMAND_OK_IN_PARALLEL_MODE) == 0) if ((readonly_flags & COMMAND_OK_IN_PARALLEL_MODE) == 0)
PreventCommandIfParallelMode(commandtag); PreventCommandIfParallelMode(GetCommandTagName(commandtag));
if ((readonly_flags & COMMAND_OK_IN_RECOVERY) == 0) if ((readonly_flags & COMMAND_OK_IN_RECOVERY) == 0)
PreventCommandDuringRecovery(commandtag); PreventCommandDuringRecovery(GetCommandTagName(commandtag));
} }
if (completionTag)
completionTag[0] = '\0';
pstate = make_parsestate(NULL); pstate = make_parsestate(NULL);
pstate->p_sourcetext = queryString; pstate->p_sourcetext = queryString;
pstate->p_queryEnv = queryEnv; pstate->p_queryEnv = queryEnv;
...@@ -623,18 +615,18 @@ standard_ProcessUtility(PlannedStmt *pstmt, ...@@ -623,18 +615,18 @@ standard_ProcessUtility(PlannedStmt *pstmt,
case TRANS_STMT_COMMIT: case TRANS_STMT_COMMIT:
if (!EndTransactionBlock(stmt->chain)) if (!EndTransactionBlock(stmt->chain))
{ {
/* report unsuccessful commit in completionTag */ /* report unsuccessful commit in qc */
if (completionTag) if (qc)
strcpy(completionTag, "ROLLBACK"); SetQueryCompletion(qc, CMDTAG_ROLLBACK, 0);
} }
break; break;
case TRANS_STMT_PREPARE: case TRANS_STMT_PREPARE:
if (!PrepareTransactionBlock(stmt->gid)) if (!PrepareTransactionBlock(stmt->gid))
{ {
/* report unsuccessful commit in completionTag */ /* report unsuccessful commit in qc */
if (completionTag) if (qc)
strcpy(completionTag, "ROLLBACK"); SetQueryCompletion(qc, CMDTAG_ROLLBACK, 0);
} }
break; break;
...@@ -693,8 +685,7 @@ standard_ProcessUtility(PlannedStmt *pstmt, ...@@ -693,8 +685,7 @@ standard_ProcessUtility(PlannedStmt *pstmt,
break; break;
case T_FetchStmt: case T_FetchStmt:
PerformPortalFetch((FetchStmt *) parsetree, dest, PerformPortalFetch((FetchStmt *) parsetree, dest, qc);
completionTag);
break; break;
case T_DoStmt: case T_DoStmt:
...@@ -729,9 +720,8 @@ standard_ProcessUtility(PlannedStmt *pstmt, ...@@ -729,9 +720,8 @@ standard_ProcessUtility(PlannedStmt *pstmt,
DoCopy(pstate, (CopyStmt *) parsetree, DoCopy(pstate, (CopyStmt *) parsetree,
pstmt->stmt_location, pstmt->stmt_len, pstmt->stmt_location, pstmt->stmt_len,
&processed); &processed);
if (completionTag) if (qc)
snprintf(completionTag, COMPLETION_TAG_BUFSIZE, SetQueryCompletion(qc, CMDTAG_COPY, processed);
"COPY " UINT64_FORMAT, processed);
} }
break; break;
...@@ -745,7 +735,7 @@ standard_ProcessUtility(PlannedStmt *pstmt, ...@@ -745,7 +735,7 @@ standard_ProcessUtility(PlannedStmt *pstmt,
ExecuteQuery(pstate, ExecuteQuery(pstate,
(ExecuteStmt *) parsetree, NULL, (ExecuteStmt *) parsetree, NULL,
params, params,
dest, completionTag); dest, qc);
break; break;
case T_DeallocateStmt: case T_DeallocateStmt:
...@@ -974,7 +964,7 @@ standard_ProcessUtility(PlannedStmt *pstmt, ...@@ -974,7 +964,7 @@ standard_ProcessUtility(PlannedStmt *pstmt,
if (EventTriggerSupportsObjectType(stmt->objtype)) if (EventTriggerSupportsObjectType(stmt->objtype))
ProcessUtilitySlow(pstate, pstmt, queryString, ProcessUtilitySlow(pstate, pstmt, queryString,
context, params, queryEnv, context, params, queryEnv,
dest, completionTag); dest, qc);
else else
ExecuteGrantStmt(stmt); ExecuteGrantStmt(stmt);
} }
...@@ -987,7 +977,7 @@ standard_ProcessUtility(PlannedStmt *pstmt, ...@@ -987,7 +977,7 @@ standard_ProcessUtility(PlannedStmt *pstmt,
if (EventTriggerSupportsObjectType(stmt->removeType)) if (EventTriggerSupportsObjectType(stmt->removeType))
ProcessUtilitySlow(pstate, pstmt, queryString, ProcessUtilitySlow(pstate, pstmt, queryString,
context, params, queryEnv, context, params, queryEnv,
dest, completionTag); dest, qc);
else else
ExecDropStmt(stmt, isTopLevel); ExecDropStmt(stmt, isTopLevel);
} }
...@@ -1000,7 +990,7 @@ standard_ProcessUtility(PlannedStmt *pstmt, ...@@ -1000,7 +990,7 @@ standard_ProcessUtility(PlannedStmt *pstmt,
if (EventTriggerSupportsObjectType(stmt->renameType)) if (EventTriggerSupportsObjectType(stmt->renameType))
ProcessUtilitySlow(pstate, pstmt, queryString, ProcessUtilitySlow(pstate, pstmt, queryString,
context, params, queryEnv, context, params, queryEnv,
dest, completionTag); dest, qc);
else else
ExecRenameStmt(stmt); ExecRenameStmt(stmt);
} }
...@@ -1013,7 +1003,7 @@ standard_ProcessUtility(PlannedStmt *pstmt, ...@@ -1013,7 +1003,7 @@ standard_ProcessUtility(PlannedStmt *pstmt,
if (EventTriggerSupportsObjectType(stmt->objectType)) if (EventTriggerSupportsObjectType(stmt->objectType))
ProcessUtilitySlow(pstate, pstmt, queryString, ProcessUtilitySlow(pstate, pstmt, queryString,
context, params, queryEnv, context, params, queryEnv,
dest, completionTag); dest, qc);
else else
ExecAlterObjectDependsStmt(stmt, NULL); ExecAlterObjectDependsStmt(stmt, NULL);
} }
...@@ -1026,7 +1016,7 @@ standard_ProcessUtility(PlannedStmt *pstmt, ...@@ -1026,7 +1016,7 @@ standard_ProcessUtility(PlannedStmt *pstmt,
if (EventTriggerSupportsObjectType(stmt->objectType)) if (EventTriggerSupportsObjectType(stmt->objectType))
ProcessUtilitySlow(pstate, pstmt, queryString, ProcessUtilitySlow(pstate, pstmt, queryString,
context, params, queryEnv, context, params, queryEnv,
dest, completionTag); dest, qc);
else else
ExecAlterObjectSchemaStmt(stmt, NULL); ExecAlterObjectSchemaStmt(stmt, NULL);
} }
...@@ -1039,7 +1029,7 @@ standard_ProcessUtility(PlannedStmt *pstmt, ...@@ -1039,7 +1029,7 @@ standard_ProcessUtility(PlannedStmt *pstmt,
if (EventTriggerSupportsObjectType(stmt->objectType)) if (EventTriggerSupportsObjectType(stmt->objectType))
ProcessUtilitySlow(pstate, pstmt, queryString, ProcessUtilitySlow(pstate, pstmt, queryString,
context, params, queryEnv, context, params, queryEnv,
dest, completionTag); dest, qc);
else else
ExecAlterOwnerStmt(stmt); ExecAlterOwnerStmt(stmt);
} }
...@@ -1052,7 +1042,7 @@ standard_ProcessUtility(PlannedStmt *pstmt, ...@@ -1052,7 +1042,7 @@ standard_ProcessUtility(PlannedStmt *pstmt,
if (EventTriggerSupportsObjectType(stmt->objtype)) if (EventTriggerSupportsObjectType(stmt->objtype))
ProcessUtilitySlow(pstate, pstmt, queryString, ProcessUtilitySlow(pstate, pstmt, queryString,
context, params, queryEnv, context, params, queryEnv,
dest, completionTag); dest, qc);
else else
CommentObject(stmt); CommentObject(stmt);
break; break;
...@@ -1065,7 +1055,7 @@ standard_ProcessUtility(PlannedStmt *pstmt, ...@@ -1065,7 +1055,7 @@ standard_ProcessUtility(PlannedStmt *pstmt,
if (EventTriggerSupportsObjectType(stmt->objtype)) if (EventTriggerSupportsObjectType(stmt->objtype))
ProcessUtilitySlow(pstate, pstmt, queryString, ProcessUtilitySlow(pstate, pstmt, queryString,
context, params, queryEnv, context, params, queryEnv,
dest, completionTag); dest, qc);
else else
ExecSecLabelStmt(stmt); ExecSecLabelStmt(stmt);
break; break;
...@@ -1075,7 +1065,7 @@ standard_ProcessUtility(PlannedStmt *pstmt, ...@@ -1075,7 +1065,7 @@ standard_ProcessUtility(PlannedStmt *pstmt,
/* All other statement types have event trigger support */ /* All other statement types have event trigger support */
ProcessUtilitySlow(pstate, pstmt, queryString, ProcessUtilitySlow(pstate, pstmt, queryString,
context, params, queryEnv, context, params, queryEnv,
dest, completionTag); dest, qc);
break; break;
} }
...@@ -1102,7 +1092,7 @@ ProcessUtilitySlow(ParseState *pstate, ...@@ -1102,7 +1092,7 @@ ProcessUtilitySlow(ParseState *pstate,
ParamListInfo params, ParamListInfo params,
QueryEnvironment *queryEnv, QueryEnvironment *queryEnv,
DestReceiver *dest, DestReceiver *dest,
char *completionTag) QueryCompletion *qc)
{ {
Node *parsetree = pstmt->utilityStmt; Node *parsetree = pstmt->utilityStmt;
bool isTopLevel = (context == PROCESS_UTILITY_TOPLEVEL); bool isTopLevel = (context == PROCESS_UTILITY_TOPLEVEL);
...@@ -1605,7 +1595,7 @@ ProcessUtilitySlow(ParseState *pstate, ...@@ -1605,7 +1595,7 @@ ProcessUtilitySlow(ParseState *pstate,
case T_CreateTableAsStmt: case T_CreateTableAsStmt:
address = ExecCreateTableAs(pstate, (CreateTableAsStmt *) parsetree, address = ExecCreateTableAs(pstate, (CreateTableAsStmt *) parsetree,
params, queryEnv, completionTag); params, queryEnv, qc);
break; break;
case T_RefreshMatViewStmt: case T_RefreshMatViewStmt:
...@@ -1620,7 +1610,7 @@ ProcessUtilitySlow(ParseState *pstate, ...@@ -1620,7 +1610,7 @@ ProcessUtilitySlow(ParseState *pstate,
PG_TRY(); PG_TRY();
{ {
address = ExecRefreshMatView((RefreshMatViewStmt *) parsetree, address = ExecRefreshMatView((RefreshMatViewStmt *) parsetree,
queryString, params, completionTag); queryString, params, qc);
} }
PG_FINALLY(); PG_FINALLY();
{ {
...@@ -2099,137 +2089,137 @@ UtilityContainsQuery(Node *parsetree) ...@@ -2099,137 +2089,137 @@ UtilityContainsQuery(Node *parsetree)
* *
* This covers most cases where ALTER is used with an ObjectType enum. * This covers most cases where ALTER is used with an ObjectType enum.
*/ */
static const char * static CommandTag
AlterObjectTypeCommandTag(ObjectType objtype) AlterObjectTypeCommandTag(ObjectType objtype)
{ {
const char *tag; CommandTag tag;
switch (objtype) switch (objtype)
{ {
case OBJECT_AGGREGATE: case OBJECT_AGGREGATE:
tag = "ALTER AGGREGATE"; tag = CMDTAG_ALTER_AGGREGATE;
break; break;
case OBJECT_ATTRIBUTE: case OBJECT_ATTRIBUTE:
tag = "ALTER TYPE"; tag = CMDTAG_ALTER_TYPE;
break; break;
case OBJECT_CAST: case OBJECT_CAST:
tag = "ALTER CAST"; tag = CMDTAG_ALTER_CAST;
break; break;
case OBJECT_COLLATION: case OBJECT_COLLATION:
tag = "ALTER COLLATION"; tag = CMDTAG_ALTER_COLLATION;
break; break;
case OBJECT_COLUMN: case OBJECT_COLUMN:
tag = "ALTER TABLE"; tag = CMDTAG_ALTER_TABLE;
break; break;
case OBJECT_CONVERSION: case OBJECT_CONVERSION:
tag = "ALTER CONVERSION"; tag = CMDTAG_ALTER_CONVERSION;
break; break;
case OBJECT_DATABASE: case OBJECT_DATABASE:
tag = "ALTER DATABASE"; tag = CMDTAG_ALTER_DATABASE;
break; break;
case OBJECT_DOMAIN: case OBJECT_DOMAIN:
case OBJECT_DOMCONSTRAINT: case OBJECT_DOMCONSTRAINT:
tag = "ALTER DOMAIN"; tag = CMDTAG_ALTER_DOMAIN;
break; break;
case OBJECT_EXTENSION: case OBJECT_EXTENSION:
tag = "ALTER EXTENSION"; tag = CMDTAG_ALTER_EXTENSION;
break; break;
case OBJECT_FDW: case OBJECT_FDW:
tag = "ALTER FOREIGN DATA WRAPPER"; tag = CMDTAG_ALTER_FOREIGN_DATA_WRAPPER;
break; break;
case OBJECT_FOREIGN_SERVER: case OBJECT_FOREIGN_SERVER:
tag = "ALTER SERVER"; tag = CMDTAG_ALTER_SERVER;
break; break;
case OBJECT_FOREIGN_TABLE: case OBJECT_FOREIGN_TABLE:
tag = "ALTER FOREIGN TABLE"; tag = CMDTAG_ALTER_FOREIGN_TABLE;
break; break;
case OBJECT_FUNCTION: case OBJECT_FUNCTION:
tag = "ALTER FUNCTION"; tag = CMDTAG_ALTER_FUNCTION;
break; break;
case OBJECT_INDEX: case OBJECT_INDEX:
tag = "ALTER INDEX"; tag = CMDTAG_ALTER_INDEX;
break; break;
case OBJECT_LANGUAGE: case OBJECT_LANGUAGE:
tag = "ALTER LANGUAGE"; tag = CMDTAG_ALTER_LANGUAGE;
break; break;
case OBJECT_LARGEOBJECT: case OBJECT_LARGEOBJECT:
tag = "ALTER LARGE OBJECT"; tag = CMDTAG_ALTER_LARGE_OBJECT;
break; break;
case OBJECT_OPCLASS: case OBJECT_OPCLASS:
tag = "ALTER OPERATOR CLASS"; tag = CMDTAG_ALTER_OPERATOR_CLASS;
break; break;
case OBJECT_OPERATOR: case OBJECT_OPERATOR:
tag = "ALTER OPERATOR"; tag = CMDTAG_ALTER_OPERATOR;
break; break;
case OBJECT_OPFAMILY: case OBJECT_OPFAMILY:
tag = "ALTER OPERATOR FAMILY"; tag = CMDTAG_ALTER_OPERATOR_FAMILY;
break; break;
case OBJECT_POLICY: case OBJECT_POLICY:
tag = "ALTER POLICY"; tag = CMDTAG_ALTER_POLICY;
break; break;
case OBJECT_PROCEDURE: case OBJECT_PROCEDURE:
tag = "ALTER PROCEDURE"; tag = CMDTAG_ALTER_PROCEDURE;
break; break;
case OBJECT_ROLE: case OBJECT_ROLE:
tag = "ALTER ROLE"; tag = CMDTAG_ALTER_ROLE;
break; break;
case OBJECT_ROUTINE: case OBJECT_ROUTINE:
tag = "ALTER ROUTINE"; tag = CMDTAG_ALTER_ROUTINE;
break; break;
case OBJECT_RULE: case OBJECT_RULE:
tag = "ALTER RULE"; tag = CMDTAG_ALTER_RULE;
break; break;
case OBJECT_SCHEMA: case OBJECT_SCHEMA:
tag = "ALTER SCHEMA"; tag = CMDTAG_ALTER_SCHEMA;
break; break;
case OBJECT_SEQUENCE: case OBJECT_SEQUENCE:
tag = "ALTER SEQUENCE"; tag = CMDTAG_ALTER_SEQUENCE;
break; break;
case OBJECT_TABLE: case OBJECT_TABLE:
case OBJECT_TABCONSTRAINT: case OBJECT_TABCONSTRAINT:
tag = "ALTER TABLE"; tag = CMDTAG_ALTER_TABLE;
break; break;
case OBJECT_TABLESPACE: case OBJECT_TABLESPACE:
tag = "ALTER TABLESPACE"; tag = CMDTAG_ALTER_TABLESPACE;
break; break;
case OBJECT_TRIGGER: case OBJECT_TRIGGER:
tag = "ALTER TRIGGER"; tag = CMDTAG_ALTER_TRIGGER;
break; break;
case OBJECT_EVENT_TRIGGER: case OBJECT_EVENT_TRIGGER:
tag = "ALTER EVENT TRIGGER"; tag = CMDTAG_ALTER_EVENT_TRIGGER;
break; break;
case OBJECT_TSCONFIGURATION: case OBJECT_TSCONFIGURATION:
tag = "ALTER TEXT SEARCH CONFIGURATION"; tag = CMDTAG_ALTER_TEXT_SEARCH_CONFIGURATION;
break; break;
case OBJECT_TSDICTIONARY: case OBJECT_TSDICTIONARY:
tag = "ALTER TEXT SEARCH DICTIONARY"; tag = CMDTAG_ALTER_TEXT_SEARCH_DICTIONARY;
break; break;
case OBJECT_TSPARSER: case OBJECT_TSPARSER:
tag = "ALTER TEXT SEARCH PARSER"; tag = CMDTAG_ALTER_TEXT_SEARCH_PARSER;
break; break;
case OBJECT_TSTEMPLATE: case OBJECT_TSTEMPLATE:
tag = "ALTER TEXT SEARCH TEMPLATE"; tag = CMDTAG_ALTER_TEXT_SEARCH_TEMPLATE;
break; break;
case OBJECT_TYPE: case OBJECT_TYPE:
tag = "ALTER TYPE"; tag = CMDTAG_ALTER_TYPE;
break; break;
case OBJECT_VIEW: case OBJECT_VIEW:
tag = "ALTER VIEW"; tag = CMDTAG_ALTER_VIEW;
break; break;
case OBJECT_MATVIEW: case OBJECT_MATVIEW:
tag = "ALTER MATERIALIZED VIEW"; tag = CMDTAG_ALTER_MATERIALIZED_VIEW;
break; break;
case OBJECT_PUBLICATION: case OBJECT_PUBLICATION:
tag = "ALTER PUBLICATION"; tag = CMDTAG_ALTER_PUBLICATION;
break; break;
case OBJECT_SUBSCRIPTION: case OBJECT_SUBSCRIPTION:
tag = "ALTER SUBSCRIPTION"; tag = CMDTAG_ALTER_SUBSCRIPTION;
break; break;
case OBJECT_STATISTIC_EXT: case OBJECT_STATISTIC_EXT:
tag = "ALTER STATISTICS"; tag = CMDTAG_ALTER_STATISTICS;
break; break;
default: default:
tag = "???"; tag = CMDTAG_UNKNOWN;
break; break;
} }
...@@ -2238,20 +2228,17 @@ AlterObjectTypeCommandTag(ObjectType objtype) ...@@ -2238,20 +2228,17 @@ AlterObjectTypeCommandTag(ObjectType objtype)
/* /*
* CreateCommandTag * CreateCommandTag
* utility to get a string representation of the command operation, * utility to get a CommandTag for the command operation,
* given either a raw (un-analyzed) parsetree, an analyzed Query, * given either a raw (un-analyzed) parsetree, an analyzed Query,
* or a PlannedStmt. * or a PlannedStmt.
* *
* This must handle all command types, but since the vast majority * This must handle all command types, but since the vast majority
* of 'em are utility commands, it seems sensible to keep it here. * of 'em are utility commands, it seems sensible to keep it here.
*
* NB: all result strings must be shorter than COMPLETION_TAG_BUFSIZE.
* Also, the result must point at a true constant (permanent storage).
*/ */
const char * CommandTag
CreateCommandTag(Node *parsetree) CreateCommandTag(Node *parsetree)
{ {
const char *tag; CommandTag tag;
switch (nodeTag(parsetree)) switch (nodeTag(parsetree))
{ {
...@@ -2262,19 +2249,19 @@ CreateCommandTag(Node *parsetree) ...@@ -2262,19 +2249,19 @@ CreateCommandTag(Node *parsetree)
/* raw plannable queries */ /* raw plannable queries */
case T_InsertStmt: case T_InsertStmt:
tag = "INSERT"; tag = CMDTAG_INSERT;
break; break;
case T_DeleteStmt: case T_DeleteStmt:
tag = "DELETE"; tag = CMDTAG_DELETE;
break; break;
case T_UpdateStmt: case T_UpdateStmt:
tag = "UPDATE"; tag = CMDTAG_UPDATE;
break; break;
case T_SelectStmt: case T_SelectStmt:
tag = "SELECT"; tag = CMDTAG_SELECT;
break; break;
/* utility statements --- same whether raw or cooked */ /* utility statements --- same whether raw or cooked */
...@@ -2285,51 +2272,51 @@ CreateCommandTag(Node *parsetree) ...@@ -2285,51 +2272,51 @@ CreateCommandTag(Node *parsetree)
switch (stmt->kind) switch (stmt->kind)
{ {
case TRANS_STMT_BEGIN: case TRANS_STMT_BEGIN:
tag = "BEGIN"; tag = CMDTAG_BEGIN;
break; break;
case TRANS_STMT_START: case TRANS_STMT_START:
tag = "START TRANSACTION"; tag = CMDTAG_START_TRANSACTION;
break; break;
case TRANS_STMT_COMMIT: case TRANS_STMT_COMMIT:
tag = "COMMIT"; tag = CMDTAG_COMMIT;
break; break;
case TRANS_STMT_ROLLBACK: case TRANS_STMT_ROLLBACK:
case TRANS_STMT_ROLLBACK_TO: case TRANS_STMT_ROLLBACK_TO:
tag = "ROLLBACK"; tag = CMDTAG_ROLLBACK;
break; break;
case TRANS_STMT_SAVEPOINT: case TRANS_STMT_SAVEPOINT:
tag = "SAVEPOINT"; tag = CMDTAG_SAVEPOINT;
break; break;
case TRANS_STMT_RELEASE: case TRANS_STMT_RELEASE:
tag = "RELEASE"; tag = CMDTAG_RELEASE;
break; break;
case TRANS_STMT_PREPARE: case TRANS_STMT_PREPARE:
tag = "PREPARE TRANSACTION"; tag = CMDTAG_PREPARE_TRANSACTION;
break; break;
case TRANS_STMT_COMMIT_PREPARED: case TRANS_STMT_COMMIT_PREPARED:
tag = "COMMIT PREPARED"; tag = CMDTAG_COMMIT_PREPARED;
break; break;
case TRANS_STMT_ROLLBACK_PREPARED: case TRANS_STMT_ROLLBACK_PREPARED:
tag = "ROLLBACK PREPARED"; tag = CMDTAG_ROLLBACK_PREPARED;
break; break;
default: default:
tag = "???"; tag = CMDTAG_UNKNOWN;
break; break;
} }
} }
break; break;
case T_DeclareCursorStmt: case T_DeclareCursorStmt:
tag = "DECLARE CURSOR"; tag = CMDTAG_DECLARE_CURSOR;
break; break;
case T_ClosePortalStmt: case T_ClosePortalStmt:
...@@ -2337,9 +2324,9 @@ CreateCommandTag(Node *parsetree) ...@@ -2337,9 +2324,9 @@ CreateCommandTag(Node *parsetree)
ClosePortalStmt *stmt = (ClosePortalStmt *) parsetree; ClosePortalStmt *stmt = (ClosePortalStmt *) parsetree;
if (stmt->portalname == NULL) if (stmt->portalname == NULL)
tag = "CLOSE CURSOR ALL"; tag = CMDTAG_CLOSE_CURSOR_ALL;
else else
tag = "CLOSE CURSOR"; tag = CMDTAG_CLOSE_CURSOR;
} }
break; break;
...@@ -2347,209 +2334,209 @@ CreateCommandTag(Node *parsetree) ...@@ -2347,209 +2334,209 @@ CreateCommandTag(Node *parsetree)
{ {
FetchStmt *stmt = (FetchStmt *) parsetree; FetchStmt *stmt = (FetchStmt *) parsetree;
tag = (stmt->ismove) ? "MOVE" : "FETCH"; tag = (stmt->ismove) ? CMDTAG_MOVE : CMDTAG_FETCH;
} }
break; break;
case T_CreateDomainStmt: case T_CreateDomainStmt:
tag = "CREATE DOMAIN"; tag = CMDTAG_CREATE_DOMAIN;
break; break;
case T_CreateSchemaStmt: case T_CreateSchemaStmt:
tag = "CREATE SCHEMA"; tag = CMDTAG_CREATE_SCHEMA;
break; break;
case T_CreateStmt: case T_CreateStmt:
tag = "CREATE TABLE"; tag = CMDTAG_CREATE_TABLE;
break; break;
case T_CreateTableSpaceStmt: case T_CreateTableSpaceStmt:
tag = "CREATE TABLESPACE"; tag = CMDTAG_CREATE_TABLESPACE;
break; break;
case T_DropTableSpaceStmt: case T_DropTableSpaceStmt:
tag = "DROP TABLESPACE"; tag = CMDTAG_DROP_TABLESPACE;
break; break;
case T_AlterTableSpaceOptionsStmt: case T_AlterTableSpaceOptionsStmt:
tag = "ALTER TABLESPACE"; tag = CMDTAG_ALTER_TABLESPACE;
break; break;
case T_CreateExtensionStmt: case T_CreateExtensionStmt:
tag = "CREATE EXTENSION"; tag = CMDTAG_CREATE_EXTENSION;
break; break;
case T_AlterExtensionStmt: case T_AlterExtensionStmt:
tag = "ALTER EXTENSION"; tag = CMDTAG_ALTER_EXTENSION;
break; break;
case T_AlterExtensionContentsStmt: case T_AlterExtensionContentsStmt:
tag = "ALTER EXTENSION"; tag = CMDTAG_ALTER_EXTENSION;
break; break;
case T_CreateFdwStmt: case T_CreateFdwStmt:
tag = "CREATE FOREIGN DATA WRAPPER"; tag = CMDTAG_CREATE_FOREIGN_DATA_WRAPPER;
break; break;
case T_AlterFdwStmt: case T_AlterFdwStmt:
tag = "ALTER FOREIGN DATA WRAPPER"; tag = CMDTAG_ALTER_FOREIGN_DATA_WRAPPER;
break; break;
case T_CreateForeignServerStmt: case T_CreateForeignServerStmt:
tag = "CREATE SERVER"; tag = CMDTAG_CREATE_SERVER;
break; break;
case T_AlterForeignServerStmt: case T_AlterForeignServerStmt:
tag = "ALTER SERVER"; tag = CMDTAG_ALTER_SERVER;
break; break;
case T_CreateUserMappingStmt: case T_CreateUserMappingStmt:
tag = "CREATE USER MAPPING"; tag = CMDTAG_CREATE_USER_MAPPING;
break; break;
case T_AlterUserMappingStmt: case T_AlterUserMappingStmt:
tag = "ALTER USER MAPPING"; tag = CMDTAG_ALTER_USER_MAPPING;
break; break;
case T_DropUserMappingStmt: case T_DropUserMappingStmt:
tag = "DROP USER MAPPING"; tag = CMDTAG_DROP_USER_MAPPING;
break; break;
case T_CreateForeignTableStmt: case T_CreateForeignTableStmt:
tag = "CREATE FOREIGN TABLE"; tag = CMDTAG_CREATE_FOREIGN_TABLE;
break; break;
case T_ImportForeignSchemaStmt: case T_ImportForeignSchemaStmt:
tag = "IMPORT FOREIGN SCHEMA"; tag = CMDTAG_IMPORT_FOREIGN_SCHEMA;
break; break;
case T_DropStmt: case T_DropStmt:
switch (((DropStmt *) parsetree)->removeType) switch (((DropStmt *) parsetree)->removeType)
{ {
case OBJECT_TABLE: case OBJECT_TABLE:
tag = "DROP TABLE"; tag = CMDTAG_DROP_TABLE;
break; break;
case OBJECT_SEQUENCE: case OBJECT_SEQUENCE:
tag = "DROP SEQUENCE"; tag = CMDTAG_DROP_SEQUENCE;
break; break;
case OBJECT_VIEW: case OBJECT_VIEW:
tag = "DROP VIEW"; tag = CMDTAG_DROP_VIEW;
break; break;
case OBJECT_MATVIEW: case OBJECT_MATVIEW:
tag = "DROP MATERIALIZED VIEW"; tag = CMDTAG_DROP_MATERIALIZED_VIEW;
break; break;
case OBJECT_INDEX: case OBJECT_INDEX:
tag = "DROP INDEX"; tag = CMDTAG_DROP_INDEX;
break; break;
case OBJECT_TYPE: case OBJECT_TYPE:
tag = "DROP TYPE"; tag = CMDTAG_DROP_TYPE;
break; break;
case OBJECT_DOMAIN: case OBJECT_DOMAIN:
tag = "DROP DOMAIN"; tag = CMDTAG_DROP_DOMAIN;
break; break;
case OBJECT_COLLATION: case OBJECT_COLLATION:
tag = "DROP COLLATION"; tag = CMDTAG_DROP_COLLATION;
break; break;
case OBJECT_CONVERSION: case OBJECT_CONVERSION:
tag = "DROP CONVERSION"; tag = CMDTAG_DROP_CONVERSION;
break; break;
case OBJECT_SCHEMA: case OBJECT_SCHEMA:
tag = "DROP SCHEMA"; tag = CMDTAG_DROP_SCHEMA;
break; break;
case OBJECT_TSPARSER: case OBJECT_TSPARSER:
tag = "DROP TEXT SEARCH PARSER"; tag = CMDTAG_DROP_TEXT_SEARCH_PARSER;
break; break;
case OBJECT_TSDICTIONARY: case OBJECT_TSDICTIONARY:
tag = "DROP TEXT SEARCH DICTIONARY"; tag = CMDTAG_DROP_TEXT_SEARCH_DICTIONARY;
break; break;
case OBJECT_TSTEMPLATE: case OBJECT_TSTEMPLATE:
tag = "DROP TEXT SEARCH TEMPLATE"; tag = CMDTAG_DROP_TEXT_SEARCH_TEMPLATE;
break; break;
case OBJECT_TSCONFIGURATION: case OBJECT_TSCONFIGURATION:
tag = "DROP TEXT SEARCH CONFIGURATION"; tag = CMDTAG_DROP_TEXT_SEARCH_CONFIGURATION;
break; break;
case OBJECT_FOREIGN_TABLE: case OBJECT_FOREIGN_TABLE:
tag = "DROP FOREIGN TABLE"; tag = CMDTAG_DROP_FOREIGN_TABLE;
break; break;
case OBJECT_EXTENSION: case OBJECT_EXTENSION:
tag = "DROP EXTENSION"; tag = CMDTAG_DROP_EXTENSION;
break; break;
case OBJECT_FUNCTION: case OBJECT_FUNCTION:
tag = "DROP FUNCTION"; tag = CMDTAG_DROP_FUNCTION;
break; break;
case OBJECT_PROCEDURE: case OBJECT_PROCEDURE:
tag = "DROP PROCEDURE"; tag = CMDTAG_DROP_PROCEDURE;
break; break;
case OBJECT_ROUTINE: case OBJECT_ROUTINE:
tag = "DROP ROUTINE"; tag = CMDTAG_DROP_ROUTINE;
break; break;
case OBJECT_AGGREGATE: case OBJECT_AGGREGATE:
tag = "DROP AGGREGATE"; tag = CMDTAG_DROP_AGGREGATE;
break; break;
case OBJECT_OPERATOR: case OBJECT_OPERATOR:
tag = "DROP OPERATOR"; tag = CMDTAG_DROP_OPERATOR;
break; break;
case OBJECT_LANGUAGE: case OBJECT_LANGUAGE:
tag = "DROP LANGUAGE"; tag = CMDTAG_DROP_LANGUAGE;
break; break;
case OBJECT_CAST: case OBJECT_CAST:
tag = "DROP CAST"; tag = CMDTAG_DROP_CAST;
break; break;
case OBJECT_TRIGGER: case OBJECT_TRIGGER:
tag = "DROP TRIGGER"; tag = CMDTAG_DROP_TRIGGER;
break; break;
case OBJECT_EVENT_TRIGGER: case OBJECT_EVENT_TRIGGER:
tag = "DROP EVENT TRIGGER"; tag = CMDTAG_DROP_EVENT_TRIGGER;
break; break;
case OBJECT_RULE: case OBJECT_RULE:
tag = "DROP RULE"; tag = CMDTAG_DROP_RULE;
break; break;
case OBJECT_FDW: case OBJECT_FDW:
tag = "DROP FOREIGN DATA WRAPPER"; tag = CMDTAG_DROP_FOREIGN_DATA_WRAPPER;
break; break;
case OBJECT_FOREIGN_SERVER: case OBJECT_FOREIGN_SERVER:
tag = "DROP SERVER"; tag = CMDTAG_DROP_SERVER;
break; break;
case OBJECT_OPCLASS: case OBJECT_OPCLASS:
tag = "DROP OPERATOR CLASS"; tag = CMDTAG_DROP_OPERATOR_CLASS;
break; break;
case OBJECT_OPFAMILY: case OBJECT_OPFAMILY:
tag = "DROP OPERATOR FAMILY"; tag = CMDTAG_DROP_OPERATOR_FAMILY;
break; break;
case OBJECT_POLICY: case OBJECT_POLICY:
tag = "DROP POLICY"; tag = CMDTAG_DROP_POLICY;
break; break;
case OBJECT_TRANSFORM: case OBJECT_TRANSFORM:
tag = "DROP TRANSFORM"; tag = CMDTAG_DROP_TRANSFORM;
break; break;
case OBJECT_ACCESS_METHOD: case OBJECT_ACCESS_METHOD:
tag = "DROP ACCESS METHOD"; tag = CMDTAG_DROP_ACCESS_METHOD;
break; break;
case OBJECT_PUBLICATION: case OBJECT_PUBLICATION:
tag = "DROP PUBLICATION"; tag = CMDTAG_DROP_PUBLICATION;
break; break;
case OBJECT_STATISTIC_EXT: case OBJECT_STATISTIC_EXT:
tag = "DROP STATISTICS"; tag = CMDTAG_DROP_STATISTICS;
break; break;
default: default:
tag = "???"; tag = CMDTAG_UNKNOWN;
} }
break; break;
case T_TruncateStmt: case T_TruncateStmt:
tag = "TRUNCATE TABLE"; tag = CMDTAG_TRUNCATE_TABLE;
break; break;
case T_CommentStmt: case T_CommentStmt:
tag = "COMMENT"; tag = CMDTAG_COMMENT;
break; break;
case T_SecLabelStmt: case T_SecLabelStmt:
tag = "SECURITY LABEL"; tag = CMDTAG_SECURITY_LABEL;
break; break;
case T_CopyStmt: case T_CopyStmt:
tag = "COPY"; tag = CMDTAG_COPY;
break; break;
case T_RenameStmt: case T_RenameStmt:
...@@ -2584,23 +2571,23 @@ CreateCommandTag(Node *parsetree) ...@@ -2584,23 +2571,23 @@ CreateCommandTag(Node *parsetree)
break; break;
case T_AlterDomainStmt: case T_AlterDomainStmt:
tag = "ALTER DOMAIN"; tag = CMDTAG_ALTER_DOMAIN;
break; break;
case T_AlterFunctionStmt: case T_AlterFunctionStmt:
switch (((AlterFunctionStmt *) parsetree)->objtype) switch (((AlterFunctionStmt *) parsetree)->objtype)
{ {
case OBJECT_FUNCTION: case OBJECT_FUNCTION:
tag = "ALTER FUNCTION"; tag = CMDTAG_ALTER_FUNCTION;
break; break;
case OBJECT_PROCEDURE: case OBJECT_PROCEDURE:
tag = "ALTER PROCEDURE"; tag = CMDTAG_ALTER_PROCEDURE;
break; break;
case OBJECT_ROUTINE: case OBJECT_ROUTINE:
tag = "ALTER ROUTINE"; tag = CMDTAG_ALTER_ROUTINE;
break; break;
default: default:
tag = "???"; tag = CMDTAG_UNKNOWN;
} }
break; break;
...@@ -2608,7 +2595,7 @@ CreateCommandTag(Node *parsetree) ...@@ -2608,7 +2595,7 @@ CreateCommandTag(Node *parsetree)
{ {
GrantStmt *stmt = (GrantStmt *) parsetree; GrantStmt *stmt = (GrantStmt *) parsetree;
tag = (stmt->is_grant) ? "GRANT" : "REVOKE"; tag = (stmt->is_grant) ? CMDTAG_GRANT : CMDTAG_REVOKE;
} }
break; break;
...@@ -2616,145 +2603,145 @@ CreateCommandTag(Node *parsetree) ...@@ -2616,145 +2603,145 @@ CreateCommandTag(Node *parsetree)
{ {
GrantRoleStmt *stmt = (GrantRoleStmt *) parsetree; GrantRoleStmt *stmt = (GrantRoleStmt *) parsetree;
tag = (stmt->is_grant) ? "GRANT ROLE" : "REVOKE ROLE"; tag = (stmt->is_grant) ? CMDTAG_GRANT_ROLE : CMDTAG_REVOKE_ROLE;
} }
break; break;
case T_AlterDefaultPrivilegesStmt: case T_AlterDefaultPrivilegesStmt:
tag = "ALTER DEFAULT PRIVILEGES"; tag = CMDTAG_ALTER_DEFAULT_PRIVILEGES;
break; break;
case T_DefineStmt: case T_DefineStmt:
switch (((DefineStmt *) parsetree)->kind) switch (((DefineStmt *) parsetree)->kind)
{ {
case OBJECT_AGGREGATE: case OBJECT_AGGREGATE:
tag = "CREATE AGGREGATE"; tag = CMDTAG_CREATE_AGGREGATE;
break; break;
case OBJECT_OPERATOR: case OBJECT_OPERATOR:
tag = "CREATE OPERATOR"; tag = CMDTAG_CREATE_OPERATOR;
break; break;
case OBJECT_TYPE: case OBJECT_TYPE:
tag = "CREATE TYPE"; tag = CMDTAG_CREATE_TYPE;
break; break;
case OBJECT_TSPARSER: case OBJECT_TSPARSER:
tag = "CREATE TEXT SEARCH PARSER"; tag = CMDTAG_CREATE_TEXT_SEARCH_PARSER;
break; break;
case OBJECT_TSDICTIONARY: case OBJECT_TSDICTIONARY:
tag = "CREATE TEXT SEARCH DICTIONARY"; tag = CMDTAG_CREATE_TEXT_SEARCH_DICTIONARY;
break; break;
case OBJECT_TSTEMPLATE: case OBJECT_TSTEMPLATE:
tag = "CREATE TEXT SEARCH TEMPLATE"; tag = CMDTAG_CREATE_TEXT_SEARCH_TEMPLATE;
break; break;
case OBJECT_TSCONFIGURATION: case OBJECT_TSCONFIGURATION:
tag = "CREATE TEXT SEARCH CONFIGURATION"; tag = CMDTAG_CREATE_TEXT_SEARCH_CONFIGURATION;
break; break;
case OBJECT_COLLATION: case OBJECT_COLLATION:
tag = "CREATE COLLATION"; tag = CMDTAG_CREATE_COLLATION;
break; break;
case OBJECT_ACCESS_METHOD: case OBJECT_ACCESS_METHOD:
tag = "CREATE ACCESS METHOD"; tag = CMDTAG_CREATE_ACCESS_METHOD;
break; break;
default: default:
tag = "???"; tag = CMDTAG_UNKNOWN;
} }
break; break;
case T_CompositeTypeStmt: case T_CompositeTypeStmt:
tag = "CREATE TYPE"; tag = CMDTAG_CREATE_TYPE;
break; break;
case T_CreateEnumStmt: case T_CreateEnumStmt:
tag = "CREATE TYPE"; tag = CMDTAG_CREATE_TYPE;
break; break;
case T_CreateRangeStmt: case T_CreateRangeStmt:
tag = "CREATE TYPE"; tag = CMDTAG_CREATE_TYPE;
break; break;
case T_AlterEnumStmt: case T_AlterEnumStmt:
tag = "ALTER TYPE"; tag = CMDTAG_ALTER_TYPE;
break; break;
case T_ViewStmt: case T_ViewStmt:
tag = "CREATE VIEW"; tag = CMDTAG_CREATE_VIEW;
break; break;
case T_CreateFunctionStmt: case T_CreateFunctionStmt:
if (((CreateFunctionStmt *) parsetree)->is_procedure) if (((CreateFunctionStmt *) parsetree)->is_procedure)
tag = "CREATE PROCEDURE"; tag = CMDTAG_CREATE_PROCEDURE;
else else
tag = "CREATE FUNCTION"; tag = CMDTAG_CREATE_FUNCTION;
break; break;
case T_IndexStmt: case T_IndexStmt:
tag = "CREATE INDEX"; tag = CMDTAG_CREATE_INDEX;
break; break;
case T_RuleStmt: case T_RuleStmt:
tag = "CREATE RULE"; tag = CMDTAG_CREATE_RULE;
break; break;
case T_CreateSeqStmt: case T_CreateSeqStmt:
tag = "CREATE SEQUENCE"; tag = CMDTAG_CREATE_SEQUENCE;
break; break;
case T_AlterSeqStmt: case T_AlterSeqStmt:
tag = "ALTER SEQUENCE"; tag = CMDTAG_ALTER_SEQUENCE;
break; break;
case T_DoStmt: case T_DoStmt:
tag = "DO"; tag = CMDTAG_DO;
break; break;
case T_CreatedbStmt: case T_CreatedbStmt:
tag = "CREATE DATABASE"; tag = CMDTAG_CREATE_DATABASE;
break; break;
case T_AlterDatabaseStmt: case T_AlterDatabaseStmt:
tag = "ALTER DATABASE"; tag = CMDTAG_ALTER_DATABASE;
break; break;
case T_AlterDatabaseSetStmt: case T_AlterDatabaseSetStmt:
tag = "ALTER DATABASE"; tag = CMDTAG_ALTER_DATABASE;
break; break;
case T_DropdbStmt: case T_DropdbStmt:
tag = "DROP DATABASE"; tag = CMDTAG_DROP_DATABASE;
break; break;
case T_NotifyStmt: case T_NotifyStmt:
tag = "NOTIFY"; tag = CMDTAG_NOTIFY;
break; break;
case T_ListenStmt: case T_ListenStmt:
tag = "LISTEN"; tag = CMDTAG_LISTEN;
break; break;
case T_UnlistenStmt: case T_UnlistenStmt:
tag = "UNLISTEN"; tag = CMDTAG_UNLISTEN;
break; break;
case T_LoadStmt: case T_LoadStmt:
tag = "LOAD"; tag = CMDTAG_LOAD;
break; break;
case T_CallStmt: case T_CallStmt:
tag = "CALL"; tag = CMDTAG_CALL;
break; break;
case T_ClusterStmt: case T_ClusterStmt:
tag = "CLUSTER"; tag = CMDTAG_CLUSTER;
break; break;
case T_VacuumStmt: case T_VacuumStmt:
if (((VacuumStmt *) parsetree)->is_vacuumcmd) if (((VacuumStmt *) parsetree)->is_vacuumcmd)
tag = "VACUUM"; tag = CMDTAG_VACUUM;
else else
tag = "ANALYZE"; tag = CMDTAG_ANALYZE;
break; break;
case T_ExplainStmt: case T_ExplainStmt:
tag = "EXPLAIN"; tag = CMDTAG_EXPLAIN;
break; break;
case T_CreateTableAsStmt: case T_CreateTableAsStmt:
...@@ -2762,24 +2749,24 @@ CreateCommandTag(Node *parsetree) ...@@ -2762,24 +2749,24 @@ CreateCommandTag(Node *parsetree)
{ {
case OBJECT_TABLE: case OBJECT_TABLE:
if (((CreateTableAsStmt *) parsetree)->is_select_into) if (((CreateTableAsStmt *) parsetree)->is_select_into)
tag = "SELECT INTO"; tag = CMDTAG_SELECT_INTO;
else else
tag = "CREATE TABLE AS"; tag = CMDTAG_CREATE_TABLE_AS;
break; break;
case OBJECT_MATVIEW: case OBJECT_MATVIEW:
tag = "CREATE MATERIALIZED VIEW"; tag = CMDTAG_CREATE_MATERIALIZED_VIEW;
break; break;
default: default:
tag = "???"; tag = CMDTAG_UNKNOWN;
} }
break; break;
case T_RefreshMatViewStmt: case T_RefreshMatViewStmt:
tag = "REFRESH MATERIALIZED VIEW"; tag = CMDTAG_REFRESH_MATERIALIZED_VIEW;
break; break;
case T_AlterSystemStmt: case T_AlterSystemStmt:
tag = "ALTER SYSTEM"; tag = CMDTAG_ALTER_SYSTEM;
break; break;
case T_VariableSetStmt: case T_VariableSetStmt:
...@@ -2789,183 +2776,183 @@ CreateCommandTag(Node *parsetree) ...@@ -2789,183 +2776,183 @@ CreateCommandTag(Node *parsetree)
case VAR_SET_CURRENT: case VAR_SET_CURRENT:
case VAR_SET_DEFAULT: case VAR_SET_DEFAULT:
case VAR_SET_MULTI: case VAR_SET_MULTI:
tag = "SET"; tag = CMDTAG_SET;
break; break;
case VAR_RESET: case VAR_RESET:
case VAR_RESET_ALL: case VAR_RESET_ALL:
tag = "RESET"; tag = CMDTAG_RESET;
break; break;
default: default:
tag = "???"; tag = CMDTAG_UNKNOWN;
} }
break; break;
case T_VariableShowStmt: case T_VariableShowStmt:
tag = "SHOW"; tag = CMDTAG_SHOW;
break; break;
case T_DiscardStmt: case T_DiscardStmt:
switch (((DiscardStmt *) parsetree)->target) switch (((DiscardStmt *) parsetree)->target)
{ {
case DISCARD_ALL: case DISCARD_ALL:
tag = "DISCARD ALL"; tag = CMDTAG_DISCARD_ALL;
break; break;
case DISCARD_PLANS: case DISCARD_PLANS:
tag = "DISCARD PLANS"; tag = CMDTAG_DISCARD_PLANS;
break; break;
case DISCARD_TEMP: case DISCARD_TEMP:
tag = "DISCARD TEMP"; tag = CMDTAG_DISCARD_TEMP;
break; break;
case DISCARD_SEQUENCES: case DISCARD_SEQUENCES:
tag = "DISCARD SEQUENCES"; tag = CMDTAG_DISCARD_SEQUENCES;
break; break;
default: default:
tag = "???"; tag = CMDTAG_UNKNOWN;
} }
break; break;
case T_CreateTransformStmt: case T_CreateTransformStmt:
tag = "CREATE TRANSFORM"; tag = CMDTAG_CREATE_TRANSFORM;
break; break;
case T_CreateTrigStmt: case T_CreateTrigStmt:
tag = "CREATE TRIGGER"; tag = CMDTAG_CREATE_TRIGGER;
break; break;
case T_CreateEventTrigStmt: case T_CreateEventTrigStmt:
tag = "CREATE EVENT TRIGGER"; tag = CMDTAG_CREATE_EVENT_TRIGGER;
break; break;
case T_AlterEventTrigStmt: case T_AlterEventTrigStmt:
tag = "ALTER EVENT TRIGGER"; tag = CMDTAG_ALTER_EVENT_TRIGGER;
break; break;
case T_CreatePLangStmt: case T_CreatePLangStmt:
tag = "CREATE LANGUAGE"; tag = CMDTAG_CREATE_LANGUAGE;
break; break;
case T_CreateRoleStmt: case T_CreateRoleStmt:
tag = "CREATE ROLE"; tag = CMDTAG_CREATE_ROLE;
break; break;
case T_AlterRoleStmt: case T_AlterRoleStmt:
tag = "ALTER ROLE"; tag = CMDTAG_ALTER_ROLE;
break; break;
case T_AlterRoleSetStmt: case T_AlterRoleSetStmt:
tag = "ALTER ROLE"; tag = CMDTAG_ALTER_ROLE;
break; break;
case T_DropRoleStmt: case T_DropRoleStmt:
tag = "DROP ROLE"; tag = CMDTAG_DROP_ROLE;
break; break;
case T_DropOwnedStmt: case T_DropOwnedStmt:
tag = "DROP OWNED"; tag = CMDTAG_DROP_OWNED;
break; break;
case T_ReassignOwnedStmt: case T_ReassignOwnedStmt:
tag = "REASSIGN OWNED"; tag = CMDTAG_REASSIGN_OWNED;
break; break;
case T_LockStmt: case T_LockStmt:
tag = "LOCK TABLE"; tag = CMDTAG_LOCK_TABLE;
break; break;
case T_ConstraintsSetStmt: case T_ConstraintsSetStmt:
tag = "SET CONSTRAINTS"; tag = CMDTAG_SET_CONSTRAINTS;
break; break;
case T_CheckPointStmt: case T_CheckPointStmt:
tag = "CHECKPOINT"; tag = CMDTAG_CHECKPOINT;
break; break;
case T_ReindexStmt: case T_ReindexStmt:
tag = "REINDEX"; tag = CMDTAG_REINDEX;
break; break;
case T_CreateConversionStmt: case T_CreateConversionStmt:
tag = "CREATE CONVERSION"; tag = CMDTAG_CREATE_CONVERSION;
break; break;
case T_CreateCastStmt: case T_CreateCastStmt:
tag = "CREATE CAST"; tag = CMDTAG_CREATE_CAST;
break; break;
case T_CreateOpClassStmt: case T_CreateOpClassStmt:
tag = "CREATE OPERATOR CLASS"; tag = CMDTAG_CREATE_OPERATOR_CLASS;
break; break;
case T_CreateOpFamilyStmt: case T_CreateOpFamilyStmt:
tag = "CREATE OPERATOR FAMILY"; tag = CMDTAG_CREATE_OPERATOR_FAMILY;
break; break;
case T_AlterOpFamilyStmt: case T_AlterOpFamilyStmt:
tag = "ALTER OPERATOR FAMILY"; tag = CMDTAG_ALTER_OPERATOR_FAMILY;
break; break;
case T_AlterOperatorStmt: case T_AlterOperatorStmt:
tag = "ALTER OPERATOR"; tag = CMDTAG_ALTER_OPERATOR;
break; break;
case T_AlterTSDictionaryStmt: case T_AlterTSDictionaryStmt:
tag = "ALTER TEXT SEARCH DICTIONARY"; tag = CMDTAG_ALTER_TEXT_SEARCH_DICTIONARY;
break; break;
case T_AlterTSConfigurationStmt: case T_AlterTSConfigurationStmt:
tag = "ALTER TEXT SEARCH CONFIGURATION"; tag = CMDTAG_ALTER_TEXT_SEARCH_CONFIGURATION;
break; break;
case T_CreatePolicyStmt: case T_CreatePolicyStmt:
tag = "CREATE POLICY"; tag = CMDTAG_CREATE_POLICY;
break; break;
case T_AlterPolicyStmt: case T_AlterPolicyStmt:
tag = "ALTER POLICY"; tag = CMDTAG_ALTER_POLICY;
break; break;
case T_CreateAmStmt: case T_CreateAmStmt:
tag = "CREATE ACCESS METHOD"; tag = CMDTAG_CREATE_ACCESS_METHOD;
break; break;
case T_CreatePublicationStmt: case T_CreatePublicationStmt:
tag = "CREATE PUBLICATION"; tag = CMDTAG_CREATE_PUBLICATION;
break; break;
case T_AlterPublicationStmt: case T_AlterPublicationStmt:
tag = "ALTER PUBLICATION"; tag = CMDTAG_ALTER_PUBLICATION;
break; break;
case T_CreateSubscriptionStmt: case T_CreateSubscriptionStmt:
tag = "CREATE SUBSCRIPTION"; tag = CMDTAG_CREATE_SUBSCRIPTION;
break; break;
case T_AlterSubscriptionStmt: case T_AlterSubscriptionStmt:
tag = "ALTER SUBSCRIPTION"; tag = CMDTAG_ALTER_SUBSCRIPTION;
break; break;
case T_DropSubscriptionStmt: case T_DropSubscriptionStmt:
tag = "DROP SUBSCRIPTION"; tag = CMDTAG_DROP_SUBSCRIPTION;
break; break;
case T_AlterCollationStmt: case T_AlterCollationStmt:
tag = "ALTER COLLATION"; tag = CMDTAG_ALTER_COLLATION;
break; break;
case T_PrepareStmt: case T_PrepareStmt:
tag = "PREPARE"; tag = CMDTAG_PREPARE;
break; break;
case T_ExecuteStmt: case T_ExecuteStmt:
tag = "EXECUTE"; tag = CMDTAG_EXECUTE;
break; break;
case T_CreateStatsStmt: case T_CreateStatsStmt:
tag = "CREATE STATISTICS"; tag = CMDTAG_CREATE_STATISTICS;
break; break;
case T_AlterStatsStmt: case T_AlterStatsStmt:
tag = "ALTER STATISTICS"; tag = CMDTAG_ALTER_STATISTICS;
break; break;
case T_DeallocateStmt: case T_DeallocateStmt:
...@@ -2973,9 +2960,9 @@ CreateCommandTag(Node *parsetree) ...@@ -2973,9 +2960,9 @@ CreateCommandTag(Node *parsetree)
DeallocateStmt *stmt = (DeallocateStmt *) parsetree; DeallocateStmt *stmt = (DeallocateStmt *) parsetree;
if (stmt->name == NULL) if (stmt->name == NULL)
tag = "DEALLOCATE ALL"; tag = CMDTAG_DEALLOCATE_ALL;
else else
tag = "DEALLOCATE"; tag = CMDTAG_DEALLOCATE;
} }
break; break;
...@@ -2999,33 +2986,33 @@ CreateCommandTag(Node *parsetree) ...@@ -2999,33 +2986,33 @@ CreateCommandTag(Node *parsetree)
switch (((PlanRowMark *) linitial(stmt->rowMarks))->strength) switch (((PlanRowMark *) linitial(stmt->rowMarks))->strength)
{ {
case LCS_FORKEYSHARE: case LCS_FORKEYSHARE:
tag = "SELECT FOR KEY SHARE"; tag = CMDTAG_SELECT_FOR_KEY_SHARE;
break; break;
case LCS_FORSHARE: case LCS_FORSHARE:
tag = "SELECT FOR SHARE"; tag = CMDTAG_SELECT_FOR_SHARE;
break; break;
case LCS_FORNOKEYUPDATE: case LCS_FORNOKEYUPDATE:
tag = "SELECT FOR NO KEY UPDATE"; tag = CMDTAG_SELECT_FOR_NO_KEY_UPDATE;
break; break;
case LCS_FORUPDATE: case LCS_FORUPDATE:
tag = "SELECT FOR UPDATE"; tag = CMDTAG_SELECT_FOR_UPDATE;
break; break;
default: default:
tag = "SELECT"; tag = CMDTAG_SELECT;
break; break;
} }
} }
else else
tag = "SELECT"; tag = CMDTAG_SELECT;
break; break;
case CMD_UPDATE: case CMD_UPDATE:
tag = "UPDATE"; tag = CMDTAG_UPDATE;
break; break;
case CMD_INSERT: case CMD_INSERT:
tag = "INSERT"; tag = CMDTAG_INSERT;
break; break;
case CMD_DELETE: case CMD_DELETE:
tag = "DELETE"; tag = CMDTAG_DELETE;
break; break;
case CMD_UTILITY: case CMD_UTILITY:
tag = CreateCommandTag(stmt->utilityStmt); tag = CreateCommandTag(stmt->utilityStmt);
...@@ -3033,7 +3020,7 @@ CreateCommandTag(Node *parsetree) ...@@ -3033,7 +3020,7 @@ CreateCommandTag(Node *parsetree)
default: default:
elog(WARNING, "unrecognized commandType: %d", elog(WARNING, "unrecognized commandType: %d",
(int) stmt->commandType); (int) stmt->commandType);
tag = "???"; tag = CMDTAG_UNKNOWN;
break; break;
} }
} }
...@@ -3059,33 +3046,33 @@ CreateCommandTag(Node *parsetree) ...@@ -3059,33 +3046,33 @@ CreateCommandTag(Node *parsetree)
switch (((RowMarkClause *) linitial(stmt->rowMarks))->strength) switch (((RowMarkClause *) linitial(stmt->rowMarks))->strength)
{ {
case LCS_FORKEYSHARE: case LCS_FORKEYSHARE:
tag = "SELECT FOR KEY SHARE"; tag = CMDTAG_SELECT_FOR_KEY_SHARE;
break; break;
case LCS_FORSHARE: case LCS_FORSHARE:
tag = "SELECT FOR SHARE"; tag = CMDTAG_SELECT_FOR_SHARE;
break; break;
case LCS_FORNOKEYUPDATE: case LCS_FORNOKEYUPDATE:
tag = "SELECT FOR NO KEY UPDATE"; tag = CMDTAG_SELECT_FOR_NO_KEY_UPDATE;
break; break;
case LCS_FORUPDATE: case LCS_FORUPDATE:
tag = "SELECT FOR UPDATE"; tag = CMDTAG_SELECT_FOR_UPDATE;
break; break;
default: default:
tag = "???"; tag = CMDTAG_UNKNOWN;
break; break;
} }
} }
else else
tag = "SELECT"; tag = CMDTAG_SELECT;
break; break;
case CMD_UPDATE: case CMD_UPDATE:
tag = "UPDATE"; tag = CMDTAG_UPDATE;
break; break;
case CMD_INSERT: case CMD_INSERT:
tag = "INSERT"; tag = CMDTAG_INSERT;
break; break;
case CMD_DELETE: case CMD_DELETE:
tag = "DELETE"; tag = CMDTAG_DELETE;
break; break;
case CMD_UTILITY: case CMD_UTILITY:
tag = CreateCommandTag(stmt->utilityStmt); tag = CreateCommandTag(stmt->utilityStmt);
...@@ -3093,7 +3080,7 @@ CreateCommandTag(Node *parsetree) ...@@ -3093,7 +3080,7 @@ CreateCommandTag(Node *parsetree)
default: default:
elog(WARNING, "unrecognized commandType: %d", elog(WARNING, "unrecognized commandType: %d",
(int) stmt->commandType); (int) stmt->commandType);
tag = "???"; tag = CMDTAG_UNKNOWN;
break; break;
} }
} }
...@@ -3102,7 +3089,7 @@ CreateCommandTag(Node *parsetree) ...@@ -3102,7 +3089,7 @@ CreateCommandTag(Node *parsetree)
default: default:
elog(WARNING, "unrecognized node type: %d", elog(WARNING, "unrecognized node type: %d",
(int) nodeTag(parsetree)); (int) nodeTag(parsetree));
tag = "???"; tag = CMDTAG_UNKNOWN;
break; break;
} }
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include "catalog/pg_event_trigger.h" #include "catalog/pg_event_trigger.h"
#include "catalog/pg_type.h" #include "catalog/pg_type.h"
#include "commands/trigger.h" #include "commands/trigger.h"
#include "tcop/cmdtag.h"
#include "utils/array.h" #include "utils/array.h"
#include "utils/builtins.h" #include "utils/builtins.h"
#include "utils/catcache.h" #include "utils/catcache.h"
...@@ -51,7 +52,7 @@ static EventTriggerCacheStateType EventTriggerCacheState = ETCS_NEEDS_REBUILD; ...@@ -51,7 +52,7 @@ static EventTriggerCacheStateType EventTriggerCacheState = ETCS_NEEDS_REBUILD;
static void BuildEventTriggerCache(void); static void BuildEventTriggerCache(void);
static void InvalidateEventCacheCallback(Datum arg, static void InvalidateEventCacheCallback(Datum arg,
int cacheid, uint32 hashvalue); int cacheid, uint32 hashvalue);
static int DecodeTextArrayToCString(Datum array, char ***cstringp); static Bitmapset *DecodeTextArrayToBitmapset(Datum array);
/* /*
* Search the event cache by trigger event. * Search the event cache by trigger event.
...@@ -180,10 +181,7 @@ BuildEventTriggerCache(void) ...@@ -180,10 +181,7 @@ BuildEventTriggerCache(void)
evttags = heap_getattr(tup, Anum_pg_event_trigger_evttags, evttags = heap_getattr(tup, Anum_pg_event_trigger_evttags,
RelationGetDescr(rel), &evttags_isnull); RelationGetDescr(rel), &evttags_isnull);
if (!evttags_isnull) if (!evttags_isnull)
{ item->tagset = DecodeTextArrayToBitmapset(evttags);
item->ntags = DecodeTextArrayToCString(evttags, &item->tag);
qsort(item->tag, item->ntags, sizeof(char *), pg_qsort_strcmp);
}
/* Add to cache entry. */ /* Add to cache entry. */
entry = hash_search(cache, &event, HASH_ENTER, &found); entry = hash_search(cache, &event, HASH_ENTER, &found);
...@@ -215,18 +213,18 @@ BuildEventTriggerCache(void) ...@@ -215,18 +213,18 @@ BuildEventTriggerCache(void)
} }
/* /*
* Decode text[] to an array of C strings. * Decode text[] to a Bitmapset of CommandTags.
* *
* We could avoid a bit of overhead here if we were willing to duplicate some * We could avoid a bit of overhead here if we were willing to duplicate some
* of the logic from deconstruct_array, but it doesn't seem worth the code * of the logic from deconstruct_array, but it doesn't seem worth the code
* complexity. * complexity.
*/ */
static int static Bitmapset *
DecodeTextArrayToCString(Datum array, char ***cstringp) DecodeTextArrayToBitmapset(Datum array)
{ {
ArrayType *arr = DatumGetArrayTypeP(array); ArrayType *arr = DatumGetArrayTypeP(array);
Datum *elems; Datum *elems;
char **cstring; Bitmapset *bms;
int i; int i;
int nelems; int nelems;
...@@ -234,13 +232,17 @@ DecodeTextArrayToCString(Datum array, char ***cstringp) ...@@ -234,13 +232,17 @@ DecodeTextArrayToCString(Datum array, char ***cstringp)
elog(ERROR, "expected 1-D text array"); elog(ERROR, "expected 1-D text array");
deconstruct_array(arr, TEXTOID, -1, false, 'i', &elems, NULL, &nelems); deconstruct_array(arr, TEXTOID, -1, false, 'i', &elems, NULL, &nelems);
cstring = palloc(nelems * sizeof(char *)); for (bms = NULL, i = 0; i < nelems; ++i)
for (i = 0; i < nelems; ++i) {
cstring[i] = TextDatumGetCString(elems[i]); char *str = TextDatumGetCString(elems[i]);
bms = bms_add_member(bms, GetCommandTagEnum(str));
pfree(str);
}
pfree(elems); pfree(elems);
*cstringp = cstring;
return nelems; return bms;
} }
/* /*
......
...@@ -158,12 +158,12 @@ InitPlanCache(void) ...@@ -158,12 +158,12 @@ InitPlanCache(void)
* *
* raw_parse_tree: output of raw_parser(), or NULL if empty query * raw_parse_tree: output of raw_parser(), or NULL if empty query
* query_string: original query text * query_string: original query text
* commandTag: compile-time-constant tag for query, or NULL if empty query * commandTag: command tag for query, or UNKNOWN if empty query
*/ */
CachedPlanSource * CachedPlanSource *
CreateCachedPlan(RawStmt *raw_parse_tree, CreateCachedPlan(RawStmt *raw_parse_tree,
const char *query_string, const char *query_string,
const char *commandTag) CommandTag commandTag)
{ {
CachedPlanSource *plansource; CachedPlanSource *plansource;
MemoryContext source_context; MemoryContext source_context;
...@@ -241,12 +241,12 @@ CreateCachedPlan(RawStmt *raw_parse_tree, ...@@ -241,12 +241,12 @@ CreateCachedPlan(RawStmt *raw_parse_tree,
* *
* raw_parse_tree: output of raw_parser(), or NULL if empty query * raw_parse_tree: output of raw_parser(), or NULL if empty query
* query_string: original query text * query_string: original query text
* commandTag: compile-time-constant tag for query, or NULL if empty query * commandTag: command tag for query, or NULL if empty query
*/ */
CachedPlanSource * CachedPlanSource *
CreateOneShotCachedPlan(RawStmt *raw_parse_tree, CreateOneShotCachedPlan(RawStmt *raw_parse_tree,
const char *query_string, const char *query_string,
const char *commandTag) CommandTag commandTag)
{ {
CachedPlanSource *plansource; CachedPlanSource *plansource;
......
...@@ -281,7 +281,7 @@ void ...@@ -281,7 +281,7 @@ void
PortalDefineQuery(Portal portal, PortalDefineQuery(Portal portal,
const char *prepStmtName, const char *prepStmtName,
const char *sourceText, const char *sourceText,
const char *commandTag, CommandTag commandTag,
List *stmts, List *stmts,
CachedPlan *cplan) CachedPlan *cplan)
{ {
...@@ -289,10 +289,12 @@ PortalDefineQuery(Portal portal, ...@@ -289,10 +289,12 @@ PortalDefineQuery(Portal portal,
AssertState(portal->status == PORTAL_NEW); AssertState(portal->status == PORTAL_NEW);
AssertArg(sourceText != NULL); AssertArg(sourceText != NULL);
AssertArg(commandTag != NULL || stmts == NIL); AssertArg(commandTag != CMDTAG_UNKNOWN || stmts == NIL);
portal->prepStmtName = prepStmtName; portal->prepStmtName = prepStmtName;
portal->sourceText = sourceText; portal->sourceText = sourceText;
portal->qc.commandTag = commandTag;
portal->qc.nprocessed = 0;
portal->commandTag = commandTag; portal->commandTag = commandTag;
portal->stmts = stmts; portal->stmts = stmts;
portal->cplan = cplan; portal->cplan = cplan;
......
...@@ -22,7 +22,8 @@ ...@@ -22,7 +22,8 @@
extern ObjectAddress ExecCreateTableAs(ParseState *pstate, CreateTableAsStmt *stmt, extern ObjectAddress ExecCreateTableAs(ParseState *pstate, CreateTableAsStmt *stmt,
ParamListInfo params, QueryEnvironment *queryEnv, char *completionTag); ParamListInfo params, QueryEnvironment *queryEnv,
QueryCompletion *qc);
extern int GetIntoRelEFlags(IntoClause *intoClause); extern int GetIntoRelEFlags(IntoClause *intoClause);
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include "catalog/objectaddress.h" #include "catalog/objectaddress.h"
#include "catalog/pg_event_trigger.h" #include "catalog/pg_event_trigger.h"
#include "nodes/parsenodes.h" #include "nodes/parsenodes.h"
#include "tcop/cmdtag.h"
#include "tcop/deparse_utility.h" #include "tcop/deparse_utility.h"
#include "utils/aclchk_internal.h" #include "utils/aclchk_internal.h"
...@@ -25,7 +26,7 @@ typedef struct EventTriggerData ...@@ -25,7 +26,7 @@ typedef struct EventTriggerData
NodeTag type; NodeTag type;
const char *event; /* event name */ const char *event; /* event name */
Node *parsetree; /* parse tree */ Node *parsetree; /* parse tree */
const char *tag; /* command tag */ CommandTag tag;
} EventTriggerData; } EventTriggerData;
#define AT_REWRITE_ALTER_PERSISTENCE 0x01 #define AT_REWRITE_ALTER_PERSISTENCE 0x01
......
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
extern void SetMatViewPopulatedState(Relation relation, bool newstate); extern void SetMatViewPopulatedState(Relation relation, bool newstate);
extern ObjectAddress ExecRefreshMatView(RefreshMatViewStmt *stmt, const char *queryString, extern ObjectAddress ExecRefreshMatView(RefreshMatViewStmt *stmt, const char *queryString,
ParamListInfo params, char *completionTag); ParamListInfo params, QueryCompletion *qc);
extern DestReceiver *CreateTransientRelDestReceiver(Oid oid); extern DestReceiver *CreateTransientRelDestReceiver(Oid oid);
......
...@@ -23,7 +23,7 @@ extern void PerformCursorOpen(ParseState *pstate, DeclareCursorStmt *cstmt, Para ...@@ -23,7 +23,7 @@ extern void PerformCursorOpen(ParseState *pstate, DeclareCursorStmt *cstmt, Para
bool isTopLevel); bool isTopLevel);
extern void PerformPortalFetch(FetchStmt *stmt, DestReceiver *dest, extern void PerformPortalFetch(FetchStmt *stmt, DestReceiver *dest,
char *completionTag); QueryCompletion *qc);
extern void PerformPortalClose(const char *name); extern void PerformPortalClose(const char *name);
......
...@@ -40,7 +40,7 @@ extern void PrepareQuery(ParseState *pstate, PrepareStmt *stmt, ...@@ -40,7 +40,7 @@ extern void PrepareQuery(ParseState *pstate, PrepareStmt *stmt,
extern void ExecuteQuery(ParseState *pstate, extern void ExecuteQuery(ParseState *pstate,
ExecuteStmt *stmt, IntoClause *intoClause, ExecuteStmt *stmt, IntoClause *intoClause,
ParamListInfo params, ParamListInfo params,
DestReceiver *dest, char *completionTag); DestReceiver *dest, QueryCompletion *qc);
extern void DeallocateQuery(DeallocateStmt *stmt); extern void DeallocateQuery(DeallocateStmt *stmt);
extern void ExplainExecuteQuery(ExecuteStmt *execstmt, IntoClause *into, extern void ExplainExecuteQuery(ExecuteStmt *execstmt, IntoClause *into,
ExplainState *es, const char *queryString, ExplainState *es, const char *queryString,
......
/*-------------------------------------------------------------------------
*
* cmdtag.h
* Declarations for commandtag names and enumeration.
*
* Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* src/include/tcop/cmdtag.h
*
*-------------------------------------------------------------------------
*/
#ifndef CMDTAG_H
#define CMDTAG_H
#define PG_CMDTAG(tag, name, evtrgok, rwrok, rowcnt) \
tag,
typedef enum CommandTag
{
#include "tcop/cmdtaglist.h"
COMMAND_TAG_NEXTTAG
} CommandTag;
#undef PG_CMDTAG
typedef struct QueryCompletion
{
CommandTag commandTag;
uint64 nprocessed;
} QueryCompletion;
static inline void
SetQueryCompletion(QueryCompletion *qc, CommandTag commandTag,
uint64 nprocessed)
{
qc->commandTag = commandTag;
qc->nprocessed = nprocessed;
}
static inline void
CopyQueryCompletion(QueryCompletion *dst, const QueryCompletion *src)
{
dst->commandTag = src->commandTag;
dst->nprocessed = src->nprocessed;
}
extern void InitializeQueryCompletion(QueryCompletion *qc);
extern const char *GetCommandTagName(CommandTag commandTag);
extern bool command_tag_display_rowcount(CommandTag commandTag);
extern bool command_tag_event_trigger_ok(CommandTag commandTag);
extern bool command_tag_table_rewrite_ok(CommandTag commandTag);
extern CommandTag GetCommandTagEnum(const char *tagname);
#endif /* CMDTAG_H */
/*----------------------------------------------------------------------
*
* cmdtaglist.h
* Command tags
*
* The command tag list is kept in its own source file for possible use
* by automatic tools. The exact representation of a command tag is
* determined by the PG_CMDTAG macro, which is not defined in this file;
* it can be defined by the caller for special purposes.
*
* Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* src/backend/tcop/cmdtaglist.h
*
*----------------------------------------------------------------------
*/
/* there is deliberately not an #ifndef CMDTAGLIST_H here */
/*
* List of command tags. The entries must be sorted alphabetically on their
* textual name, so that we can bsearch on it; see GetCommandTagEnum().
*/
/* symbol name, textual name, event_trigger_ok, table_rewrite_ok, rowcount, last_oid */
PG_CMDTAG(CMDTAG_UNKNOWN, "???", false, false, false)
PG_CMDTAG(CMDTAG_ALTER_ACCESS_METHOD, "ALTER ACCESS METHOD", true, false, false)
PG_CMDTAG(CMDTAG_ALTER_AGGREGATE, "ALTER AGGREGATE", true, false, false)
PG_CMDTAG(CMDTAG_ALTER_CAST, "ALTER CAST", true, false, false)
PG_CMDTAG(CMDTAG_ALTER_COLLATION, "ALTER COLLATION", true, false, false)
PG_CMDTAG(CMDTAG_ALTER_CONSTRAINT, "ALTER CONSTRAINT", true, false, false)
PG_CMDTAG(CMDTAG_ALTER_CONVERSION, "ALTER CONVERSION", true, false, false)
PG_CMDTAG(CMDTAG_ALTER_DATABASE, "ALTER DATABASE", false, false, false)
PG_CMDTAG(CMDTAG_ALTER_DEFAULT_PRIVILEGES, "ALTER DEFAULT PRIVILEGES", true, false, false)
PG_CMDTAG(CMDTAG_ALTER_DOMAIN, "ALTER DOMAIN", true, false, false)
PG_CMDTAG(CMDTAG_ALTER_EVENT_TRIGGER, "ALTER EVENT TRIGGER", false, false, false)
PG_CMDTAG(CMDTAG_ALTER_EXTENSION, "ALTER EXTENSION", true, false, false)
PG_CMDTAG(CMDTAG_ALTER_FOREIGN_DATA_WRAPPER, "ALTER FOREIGN DATA WRAPPER", true, false, false)
PG_CMDTAG(CMDTAG_ALTER_FOREIGN_TABLE, "ALTER FOREIGN TABLE", true, false, false)
PG_CMDTAG(CMDTAG_ALTER_FUNCTION, "ALTER FUNCTION", true, false, false)
PG_CMDTAG(CMDTAG_ALTER_INDEX, "ALTER INDEX", true, false, false)
PG_CMDTAG(CMDTAG_ALTER_LANGUAGE, "ALTER LANGUAGE", true, false, false)
PG_CMDTAG(CMDTAG_ALTER_LARGE_OBJECT, "ALTER LARGE OBJECT", true, false, false)
PG_CMDTAG(CMDTAG_ALTER_MATERIALIZED_VIEW, "ALTER MATERIALIZED VIEW", true, false, false)
PG_CMDTAG(CMDTAG_ALTER_OPERATOR, "ALTER OPERATOR", true, false, false)
PG_CMDTAG(CMDTAG_ALTER_OPERATOR_CLASS, "ALTER OPERATOR CLASS", true, false, false)
PG_CMDTAG(CMDTAG_ALTER_OPERATOR_FAMILY, "ALTER OPERATOR FAMILY", true, false, false)
PG_CMDTAG(CMDTAG_ALTER_POLICY, "ALTER POLICY", true, false, false)
PG_CMDTAG(CMDTAG_ALTER_PROCEDURE, "ALTER PROCEDURE", true, false, false)
PG_CMDTAG(CMDTAG_ALTER_PUBLICATION, "ALTER PUBLICATION", true, false, false)
PG_CMDTAG(CMDTAG_ALTER_ROLE, "ALTER ROLE", false, false, false)
PG_CMDTAG(CMDTAG_ALTER_ROUTINE, "ALTER ROUTINE", true, false, false)
PG_CMDTAG(CMDTAG_ALTER_RULE, "ALTER RULE", true, false, false)
PG_CMDTAG(CMDTAG_ALTER_SCHEMA, "ALTER SCHEMA", true, false, false)
PG_CMDTAG(CMDTAG_ALTER_SEQUENCE, "ALTER SEQUENCE", true, false, false)
PG_CMDTAG(CMDTAG_ALTER_SERVER, "ALTER SERVER", true, false, false)
PG_CMDTAG(CMDTAG_ALTER_STATISTICS, "ALTER STATISTICS", true, false, false)
PG_CMDTAG(CMDTAG_ALTER_SUBSCRIPTION, "ALTER SUBSCRIPTION", true, false, false)
PG_CMDTAG(CMDTAG_ALTER_SYSTEM, "ALTER SYSTEM", false, false, false)
PG_CMDTAG(CMDTAG_ALTER_TABLE, "ALTER TABLE", true, true, false)
PG_CMDTAG(CMDTAG_ALTER_TABLESPACE, "ALTER TABLESPACE", false, false, false)
PG_CMDTAG(CMDTAG_ALTER_TEXT_SEARCH_CONFIGURATION, "ALTER TEXT SEARCH CONFIGURATION", true, false, false)
PG_CMDTAG(CMDTAG_ALTER_TEXT_SEARCH_DICTIONARY, "ALTER TEXT SEARCH DICTIONARY", true, false, false)
PG_CMDTAG(CMDTAG_ALTER_TEXT_SEARCH_PARSER, "ALTER TEXT SEARCH PARSER", true, false, false)
PG_CMDTAG(CMDTAG_ALTER_TEXT_SEARCH_TEMPLATE, "ALTER TEXT SEARCH TEMPLATE", true, false, false)
PG_CMDTAG(CMDTAG_ALTER_TRANSFORM, "ALTER TRANSFORM", true, false, false)
PG_CMDTAG(CMDTAG_ALTER_TRIGGER, "ALTER TRIGGER", true, false, false)
PG_CMDTAG(CMDTAG_ALTER_TYPE, "ALTER TYPE", true, true, false)
PG_CMDTAG(CMDTAG_ALTER_USER_MAPPING, "ALTER USER MAPPING", true, false, false)
PG_CMDTAG(CMDTAG_ALTER_VIEW, "ALTER VIEW", true, false, false)
PG_CMDTAG(CMDTAG_ANALYZE, "ANALYZE", false, false, false)
PG_CMDTAG(CMDTAG_BEGIN, "BEGIN", false, false, false)
PG_CMDTAG(CMDTAG_CALL, "CALL", false, false, false)
PG_CMDTAG(CMDTAG_CHECKPOINT, "CHECKPOINT", false, false, false)
PG_CMDTAG(CMDTAG_CLOSE, "CLOSE", false, false, false)
PG_CMDTAG(CMDTAG_CLOSE_CURSOR, "CLOSE CURSOR", false, false, false)
PG_CMDTAG(CMDTAG_CLOSE_CURSOR_ALL, "CLOSE CURSOR ALL", false, false, false)
PG_CMDTAG(CMDTAG_CLUSTER, "CLUSTER", false, false, false)
PG_CMDTAG(CMDTAG_COMMENT, "COMMENT", true, false, false)
PG_CMDTAG(CMDTAG_COMMIT, "COMMIT", false, false, false)
PG_CMDTAG(CMDTAG_COMMIT_PREPARED, "COMMIT PREPARED", false, false, false)
PG_CMDTAG(CMDTAG_COPY, "COPY", false, false, true)
PG_CMDTAG(CMDTAG_COPY_FROM, "COPY FROM", false, false, false)
PG_CMDTAG(CMDTAG_CREATE_ACCESS_METHOD, "CREATE ACCESS METHOD", true, false, false)
PG_CMDTAG(CMDTAG_CREATE_AGGREGATE, "CREATE AGGREGATE", true, false, false)
PG_CMDTAG(CMDTAG_CREATE_CAST, "CREATE CAST", true, false, false)
PG_CMDTAG(CMDTAG_CREATE_COLLATION, "CREATE COLLATION", true, false, false)
PG_CMDTAG(CMDTAG_CREATE_CONSTRAINT, "CREATE CONSTRAINT", true, false, false)
PG_CMDTAG(CMDTAG_CREATE_CONVERSION, "CREATE CONVERSION", true, false, false)
PG_CMDTAG(CMDTAG_CREATE_DATABASE, "CREATE DATABASE", false, false, false)
PG_CMDTAG(CMDTAG_CREATE_DOMAIN, "CREATE DOMAIN", true, false, false)
PG_CMDTAG(CMDTAG_CREATE_EVENT_TRIGGER, "CREATE EVENT TRIGGER", false, false, false)
PG_CMDTAG(CMDTAG_CREATE_EXTENSION, "CREATE EXTENSION", true, false, false)
PG_CMDTAG(CMDTAG_CREATE_FOREIGN_DATA_WRAPPER, "CREATE FOREIGN DATA WRAPPER", true, false, false)
PG_CMDTAG(CMDTAG_CREATE_FOREIGN_TABLE, "CREATE FOREIGN TABLE", true, false, false)
PG_CMDTAG(CMDTAG_CREATE_FUNCTION, "CREATE FUNCTION", true, false, false)
PG_CMDTAG(CMDTAG_CREATE_INDEX, "CREATE INDEX", true, false, false)
PG_CMDTAG(CMDTAG_CREATE_LANGUAGE, "CREATE LANGUAGE", true, false, false)
PG_CMDTAG(CMDTAG_CREATE_MATERIALIZED_VIEW, "CREATE MATERIALIZED VIEW", true, false, false)
PG_CMDTAG(CMDTAG_CREATE_OPERATOR, "CREATE OPERATOR", true, false, false)
PG_CMDTAG(CMDTAG_CREATE_OPERATOR_CLASS, "CREATE OPERATOR CLASS", true, false, false)
PG_CMDTAG(CMDTAG_CREATE_OPERATOR_FAMILY, "CREATE OPERATOR FAMILY", true, false, false)
PG_CMDTAG(CMDTAG_CREATE_POLICY, "CREATE POLICY", true, false, false)
PG_CMDTAG(CMDTAG_CREATE_PROCEDURE, "CREATE PROCEDURE", true, false, false)
PG_CMDTAG(CMDTAG_CREATE_PUBLICATION, "CREATE PUBLICATION", true, false, false)
PG_CMDTAG(CMDTAG_CREATE_ROLE, "CREATE ROLE", false, false, false)
PG_CMDTAG(CMDTAG_CREATE_ROUTINE, "CREATE ROUTINE", true, false, false)
PG_CMDTAG(CMDTAG_CREATE_RULE, "CREATE RULE", true, false, false)
PG_CMDTAG(CMDTAG_CREATE_SCHEMA, "CREATE SCHEMA", true, false, false)
PG_CMDTAG(CMDTAG_CREATE_SEQUENCE, "CREATE SEQUENCE", true, false, false)
PG_CMDTAG(CMDTAG_CREATE_SERVER, "CREATE SERVER", true, false, false)
PG_CMDTAG(CMDTAG_CREATE_STATISTICS, "CREATE STATISTICS", true, false, false)
PG_CMDTAG(CMDTAG_CREATE_SUBSCRIPTION, "CREATE SUBSCRIPTION", true, false, false)
PG_CMDTAG(CMDTAG_CREATE_TABLE, "CREATE TABLE", true, false, false)
PG_CMDTAG(CMDTAG_CREATE_TABLE_AS, "CREATE TABLE AS", true, false, false)
PG_CMDTAG(CMDTAG_CREATE_TABLESPACE, "CREATE TABLESPACE", false, false, false)
PG_CMDTAG(CMDTAG_CREATE_TEXT_SEARCH_CONFIGURATION, "CREATE TEXT SEARCH CONFIGURATION", true, false, false)
PG_CMDTAG(CMDTAG_CREATE_TEXT_SEARCH_DICTIONARY, "CREATE TEXT SEARCH DICTIONARY", true, false, false)
PG_CMDTAG(CMDTAG_CREATE_TEXT_SEARCH_PARSER, "CREATE TEXT SEARCH PARSER", true, false, false)
PG_CMDTAG(CMDTAG_CREATE_TEXT_SEARCH_TEMPLATE, "CREATE TEXT SEARCH TEMPLATE", true, false, false)
PG_CMDTAG(CMDTAG_CREATE_TRANSFORM, "CREATE TRANSFORM", true, false, false)
PG_CMDTAG(CMDTAG_CREATE_TRIGGER, "CREATE TRIGGER", true, false, false)
PG_CMDTAG(CMDTAG_CREATE_TYPE, "CREATE TYPE", true, false, false)
PG_CMDTAG(CMDTAG_CREATE_USER_MAPPING, "CREATE USER MAPPING", true, false, false)
PG_CMDTAG(CMDTAG_CREATE_VIEW, "CREATE VIEW", true, false, false)
PG_CMDTAG(CMDTAG_DEALLOCATE, "DEALLOCATE", false, false, false)
PG_CMDTAG(CMDTAG_DEALLOCATE_ALL, "DEALLOCATE ALL", false, false, false)
PG_CMDTAG(CMDTAG_DECLARE_CURSOR, "DECLARE CURSOR", false, false, false)
PG_CMDTAG(CMDTAG_DELETE, "DELETE", false, false, true)
PG_CMDTAG(CMDTAG_DISCARD, "DISCARD", false, false, false)
PG_CMDTAG(CMDTAG_DISCARD_ALL, "DISCARD ALL", false, false, false)
PG_CMDTAG(CMDTAG_DISCARD_PLANS, "DISCARD PLANS", false, false, false)
PG_CMDTAG(CMDTAG_DISCARD_SEQUENCES, "DISCARD SEQUENCES", false, false, false)
PG_CMDTAG(CMDTAG_DISCARD_TEMP, "DISCARD TEMP", false, false, false)
PG_CMDTAG(CMDTAG_DO, "DO", false, false, false)
PG_CMDTAG(CMDTAG_DROP_ACCESS_METHOD, "DROP ACCESS METHOD", true, false, false)
PG_CMDTAG(CMDTAG_DROP_AGGREGATE, "DROP AGGREGATE", true, false, false)
PG_CMDTAG(CMDTAG_DROP_CAST, "DROP CAST", true, false, false)
PG_CMDTAG(CMDTAG_DROP_COLLATION, "DROP COLLATION", true, false, false)
PG_CMDTAG(CMDTAG_DROP_CONSTRAINT, "DROP CONSTRAINT", true, false, false)
PG_CMDTAG(CMDTAG_DROP_CONVERSION, "DROP CONVERSION", true, false, false)
PG_CMDTAG(CMDTAG_DROP_DATABASE, "DROP DATABASE", false, false, false)
PG_CMDTAG(CMDTAG_DROP_DOMAIN, "DROP DOMAIN", true, false, false)
PG_CMDTAG(CMDTAG_DROP_EVENT_TRIGGER, "DROP EVENT TRIGGER", false, false, false)
PG_CMDTAG(CMDTAG_DROP_EXTENSION, "DROP EXTENSION", true, false, false)
PG_CMDTAG(CMDTAG_DROP_FOREIGN_DATA_WRAPPER, "DROP FOREIGN DATA WRAPPER", true, false, false)
PG_CMDTAG(CMDTAG_DROP_FOREIGN_TABLE, "DROP FOREIGN TABLE", true, false, false)
PG_CMDTAG(CMDTAG_DROP_FUNCTION, "DROP FUNCTION", true, false, false)
PG_CMDTAG(CMDTAG_DROP_INDEX, "DROP INDEX", true, false, false)
PG_CMDTAG(CMDTAG_DROP_LANGUAGE, "DROP LANGUAGE", true, false, false)
PG_CMDTAG(CMDTAG_DROP_MATERIALIZED_VIEW, "DROP MATERIALIZED VIEW", true, false, false)
PG_CMDTAG(CMDTAG_DROP_OPERATOR, "DROP OPERATOR", true, false, false)
PG_CMDTAG(CMDTAG_DROP_OPERATOR_CLASS, "DROP OPERATOR CLASS", true, false, false)
PG_CMDTAG(CMDTAG_DROP_OPERATOR_FAMILY, "DROP OPERATOR FAMILY", true, false, false)
PG_CMDTAG(CMDTAG_DROP_OWNED, "DROP OWNED", true, false, false)
PG_CMDTAG(CMDTAG_DROP_POLICY, "DROP POLICY", true, false, false)
PG_CMDTAG(CMDTAG_DROP_PROCEDURE, "DROP PROCEDURE", true, false, false)
PG_CMDTAG(CMDTAG_DROP_PUBLICATION, "DROP PUBLICATION", true, false, false)
PG_CMDTAG(CMDTAG_DROP_REPLICATION_SLOT, "DROP REPLICATION SLOT", false, false, false)
PG_CMDTAG(CMDTAG_DROP_ROLE, "DROP ROLE", false, false, false)
PG_CMDTAG(CMDTAG_DROP_ROUTINE, "DROP ROUTINE", true, false, false)
PG_CMDTAG(CMDTAG_DROP_RULE, "DROP RULE", true, false, false)
PG_CMDTAG(CMDTAG_DROP_SCHEMA, "DROP SCHEMA", true, false, false)
PG_CMDTAG(CMDTAG_DROP_SEQUENCE, "DROP SEQUENCE", true, false, false)
PG_CMDTAG(CMDTAG_DROP_SERVER, "DROP SERVER", true, false, false)
PG_CMDTAG(CMDTAG_DROP_STATISTICS, "DROP STATISTICS", true, false, false)
PG_CMDTAG(CMDTAG_DROP_SUBSCRIPTION, "DROP SUBSCRIPTION", true, false, false)
PG_CMDTAG(CMDTAG_DROP_TABLE, "DROP TABLE", true, false, false)
PG_CMDTAG(CMDTAG_DROP_TABLESPACE, "DROP TABLESPACE", false, false, false)
PG_CMDTAG(CMDTAG_DROP_TEXT_SEARCH_CONFIGURATION, "DROP TEXT SEARCH CONFIGURATION", true, false, false)
PG_CMDTAG(CMDTAG_DROP_TEXT_SEARCH_DICTIONARY, "DROP TEXT SEARCH DICTIONARY", true, false, false)
PG_CMDTAG(CMDTAG_DROP_TEXT_SEARCH_PARSER, "DROP TEXT SEARCH PARSER", true, false, false)
PG_CMDTAG(CMDTAG_DROP_TEXT_SEARCH_TEMPLATE, "DROP TEXT SEARCH TEMPLATE", true, false, false)
PG_CMDTAG(CMDTAG_DROP_TRANSFORM, "DROP TRANSFORM", true, false, false)
PG_CMDTAG(CMDTAG_DROP_TRIGGER, "DROP TRIGGER", true, false, false)
PG_CMDTAG(CMDTAG_DROP_TYPE, "DROP TYPE", true, false, false)
PG_CMDTAG(CMDTAG_DROP_USER_MAPPING, "DROP USER MAPPING", true, false, false)
PG_CMDTAG(CMDTAG_DROP_VIEW, "DROP VIEW", true, false, false)
PG_CMDTAG(CMDTAG_EXECUTE, "EXECUTE", false, false, false)
PG_CMDTAG(CMDTAG_EXPLAIN, "EXPLAIN", false, false, false)
PG_CMDTAG(CMDTAG_FETCH, "FETCH", false, false, true)
PG_CMDTAG(CMDTAG_GRANT, "GRANT", true, false, false)
PG_CMDTAG(CMDTAG_GRANT_ROLE, "GRANT ROLE", false, false, false)
PG_CMDTAG(CMDTAG_IMPORT_FOREIGN_SCHEMA, "IMPORT FOREIGN SCHEMA", true, false, false)
PG_CMDTAG(CMDTAG_INSERT, "INSERT", false, false, true)
PG_CMDTAG(CMDTAG_LISTEN, "LISTEN", false, false, false)
PG_CMDTAG(CMDTAG_LOAD, "LOAD", false, false, false)
PG_CMDTAG(CMDTAG_LOCK_TABLE, "LOCK TABLE", false, false, false)
PG_CMDTAG(CMDTAG_MOVE, "MOVE", false, false, true)
PG_CMDTAG(CMDTAG_NOTIFY, "NOTIFY", false, false, false)
PG_CMDTAG(CMDTAG_PREPARE, "PREPARE", false, false, false)
PG_CMDTAG(CMDTAG_PREPARE_TRANSACTION, "PREPARE TRANSACTION", false, false, false)
PG_CMDTAG(CMDTAG_REASSIGN_OWNED, "REASSIGN OWNED", false, false, false)
PG_CMDTAG(CMDTAG_REFRESH_MATERIALIZED_VIEW, "REFRESH MATERIALIZED VIEW", true, false, false)
PG_CMDTAG(CMDTAG_REINDEX, "REINDEX", false, false, false)
PG_CMDTAG(CMDTAG_RELEASE, "RELEASE", false, false, false)
PG_CMDTAG(CMDTAG_RESET, "RESET", false, false, false)
PG_CMDTAG(CMDTAG_REVOKE, "REVOKE", true, false, false)
PG_CMDTAG(CMDTAG_REVOKE_ROLE, "REVOKE ROLE", false, false, false)
PG_CMDTAG(CMDTAG_ROLLBACK, "ROLLBACK", false, false, false)
PG_CMDTAG(CMDTAG_ROLLBACK_PREPARED, "ROLLBACK PREPARED", false, false, false)
PG_CMDTAG(CMDTAG_SAVEPOINT, "SAVEPOINT", false, false, false)
PG_CMDTAG(CMDTAG_SECURITY_LABEL, "SECURITY LABEL", true, false, false)
PG_CMDTAG(CMDTAG_SELECT, "SELECT", false, false, true)
PG_CMDTAG(CMDTAG_SELECT_FOR_KEY_SHARE, "SELECT FOR KEY SHARE", false, false, false)
PG_CMDTAG(CMDTAG_SELECT_FOR_NO_KEY_UPDATE, "SELECT FOR NO KEY UPDATE", false, false, false)
PG_CMDTAG(CMDTAG_SELECT_FOR_SHARE, "SELECT FOR SHARE", false, false, false)
PG_CMDTAG(CMDTAG_SELECT_FOR_UPDATE, "SELECT FOR UPDATE", false, false, false)
PG_CMDTAG(CMDTAG_SELECT_INTO, "SELECT INTO", true, false, false)
PG_CMDTAG(CMDTAG_SET, "SET", false, false, false)
PG_CMDTAG(CMDTAG_SET_CONSTRAINTS, "SET CONSTRAINTS", false, false, false)
PG_CMDTAG(CMDTAG_SHOW, "SHOW", false, false, false)
PG_CMDTAG(CMDTAG_START_TRANSACTION, "START TRANSACTION", false, false, false)
PG_CMDTAG(CMDTAG_TRUNCATE_TABLE, "TRUNCATE TABLE", false, false, false)
PG_CMDTAG(CMDTAG_UNLISTEN, "UNLISTEN", false, false, false)
PG_CMDTAG(CMDTAG_UPDATE, "UPDATE", false, false, true)
PG_CMDTAG(CMDTAG_VACUUM, "VACUUM", false, false, false)
...@@ -68,6 +68,7 @@ ...@@ -68,6 +68,7 @@
#define DEST_H #define DEST_H
#include "executor/tuptable.h" #include "executor/tuptable.h"
#include "tcop/cmdtag.h"
/* buffer size to use for command completion tags */ /* buffer size to use for command completion tags */
...@@ -134,9 +135,10 @@ extern PGDLLIMPORT DestReceiver *None_Receiver; /* permanent receiver for ...@@ -134,9 +135,10 @@ extern PGDLLIMPORT DestReceiver *None_Receiver; /* permanent receiver for
/* The primary destination management functions */ /* The primary destination management functions */
extern void BeginCommand(const char *commandTag, CommandDest dest); extern void BeginCommand(CommandTag commandTag, CommandDest dest);
extern DestReceiver *CreateDestReceiver(CommandDest dest); extern DestReceiver *CreateDestReceiver(CommandDest dest);
extern void EndCommand(const char *commandTag, CommandDest dest); extern void EndCommand(const QueryCompletion *qc, CommandDest dest,
bool force_undecorated_output);
/* Additional functions that go with destination management, more or less. */ /* Additional functions that go with destination management, more or less. */
......
...@@ -35,7 +35,7 @@ extern void PortalSetResultFormat(Portal portal, int nFormats, ...@@ -35,7 +35,7 @@ extern void PortalSetResultFormat(Portal portal, int nFormats,
extern bool PortalRun(Portal portal, long count, bool isTopLevel, extern bool PortalRun(Portal portal, long count, bool isTopLevel,
bool run_once, DestReceiver *dest, DestReceiver *altdest, bool run_once, DestReceiver *dest, DestReceiver *altdest,
char *completionTag); QueryCompletion *qc);
extern uint64 PortalRunFetch(Portal portal, extern uint64 PortalRunFetch(Portal portal,
FetchDirection fdirection, FetchDirection fdirection,
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#ifndef UTILITY_H #ifndef UTILITY_H
#define UTILITY_H #define UTILITY_H
#include "tcop/cmdtag.h"
#include "tcop/tcopprot.h" #include "tcop/tcopprot.h"
typedef enum typedef enum
...@@ -71,17 +72,17 @@ typedef void (*ProcessUtility_hook_type) (PlannedStmt *pstmt, ...@@ -71,17 +72,17 @@ typedef void (*ProcessUtility_hook_type) (PlannedStmt *pstmt,
const char *queryString, ProcessUtilityContext context, const char *queryString, ProcessUtilityContext context,
ParamListInfo params, ParamListInfo params,
QueryEnvironment *queryEnv, QueryEnvironment *queryEnv,
DestReceiver *dest, char *completionTag); DestReceiver *dest, QueryCompletion *qc);
extern PGDLLIMPORT ProcessUtility_hook_type ProcessUtility_hook; extern PGDLLIMPORT ProcessUtility_hook_type ProcessUtility_hook;
extern void ProcessUtility(PlannedStmt *pstmt, const char *queryString, extern void ProcessUtility(PlannedStmt *pstmt, const char *queryString,
ProcessUtilityContext context, ParamListInfo params, ProcessUtilityContext context, ParamListInfo params,
QueryEnvironment *queryEnv, QueryEnvironment *queryEnv,
DestReceiver *dest, char *completionTag); DestReceiver *dest, QueryCompletion *qc);
extern void standard_ProcessUtility(PlannedStmt *pstmt, const char *queryString, extern void standard_ProcessUtility(PlannedStmt *pstmt, const char *queryString,
ProcessUtilityContext context, ParamListInfo params, ProcessUtilityContext context, ParamListInfo params,
QueryEnvironment *queryEnv, QueryEnvironment *queryEnv,
DestReceiver *dest, char *completionTag); DestReceiver *dest, QueryCompletion *qc);
extern void ProcessUtilityForAlterTable(Node *stmt, extern void ProcessUtilityForAlterTable(Node *stmt,
AlterTableUtilityContext *context); AlterTableUtilityContext *context);
...@@ -92,7 +93,13 @@ extern TupleDesc UtilityTupleDescriptor(Node *parsetree); ...@@ -92,7 +93,13 @@ extern TupleDesc UtilityTupleDescriptor(Node *parsetree);
extern Query *UtilityContainsQuery(Node *parsetree); extern Query *UtilityContainsQuery(Node *parsetree);
extern const char *CreateCommandTag(Node *parsetree); extern CommandTag CreateCommandTag(Node *parsetree);
static inline const char *
CreateCommandName(Node *parsetree)
{
return GetCommandTagName(CreateCommandTag(parsetree));
}
extern LogStmtLevel GetCommandLogLevel(Node *parsetree); extern LogStmtLevel GetCommandLogLevel(Node *parsetree);
......
...@@ -28,8 +28,7 @@ typedef struct ...@@ -28,8 +28,7 @@ typedef struct
{ {
Oid fnoid; /* function to be called */ Oid fnoid; /* function to be called */
char enabled; /* as SESSION_REPLICATION_ROLE_* */ char enabled; /* as SESSION_REPLICATION_ROLE_* */
int ntags; /* number of command tags */ Bitmapset *tagset; /* command tags, or NULL if empty */
char **tag; /* command tags in SORTED order */
} EventTriggerCacheItem; } EventTriggerCacheItem;
extern List *EventCacheLookup(EventTriggerEvent event); extern List *EventCacheLookup(EventTriggerEvent event);
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include "access/tupdesc.h" #include "access/tupdesc.h"
#include "lib/ilist.h" #include "lib/ilist.h"
#include "nodes/params.h" #include "nodes/params.h"
#include "tcop/cmdtag.h"
#include "utils/queryenvironment.h" #include "utils/queryenvironment.h"
/* Forward declaration, to avoid including parsenodes.h here */ /* Forward declaration, to avoid including parsenodes.h here */
...@@ -95,7 +96,7 @@ typedef struct CachedPlanSource ...@@ -95,7 +96,7 @@ typedef struct CachedPlanSource
int magic; /* should equal CACHEDPLANSOURCE_MAGIC */ int magic; /* should equal CACHEDPLANSOURCE_MAGIC */
struct RawStmt *raw_parse_tree; /* output of raw_parser(), or NULL */ struct RawStmt *raw_parse_tree; /* output of raw_parser(), or NULL */
const char *query_string; /* source text of query */ const char *query_string; /* source text of query */
const char *commandTag; /* command tag (a constant!), or NULL */ CommandTag commandTag; /* 'nuff said */
Oid *param_types; /* array of parameter type OIDs, or NULL */ Oid *param_types; /* array of parameter type OIDs, or NULL */
int num_params; /* length of param_types array */ int num_params; /* length of param_types array */
ParserSetupHook parserSetup; /* alternative parameter spec method */ ParserSetupHook parserSetup; /* alternative parameter spec method */
...@@ -186,10 +187,10 @@ extern void ResetPlanCache(void); ...@@ -186,10 +187,10 @@ extern void ResetPlanCache(void);
extern CachedPlanSource *CreateCachedPlan(struct RawStmt *raw_parse_tree, extern CachedPlanSource *CreateCachedPlan(struct RawStmt *raw_parse_tree,
const char *query_string, const char *query_string,
const char *commandTag); CommandTag commandTag);
extern CachedPlanSource *CreateOneShotCachedPlan(struct RawStmt *raw_parse_tree, extern CachedPlanSource *CreateOneShotCachedPlan(struct RawStmt *raw_parse_tree,
const char *query_string, const char *query_string,
const char *commandTag); CommandTag commandTag);
extern void CompleteCachedPlan(CachedPlanSource *plansource, extern void CompleteCachedPlan(CachedPlanSource *plansource,
List *querytree_list, List *querytree_list,
MemoryContext querytree_context, MemoryContext querytree_context,
......
...@@ -48,6 +48,7 @@ ...@@ -48,6 +48,7 @@
#include "datatype/timestamp.h" #include "datatype/timestamp.h"
#include "executor/execdesc.h" #include "executor/execdesc.h"
#include "tcop/cmdtag.h"
#include "utils/plancache.h" #include "utils/plancache.h"
#include "utils/resowner.h" #include "utils/resowner.h"
...@@ -132,7 +133,8 @@ typedef struct PortalData ...@@ -132,7 +133,8 @@ typedef struct PortalData
/* The query or queries the portal will execute */ /* The query or queries the portal will execute */
const char *sourceText; /* text of query (as of 8.4, never NULL) */ const char *sourceText; /* text of query (as of 8.4, never NULL) */
const char *commandTag; /* command tag for original query */ CommandTag commandTag; /* command tag for original query */
QueryCompletion qc; /* command completion data for executed query */
List *stmts; /* list of PlannedStmts */ List *stmts; /* list of PlannedStmts */
CachedPlan *cplan; /* CachedPlan, if stmts are from one */ CachedPlan *cplan; /* CachedPlan, if stmts are from one */
...@@ -227,7 +229,7 @@ extern Portal GetPortalByName(const char *name); ...@@ -227,7 +229,7 @@ extern Portal GetPortalByName(const char *name);
extern void PortalDefineQuery(Portal portal, extern void PortalDefineQuery(Portal portal,
const char *prepStmtName, const char *prepStmtName,
const char *sourceText, const char *sourceText,
const char *commandTag, CommandTag commandTag,
List *stmts, List *stmts,
CachedPlan *cplan); CachedPlan *cplan);
extern PlannedStmt *PortalGetPrimaryStmt(Portal portal); extern PlannedStmt *PortalGetPrimaryStmt(Portal portal);
......
...@@ -1737,7 +1737,7 @@ plperl_event_trigger_build_args(FunctionCallInfo fcinfo) ...@@ -1737,7 +1737,7 @@ plperl_event_trigger_build_args(FunctionCallInfo fcinfo)
tdata = (EventTriggerData *) fcinfo->context; tdata = (EventTriggerData *) fcinfo->context;
hv_store_string(hv, "event", cstr2sv(tdata->event)); hv_store_string(hv, "event", cstr2sv(tdata->event));
hv_store_string(hv, "tag", cstr2sv(tdata->tag)); hv_store_string(hv, "tag", cstr2sv(GetCommandTagName(tdata->tag)));
return newRV_noinc((SV *) hv); return newRV_noinc((SV *) hv);
} }
......
...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
#include "parser/scansup.h" #include "parser/scansup.h"
#include "plpgsql.h" #include "plpgsql.h"
#include "storage/proc.h" #include "storage/proc.h"
#include "tcop/cmdtag.h"
#include "tcop/tcopprot.h" #include "tcop/tcopprot.h"
#include "tcop/utility.h" #include "tcop/utility.h"
#include "utils/array.h" #include "utils/array.h"
...@@ -1473,7 +1474,7 @@ plpgsql_fulfill_promise(PLpgSQL_execstate *estate, ...@@ -1473,7 +1474,7 @@ plpgsql_fulfill_promise(PLpgSQL_execstate *estate,
case PLPGSQL_PROMISE_TG_TAG: case PLPGSQL_PROMISE_TG_TAG:
if (estate->evtrigdata == NULL) if (estate->evtrigdata == NULL)
elog(ERROR, "event trigger promise is not in an event trigger function"); elog(ERROR, "event trigger promise is not in an event trigger function");
assign_text_var(estate, var, estate->evtrigdata->tag); assign_text_var(estate, var, GetCommandTagName(estate->evtrigdata->tag));
break; break;
default: default:
...@@ -4115,10 +4116,9 @@ exec_stmt_execsql(PLpgSQL_execstate *estate, ...@@ -4115,10 +4116,9 @@ exec_stmt_execsql(PLpgSQL_execstate *estate,
* tree(s), since those are the result of rewriting and could have * tree(s), since those are the result of rewriting and could have
* been transmogrified into something else entirely. * been transmogrified into something else entirely.
*/ */
if (plansource->commandTag && if (plansource->commandTag == CMDTAG_INSERT ||
(strcmp(plansource->commandTag, "INSERT") == 0 || plansource->commandTag == CMDTAG_UPDATE ||
strcmp(plansource->commandTag, "UPDATE") == 0 || plansource->commandTag == CMDTAG_DELETE)
strcmp(plansource->commandTag, "DELETE") == 0))
{ {
stmt->mod_stmt = true; stmt->mod_stmt = true;
break; break;
......
...@@ -1329,7 +1329,8 @@ pltcl_event_trigger_handler(PG_FUNCTION_ARGS, pltcl_call_state *call_state, ...@@ -1329,7 +1329,8 @@ pltcl_event_trigger_handler(PG_FUNCTION_ARGS, pltcl_call_state *call_state,
Tcl_ListObjAppendElement(NULL, tcl_cmd, Tcl_ListObjAppendElement(NULL, tcl_cmd,
Tcl_NewStringObj(utf_e2u(tdata->event), -1)); Tcl_NewStringObj(utf_e2u(tdata->event), -1));
Tcl_ListObjAppendElement(NULL, tcl_cmd, Tcl_ListObjAppendElement(NULL, tcl_cmd,
Tcl_NewStringObj(utf_e2u(tdata->tag), -1)); Tcl_NewStringObj(utf_e2u(GetCommandTagName(tdata->tag)),
-1));
tcl_rc = Tcl_EvalObjEx(interp, tcl_cmd, (TCL_EVAL_DIRECT | TCL_EVAL_GLOBAL)); tcl_rc = Tcl_EvalObjEx(interp, tcl_cmd, (TCL_EVAL_DIRECT | TCL_EVAL_GLOBAL));
......
...@@ -74,7 +74,7 @@ get_command_tag(PG_FUNCTION_ARGS) ...@@ -74,7 +74,7 @@ get_command_tag(PG_FUNCTION_ARGS)
if (!cmd->parsetree) if (!cmd->parsetree)
PG_RETURN_NULL(); PG_RETURN_NULL();
PG_RETURN_TEXT_P(cstring_to_text(CreateCommandTag(cmd->parsetree))); PG_RETURN_TEXT_P(cstring_to_text(CreateCommandName(cmd->parsetree)));
} }
/* /*
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment