From a6e2e6493d13e14e0d52473e9af6c6b6f7947be3 Mon Sep 17 00:00:00 2001 From: Mark Dilger Date: Sun, 2 Feb 2020 10:14:26 -0800 Subject: [PATCH v1 1/2] Migrating commandTag from string to enum. The backend uses strings to represent command tags and does string comparisons in multiple places. Fixing that by creating a new CommandTag enum and using it instead. --- src/backend/commands/async.c | 2 +- src/backend/commands/copy.c | 2 +- src/backend/commands/event_trigger.c | 383 ++++++++---- src/backend/commands/portalcmds.c | 3 +- src/backend/commands/sequence.c | 8 +- src/backend/executor/functions.c | 4 +- src/backend/executor/spi.c | 6 +- src/backend/replication/walsender.c | 4 +- src/backend/tcop/dest.c | 10 +- src/backend/tcop/postgres.c | 12 +- src/backend/tcop/pquery.c | 30 +- src/backend/tcop/utility.c | 576 ++++++++++-------- src/backend/utils/adt/txid.c | 2 +- src/backend/utils/cache/plancache.c | 4 +- src/backend/utils/mmgr/portalmem.c | 6 +- src/common/Makefile | 1 + src/common/commandtag.c | 382 ++++++++++++ src/include/common/commandtag.h | 254 ++++++++ src/include/miscadmin.h | 10 +- src/include/nodes/parsenodes.h | 1 + src/include/tcop/dest.h | 5 +- src/include/tcop/utility.h | 2 +- src/include/utils/plancache.h | 6 +- src/include/utils/portal.h | 13 +- src/pl/plpgsql/src/pl_exec.c | 7 +- .../test_ddl_deparse/test_ddl_deparse.c | 2 +- 26 files changed, 1298 insertions(+), 437 deletions(-) create mode 100644 src/common/commandtag.c create mode 100644 src/include/common/commandtag.h diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index 9aa2b61600..5322c14ce4 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -594,7 +594,7 @@ pg_notify(PG_FUNCTION_ARGS) payload = text_to_cstring(PG_GETARG_TEXT_PP(1)); /* For NOTIFY as a statement, this is checked in ProcessUtility */ - PreventCommandDuringRecovery("NOTIFY"); + PreventCommandDuringRecovery(COMMANDTAG_NOTIFY); Async_Notify(channel, payload); diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c index 40a8ec1abd..4828e75bd5 100644 --- a/src/backend/commands/copy.c +++ b/src/backend/commands/copy.c @@ -1063,7 +1063,7 @@ DoCopy(ParseState *pstate, const CopyStmt *stmt, /* check read-only transaction and parallel mode */ if (XactReadOnly && !rel->rd_islocaltemp) - PreventCommandIfReadOnly("COPY FROM"); + PreventCommandIfReadOnly(COMMANDTAG_COPY_FROM); cstate = BeginCopyFrom(pstate, rel, stmt->filename, stmt->is_program, NULL, stmt->attlist, stmt->options); diff --git a/src/backend/commands/event_trigger.c b/src/backend/commands/event_trigger.c index 71911d4067..ad80616f78 100644 --- a/src/backend/commands/event_trigger.c +++ b/src/backend/commands/event_trigger.c @@ -32,6 +32,7 @@ #include "commands/event_trigger.h" #include "commands/extension.h" #include "commands/trigger.h" +#include "common/commandtag.h" #include "funcapi.h" #include "lib/ilist.h" #include "miscadmin.h" @@ -85,52 +86,6 @@ typedef enum 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 */ typedef struct SQLDropObject { @@ -150,8 +105,8 @@ typedef struct SQLDropObject static void AlterEventTriggerOwner_internal(Relation rel, HeapTuple tup, 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 event_trigger_command_tag_check_result check_ddl_tag(CommandTag commandTag); +static event_trigger_command_tag_check_result check_table_rewrite_ddl_tag(CommandTag commandTag); static void error_duplicate_filter_variable(const char *defname); static Datum filter_list_to_array(List *filterlist); static Oid insert_event_trigger_tuple(const char *trigname, const char *eventname, @@ -259,69 +214,264 @@ validate_ddl_tags(const char *filtervar, List *taglist) foreach(lc, taglist) { - const char *tag = strVal(lfirst(lc)); + const char *tagstr = strVal(lfirst(lc)); + CommandTag commandTag = GetCommandTagEnum(tagstr); event_trigger_command_tag_check_result result; - result = check_ddl_tag(tag); + result = check_ddl_tag(commandTag); if (result == EVENT_TRIGGER_COMMAND_TAG_NOT_RECOGNIZED) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("filter value \"%s\" not recognized for filter variable \"%s\"", - tag, filtervar))); + tagstr, filtervar))); if (result == EVENT_TRIGGER_COMMAND_TAG_NOT_SUPPORTED) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), /* translator: %s represents an SQL statement name */ errmsg("event triggers are not supported for %s", - tag))); + tagstr))); } } static event_trigger_command_tag_check_result -check_ddl_tag(const char *tag) +check_ddl_tag(CommandTag commandTag) { - const char *obtypename; - const event_trigger_support_data *etsd; + switch (commandTag) + { + /* + * Supported idiosyncratic special cases. + */ + case COMMANDTAG_ALTER_DEFAULT_PRIVILEGES: + case COMMANDTAG_ALTER_LARGE_OBJECT: + case COMMANDTAG_COMMENT: + case COMMANDTAG_CREATE_TABLE_AS: + case COMMANDTAG_DROP_OWNED: + case COMMANDTAG_GRANT: + case COMMANDTAG_IMPORT_FOREIGN_SCHEMA: + case COMMANDTAG_REFRESH_MATERIALIZED_VIEW: + case COMMANDTAG_REVOKE: + case COMMANDTAG_SECURITY_LABEL: + case COMMANDTAG_SELECT_INTO: - /* - * 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; + /* + * Supported CREATE commands + */ + case COMMANDTAG_CREATE_ACCESS_METHOD: + case COMMANDTAG_CREATE_AGGREGATE: + case COMMANDTAG_CREATE_CAST: + case COMMANDTAG_CREATE_COLLATION: + case COMMANDTAG_CREATE_CONSTRAINT: + case COMMANDTAG_CREATE_CONVERSION: + case COMMANDTAG_CREATE_DOMAIN: + case COMMANDTAG_CREATE_EXTENSION: + case COMMANDTAG_CREATE_FOREIGN_DATA_WRAPPER: + case COMMANDTAG_CREATE_FOREIGN_TABLE: + case COMMANDTAG_CREATE_FUNCTION: + case COMMANDTAG_CREATE_INDEX: + case COMMANDTAG_CREATE_LANGUAGE: + case COMMANDTAG_CREATE_MATERIALIZED_VIEW: + case COMMANDTAG_CREATE_OPERATOR: + case COMMANDTAG_CREATE_OPERATOR_CLASS: + case COMMANDTAG_CREATE_OPERATOR_FAMILY: + case COMMANDTAG_CREATE_POLICY: + case COMMANDTAG_CREATE_PROCEDURE: + case COMMANDTAG_CREATE_PUBLICATION: + case COMMANDTAG_CREATE_ROUTINE: + case COMMANDTAG_CREATE_RULE: + case COMMANDTAG_CREATE_SCHEMA: + case COMMANDTAG_CREATE_SEQUENCE: + case COMMANDTAG_CREATE_SERVER: + case COMMANDTAG_CREATE_STATISTICS: + case COMMANDTAG_CREATE_SUBSCRIPTION: + case COMMANDTAG_CREATE_TABLE: + case COMMANDTAG_CREATE_TEXT_SEARCH_CONFIGURATION: + case COMMANDTAG_CREATE_TEXT_SEARCH_DICTIONARY: + case COMMANDTAG_CREATE_TEXT_SEARCH_PARSER: + case COMMANDTAG_CREATE_TEXT_SEARCH_TEMPLATE: + case COMMANDTAG_CREATE_TRANSFORM: + case COMMANDTAG_CREATE_TRIGGER: + case COMMANDTAG_CREATE_TYPE: + case COMMANDTAG_CREATE_USER_MAPPING: + case COMMANDTAG_CREATE_VIEW: - /* - * 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; + /* + * Supported ALTER commands + */ + case COMMANDTAG_ALTER_ACCESS_METHOD: + case COMMANDTAG_ALTER_AGGREGATE: + case COMMANDTAG_ALTER_CAST: + case COMMANDTAG_ALTER_COLLATION: + case COMMANDTAG_ALTER_CONSTRAINT: + case COMMANDTAG_ALTER_CONVERSION: + case COMMANDTAG_ALTER_DOMAIN: + case COMMANDTAG_ALTER_EXTENSION: + case COMMANDTAG_ALTER_FOREIGN_DATA_WRAPPER: + case COMMANDTAG_ALTER_FOREIGN_TABLE: + case COMMANDTAG_ALTER_FUNCTION: + case COMMANDTAG_ALTER_INDEX: + case COMMANDTAG_ALTER_LANGUAGE: + case COMMANDTAG_ALTER_MATERIALIZED_VIEW: + case COMMANDTAG_ALTER_OPERATOR: + case COMMANDTAG_ALTER_OPERATOR_CLASS: + case COMMANDTAG_ALTER_OPERATOR_FAMILY: + case COMMANDTAG_ALTER_POLICY: + case COMMANDTAG_ALTER_PROCEDURE: + case COMMANDTAG_ALTER_PUBLICATION: + case COMMANDTAG_ALTER_ROUTINE: + case COMMANDTAG_ALTER_RULE: + case COMMANDTAG_ALTER_SCHEMA: + case COMMANDTAG_ALTER_SEQUENCE: + case COMMANDTAG_ALTER_SERVER: + case COMMANDTAG_ALTER_STATISTICS: + case COMMANDTAG_ALTER_SUBSCRIPTION: + case COMMANDTAG_ALTER_TABLE: + case COMMANDTAG_ALTER_TEXT_SEARCH_CONFIGURATION: + case COMMANDTAG_ALTER_TEXT_SEARCH_DICTIONARY: + case COMMANDTAG_ALTER_TEXT_SEARCH_PARSER: + case COMMANDTAG_ALTER_TEXT_SEARCH_TEMPLATE: + case COMMANDTAG_ALTER_TRANSFORM: + case COMMANDTAG_ALTER_TRIGGER: + case COMMANDTAG_ALTER_TYPE: + case COMMANDTAG_ALTER_USER_MAPPING: + case COMMANDTAG_ALTER_VIEW: - /* - * ...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; + /* + * Supported DROP commands + */ + case COMMANDTAG_DROP_ACCESS_METHOD: + case COMMANDTAG_DROP_AGGREGATE: + case COMMANDTAG_DROP_CAST: + case COMMANDTAG_DROP_COLLATION: + case COMMANDTAG_DROP_CONSTRAINT: + case COMMANDTAG_DROP_CONVERSION: + case COMMANDTAG_DROP_DOMAIN: + case COMMANDTAG_DROP_EXTENSION: + case COMMANDTAG_DROP_FOREIGN_DATA_WRAPPER: + case COMMANDTAG_DROP_FOREIGN_TABLE: + case COMMANDTAG_DROP_FUNCTION: + case COMMANDTAG_DROP_INDEX: + case COMMANDTAG_DROP_LANGUAGE: + case COMMANDTAG_DROP_MATERIALIZED_VIEW: + case COMMANDTAG_DROP_OPERATOR: + case COMMANDTAG_DROP_OPERATOR_CLASS: + case COMMANDTAG_DROP_OPERATOR_FAMILY: + case COMMANDTAG_DROP_POLICY: + case COMMANDTAG_DROP_PROCEDURE: + case COMMANDTAG_DROP_PUBLICATION: + case COMMANDTAG_DROP_ROUTINE: + case COMMANDTAG_DROP_RULE: + case COMMANDTAG_DROP_SCHEMA: + case COMMANDTAG_DROP_SEQUENCE: + case COMMANDTAG_DROP_SERVER: + case COMMANDTAG_DROP_STATISTICS: + case COMMANDTAG_DROP_SUBSCRIPTION: + case COMMANDTAG_DROP_TABLE: + case COMMANDTAG_DROP_TEXT_SEARCH_CONFIGURATION: + case COMMANDTAG_DROP_TEXT_SEARCH_DICTIONARY: + case COMMANDTAG_DROP_TEXT_SEARCH_PARSER: + case COMMANDTAG_DROP_TEXT_SEARCH_TEMPLATE: + case COMMANDTAG_DROP_TRANSFORM: + case COMMANDTAG_DROP_TRIGGER: + case COMMANDTAG_DROP_TYPE: + case COMMANDTAG_DROP_USER_MAPPING: + case COMMANDTAG_DROP_VIEW: + return EVENT_TRIGGER_COMMAND_TAG_OK; + + /* + * Unsupported CREATE commands + */ + case COMMANDTAG_CREATE_DATABASE: + case COMMANDTAG_CREATE_EVENT_TRIGGER: + case COMMANDTAG_CREATE_ROLE: + case COMMANDTAG_CREATE_TABLESPACE: + + /* + * Unsupported ALTER commands + */ + case COMMANDTAG_ALTER_DATABASE: + case COMMANDTAG_ALTER_EVENT_TRIGGER: + case COMMANDTAG_ALTER_ROLE: + case COMMANDTAG_ALTER_TABLESPACE: + + /* + * Unsupported DROP commands + */ + case COMMANDTAG_DROP_DATABASE: + case COMMANDTAG_DROP_EVENT_TRIGGER: + case COMMANDTAG_DROP_ROLE: + case COMMANDTAG_DROP_TABLESPACE: + + /* + * Other unsupported commands. These used to return + * EVENT_TRIGGER_COMMAND_TAG_NOT_RECOGNIZED prior to the + * conversion of commandTag from string to enum. + */ + case COMMANDTAG_ALTER_SYSTEM: + case COMMANDTAG_ANALYZE: + case COMMANDTAG_BEGIN: + case COMMANDTAG_CALL: + case COMMANDTAG_CHECKPOINT: + case COMMANDTAG_CLOSE: + case COMMANDTAG_CLOSE_CURSOR: + case COMMANDTAG_CLOSE_CURSOR_ALL: + case COMMANDTAG_CLUSTER: + case COMMANDTAG_COMMIT: + case COMMANDTAG_COMMIT_PREPARED: + case COMMANDTAG_COPY: + case COMMANDTAG_COPY_FROM: + case COMMANDTAG_DEALLOCATE: + case COMMANDTAG_DEALLOCATE_ALL: + case COMMANDTAG_DECLARE_CURSOR: + case COMMANDTAG_DELETE: + case COMMANDTAG_DISCARD: + case COMMANDTAG_DISCARD_ALL: + case COMMANDTAG_DISCARD_PLANS: + case COMMANDTAG_DISCARD_SEQUENCES: + case COMMANDTAG_DISCARD_TEMP: + case COMMANDTAG_DO: + case COMMANDTAG_DROP_REPLICATION_SLOT: + case COMMANDTAG_EXECUTE: + case COMMANDTAG_EXPLAIN: + case COMMANDTAG_FETCH: + case COMMANDTAG_GRANT_ROLE: + case COMMANDTAG_INSERT: + case COMMANDTAG_LISTEN: + case COMMANDTAG_LOAD: + case COMMANDTAG_LOCK_TABLE: + case COMMANDTAG_MOVE: + case COMMANDTAG_NOTIFY: + case COMMANDTAG_PREPARE: + case COMMANDTAG_PREPARE_TRANSACTION: + case COMMANDTAG_REASSIGN_OWNED: + case COMMANDTAG_REINDEX: + case COMMANDTAG_RELEASE: + case COMMANDTAG_RESET: + case COMMANDTAG_REVOKE_ROLE: + case COMMANDTAG_ROLLBACK: + case COMMANDTAG_ROLLBACK_PREPARED: + case COMMANDTAG_SAVEPOINT: + case COMMANDTAG_SELECT: + case COMMANDTAG_SELECT_FOR_KEY_SHARE: + case COMMANDTAG_SELECT_FOR_NO_KEY_UPDATE: + case COMMANDTAG_SELECT_FOR_SHARE: + case COMMANDTAG_SELECT_FOR_UPDATE: + case COMMANDTAG_SET: + case COMMANDTAG_SET_CONSTRAINTS: + case COMMANDTAG_SHOW: + case COMMANDTAG_START_TRANSACTION: + case COMMANDTAG_TRUNCATE_TABLE: + case COMMANDTAG_UNLISTEN: + case COMMANDTAG_UPDATE: + case COMMANDTAG_VACUUM: + return EVENT_TRIGGER_COMMAND_TAG_NOT_SUPPORTED; + + case COMMANDTAG_NULL: + case COMMANDTAG_UNKNOWN: + break; /* fall through */ + + /* Intentionally no 'default' clause. */ + } + return EVENT_TRIGGER_COMMAND_TAG_NOT_RECOGNIZED; } /* @@ -334,26 +484,37 @@ validate_table_rewrite_tags(const char *filtervar, List *taglist) foreach(lc, taglist) { - const char *tag = strVal(lfirst(lc)); + const char *tagstr = strVal(lfirst(lc)); + CommandTag commandTag = GetCommandTagEnum(tagstr); event_trigger_command_tag_check_result result; - result = check_table_rewrite_ddl_tag(tag); - if (result == EVENT_TRIGGER_COMMAND_TAG_NOT_SUPPORTED) - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - /* translator: %s represents an SQL statement name */ - errmsg("event triggers are not supported for %s", - tag))); + result = check_table_rewrite_ddl_tag(commandTag); + switch (result) + { + case EVENT_TRIGGER_COMMAND_TAG_NOT_SUPPORTED: + case EVENT_TRIGGER_COMMAND_TAG_NOT_RECOGNIZED: + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + /* translator: %s represents an SQL statement name */ + errmsg("event triggers are not supported for %s", + tagstr))); + case EVENT_TRIGGER_COMMAND_TAG_OK: + break; + } } } static event_trigger_command_tag_check_result -check_table_rewrite_ddl_tag(const char *tag) +check_table_rewrite_ddl_tag(CommandTag commandTag) { - if (pg_strcasecmp(tag, "ALTER TABLE") == 0 || - pg_strcasecmp(tag, "ALTER TYPE") == 0) - return EVENT_TRIGGER_COMMAND_TAG_OK; - + switch (commandTag) + { + case COMMANDTAG_ALTER_TABLE: + case COMMANDTAG_ALTER_TYPE: + return EVENT_TRIGGER_COMMAND_TAG_OK; + default: + break; + } return EVENT_TRIGGER_COMMAND_TAG_NOT_SUPPORTED; } @@ -721,7 +882,7 @@ EventTriggerCommonSetup(Node *parsetree, */ #ifdef USE_ASSERT_CHECKING { - const char *dbgtag; + CommandTag dbgtag; dbgtag = CreateCommandTag(parsetree); if (event == EVT_DDLCommandStart || @@ -729,12 +890,12 @@ EventTriggerCommonSetup(Node *parsetree, event == EVT_SQLDrop) { if (check_ddl_tag(dbgtag) != EVENT_TRIGGER_COMMAND_TAG_OK) - elog(ERROR, "unexpected command tag \"%s\"", dbgtag); + elog(ERROR, "unexpected command tag \"%s\"", GetCommandTagName(dbgtag)); } else if (event == EVT_TableRewrite) { if (check_table_rewrite_ddl_tag(dbgtag) != EVENT_TRIGGER_COMMAND_TAG_OK) - elog(ERROR, "unexpected command tag \"%s\"", dbgtag); + elog(ERROR, "unexpected command tag \"%s\"", GetCommandTagName(dbgtag)); } } #endif @@ -745,7 +906,7 @@ EventTriggerCommonSetup(Node *parsetree, return NIL; /* Get the command tag. */ - tag = CreateCommandTag(parsetree); + tag = GetCommandTagName(CreateCommandTag(parsetree)); /* * Filter list of event triggers by command tag, and copy them into our @@ -2136,7 +2297,7 @@ pg_event_trigger_ddl_commands(PG_FUNCTION_ARGS) /* objsubid */ values[i++] = Int32GetDatum(addr.objectSubId); /* command tag */ - values[i++] = CStringGetTextDatum(CreateCommandTag(cmd->parsetree)); + values[i++] = CStringGetTextDatum(GetCommandTagName(CreateCommandTag(cmd->parsetree))); /* object_type */ values[i++] = CStringGetTextDatum(type); /* schema */ @@ -2161,7 +2322,7 @@ pg_event_trigger_ddl_commands(PG_FUNCTION_ARGS) /* objsubid */ nulls[i++] = true; /* command tag */ - values[i++] = CStringGetTextDatum(CreateCommandTag(cmd->parsetree)); + values[i++] = CStringGetTextDatum(GetCommandTagName(CreateCommandTag(cmd->parsetree))); /* object_type */ values[i++] = CStringGetTextDatum(stringify_adefprivs_objtype(cmd->d.defprivs.objtype)); /* schema */ diff --git a/src/backend/commands/portalcmds.c b/src/backend/commands/portalcmds.c index 7e5c805a1e..ef541e8d01 100644 --- a/src/backend/commands/portalcmds.c +++ b/src/backend/commands/portalcmds.c @@ -106,7 +106,8 @@ PerformCursorOpen(ParseState *pstate, DeclareCursorStmt *cstmt, ParamListInfo pa PortalDefineQuery(portal, NULL, queryString, - "SELECT", /* cursor's query is always a SELECT */ + COMMANDTAG_SELECT, /* cursor's query is always a + * SELECT */ list_make1(plan), NULL); diff --git a/src/backend/commands/sequence.c b/src/backend/commands/sequence.c index 6aab73bfd4..d6c06fec9f 100644 --- a/src/backend/commands/sequence.c +++ b/src/backend/commands/sequence.c @@ -612,14 +612,14 @@ nextval_internal(Oid relid, bool check_permissions) /* read-only transactions may only modify temp sequences */ if (!seqrel->rd_islocaltemp) - PreventCommandIfReadOnly("nextval()"); + PreventCommandStrIfReadOnly("nextval()"); /* * Forbid this during parallel operation because, to make it work, the * cooperating backends would need to share the backend-local cached * sequence information. Currently, we don't support that. */ - PreventCommandIfParallelMode("nextval()"); + PreventCommandStrIfParallelMode("nextval()"); if (elm->last != elm->cached) /* some numbers were cached */ { @@ -937,14 +937,14 @@ do_setval(Oid relid, int64 next, bool iscalled) /* read-only transactions may only modify temp sequences */ if (!seqrel->rd_islocaltemp) - PreventCommandIfReadOnly("setval()"); + PreventCommandStrIfReadOnly("setval()"); /* * Forbid this during parallel operation because, to make it work, the * cooperating backends would need to share the backend-local cached * sequence information. Currently, we don't support that. */ - PreventCommandIfParallelMode("setval()"); + PreventCommandStrIfParallelMode("setval()"); /* lock page' buffer and read tuple */ seq = read_seq_tuple(seqrel, &buf, &seqdatatuple); diff --git a/src/backend/executor/functions.c b/src/backend/executor/functions.c index 5cff6c4321..57ae9b6c7f 100644 --- a/src/backend/executor/functions.c +++ b/src/backend/executor/functions.c @@ -530,7 +530,7 @@ init_execution_state(List *queryTree_list, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), /* translator: %s is a SQL statement name */ errmsg("%s is not allowed in a SQL function", - CreateCommandTag(stmt->utilityStmt)))); + GetCommandTagName(CreateCommandTag(stmt->utilityStmt))))); } if (fcache->readonly_func && !CommandIsReadOnly(stmt)) @@ -538,7 +538,7 @@ init_execution_state(List *queryTree_list, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), /* translator: %s is a SQL statement name */ errmsg("%s is not allowed in a non-volatile function", - CreateCommandTag((Node *) stmt)))); + GetCommandTagName(CreateCommandTag((Node *) stmt))))); /* OK, build the execution_state for this query */ newes = (execution_state *) palloc(sizeof(execution_state)); diff --git a/src/backend/executor/spi.c b/src/backend/executor/spi.c index c46764bf42..ab081eeebc 100644 --- a/src/backend/executor/spi.c +++ b/src/backend/executor/spi.c @@ -1338,7 +1338,7 @@ SPI_cursor_open_internal(const char *name, SPIPlanPtr plan, (errcode(ERRCODE_INVALID_CURSOR_DEFINITION), /* translator: %s is name of a SQL command, eg INSERT */ errmsg("cannot open %s query as cursor", - plansource->commandTag))); + GetCommandTagName(plansource->commandTag)))); } Assert(list_length(plan->plancache_list) == 1); @@ -1469,7 +1469,7 @@ SPI_cursor_open_internal(const char *name, SPIPlanPtr plan, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), /* translator: %s is a SQL statement name */ errmsg("%s is not allowed in a non-volatile function", - CreateCommandTag((Node *) pstmt)))); + GetCommandTagName(CreateCommandTag((Node *) pstmt))))); } } @@ -2255,7 +2255,7 @@ _SPI_execute_plan(SPIPlanPtr plan, ParamListInfo paramLI, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), /* translator: %s is a SQL statement name */ errmsg("%s is not allowed in a non-volatile function", - CreateCommandTag((Node *) stmt)))); + GetCommandTagName(CreateCommandTag((Node *) stmt))))); /* * If not read-only mode, advance the command counter before each diff --git a/src/backend/replication/walsender.c b/src/backend/replication/walsender.c index abb533b9d0..44e4c97ebc 100644 --- a/src/backend/replication/walsender.c +++ b/src/backend/replication/walsender.c @@ -1075,7 +1075,7 @@ static void DropReplicationSlot(DropReplicationSlotCmd *cmd) { ReplicationSlotDrop(cmd->slotname, !cmd->wait); - EndCommand("DROP_REPLICATION_SLOT", DestRemote); + EndCommand(GetCommandTagName(COMMANDTAG_DROP_REPLICATION_SLOT), DestRemote); } /* @@ -1614,7 +1614,7 @@ exec_replication_command(const char *cmd_string) MemoryContextDelete(cmd_context); /* Send CommandComplete message */ - EndCommand("SELECT", DestRemote); + EndCommand(GetCommandTagName(COMMANDTAG_SELECT), DestRemote); /* Report to pgstat that this process is now idle */ pgstat_report_activity(STATE_IDLE, NULL); diff --git a/src/backend/tcop/dest.c b/src/backend/tcop/dest.c index 09c1dcbb53..5fed5b1b23 100644 --- a/src/backend/tcop/dest.c +++ b/src/backend/tcop/dest.c @@ -100,7 +100,7 @@ DestReceiver *None_Receiver = (DestReceiver *) &donothingDR; * ---------------- */ void -BeginCommand(const char *commandTag, CommandDest dest) +BeginCommand(CommandTag commandTag, CommandDest dest) { /* Nothing to do at present */ } @@ -163,7 +163,7 @@ CreateDestReceiver(CommandDest dest) * ---------------- */ void -EndCommand(const char *commandTag, CommandDest dest) +EndCommand(const char *completionTag, CommandDest dest) { switch (dest) { @@ -172,10 +172,10 @@ EndCommand(const char *commandTag, CommandDest dest) case DestRemoteSimple: /* - * We assume the commandTag is plain ASCII and therefore requires - * no encoding conversion. + * We assume the completionTag is plain ASCII and therefore + * requires no encoding conversion. */ - pq_putmessage('C', commandTag, strlen(commandTag) + 1); + pq_putmessage('C', completionTag, strlen(completionTag) + 1); break; case DestNone: diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index 0a6f80963b..8c4ee7367a 100644 --- a/src/backend/tcop/postgres.c +++ b/src/backend/tcop/postgres.c @@ -1064,7 +1064,7 @@ exec_simple_query(const char *query_string) { RawStmt *parsetree = lfirst_node(RawStmt, parsetree_item); bool snapshot_set = false; - const char *commandTag; + CommandTag commandTag; char completionTag[COMPLETION_TAG_BUFSIZE]; MemoryContext per_parsetree_context = NULL; List *querytree_list, @@ -1081,7 +1081,7 @@ exec_simple_query(const char *query_string) */ commandTag = CreateCommandTag(parsetree->stmt); - set_ps_display(commandTag, false); + set_ps_display(GetCommandTagName(commandTag), false); BeginCommand(commandTag, dest); @@ -1343,7 +1343,7 @@ exec_parse_message(const char *query_string, /* string to execute */ MemoryContext oldcontext; List *parsetree_list; RawStmt *raw_parse_tree; - const char *commandTag; + CommandTag commandTag; List *querytree_list; CachedPlanSource *psrc; bool is_named; @@ -1505,7 +1505,7 @@ exec_parse_message(const char *query_string, /* string to execute */ { /* Empty input string. This is legal. */ raw_parse_tree = NULL; - commandTag = NULL; + commandTag = COMMANDTAG_NULL; psrc = CreateCachedPlan(raw_parse_tree, query_string, commandTag); querytree_list = NIL; } @@ -2049,7 +2049,7 @@ exec_execute_message(const char *portal_name, long max_rows) * If the original query was a null string, just return * EmptyQueryResponse. */ - if (portal->commandTag == NULL) + if (portal->commandTag == COMMANDTAG_NULL) { Assert(portal->stmts == NIL); NullCommand(dest); @@ -2095,7 +2095,7 @@ exec_execute_message(const char *portal_name, long max_rows) pgstat_report_activity(STATE_RUNNING, sourceText); - set_ps_display(portal->commandTag, false); + set_ps_display(GetCommandTagName(portal->commandTag), false); if (save_log_statement_stats) ResetUsage(); diff --git a/src/backend/tcop/pquery.c b/src/backend/tcop/pquery.c index 0f5801e046..8b8ac354fd 100644 --- a/src/backend/tcop/pquery.c +++ b/src/backend/tcop/pquery.c @@ -774,13 +774,13 @@ PortalRun(Portal portal, long count, bool isTopLevel, bool run_once, * gave us a pointer to store it, copy it. Patch the "SELECT" * tag to also provide the rowcount. */ - if (completionTag && portal->commandTag) + if (completionTag && portal->commandTag != COMMANDTAG_NULL) { - if (strcmp(portal->commandTag, "SELECT") == 0) + if (portal->commandTag == COMMANDTAG_SELECT) snprintf(completionTag, COMPLETION_TAG_BUFSIZE, "SELECT " UINT64_FORMAT, nprocessed); else - strcpy(completionTag, portal->commandTag); + strlcpy(completionTag, PortalGetCompletionTag(portal), COMPLETION_TAG_BUFSIZE); } /* Mark portal not active */ @@ -1044,7 +1044,17 @@ FillPortalStore(Portal portal, bool isTopLevel) /* Override default completion tag with actual command result */ if (completionTag[0] != '\0') - portal->commandTag = pstrdup(completionTag); + { + /* + * The commandTag used to serve double duty, and we overwrote it here + * with the completionTag. That would mean, for instance, that if the + * original commandTag was EXECUTE, we'd overwrite that with SELECT 5 + * or whatever. We now store the completiionTag in this context and + * leave the portal's commandTag alone. If you want to extract a + * commandTag from the completionTag, you can always do so explicitly. + */ + strlcpy(portal->completionTag, completionTag, COMPLETION_TAG_BUFSIZE); + } treceiver->rDestroy(treceiver); } @@ -1363,16 +1373,16 @@ PortalRunMulti(Portal portal, */ if (completionTag && completionTag[0] == '\0') { - if (portal->commandTag) - strcpy(completionTag, portal->commandTag); + if (portal->commandTag != COMMANDTAG_NULL) + strlcpy(completionTag, PortalGetCompletionTag(portal), COMPLETION_TAG_BUFSIZE); if (strcmp(completionTag, "SELECT") == 0) - sprintf(completionTag, "SELECT 0 0"); + strlcpy(completionTag, "SELECT 0 0", COMPLETION_TAG_BUFSIZE); else if (strcmp(completionTag, "INSERT") == 0) - strcpy(completionTag, "INSERT 0 0"); + strlcpy(completionTag, "INSERT 0 0", COMPLETION_TAG_BUFSIZE); else if (strcmp(completionTag, "UPDATE") == 0) - strcpy(completionTag, "UPDATE 0"); + strlcpy(completionTag, "UPDATE 0", COMPLETION_TAG_BUFSIZE); else if (strcmp(completionTag, "DELETE") == 0) - strcpy(completionTag, "DELETE 0"); + strlcpy(completionTag, "DELETE 0", COMPLETION_TAG_BUFSIZE); } } diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c index bb85b5e52a..850e19846d 100644 --- a/src/backend/tcop/utility.c +++ b/src/backend/tcop/utility.c @@ -396,20 +396,33 @@ ClassifyUtilityCommandAsReadOnly(Node *parsetree) } /* - * PreventCommandIfReadOnly: throw error if XactReadOnly + * PreventCommandStrIfReadOnly: throw error if XactReadOnly * * This is useful partly to ensure consistency of the error message wording; * some callers have checked XactReadOnly for themselves. */ +static inline void +PreventCommandReadOnly(const char *commandstr) +{ + ereport(ERROR, + (errcode(ERRCODE_READ_ONLY_SQL_TRANSACTION), + /* translator: %s is name of a SQL command, eg CREATE */ + errmsg("cannot execute %s in a read-only transaction", + commandstr))); +} + void -PreventCommandIfReadOnly(const char *cmdname) +PreventCommandStrIfReadOnly(const char *commandstr) { if (XactReadOnly) - ereport(ERROR, - (errcode(ERRCODE_READ_ONLY_SQL_TRANSACTION), - /* translator: %s is name of a SQL command, eg CREATE */ - errmsg("cannot execute %s in a read-only transaction", - cmdname))); + PreventCommandReadOnly(commandstr); +} + +void +PreventCommandIfReadOnly(CommandTag commandTag) +{ + if (XactReadOnly) + PreventCommandReadOnly(GetCommandTagName(commandTag)); } /* @@ -419,15 +432,28 @@ PreventCommandIfReadOnly(const char *cmdname) * This is useful partly to ensure consistency of the error message wording; * some callers have checked IsInParallelMode() for themselves. */ +static inline void +PreventCommandParallelMode(const char *commandstr) +{ + ereport(ERROR, + (errcode(ERRCODE_INVALID_TRANSACTION_STATE), + /* translator: %s is name of a SQL command, eg CREATE */ + errmsg("cannot execute %s during a parallel operation", + commandstr))); +} + void -PreventCommandIfParallelMode(const char *cmdname) +PreventCommandStrIfParallelMode(const char *commandstr) { if (IsInParallelMode()) - ereport(ERROR, - (errcode(ERRCODE_INVALID_TRANSACTION_STATE), - /* translator: %s is name of a SQL command, eg CREATE */ - errmsg("cannot execute %s during a parallel operation", - cmdname))); + PreventCommandParallelMode(commandstr); +} + +void +PreventCommandIfParallelMode(CommandTag commandTag) +{ + if (IsInParallelMode()) + PreventCommandParallelMode(GetCommandTagName(commandTag)); } /* @@ -438,15 +464,28 @@ PreventCommandIfParallelMode(const char *cmdname) * commands that are allowed in "read-only" xacts but cannot be allowed * in Hot Standby mode. Those commands should call this function. */ +static inline void +PreventCommandRecovery(const char *commandstr) +{ + ereport(ERROR, + (errcode(ERRCODE_READ_ONLY_SQL_TRANSACTION), + /* translator: %s is name of a SQL command, eg CREATE */ + errmsg("cannot execute %s during recovery", + commandstr))); +} + void -PreventCommandDuringRecovery(const char *cmdname) +PreventCommandStrDuringRecovery(const char *commandstr) { if (RecoveryInProgress()) - ereport(ERROR, - (errcode(ERRCODE_READ_ONLY_SQL_TRANSACTION), - /* translator: %s is name of a SQL command, eg CREATE */ - errmsg("cannot execute %s during recovery", - cmdname))); + PreventCommandRecovery(commandstr); +} + +void +PreventCommandDuringRecovery(CommandTag commandTag) +{ + if (RecoveryInProgress()) + PreventCommandRecovery(GetCommandTagName(commandTag)); } /* @@ -457,14 +496,14 @@ PreventCommandDuringRecovery(const char *cmdname) * better-defined protection mechanism, such as ownership. */ static void -CheckRestrictedOperation(const char *cmdname) +CheckRestrictedOperation(CommandTag commandTag) { if (InSecurityRestrictedOperation()) ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), /* translator: %s is name of a SQL command, eg PREPARE */ errmsg("cannot execute %s within security-restricted operation", - cmdname))); + GetCommandTagName(commandTag)))); } @@ -562,7 +601,7 @@ standard_ProcessUtility(PlannedStmt *pstmt, if (readonly_flags != COMMAND_IS_STRICTLY_READ_ONLY && (XactReadOnly || IsInParallelMode())) { - const char *commandtag = CreateCommandTag(parsetree); + CommandTag commandtag = CreateCommandTag(parsetree); if ((readonly_flags & COMMAND_OK_IN_READ_ONLY_TXN) == 0) PreventCommandIfReadOnly(commandtag); @@ -687,7 +726,7 @@ standard_ProcessUtility(PlannedStmt *pstmt, { ClosePortalStmt *stmt = (ClosePortalStmt *) parsetree; - CheckRestrictedOperation("CLOSE"); + CheckRestrictedOperation(COMMANDTAG_CLOSE); PerformPortalClose(stmt->portalname); } break; @@ -736,7 +775,7 @@ standard_ProcessUtility(PlannedStmt *pstmt, break; case T_PrepareStmt: - CheckRestrictedOperation("PREPARE"); + CheckRestrictedOperation(COMMANDTAG_PREPARE); PrepareQuery(pstate, (PrepareStmt *) parsetree, pstmt->stmt_location, pstmt->stmt_len); break; @@ -749,7 +788,7 @@ standard_ProcessUtility(PlannedStmt *pstmt, break; case T_DeallocateStmt: - CheckRestrictedOperation("DEALLOCATE"); + CheckRestrictedOperation(COMMANDTAG_DEALLOCATE); DeallocateQuery((DeallocateStmt *) parsetree); break; @@ -793,7 +832,7 @@ standard_ProcessUtility(PlannedStmt *pstmt, { ListenStmt *stmt = (ListenStmt *) parsetree; - CheckRestrictedOperation("LISTEN"); + CheckRestrictedOperation(COMMANDTAG_LISTEN); Async_Listen(stmt->conditionname); } break; @@ -802,7 +841,7 @@ standard_ProcessUtility(PlannedStmt *pstmt, { UnlistenStmt *stmt = (UnlistenStmt *) parsetree; - CheckRestrictedOperation("UNLISTEN"); + CheckRestrictedOperation(COMMANDTAG_UNLISTEN); if (stmt->conditionname) Async_Unlisten(stmt->conditionname); else @@ -855,7 +894,7 @@ standard_ProcessUtility(PlannedStmt *pstmt, case T_DiscardStmt: /* should we allow DISCARD PLANS? */ - CheckRestrictedOperation("DISCARD"); + CheckRestrictedOperation(COMMANDTAG_DISCARD); DiscardCommand((DiscardStmt *) parsetree, isTopLevel); break; @@ -2099,137 +2138,137 @@ UtilityContainsQuery(Node *parsetree) * * This covers most cases where ALTER is used with an ObjectType enum. */ -static const char * +static CommandTag AlterObjectTypeCommandTag(ObjectType objtype) { - const char *tag; + CommandTag tag; switch (objtype) { case OBJECT_AGGREGATE: - tag = "ALTER AGGREGATE"; + tag = COMMANDTAG_ALTER_AGGREGATE; break; case OBJECT_ATTRIBUTE: - tag = "ALTER TYPE"; + tag = COMMANDTAG_ALTER_TYPE; break; case OBJECT_CAST: - tag = "ALTER CAST"; + tag = COMMANDTAG_ALTER_CAST; break; case OBJECT_COLLATION: - tag = "ALTER COLLATION"; + tag = COMMANDTAG_ALTER_COLLATION; break; case OBJECT_COLUMN: - tag = "ALTER TABLE"; + tag = COMMANDTAG_ALTER_TABLE; break; case OBJECT_CONVERSION: - tag = "ALTER CONVERSION"; + tag = COMMANDTAG_ALTER_CONVERSION; break; case OBJECT_DATABASE: - tag = "ALTER DATABASE"; + tag = COMMANDTAG_ALTER_DATABASE; break; case OBJECT_DOMAIN: case OBJECT_DOMCONSTRAINT: - tag = "ALTER DOMAIN"; + tag = COMMANDTAG_ALTER_DOMAIN; break; case OBJECT_EXTENSION: - tag = "ALTER EXTENSION"; + tag = COMMANDTAG_ALTER_EXTENSION; break; case OBJECT_FDW: - tag = "ALTER FOREIGN DATA WRAPPER"; + tag = COMMANDTAG_ALTER_FOREIGN_DATA_WRAPPER; break; case OBJECT_FOREIGN_SERVER: - tag = "ALTER SERVER"; + tag = COMMANDTAG_ALTER_SERVER; break; case OBJECT_FOREIGN_TABLE: - tag = "ALTER FOREIGN TABLE"; + tag = COMMANDTAG_ALTER_FOREIGN_TABLE; break; case OBJECT_FUNCTION: - tag = "ALTER FUNCTION"; + tag = COMMANDTAG_ALTER_FUNCTION; break; case OBJECT_INDEX: - tag = "ALTER INDEX"; + tag = COMMANDTAG_ALTER_INDEX; break; case OBJECT_LANGUAGE: - tag = "ALTER LANGUAGE"; + tag = COMMANDTAG_ALTER_LANGUAGE; break; case OBJECT_LARGEOBJECT: - tag = "ALTER LARGE OBJECT"; + tag = COMMANDTAG_ALTER_LARGE_OBJECT; break; case OBJECT_OPCLASS: - tag = "ALTER OPERATOR CLASS"; + tag = COMMANDTAG_ALTER_OPERATOR_CLASS; break; case OBJECT_OPERATOR: - tag = "ALTER OPERATOR"; + tag = COMMANDTAG_ALTER_OPERATOR; break; case OBJECT_OPFAMILY: - tag = "ALTER OPERATOR FAMILY"; + tag = COMMANDTAG_ALTER_OPERATOR_FAMILY; break; case OBJECT_POLICY: - tag = "ALTER POLICY"; + tag = COMMANDTAG_ALTER_POLICY; break; case OBJECT_PROCEDURE: - tag = "ALTER PROCEDURE"; + tag = COMMANDTAG_ALTER_PROCEDURE; break; case OBJECT_ROLE: - tag = "ALTER ROLE"; + tag = COMMANDTAG_ALTER_ROLE; break; case OBJECT_ROUTINE: - tag = "ALTER ROUTINE"; + tag = COMMANDTAG_ALTER_ROUTINE; break; case OBJECT_RULE: - tag = "ALTER RULE"; + tag = COMMANDTAG_ALTER_RULE; break; case OBJECT_SCHEMA: - tag = "ALTER SCHEMA"; + tag = COMMANDTAG_ALTER_SCHEMA; break; case OBJECT_SEQUENCE: - tag = "ALTER SEQUENCE"; + tag = COMMANDTAG_ALTER_SEQUENCE; break; case OBJECT_TABLE: case OBJECT_TABCONSTRAINT: - tag = "ALTER TABLE"; + tag = COMMANDTAG_ALTER_TABLE; break; case OBJECT_TABLESPACE: - tag = "ALTER TABLESPACE"; + tag = COMMANDTAG_ALTER_TABLESPACE; break; case OBJECT_TRIGGER: - tag = "ALTER TRIGGER"; + tag = COMMANDTAG_ALTER_TRIGGER; break; case OBJECT_EVENT_TRIGGER: - tag = "ALTER EVENT TRIGGER"; + tag = COMMANDTAG_ALTER_EVENT_TRIGGER; break; case OBJECT_TSCONFIGURATION: - tag = "ALTER TEXT SEARCH CONFIGURATION"; + tag = COMMANDTAG_ALTER_TEXT_SEARCH_CONFIGURATION; break; case OBJECT_TSDICTIONARY: - tag = "ALTER TEXT SEARCH DICTIONARY"; + tag = COMMANDTAG_ALTER_TEXT_SEARCH_DICTIONARY; break; case OBJECT_TSPARSER: - tag = "ALTER TEXT SEARCH PARSER"; + tag = COMMANDTAG_ALTER_TEXT_SEARCH_PARSER; break; case OBJECT_TSTEMPLATE: - tag = "ALTER TEXT SEARCH TEMPLATE"; + tag = COMMANDTAG_ALTER_TEXT_SEARCH_TEMPLATE; break; case OBJECT_TYPE: - tag = "ALTER TYPE"; + tag = COMMANDTAG_ALTER_TYPE; break; case OBJECT_VIEW: - tag = "ALTER VIEW"; + tag = COMMANDTAG_ALTER_VIEW; break; case OBJECT_MATVIEW: - tag = "ALTER MATERIALIZED VIEW"; + tag = COMMANDTAG_ALTER_MATERIALIZED_VIEW; break; case OBJECT_PUBLICATION: - tag = "ALTER PUBLICATION"; + tag = COMMANDTAG_ALTER_PUBLICATION; break; case OBJECT_SUBSCRIPTION: - tag = "ALTER SUBSCRIPTION"; + tag = COMMANDTAG_ALTER_SUBSCRIPTION; break; case OBJECT_STATISTIC_EXT: - tag = "ALTER STATISTICS"; + tag = COMMANDTAG_ALTER_STATISTICS; break; default: - tag = "???"; + tag = COMMANDTAG_UNKNOWN; break; } @@ -2238,20 +2277,17 @@ AlterObjectTypeCommandTag(ObjectType objtype) /* * 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, * or a PlannedStmt. * * This must handle all command types, but since the vast majority * 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) { - const char *tag; + CommandTag tag; switch (nodeTag(parsetree)) { @@ -2262,19 +2298,19 @@ CreateCommandTag(Node *parsetree) /* raw plannable queries */ case T_InsertStmt: - tag = "INSERT"; + tag = COMMANDTAG_INSERT; break; case T_DeleteStmt: - tag = "DELETE"; + tag = COMMANDTAG_DELETE; break; case T_UpdateStmt: - tag = "UPDATE"; + tag = COMMANDTAG_UPDATE; break; case T_SelectStmt: - tag = "SELECT"; + tag = COMMANDTAG_SELECT; break; /* utility statements --- same whether raw or cooked */ @@ -2285,51 +2321,51 @@ CreateCommandTag(Node *parsetree) switch (stmt->kind) { case TRANS_STMT_BEGIN: - tag = "BEGIN"; + tag = COMMANDTAG_BEGIN; break; case TRANS_STMT_START: - tag = "START TRANSACTION"; + tag = COMMANDTAG_START_TRANSACTION; break; case TRANS_STMT_COMMIT: - tag = "COMMIT"; + tag = COMMANDTAG_COMMIT; break; case TRANS_STMT_ROLLBACK: case TRANS_STMT_ROLLBACK_TO: - tag = "ROLLBACK"; + tag = COMMANDTAG_ROLLBACK; break; case TRANS_STMT_SAVEPOINT: - tag = "SAVEPOINT"; + tag = COMMANDTAG_SAVEPOINT; break; case TRANS_STMT_RELEASE: - tag = "RELEASE"; + tag = COMMANDTAG_RELEASE; break; case TRANS_STMT_PREPARE: - tag = "PREPARE TRANSACTION"; + tag = COMMANDTAG_PREPARE_TRANSACTION; break; case TRANS_STMT_COMMIT_PREPARED: - tag = "COMMIT PREPARED"; + tag = COMMANDTAG_COMMIT_PREPARED; break; case TRANS_STMT_ROLLBACK_PREPARED: - tag = "ROLLBACK PREPARED"; + tag = COMMANDTAG_ROLLBACK_PREPARED; break; default: - tag = "???"; + tag = COMMANDTAG_UNKNOWN; break; } } break; case T_DeclareCursorStmt: - tag = "DECLARE CURSOR"; + tag = COMMANDTAG_DECLARE_CURSOR; break; case T_ClosePortalStmt: @@ -2337,9 +2373,9 @@ CreateCommandTag(Node *parsetree) ClosePortalStmt *stmt = (ClosePortalStmt *) parsetree; if (stmt->portalname == NULL) - tag = "CLOSE CURSOR ALL"; + tag = COMMANDTAG_CLOSE_CURSOR_ALL; else - tag = "CLOSE CURSOR"; + tag = COMMANDTAG_CLOSE_CURSOR; } break; @@ -2347,209 +2383,209 @@ CreateCommandTag(Node *parsetree) { FetchStmt *stmt = (FetchStmt *) parsetree; - tag = (stmt->ismove) ? "MOVE" : "FETCH"; + tag = (stmt->ismove) ? COMMANDTAG_MOVE : COMMANDTAG_FETCH; } break; case T_CreateDomainStmt: - tag = "CREATE DOMAIN"; + tag = COMMANDTAG_CREATE_DOMAIN; break; case T_CreateSchemaStmt: - tag = "CREATE SCHEMA"; + tag = COMMANDTAG_CREATE_SCHEMA; break; case T_CreateStmt: - tag = "CREATE TABLE"; + tag = COMMANDTAG_CREATE_TABLE; break; case T_CreateTableSpaceStmt: - tag = "CREATE TABLESPACE"; + tag = COMMANDTAG_CREATE_TABLESPACE; break; case T_DropTableSpaceStmt: - tag = "DROP TABLESPACE"; + tag = COMMANDTAG_DROP_TABLESPACE; break; case T_AlterTableSpaceOptionsStmt: - tag = "ALTER TABLESPACE"; + tag = COMMANDTAG_ALTER_TABLESPACE; break; case T_CreateExtensionStmt: - tag = "CREATE EXTENSION"; + tag = COMMANDTAG_CREATE_EXTENSION; break; case T_AlterExtensionStmt: - tag = "ALTER EXTENSION"; + tag = COMMANDTAG_ALTER_EXTENSION; break; case T_AlterExtensionContentsStmt: - tag = "ALTER EXTENSION"; + tag = COMMANDTAG_ALTER_EXTENSION; break; case T_CreateFdwStmt: - tag = "CREATE FOREIGN DATA WRAPPER"; + tag = COMMANDTAG_CREATE_FOREIGN_DATA_WRAPPER; break; case T_AlterFdwStmt: - tag = "ALTER FOREIGN DATA WRAPPER"; + tag = COMMANDTAG_ALTER_FOREIGN_DATA_WRAPPER; break; case T_CreateForeignServerStmt: - tag = "CREATE SERVER"; + tag = COMMANDTAG_CREATE_SERVER; break; case T_AlterForeignServerStmt: - tag = "ALTER SERVER"; + tag = COMMANDTAG_ALTER_SERVER; break; case T_CreateUserMappingStmt: - tag = "CREATE USER MAPPING"; + tag = COMMANDTAG_CREATE_USER_MAPPING; break; case T_AlterUserMappingStmt: - tag = "ALTER USER MAPPING"; + tag = COMMANDTAG_ALTER_USER_MAPPING; break; case T_DropUserMappingStmt: - tag = "DROP USER MAPPING"; + tag = COMMANDTAG_DROP_USER_MAPPING; break; case T_CreateForeignTableStmt: - tag = "CREATE FOREIGN TABLE"; + tag = COMMANDTAG_CREATE_FOREIGN_TABLE; break; case T_ImportForeignSchemaStmt: - tag = "IMPORT FOREIGN SCHEMA"; + tag = COMMANDTAG_IMPORT_FOREIGN_SCHEMA; break; case T_DropStmt: switch (((DropStmt *) parsetree)->removeType) { case OBJECT_TABLE: - tag = "DROP TABLE"; + tag = COMMANDTAG_DROP_TABLE; break; case OBJECT_SEQUENCE: - tag = "DROP SEQUENCE"; + tag = COMMANDTAG_DROP_SEQUENCE; break; case OBJECT_VIEW: - tag = "DROP VIEW"; + tag = COMMANDTAG_DROP_VIEW; break; case OBJECT_MATVIEW: - tag = "DROP MATERIALIZED VIEW"; + tag = COMMANDTAG_DROP_MATERIALIZED_VIEW; break; case OBJECT_INDEX: - tag = "DROP INDEX"; + tag = COMMANDTAG_DROP_INDEX; break; case OBJECT_TYPE: - tag = "DROP TYPE"; + tag = COMMANDTAG_DROP_TYPE; break; case OBJECT_DOMAIN: - tag = "DROP DOMAIN"; + tag = COMMANDTAG_DROP_DOMAIN; break; case OBJECT_COLLATION: - tag = "DROP COLLATION"; + tag = COMMANDTAG_DROP_COLLATION; break; case OBJECT_CONVERSION: - tag = "DROP CONVERSION"; + tag = COMMANDTAG_DROP_CONVERSION; break; case OBJECT_SCHEMA: - tag = "DROP SCHEMA"; + tag = COMMANDTAG_DROP_SCHEMA; break; case OBJECT_TSPARSER: - tag = "DROP TEXT SEARCH PARSER"; + tag = COMMANDTAG_DROP_TEXT_SEARCH_PARSER; break; case OBJECT_TSDICTIONARY: - tag = "DROP TEXT SEARCH DICTIONARY"; + tag = COMMANDTAG_DROP_TEXT_SEARCH_DICTIONARY; break; case OBJECT_TSTEMPLATE: - tag = "DROP TEXT SEARCH TEMPLATE"; + tag = COMMANDTAG_DROP_TEXT_SEARCH_TEMPLATE; break; case OBJECT_TSCONFIGURATION: - tag = "DROP TEXT SEARCH CONFIGURATION"; + tag = COMMANDTAG_DROP_TEXT_SEARCH_CONFIGURATION; break; case OBJECT_FOREIGN_TABLE: - tag = "DROP FOREIGN TABLE"; + tag = COMMANDTAG_DROP_FOREIGN_TABLE; break; case OBJECT_EXTENSION: - tag = "DROP EXTENSION"; + tag = COMMANDTAG_DROP_EXTENSION; break; case OBJECT_FUNCTION: - tag = "DROP FUNCTION"; + tag = COMMANDTAG_DROP_FUNCTION; break; case OBJECT_PROCEDURE: - tag = "DROP PROCEDURE"; + tag = COMMANDTAG_DROP_PROCEDURE; break; case OBJECT_ROUTINE: - tag = "DROP ROUTINE"; + tag = COMMANDTAG_DROP_ROUTINE; break; case OBJECT_AGGREGATE: - tag = "DROP AGGREGATE"; + tag = COMMANDTAG_DROP_AGGREGATE; break; case OBJECT_OPERATOR: - tag = "DROP OPERATOR"; + tag = COMMANDTAG_DROP_OPERATOR; break; case OBJECT_LANGUAGE: - tag = "DROP LANGUAGE"; + tag = COMMANDTAG_DROP_LANGUAGE; break; case OBJECT_CAST: - tag = "DROP CAST"; + tag = COMMANDTAG_DROP_CAST; break; case OBJECT_TRIGGER: - tag = "DROP TRIGGER"; + tag = COMMANDTAG_DROP_TRIGGER; break; case OBJECT_EVENT_TRIGGER: - tag = "DROP EVENT TRIGGER"; + tag = COMMANDTAG_DROP_EVENT_TRIGGER; break; case OBJECT_RULE: - tag = "DROP RULE"; + tag = COMMANDTAG_DROP_RULE; break; case OBJECT_FDW: - tag = "DROP FOREIGN DATA WRAPPER"; + tag = COMMANDTAG_DROP_FOREIGN_DATA_WRAPPER; break; case OBJECT_FOREIGN_SERVER: - tag = "DROP SERVER"; + tag = COMMANDTAG_DROP_SERVER; break; case OBJECT_OPCLASS: - tag = "DROP OPERATOR CLASS"; + tag = COMMANDTAG_DROP_OPERATOR_CLASS; break; case OBJECT_OPFAMILY: - tag = "DROP OPERATOR FAMILY"; + tag = COMMANDTAG_DROP_OPERATOR_FAMILY; break; case OBJECT_POLICY: - tag = "DROP POLICY"; + tag = COMMANDTAG_DROP_POLICY; break; case OBJECT_TRANSFORM: - tag = "DROP TRANSFORM"; + tag = COMMANDTAG_DROP_TRANSFORM; break; case OBJECT_ACCESS_METHOD: - tag = "DROP ACCESS METHOD"; + tag = COMMANDTAG_DROP_ACCESS_METHOD; break; case OBJECT_PUBLICATION: - tag = "DROP PUBLICATION"; + tag = COMMANDTAG_DROP_PUBLICATION; break; case OBJECT_STATISTIC_EXT: - tag = "DROP STATISTICS"; + tag = COMMANDTAG_DROP_STATISTICS; break; default: - tag = "???"; + tag = COMMANDTAG_UNKNOWN; } break; case T_TruncateStmt: - tag = "TRUNCATE TABLE"; + tag = COMMANDTAG_TRUNCATE_TABLE; break; case T_CommentStmt: - tag = "COMMENT"; + tag = COMMANDTAG_COMMENT; break; case T_SecLabelStmt: - tag = "SECURITY LABEL"; + tag = COMMANDTAG_SECURITY_LABEL; break; case T_CopyStmt: - tag = "COPY"; + tag = COMMANDTAG_COPY; break; case T_RenameStmt: @@ -2584,23 +2620,23 @@ CreateCommandTag(Node *parsetree) break; case T_AlterDomainStmt: - tag = "ALTER DOMAIN"; + tag = COMMANDTAG_ALTER_DOMAIN; break; case T_AlterFunctionStmt: switch (((AlterFunctionStmt *) parsetree)->objtype) { case OBJECT_FUNCTION: - tag = "ALTER FUNCTION"; + tag = COMMANDTAG_ALTER_FUNCTION; break; case OBJECT_PROCEDURE: - tag = "ALTER PROCEDURE"; + tag = COMMANDTAG_ALTER_PROCEDURE; break; case OBJECT_ROUTINE: - tag = "ALTER ROUTINE"; + tag = COMMANDTAG_ALTER_ROUTINE; break; default: - tag = "???"; + tag = COMMANDTAG_UNKNOWN; } break; @@ -2608,7 +2644,7 @@ CreateCommandTag(Node *parsetree) { GrantStmt *stmt = (GrantStmt *) parsetree; - tag = (stmt->is_grant) ? "GRANT" : "REVOKE"; + tag = (stmt->is_grant) ? COMMANDTAG_GRANT : COMMANDTAG_REVOKE; } break; @@ -2616,145 +2652,145 @@ CreateCommandTag(Node *parsetree) { GrantRoleStmt *stmt = (GrantRoleStmt *) parsetree; - tag = (stmt->is_grant) ? "GRANT ROLE" : "REVOKE ROLE"; + tag = (stmt->is_grant) ? COMMANDTAG_GRANT_ROLE : COMMANDTAG_REVOKE_ROLE; } break; case T_AlterDefaultPrivilegesStmt: - tag = "ALTER DEFAULT PRIVILEGES"; + tag = COMMANDTAG_ALTER_DEFAULT_PRIVILEGES; break; case T_DefineStmt: switch (((DefineStmt *) parsetree)->kind) { case OBJECT_AGGREGATE: - tag = "CREATE AGGREGATE"; + tag = COMMANDTAG_CREATE_AGGREGATE; break; case OBJECT_OPERATOR: - tag = "CREATE OPERATOR"; + tag = COMMANDTAG_CREATE_OPERATOR; break; case OBJECT_TYPE: - tag = "CREATE TYPE"; + tag = COMMANDTAG_CREATE_TYPE; break; case OBJECT_TSPARSER: - tag = "CREATE TEXT SEARCH PARSER"; + tag = COMMANDTAG_CREATE_TEXT_SEARCH_PARSER; break; case OBJECT_TSDICTIONARY: - tag = "CREATE TEXT SEARCH DICTIONARY"; + tag = COMMANDTAG_CREATE_TEXT_SEARCH_DICTIONARY; break; case OBJECT_TSTEMPLATE: - tag = "CREATE TEXT SEARCH TEMPLATE"; + tag = COMMANDTAG_CREATE_TEXT_SEARCH_TEMPLATE; break; case OBJECT_TSCONFIGURATION: - tag = "CREATE TEXT SEARCH CONFIGURATION"; + tag = COMMANDTAG_CREATE_TEXT_SEARCH_CONFIGURATION; break; case OBJECT_COLLATION: - tag = "CREATE COLLATION"; + tag = COMMANDTAG_CREATE_COLLATION; break; case OBJECT_ACCESS_METHOD: - tag = "CREATE ACCESS METHOD"; + tag = COMMANDTAG_CREATE_ACCESS_METHOD; break; default: - tag = "???"; + tag = COMMANDTAG_UNKNOWN; } break; case T_CompositeTypeStmt: - tag = "CREATE TYPE"; + tag = COMMANDTAG_CREATE_TYPE; break; case T_CreateEnumStmt: - tag = "CREATE TYPE"; + tag = COMMANDTAG_CREATE_TYPE; break; case T_CreateRangeStmt: - tag = "CREATE TYPE"; + tag = COMMANDTAG_CREATE_TYPE; break; case T_AlterEnumStmt: - tag = "ALTER TYPE"; + tag = COMMANDTAG_ALTER_TYPE; break; case T_ViewStmt: - tag = "CREATE VIEW"; + tag = COMMANDTAG_CREATE_VIEW; break; case T_CreateFunctionStmt: if (((CreateFunctionStmt *) parsetree)->is_procedure) - tag = "CREATE PROCEDURE"; + tag = COMMANDTAG_CREATE_PROCEDURE; else - tag = "CREATE FUNCTION"; + tag = COMMANDTAG_CREATE_FUNCTION; break; case T_IndexStmt: - tag = "CREATE INDEX"; + tag = COMMANDTAG_CREATE_INDEX; break; case T_RuleStmt: - tag = "CREATE RULE"; + tag = COMMANDTAG_CREATE_RULE; break; case T_CreateSeqStmt: - tag = "CREATE SEQUENCE"; + tag = COMMANDTAG_CREATE_SEQUENCE; break; case T_AlterSeqStmt: - tag = "ALTER SEQUENCE"; + tag = COMMANDTAG_ALTER_SEQUENCE; break; case T_DoStmt: - tag = "DO"; + tag = COMMANDTAG_DO; break; case T_CreatedbStmt: - tag = "CREATE DATABASE"; + tag = COMMANDTAG_CREATE_DATABASE; break; case T_AlterDatabaseStmt: - tag = "ALTER DATABASE"; + tag = COMMANDTAG_ALTER_DATABASE; break; case T_AlterDatabaseSetStmt: - tag = "ALTER DATABASE"; + tag = COMMANDTAG_ALTER_DATABASE; break; case T_DropdbStmt: - tag = "DROP DATABASE"; + tag = COMMANDTAG_DROP_DATABASE; break; case T_NotifyStmt: - tag = "NOTIFY"; + tag = COMMANDTAG_NOTIFY; break; case T_ListenStmt: - tag = "LISTEN"; + tag = COMMANDTAG_LISTEN; break; case T_UnlistenStmt: - tag = "UNLISTEN"; + tag = COMMANDTAG_UNLISTEN; break; case T_LoadStmt: - tag = "LOAD"; + tag = COMMANDTAG_LOAD; break; case T_CallStmt: - tag = "CALL"; + tag = COMMANDTAG_CALL; break; case T_ClusterStmt: - tag = "CLUSTER"; + tag = COMMANDTAG_CLUSTER; break; case T_VacuumStmt: if (((VacuumStmt *) parsetree)->is_vacuumcmd) - tag = "VACUUM"; + tag = COMMANDTAG_VACUUM; else - tag = "ANALYZE"; + tag = COMMANDTAG_ANALYZE; break; case T_ExplainStmt: - tag = "EXPLAIN"; + tag = COMMANDTAG_EXPLAIN; break; case T_CreateTableAsStmt: @@ -2762,24 +2798,24 @@ CreateCommandTag(Node *parsetree) { case OBJECT_TABLE: if (((CreateTableAsStmt *) parsetree)->is_select_into) - tag = "SELECT INTO"; + tag = COMMANDTAG_SELECT_INTO; else - tag = "CREATE TABLE AS"; + tag = COMMANDTAG_CREATE_TABLE_AS; break; case OBJECT_MATVIEW: - tag = "CREATE MATERIALIZED VIEW"; + tag = COMMANDTAG_CREATE_MATERIALIZED_VIEW; break; default: - tag = "???"; + tag = COMMANDTAG_UNKNOWN; } break; case T_RefreshMatViewStmt: - tag = "REFRESH MATERIALIZED VIEW"; + tag = COMMANDTAG_REFRESH_MATERIALIZED_VIEW; break; case T_AlterSystemStmt: - tag = "ALTER SYSTEM"; + tag = COMMANDTAG_ALTER_SYSTEM; break; case T_VariableSetStmt: @@ -2789,183 +2825,183 @@ CreateCommandTag(Node *parsetree) case VAR_SET_CURRENT: case VAR_SET_DEFAULT: case VAR_SET_MULTI: - tag = "SET"; + tag = COMMANDTAG_SET; break; case VAR_RESET: case VAR_RESET_ALL: - tag = "RESET"; + tag = COMMANDTAG_RESET; break; default: - tag = "???"; + tag = COMMANDTAG_UNKNOWN; } break; case T_VariableShowStmt: - tag = "SHOW"; + tag = COMMANDTAG_SHOW; break; case T_DiscardStmt: switch (((DiscardStmt *) parsetree)->target) { case DISCARD_ALL: - tag = "DISCARD ALL"; + tag = COMMANDTAG_DISCARD_ALL; break; case DISCARD_PLANS: - tag = "DISCARD PLANS"; + tag = COMMANDTAG_DISCARD_PLANS; break; case DISCARD_TEMP: - tag = "DISCARD TEMP"; + tag = COMMANDTAG_DISCARD_TEMP; break; case DISCARD_SEQUENCES: - tag = "DISCARD SEQUENCES"; + tag = COMMANDTAG_DISCARD_SEQUENCES; break; default: - tag = "???"; + tag = COMMANDTAG_UNKNOWN; } break; case T_CreateTransformStmt: - tag = "CREATE TRANSFORM"; + tag = COMMANDTAG_CREATE_TRANSFORM; break; case T_CreateTrigStmt: - tag = "CREATE TRIGGER"; + tag = COMMANDTAG_CREATE_TRIGGER; break; case T_CreateEventTrigStmt: - tag = "CREATE EVENT TRIGGER"; + tag = COMMANDTAG_CREATE_EVENT_TRIGGER; break; case T_AlterEventTrigStmt: - tag = "ALTER EVENT TRIGGER"; + tag = COMMANDTAG_ALTER_EVENT_TRIGGER; break; case T_CreatePLangStmt: - tag = "CREATE LANGUAGE"; + tag = COMMANDTAG_CREATE_LANGUAGE; break; case T_CreateRoleStmt: - tag = "CREATE ROLE"; + tag = COMMANDTAG_CREATE_ROLE; break; case T_AlterRoleStmt: - tag = "ALTER ROLE"; + tag = COMMANDTAG_ALTER_ROLE; break; case T_AlterRoleSetStmt: - tag = "ALTER ROLE"; + tag = COMMANDTAG_ALTER_ROLE; break; case T_DropRoleStmt: - tag = "DROP ROLE"; + tag = COMMANDTAG_DROP_ROLE; break; case T_DropOwnedStmt: - tag = "DROP OWNED"; + tag = COMMANDTAG_DROP_OWNED; break; case T_ReassignOwnedStmt: - tag = "REASSIGN OWNED"; + tag = COMMANDTAG_REASSIGN_OWNED; break; case T_LockStmt: - tag = "LOCK TABLE"; + tag = COMMANDTAG_LOCK_TABLE; break; case T_ConstraintsSetStmt: - tag = "SET CONSTRAINTS"; + tag = COMMANDTAG_SET_CONSTRAINTS; break; case T_CheckPointStmt: - tag = "CHECKPOINT"; + tag = COMMANDTAG_CHECKPOINT; break; case T_ReindexStmt: - tag = "REINDEX"; + tag = COMMANDTAG_REINDEX; break; case T_CreateConversionStmt: - tag = "CREATE CONVERSION"; + tag = COMMANDTAG_CREATE_CONVERSION; break; case T_CreateCastStmt: - tag = "CREATE CAST"; + tag = COMMANDTAG_CREATE_CAST; break; case T_CreateOpClassStmt: - tag = "CREATE OPERATOR CLASS"; + tag = COMMANDTAG_CREATE_OPERATOR_CLASS; break; case T_CreateOpFamilyStmt: - tag = "CREATE OPERATOR FAMILY"; + tag = COMMANDTAG_CREATE_OPERATOR_FAMILY; break; case T_AlterOpFamilyStmt: - tag = "ALTER OPERATOR FAMILY"; + tag = COMMANDTAG_ALTER_OPERATOR_FAMILY; break; case T_AlterOperatorStmt: - tag = "ALTER OPERATOR"; + tag = COMMANDTAG_ALTER_OPERATOR; break; case T_AlterTSDictionaryStmt: - tag = "ALTER TEXT SEARCH DICTIONARY"; + tag = COMMANDTAG_ALTER_TEXT_SEARCH_DICTIONARY; break; case T_AlterTSConfigurationStmt: - tag = "ALTER TEXT SEARCH CONFIGURATION"; + tag = COMMANDTAG_ALTER_TEXT_SEARCH_CONFIGURATION; break; case T_CreatePolicyStmt: - tag = "CREATE POLICY"; + tag = COMMANDTAG_CREATE_POLICY; break; case T_AlterPolicyStmt: - tag = "ALTER POLICY"; + tag = COMMANDTAG_ALTER_POLICY; break; case T_CreateAmStmt: - tag = "CREATE ACCESS METHOD"; + tag = COMMANDTAG_CREATE_ACCESS_METHOD; break; case T_CreatePublicationStmt: - tag = "CREATE PUBLICATION"; + tag = COMMANDTAG_CREATE_PUBLICATION; break; case T_AlterPublicationStmt: - tag = "ALTER PUBLICATION"; + tag = COMMANDTAG_ALTER_PUBLICATION; break; case T_CreateSubscriptionStmt: - tag = "CREATE SUBSCRIPTION"; + tag = COMMANDTAG_CREATE_SUBSCRIPTION; break; case T_AlterSubscriptionStmt: - tag = "ALTER SUBSCRIPTION"; + tag = COMMANDTAG_ALTER_SUBSCRIPTION; break; case T_DropSubscriptionStmt: - tag = "DROP SUBSCRIPTION"; + tag = COMMANDTAG_DROP_SUBSCRIPTION; break; case T_AlterCollationStmt: - tag = "ALTER COLLATION"; + tag = COMMANDTAG_ALTER_COLLATION; break; case T_PrepareStmt: - tag = "PREPARE"; + tag = COMMANDTAG_PREPARE; break; case T_ExecuteStmt: - tag = "EXECUTE"; + tag = COMMANDTAG_EXECUTE; break; case T_CreateStatsStmt: - tag = "CREATE STATISTICS"; + tag = COMMANDTAG_CREATE_STATISTICS; break; case T_AlterStatsStmt: - tag = "ALTER STATISTICS"; + tag = COMMANDTAG_ALTER_STATISTICS; break; case T_DeallocateStmt: @@ -2973,9 +3009,9 @@ CreateCommandTag(Node *parsetree) DeallocateStmt *stmt = (DeallocateStmt *) parsetree; if (stmt->name == NULL) - tag = "DEALLOCATE ALL"; + tag = COMMANDTAG_DEALLOCATE_ALL; else - tag = "DEALLOCATE"; + tag = COMMANDTAG_DEALLOCATE; } break; @@ -2999,33 +3035,33 @@ CreateCommandTag(Node *parsetree) switch (((PlanRowMark *) linitial(stmt->rowMarks))->strength) { case LCS_FORKEYSHARE: - tag = "SELECT FOR KEY SHARE"; + tag = COMMANDTAG_SELECT_FOR_KEY_SHARE; break; case LCS_FORSHARE: - tag = "SELECT FOR SHARE"; + tag = COMMANDTAG_SELECT_FOR_SHARE; break; case LCS_FORNOKEYUPDATE: - tag = "SELECT FOR NO KEY UPDATE"; + tag = COMMANDTAG_SELECT_FOR_NO_KEY_UPDATE; break; case LCS_FORUPDATE: - tag = "SELECT FOR UPDATE"; + tag = COMMANDTAG_SELECT_FOR_UPDATE; break; default: - tag = "SELECT"; + tag = COMMANDTAG_SELECT; break; } } else - tag = "SELECT"; + tag = COMMANDTAG_SELECT; break; case CMD_UPDATE: - tag = "UPDATE"; + tag = COMMANDTAG_UPDATE; break; case CMD_INSERT: - tag = "INSERT"; + tag = COMMANDTAG_INSERT; break; case CMD_DELETE: - tag = "DELETE"; + tag = COMMANDTAG_DELETE; break; case CMD_UTILITY: tag = CreateCommandTag(stmt->utilityStmt); @@ -3033,7 +3069,7 @@ CreateCommandTag(Node *parsetree) default: elog(WARNING, "unrecognized commandType: %d", (int) stmt->commandType); - tag = "???"; + tag = COMMANDTAG_UNKNOWN; break; } } @@ -3059,33 +3095,33 @@ CreateCommandTag(Node *parsetree) switch (((RowMarkClause *) linitial(stmt->rowMarks))->strength) { case LCS_FORKEYSHARE: - tag = "SELECT FOR KEY SHARE"; + tag = COMMANDTAG_SELECT_FOR_KEY_SHARE; break; case LCS_FORSHARE: - tag = "SELECT FOR SHARE"; + tag = COMMANDTAG_SELECT_FOR_SHARE; break; case LCS_FORNOKEYUPDATE: - tag = "SELECT FOR NO KEY UPDATE"; + tag = COMMANDTAG_SELECT_FOR_NO_KEY_UPDATE; break; case LCS_FORUPDATE: - tag = "SELECT FOR UPDATE"; + tag = COMMANDTAG_SELECT_FOR_UPDATE; break; default: - tag = "???"; + tag = COMMANDTAG_UNKNOWN; break; } } else - tag = "SELECT"; + tag = COMMANDTAG_SELECT; break; case CMD_UPDATE: - tag = "UPDATE"; + tag = COMMANDTAG_UPDATE; break; case CMD_INSERT: - tag = "INSERT"; + tag = COMMANDTAG_INSERT; break; case CMD_DELETE: - tag = "DELETE"; + tag = COMMANDTAG_DELETE; break; case CMD_UTILITY: tag = CreateCommandTag(stmt->utilityStmt); @@ -3093,7 +3129,7 @@ CreateCommandTag(Node *parsetree) default: elog(WARNING, "unrecognized commandType: %d", (int) stmt->commandType); - tag = "???"; + tag = COMMANDTAG_UNKNOWN; break; } } @@ -3102,7 +3138,7 @@ CreateCommandTag(Node *parsetree) default: elog(WARNING, "unrecognized node type: %d", (int) nodeTag(parsetree)); - tag = "???"; + tag = COMMANDTAG_UNKNOWN; break; } diff --git a/src/backend/utils/adt/txid.c b/src/backend/utils/adt/txid.c index 33272f8030..37e3cc70f8 100644 --- a/src/backend/utils/adt/txid.c +++ b/src/backend/utils/adt/txid.c @@ -425,7 +425,7 @@ txid_current(PG_FUNCTION_ARGS) * to always return a valid current xid, so we should not change this to * return NULL or similar invalid xid. */ - PreventCommandDuringRecovery("txid_current()"); + PreventCommandStrDuringRecovery("txid_current()"); load_xid_epoch(&state); diff --git a/src/backend/utils/cache/plancache.c b/src/backend/utils/cache/plancache.c index c47be0ba4c..53401bd4e9 100644 --- a/src/backend/utils/cache/plancache.c +++ b/src/backend/utils/cache/plancache.c @@ -163,7 +163,7 @@ InitPlanCache(void) CachedPlanSource * CreateCachedPlan(RawStmt *raw_parse_tree, const char *query_string, - const char *commandTag) + CommandTag commandTag) { CachedPlanSource *plansource; MemoryContext source_context; @@ -246,7 +246,7 @@ CreateCachedPlan(RawStmt *raw_parse_tree, CachedPlanSource * CreateOneShotCachedPlan(RawStmt *raw_parse_tree, const char *query_string, - const char *commandTag) + CommandTag commandTag) { CachedPlanSource *plansource; diff --git a/src/backend/utils/mmgr/portalmem.c b/src/backend/utils/mmgr/portalmem.c index b675575c31..b1c45ca369 100644 --- a/src/backend/utils/mmgr/portalmem.c +++ b/src/backend/utils/mmgr/portalmem.c @@ -281,7 +281,7 @@ void PortalDefineQuery(Portal portal, const char *prepStmtName, const char *sourceText, - const char *commandTag, + CommandTag commandTag, List *stmts, CachedPlan *cplan) { @@ -289,10 +289,12 @@ PortalDefineQuery(Portal portal, AssertState(portal->status == PORTAL_NEW); AssertArg(sourceText != NULL); - AssertArg(commandTag != NULL || stmts == NIL); + AssertArg(commandTag != COMMANDTAG_NULL || stmts == NIL); portal->prepStmtName = prepStmtName; portal->sourceText = sourceText; + Assert(COMPLETION_TAG_BUFSIZE > 0); + portal->completionTag[0] = '\0'; portal->commandTag = commandTag; portal->stmts = stmts; portal->cplan = cplan; diff --git a/src/common/Makefile b/src/common/Makefile index e757fb7399..30a0f5c559 100644 --- a/src/common/Makefile +++ b/src/common/Makefile @@ -48,6 +48,7 @@ LIBS += $(PTHREAD_LIBS) OBJS_COMMON = \ base64.o \ + commandtag.o \ config_info.o \ controldata_utils.o \ d2s.o \ diff --git a/src/common/commandtag.c b/src/common/commandtag.c new file mode 100644 index 0000000000..09455f7f1f --- /dev/null +++ b/src/common/commandtag.c @@ -0,0 +1,382 @@ +/*------------------------------------------------------------------------- + * + * commandtag.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/common/commandtag.c + * + *------------------------------------------------------------------------- + */ + +#ifdef FRONTEND +#include "postgres_fe.h" +#define elog(...) +#else +#include "postgres.h" +#endif + +#include "c.h" +#include "common/commandtag.h" + +typedef struct command_tag_name_map +{ + CommandTag commandTag; + const char *commandname; +} command_tag_name_map; + +const command_tag_name_map tag_names[] = { + {COMMANDTAG_NULL, ""}, + {COMMANDTAG_UNKNOWN, "???"}, + {COMMANDTAG_ALTER_ACCESS_METHOD, "ALTER ACCESS METHOD"}, + {COMMANDTAG_ALTER_AGGREGATE, "ALTER AGGREGATE"}, + {COMMANDTAG_ALTER_CAST, "ALTER CAST"}, + {COMMANDTAG_ALTER_COLLATION, "ALTER COLLATION"}, + {COMMANDTAG_ALTER_CONSTRAINT, "ALTER CONSTRAINT"}, + {COMMANDTAG_ALTER_CONVERSION, "ALTER CONVERSION"}, + {COMMANDTAG_ALTER_DATABASE, "ALTER DATABASE"}, + {COMMANDTAG_ALTER_DEFAULT_PRIVILEGES, "ALTER DEFAULT PRIVILEGES"}, + {COMMANDTAG_ALTER_DOMAIN, "ALTER DOMAIN"}, + {COMMANDTAG_ALTER_EVENT_TRIGGER, "ALTER EVENT TRIGGER"}, + {COMMANDTAG_ALTER_EXTENSION, "ALTER EXTENSION"}, + {COMMANDTAG_ALTER_FOREIGN_DATA_WRAPPER, "ALTER FOREIGN DATA WRAPPER"}, + {COMMANDTAG_ALTER_FOREIGN_TABLE, "ALTER FOREIGN TABLE"}, + {COMMANDTAG_ALTER_FUNCTION, "ALTER FUNCTION"}, + {COMMANDTAG_ALTER_INDEX, "ALTER INDEX"}, + {COMMANDTAG_ALTER_LANGUAGE, "ALTER LANGUAGE"}, + {COMMANDTAG_ALTER_LARGE_OBJECT, "ALTER LARGE OBJECT"}, + {COMMANDTAG_ALTER_MATERIALIZED_VIEW, "ALTER MATERIALIZED VIEW"}, + {COMMANDTAG_ALTER_OPERATOR, "ALTER OPERATOR"}, + {COMMANDTAG_ALTER_OPERATOR_CLASS, "ALTER OPERATOR CLASS"}, + {COMMANDTAG_ALTER_OPERATOR_FAMILY, "ALTER OPERATOR FAMILY"}, + {COMMANDTAG_ALTER_POLICY, "ALTER POLICY"}, + {COMMANDTAG_ALTER_PROCEDURE, "ALTER PROCEDURE"}, + {COMMANDTAG_ALTER_PUBLICATION, "ALTER PUBLICATION"}, + {COMMANDTAG_ALTER_ROLE, "ALTER ROLE"}, + {COMMANDTAG_ALTER_ROUTINE, "ALTER ROUTINE"}, + {COMMANDTAG_ALTER_RULE, "ALTER RULE"}, + {COMMANDTAG_ALTER_SCHEMA, "ALTER SCHEMA"}, + {COMMANDTAG_ALTER_SEQUENCE, "ALTER SEQUENCE"}, + {COMMANDTAG_ALTER_SERVER, "ALTER SERVER"}, + {COMMANDTAG_ALTER_STATISTICS, "ALTER STATISTICS"}, + {COMMANDTAG_ALTER_SUBSCRIPTION, "ALTER SUBSCRIPTION"}, + {COMMANDTAG_ALTER_SYSTEM, "ALTER SYSTEM"}, + {COMMANDTAG_ALTER_TABLE, "ALTER TABLE"}, + {COMMANDTAG_ALTER_TABLESPACE, "ALTER TABLESPACE"}, + {COMMANDTAG_ALTER_TEXT_SEARCH_CONFIGURATION, "ALTER TEXT SEARCH CONFIGURATION"}, + {COMMANDTAG_ALTER_TEXT_SEARCH_DICTIONARY, "ALTER TEXT SEARCH DICTIONARY"}, + {COMMANDTAG_ALTER_TEXT_SEARCH_PARSER, "ALTER TEXT SEARCH PARSER"}, + {COMMANDTAG_ALTER_TEXT_SEARCH_TEMPLATE, "ALTER TEXT SEARCH TEMPLATE"}, + {COMMANDTAG_ALTER_TRANSFORM, "ALTER TRANSFORM"}, + {COMMANDTAG_ALTER_TRIGGER, "ALTER TRIGGER"}, + {COMMANDTAG_ALTER_TYPE, "ALTER TYPE"}, + {COMMANDTAG_ALTER_USER_MAPPING, "ALTER USER MAPPING"}, + {COMMANDTAG_ALTER_VIEW, "ALTER VIEW"}, + {COMMANDTAG_ANALYZE, "ANALYZE"}, + {COMMANDTAG_BEGIN, "BEGIN"}, + {COMMANDTAG_CALL, "CALL"}, + {COMMANDTAG_CHECKPOINT, "CHECKPOINT"}, + {COMMANDTAG_CLOSE, "CLOSE"}, + {COMMANDTAG_CLOSE_CURSOR, "CLOSE CURSOR"}, + {COMMANDTAG_CLOSE_CURSOR_ALL, "CLOSE CURSOR ALL"}, + {COMMANDTAG_CLUSTER, "CLUSTER"}, + {COMMANDTAG_COMMENT, "COMMENT"}, + {COMMANDTAG_COMMIT, "COMMIT"}, + {COMMANDTAG_COMMIT_PREPARED, "COMMIT PREPARED"}, + {COMMANDTAG_COPY, "COPY"}, + {COMMANDTAG_COPY_FROM, "COPY FROM"}, + {COMMANDTAG_CREATE_ACCESS_METHOD, "CREATE ACCESS METHOD"}, + {COMMANDTAG_CREATE_AGGREGATE, "CREATE AGGREGATE"}, + {COMMANDTAG_CREATE_CAST, "CREATE CAST"}, + {COMMANDTAG_CREATE_COLLATION, "CREATE COLLATION"}, + {COMMANDTAG_CREATE_CONSTRAINT, "CREATE CONSTRAINT"}, + {COMMANDTAG_CREATE_CONVERSION, "CREATE CONVERSION"}, + {COMMANDTAG_CREATE_DATABASE, "CREATE DATABASE"}, + {COMMANDTAG_CREATE_DOMAIN, "CREATE DOMAIN"}, + {COMMANDTAG_CREATE_EVENT_TRIGGER, "CREATE EVENT TRIGGER"}, + {COMMANDTAG_CREATE_EXTENSION, "CREATE EXTENSION"}, + {COMMANDTAG_CREATE_FOREIGN_DATA_WRAPPER, "CREATE FOREIGN DATA WRAPPER"}, + {COMMANDTAG_CREATE_FOREIGN_TABLE, "CREATE FOREIGN TABLE"}, + {COMMANDTAG_CREATE_FUNCTION, "CREATE FUNCTION"}, + {COMMANDTAG_CREATE_INDEX, "CREATE INDEX"}, + {COMMANDTAG_CREATE_LANGUAGE, "CREATE LANGUAGE"}, + {COMMANDTAG_CREATE_MATERIALIZED_VIEW, "CREATE MATERIALIZED VIEW"}, + {COMMANDTAG_CREATE_OPERATOR, "CREATE OPERATOR"}, + {COMMANDTAG_CREATE_OPERATOR_CLASS, "CREATE OPERATOR CLASS"}, + {COMMANDTAG_CREATE_OPERATOR_FAMILY, "CREATE OPERATOR FAMILY"}, + {COMMANDTAG_CREATE_POLICY, "CREATE POLICY"}, + {COMMANDTAG_CREATE_PROCEDURE, "CREATE PROCEDURE"}, + {COMMANDTAG_CREATE_PUBLICATION, "CREATE PUBLICATION"}, + {COMMANDTAG_CREATE_ROLE, "CREATE ROLE"}, + {COMMANDTAG_CREATE_ROUTINE, "CREATE ROUTINE"}, + {COMMANDTAG_CREATE_RULE, "CREATE RULE"}, + {COMMANDTAG_CREATE_SCHEMA, "CREATE SCHEMA"}, + {COMMANDTAG_CREATE_SEQUENCE, "CREATE SEQUENCE"}, + {COMMANDTAG_CREATE_SERVER, "CREATE SERVER"}, + {COMMANDTAG_CREATE_STATISTICS, "CREATE STATISTICS"}, + {COMMANDTAG_CREATE_SUBSCRIPTION, "CREATE SUBSCRIPTION"}, + {COMMANDTAG_CREATE_TABLE, "CREATE TABLE"}, + {COMMANDTAG_CREATE_TABLE_AS, "CREATE TABLE AS"}, + {COMMANDTAG_CREATE_TABLESPACE, "CREATE TABLESPACE"}, + {COMMANDTAG_CREATE_TEXT_SEARCH_CONFIGURATION, "CREATE TEXT SEARCH CONFIGURATION"}, + {COMMANDTAG_CREATE_TEXT_SEARCH_DICTIONARY, "CREATE TEXT SEARCH DICTIONARY"}, + {COMMANDTAG_CREATE_TEXT_SEARCH_PARSER, "CREATE TEXT SEARCH PARSER"}, + {COMMANDTAG_CREATE_TEXT_SEARCH_TEMPLATE, "CREATE TEXT SEARCH TEMPLATE"}, + {COMMANDTAG_CREATE_TRANSFORM, "CREATE TRANSFORM"}, + {COMMANDTAG_CREATE_TRIGGER, "CREATE TRIGGER"}, + {COMMANDTAG_CREATE_TYPE, "CREATE TYPE"}, + {COMMANDTAG_CREATE_USER_MAPPING, "CREATE USER MAPPING"}, + {COMMANDTAG_CREATE_VIEW, "CREATE VIEW"}, + {COMMANDTAG_DEALLOCATE, "DEALLOCATE"}, + {COMMANDTAG_DEALLOCATE_ALL, "DEALLOCATE ALL"}, + {COMMANDTAG_DECLARE_CURSOR, "DECLARE CURSOR"}, + {COMMANDTAG_DELETE, "DELETE"}, + {COMMANDTAG_DISCARD, "DISCARD"}, + {COMMANDTAG_DISCARD_ALL, "DISCARD ALL"}, + {COMMANDTAG_DISCARD_PLANS, "DISCARD PLANS"}, + {COMMANDTAG_DISCARD_SEQUENCES, "DISCARD SEQUENCES"}, + {COMMANDTAG_DISCARD_TEMP, "DISCARD TEMP"}, + {COMMANDTAG_DO, "DO"}, + {COMMANDTAG_DROP_ACCESS_METHOD, "DROP ACCESS METHOD"}, + {COMMANDTAG_DROP_AGGREGATE, "DROP AGGREGATE"}, + {COMMANDTAG_DROP_CAST, "DROP CAST"}, + {COMMANDTAG_DROP_COLLATION, "DROP COLLATION"}, + {COMMANDTAG_DROP_CONSTRAINT, "DROP CONSTRAINT"}, + {COMMANDTAG_DROP_CONVERSION, "DROP CONVERSION"}, + {COMMANDTAG_DROP_DATABASE, "DROP DATABASE"}, + {COMMANDTAG_DROP_DOMAIN, "DROP DOMAIN"}, + {COMMANDTAG_DROP_EVENT_TRIGGER, "DROP EVENT TRIGGER"}, + {COMMANDTAG_DROP_EXTENSION, "DROP EXTENSION"}, + {COMMANDTAG_DROP_FOREIGN_DATA_WRAPPER, "DROP FOREIGN DATA WRAPPER"}, + {COMMANDTAG_DROP_FOREIGN_TABLE, "DROP FOREIGN TABLE"}, + {COMMANDTAG_DROP_FUNCTION, "DROP FUNCTION"}, + {COMMANDTAG_DROP_INDEX, "DROP INDEX"}, + {COMMANDTAG_DROP_LANGUAGE, "DROP LANGUAGE"}, + {COMMANDTAG_DROP_MATERIALIZED_VIEW, "DROP MATERIALIZED VIEW"}, + {COMMANDTAG_DROP_OPERATOR, "DROP OPERATOR"}, + {COMMANDTAG_DROP_OPERATOR_CLASS, "DROP OPERATOR CLASS"}, + {COMMANDTAG_DROP_OPERATOR_FAMILY, "DROP OPERATOR FAMILY"}, + {COMMANDTAG_DROP_OWNED, "DROP OWNED"}, + {COMMANDTAG_DROP_POLICY, "DROP POLICY"}, + {COMMANDTAG_DROP_PROCEDURE, "DROP PROCEDURE"}, + {COMMANDTAG_DROP_PUBLICATION, "DROP PUBLICATION"}, + {COMMANDTAG_DROP_REPLICATION_SLOT, "DROP REPLICATION SLOT"}, + {COMMANDTAG_DROP_ROLE, "DROP ROLE"}, + {COMMANDTAG_DROP_ROUTINE, "DROP ROUTINE"}, + {COMMANDTAG_DROP_RULE, "DROP RULE"}, + {COMMANDTAG_DROP_SCHEMA, "DROP SCHEMA"}, + {COMMANDTAG_DROP_SEQUENCE, "DROP SEQUENCE"}, + {COMMANDTAG_DROP_SERVER, "DROP SERVER"}, + {COMMANDTAG_DROP_STATISTICS, "DROP STATISTICS"}, + {COMMANDTAG_DROP_SUBSCRIPTION, "DROP SUBSCRIPTION"}, + {COMMANDTAG_DROP_TABLE, "DROP TABLE"}, + {COMMANDTAG_DROP_TABLESPACE, "DROP TABLESPACE"}, + {COMMANDTAG_DROP_TEXT_SEARCH_CONFIGURATION, "DROP TEXT SEARCH CONFIGURATION"}, + {COMMANDTAG_DROP_TEXT_SEARCH_DICTIONARY, "DROP TEXT SEARCH DICTIONARY"}, + {COMMANDTAG_DROP_TEXT_SEARCH_PARSER, "DROP TEXT SEARCH PARSER"}, + {COMMANDTAG_DROP_TEXT_SEARCH_TEMPLATE, "DROP TEXT SEARCH TEMPLATE"}, + {COMMANDTAG_DROP_TRANSFORM, "DROP TRANSFORM"}, + {COMMANDTAG_DROP_TRIGGER, "DROP TRIGGER"}, + {COMMANDTAG_DROP_TYPE, "DROP TYPE"}, + {COMMANDTAG_DROP_USER_MAPPING, "DROP USER MAPPING"}, + {COMMANDTAG_DROP_VIEW, "DROP VIEW"}, + {COMMANDTAG_EXECUTE, "EXECUTE"}, + {COMMANDTAG_EXPLAIN, "EXPLAIN"}, + {COMMANDTAG_FETCH, "FETCH"}, + {COMMANDTAG_GRANT, "GRANT"}, + {COMMANDTAG_GRANT_ROLE, "GRANT ROLE"}, + {COMMANDTAG_IMPORT_FOREIGN_SCHEMA, "IMPORT FOREIGN SCHEMA"}, + {COMMANDTAG_INSERT, "INSERT"}, + {COMMANDTAG_LISTEN, "LISTEN"}, + {COMMANDTAG_LOAD, "LOAD"}, + {COMMANDTAG_LOCK_TABLE, "LOCK TABLE"}, + {COMMANDTAG_MOVE, "MOVE"}, + {COMMANDTAG_NOTIFY, "NOTIFY"}, + {COMMANDTAG_PREPARE, "PREPARE"}, + {COMMANDTAG_PREPARE_TRANSACTION, "PREPARE TRANSACTION"}, + {COMMANDTAG_REASSIGN_OWNED, "REASSIGN OWNED"}, + {COMMANDTAG_REFRESH_MATERIALIZED_VIEW, "REFRESH MATERIALIZED VIEW"}, + {COMMANDTAG_REINDEX, "REINDEX"}, + {COMMANDTAG_RELEASE, "RELEASE"}, + {COMMANDTAG_RESET, "RESET"}, + {COMMANDTAG_REVOKE, "REVOKE"}, + {COMMANDTAG_REVOKE_ROLE, "REVOKE ROLE"}, + {COMMANDTAG_ROLLBACK, "ROLLBACK"}, + {COMMANDTAG_ROLLBACK_PREPARED, "ROLLBACK PREPARED"}, + {COMMANDTAG_SAVEPOINT, "SAVEPOINT"}, + {COMMANDTAG_SECURITY_LABEL, "SECURITY LABEL"}, + {COMMANDTAG_SELECT, "SELECT"}, + {COMMANDTAG_SELECT_FOR_KEY_SHARE, "SELECT FOR KEY SHARE"}, + {COMMANDTAG_SELECT_FOR_NO_KEY_UPDATE, "SELECT FOR NO KEY UPDATE"}, + {COMMANDTAG_SELECT_FOR_SHARE, "SELECT FOR SHARE"}, + {COMMANDTAG_SELECT_FOR_UPDATE, "SELECT FOR UPDATE"}, + {COMMANDTAG_SELECT_INTO, "SELECT INTO"}, + {COMMANDTAG_SET, "SET"}, + {COMMANDTAG_SET_CONSTRAINTS, "SET CONSTRAINTS"}, + {COMMANDTAG_SHOW, "SHOW"}, + {COMMANDTAG_START_TRANSACTION, "START TRANSACTION"}, + {COMMANDTAG_TRUNCATE_TABLE, "TRUNCATE TABLE"}, + {COMMANDTAG_UNLISTEN, "UNLISTEN"}, + {COMMANDTAG_UPDATE, "UPDATE"}, + {COMMANDTAG_VACUUM, "VACUUM"}, + {(CommandTag) 0, ""} /* Sentinel */ +}; + +#ifdef COMMANDTAG_CHECKING +static bool commandtags_have_been_checked = false; +static inline void +OPTIONALLY_CHECK_COMMAND_TAGS() +{ + if (!commandtags_have_been_checked) + { + Assert(CheckCommandTagEnum()); + commandtags_have_been_checked = true; + } +} +#else +#define OPTIONALLY_CHECK_COMMAND_TAGS() +#endif + +/* + * Search CommandTag by name + * + * Returns CommandTag, or COMMANDTAG_UNKNOWN if not recognized + */ +CommandTag +GetCommandTagEnum(const char *commandname) +{ + unsigned int tnl = lengthof(tag_names); + const command_tag_name_map *base = tag_names, + *last = base + tnl - 2, + *position; + int result; + + OPTIONALLY_CHECK_COMMAND_TAGS(); + + if (commandname == NULL || *commandname == '\0') + return COMMANDTAG_UNKNOWN; + + while (last >= base) + { + position = base + ((last - base) >> 1); + result = pg_strcasecmp(commandname, position->commandname); + if (result == 0) + return position->commandTag; + else if (result < 0) + last = position - 1; + else + base = position + 1; + } + return COMMANDTAG_UNKNOWN; +} + +const char * +GetCommandTagName(CommandTag commandTag) +{ + OPTIONALLY_CHECK_COMMAND_TAGS(); + if (PG_VALID_COMMANDTAG(commandTag)) + return tag_names[commandTag].commandname; + return "???"; +} + +#ifdef COMMANDTAG_CHECKING +bool +CheckCommandTagEnum() +{ + unsigned int tnl = lengthof(tag_names); + const command_tag_name_map *first, + *last, + *sentinel, + *position, + *alternate; + CommandTag commandTag; + + if (FIRST_COMMAND_TAG < 0 || LAST_COMMAND_TAG < 0 || LAST_COMMAND_TAG < FIRST_COMMAND_TAG) + { + elog(ERROR, "FIRST_COMMAND_TAG (%d), LAST_COMMAND_TAG (%d) not reasonable", + (int) FIRST_COMMAND_TAG, (int) LAST_COMMAND_TAG); + return false; + } + + first = &tag_names[FIRST_COMMAND_TAG]; + last = &tag_names[LAST_COMMAND_TAG]; + sentinel = last + 1; + + if (sentinel != tag_names + tnl - 1) + { + elog(ERROR, "CommandTag sentinel in wrong location"); + return false; + } + if (sentinel->commandTag != (CommandTag) 0) + { + elog(ERROR, "CommandTag sentinel has wrong commandTag value"); + return false; + } + if (sentinel->commandname == NULL) + { + elog(ERROR, "CommandTag sentinel has null commandname"); + return false; + } + if (strcmp(sentinel->commandname, "") != 0) + { + elog(ERROR, "CommandTag sentinel commandname should be \"\""); + return false; + } + + for (commandTag = FIRST_COMMAND_TAG; commandTag <= LAST_COMMAND_TAG; commandTag++) + { + if (tag_names[commandTag].commandTag != commandTag) + { + elog(ERROR, "tag_names[] commandTag field disordered"); + return false; + } + } + + for (position = first; position < last; position++) + { + if (!position->commandname) + { + elog(ERROR, "CommandTag found with null commandname"); + return false; + } + } + for (position = first; position < last; position++) + { + if (position->commandTag < FIRST_COMMAND_TAG) + { + elog(ERROR, "Found CommandTag before FIRST_COMMAND_TAG"); + return false; + } + if (position->commandTag > LAST_COMMAND_TAG) + { + elog(ERROR, "Found CommandTag after LAST_COMMAND_TAG"); + return false; + } + for (alternate = position + 1; alternate <= last; alternate++) + { + int cmp; + + if (position->commandTag == alternate->commandTag) + { + elog(ERROR, "Found duplicate commandTags"); + return false; + } + cmp = pg_strcasecmp(position->commandname, alternate->commandname); + if (cmp == 0) + { + elog(ERROR, "Found duplicate commandnames"); + return false; + } + else if (cmp > 0) + { + elog(ERROR, "Found commandnames out of order"); + return false; + } + } + } + return true; +} +#endif diff --git a/src/include/common/commandtag.h b/src/include/common/commandtag.h new file mode 100644 index 0000000000..e0388d2973 --- /dev/null +++ b/src/include/common/commandtag.h @@ -0,0 +1,254 @@ +/*------------------------------------------------------------------------- + * + * commandtag.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/utils/commandtag.h + * + *------------------------------------------------------------------------- + */ + +#ifndef COMMANDTAG_H +#define COMMANDTAG_H + +/* + * BEWARE: These are in sorted order, but ordered by their printed + * values in command_tag_name_map (see common/commandtag.c). + * In particular it matters because the sort ordering changes + * when you replace a space with an underscore. To wit: + * + * "CREATE TABLE" + * "CREATE TABLE AS" + * "CREATE TABLESPACE" + * + * but... + * + * CREATE_TABLE + * CREATE_TABLESPACE + * CREATE_TABLE_AS + * + * It also matters that tags NULL and UNKNOWN have + * string values "" and "???". + * + * If you add a value here, add it in common/commandtag.c also, and + * be careful to get the ordering right. You can build with + * COMMANDTAG_CHECKING to have this automatically checked + * at runtime, but that adds considerable overhead, so do so sparingly. + */ +typedef enum CommandTag +{ +#define FIRST_COMMAND_TAG COMMANDTAG_NULL + COMMANDTAG_NULL, + COMMANDTAG_UNKNOWN, + COMMANDTAG_ALTER_ACCESS_METHOD, + COMMANDTAG_ALTER_AGGREGATE, + COMMANDTAG_ALTER_CAST, + COMMANDTAG_ALTER_COLLATION, + COMMANDTAG_ALTER_CONSTRAINT, + COMMANDTAG_ALTER_CONVERSION, + COMMANDTAG_ALTER_DATABASE, + COMMANDTAG_ALTER_DEFAULT_PRIVILEGES, + COMMANDTAG_ALTER_DOMAIN, + COMMANDTAG_ALTER_EVENT_TRIGGER, + COMMANDTAG_ALTER_EXTENSION, + COMMANDTAG_ALTER_FOREIGN_DATA_WRAPPER, + COMMANDTAG_ALTER_FOREIGN_TABLE, + COMMANDTAG_ALTER_FUNCTION, + COMMANDTAG_ALTER_INDEX, + COMMANDTAG_ALTER_LANGUAGE, + COMMANDTAG_ALTER_LARGE_OBJECT, + COMMANDTAG_ALTER_MATERIALIZED_VIEW, + COMMANDTAG_ALTER_OPERATOR, + COMMANDTAG_ALTER_OPERATOR_CLASS, + COMMANDTAG_ALTER_OPERATOR_FAMILY, + COMMANDTAG_ALTER_POLICY, + COMMANDTAG_ALTER_PROCEDURE, + COMMANDTAG_ALTER_PUBLICATION, + COMMANDTAG_ALTER_ROLE, + COMMANDTAG_ALTER_ROUTINE, + COMMANDTAG_ALTER_RULE, + COMMANDTAG_ALTER_SCHEMA, + COMMANDTAG_ALTER_SEQUENCE, + COMMANDTAG_ALTER_SERVER, + COMMANDTAG_ALTER_STATISTICS, + COMMANDTAG_ALTER_SUBSCRIPTION, + COMMANDTAG_ALTER_SYSTEM, + COMMANDTAG_ALTER_TABLE, + COMMANDTAG_ALTER_TABLESPACE, + COMMANDTAG_ALTER_TEXT_SEARCH_CONFIGURATION, + COMMANDTAG_ALTER_TEXT_SEARCH_DICTIONARY, + COMMANDTAG_ALTER_TEXT_SEARCH_PARSER, + COMMANDTAG_ALTER_TEXT_SEARCH_TEMPLATE, + COMMANDTAG_ALTER_TRANSFORM, + COMMANDTAG_ALTER_TRIGGER, + COMMANDTAG_ALTER_TYPE, + COMMANDTAG_ALTER_USER_MAPPING, + COMMANDTAG_ALTER_VIEW, + COMMANDTAG_ANALYZE, + COMMANDTAG_BEGIN, + COMMANDTAG_CALL, + COMMANDTAG_CHECKPOINT, + COMMANDTAG_CLOSE, + COMMANDTAG_CLOSE_CURSOR, + COMMANDTAG_CLOSE_CURSOR_ALL, + COMMANDTAG_CLUSTER, + COMMANDTAG_COMMENT, + COMMANDTAG_COMMIT, + COMMANDTAG_COMMIT_PREPARED, + COMMANDTAG_COPY, + COMMANDTAG_COPY_FROM, + COMMANDTAG_CREATE_ACCESS_METHOD, + COMMANDTAG_CREATE_AGGREGATE, + COMMANDTAG_CREATE_CAST, + COMMANDTAG_CREATE_COLLATION, + COMMANDTAG_CREATE_CONSTRAINT, + COMMANDTAG_CREATE_CONVERSION, + COMMANDTAG_CREATE_DATABASE, + COMMANDTAG_CREATE_DOMAIN, + COMMANDTAG_CREATE_EVENT_TRIGGER, + COMMANDTAG_CREATE_EXTENSION, + COMMANDTAG_CREATE_FOREIGN_DATA_WRAPPER, + COMMANDTAG_CREATE_FOREIGN_TABLE, + COMMANDTAG_CREATE_FUNCTION, + COMMANDTAG_CREATE_INDEX, + COMMANDTAG_CREATE_LANGUAGE, + COMMANDTAG_CREATE_MATERIALIZED_VIEW, + COMMANDTAG_CREATE_OPERATOR, + COMMANDTAG_CREATE_OPERATOR_CLASS, + COMMANDTAG_CREATE_OPERATOR_FAMILY, + COMMANDTAG_CREATE_POLICY, + COMMANDTAG_CREATE_PROCEDURE, + COMMANDTAG_CREATE_PUBLICATION, + COMMANDTAG_CREATE_ROLE, + COMMANDTAG_CREATE_ROUTINE, + COMMANDTAG_CREATE_RULE, + COMMANDTAG_CREATE_SCHEMA, + COMMANDTAG_CREATE_SEQUENCE, + COMMANDTAG_CREATE_SERVER, + COMMANDTAG_CREATE_STATISTICS, + COMMANDTAG_CREATE_SUBSCRIPTION, + COMMANDTAG_CREATE_TABLE, + COMMANDTAG_CREATE_TABLE_AS, + COMMANDTAG_CREATE_TABLESPACE, + COMMANDTAG_CREATE_TEXT_SEARCH_CONFIGURATION, + COMMANDTAG_CREATE_TEXT_SEARCH_DICTIONARY, + COMMANDTAG_CREATE_TEXT_SEARCH_PARSER, + COMMANDTAG_CREATE_TEXT_SEARCH_TEMPLATE, + COMMANDTAG_CREATE_TRANSFORM, + COMMANDTAG_CREATE_TRIGGER, + COMMANDTAG_CREATE_TYPE, + COMMANDTAG_CREATE_USER_MAPPING, + COMMANDTAG_CREATE_VIEW, + COMMANDTAG_DEALLOCATE, + COMMANDTAG_DEALLOCATE_ALL, + COMMANDTAG_DECLARE_CURSOR, + COMMANDTAG_DELETE, + COMMANDTAG_DISCARD, + COMMANDTAG_DISCARD_ALL, + COMMANDTAG_DISCARD_PLANS, + COMMANDTAG_DISCARD_SEQUENCES, + COMMANDTAG_DISCARD_TEMP, + COMMANDTAG_DO, + COMMANDTAG_DROP_ACCESS_METHOD, + COMMANDTAG_DROP_AGGREGATE, + COMMANDTAG_DROP_CAST, + COMMANDTAG_DROP_COLLATION, + COMMANDTAG_DROP_CONSTRAINT, + COMMANDTAG_DROP_CONVERSION, + COMMANDTAG_DROP_DATABASE, + COMMANDTAG_DROP_DOMAIN, + COMMANDTAG_DROP_EVENT_TRIGGER, + COMMANDTAG_DROP_EXTENSION, + COMMANDTAG_DROP_FOREIGN_DATA_WRAPPER, + COMMANDTAG_DROP_FOREIGN_TABLE, + COMMANDTAG_DROP_FUNCTION, + COMMANDTAG_DROP_INDEX, + COMMANDTAG_DROP_LANGUAGE, + COMMANDTAG_DROP_MATERIALIZED_VIEW, + COMMANDTAG_DROP_OPERATOR, + COMMANDTAG_DROP_OPERATOR_CLASS, + COMMANDTAG_DROP_OPERATOR_FAMILY, + COMMANDTAG_DROP_OWNED, + COMMANDTAG_DROP_POLICY, + COMMANDTAG_DROP_PROCEDURE, + COMMANDTAG_DROP_PUBLICATION, + COMMANDTAG_DROP_REPLICATION_SLOT, + COMMANDTAG_DROP_ROLE, + COMMANDTAG_DROP_ROUTINE, + COMMANDTAG_DROP_RULE, + COMMANDTAG_DROP_SCHEMA, + COMMANDTAG_DROP_SEQUENCE, + COMMANDTAG_DROP_SERVER, + COMMANDTAG_DROP_STATISTICS, + COMMANDTAG_DROP_SUBSCRIPTION, + COMMANDTAG_DROP_TABLE, + COMMANDTAG_DROP_TABLESPACE, + COMMANDTAG_DROP_TEXT_SEARCH_CONFIGURATION, + COMMANDTAG_DROP_TEXT_SEARCH_DICTIONARY, + COMMANDTAG_DROP_TEXT_SEARCH_PARSER, + COMMANDTAG_DROP_TEXT_SEARCH_TEMPLATE, + COMMANDTAG_DROP_TRANSFORM, + COMMANDTAG_DROP_TRIGGER, + COMMANDTAG_DROP_TYPE, + COMMANDTAG_DROP_USER_MAPPING, + COMMANDTAG_DROP_VIEW, + COMMANDTAG_EXECUTE, + COMMANDTAG_EXPLAIN, + COMMANDTAG_FETCH, + COMMANDTAG_GRANT, + COMMANDTAG_GRANT_ROLE, + COMMANDTAG_IMPORT_FOREIGN_SCHEMA, + COMMANDTAG_INSERT, + COMMANDTAG_LISTEN, + COMMANDTAG_LOAD, + COMMANDTAG_LOCK_TABLE, + COMMANDTAG_MOVE, + COMMANDTAG_NOTIFY, + COMMANDTAG_PREPARE, + COMMANDTAG_PREPARE_TRANSACTION, + COMMANDTAG_REASSIGN_OWNED, + COMMANDTAG_REFRESH_MATERIALIZED_VIEW, + COMMANDTAG_REINDEX, + COMMANDTAG_RELEASE, + COMMANDTAG_RESET, + COMMANDTAG_REVOKE, + COMMANDTAG_REVOKE_ROLE, + COMMANDTAG_ROLLBACK, + COMMANDTAG_ROLLBACK_PREPARED, + COMMANDTAG_SAVEPOINT, + COMMANDTAG_SECURITY_LABEL, + COMMANDTAG_SELECT, + COMMANDTAG_SELECT_FOR_KEY_SHARE, + COMMANDTAG_SELECT_FOR_NO_KEY_UPDATE, + COMMANDTAG_SELECT_FOR_SHARE, + COMMANDTAG_SELECT_FOR_UPDATE, + COMMANDTAG_SELECT_INTO, + COMMANDTAG_SET, + COMMANDTAG_SET_CONSTRAINTS, + COMMANDTAG_SHOW, + COMMANDTAG_START_TRANSACTION, + COMMANDTAG_TRUNCATE_TABLE, + COMMANDTAG_UNLISTEN, + COMMANDTAG_UPDATE, + COMMANDTAG_VACUUM +#define LAST_COMMAND_TAG COMMANDTAG_VACUUM +} CommandTag; + +static inline bool +PG_VALID_COMMANDTAG(CommandTag commandTag) +{ + return (commandTag >= FIRST_COMMAND_TAG && + commandTag <= LAST_COMMAND_TAG); +} + +extern const char *GetCommandTagName(CommandTag commandTag); +extern CommandTag GetCommandTagEnum(const char *tagname); + +#ifdef COMMANDTAG_CHECKING +extern bool CheckCommandTagEnum(void); +#endif + +#endif /* COMMANDTAG_H */ diff --git a/src/include/miscadmin.h b/src/include/miscadmin.h index 62d64aa0a1..577ad55c0f 100644 --- a/src/include/miscadmin.h +++ b/src/include/miscadmin.h @@ -26,6 +26,7 @@ #include #include "datatype/timestamp.h" /* for TimestampTz */ +#include "common/commandtag.h" /* for CommandTag enum */ #include "pgtime.h" /* for pg_time_t */ @@ -280,9 +281,12 @@ extern void check_stack_depth(void); extern bool stack_is_too_deep(void); /* in tcop/utility.c */ -extern void PreventCommandIfReadOnly(const char *cmdname); -extern void PreventCommandIfParallelMode(const char *cmdname); -extern void PreventCommandDuringRecovery(const char *cmdname); +extern void PreventCommandStrIfReadOnly(const char *commandstr); +extern void PreventCommandStrIfParallelMode(const char *commandstr); +extern void PreventCommandStrDuringRecovery(const char *commandstr); +extern void PreventCommandIfReadOnly(CommandTag commandTag); +extern void PreventCommandIfParallelMode(CommandTag commandTag); +extern void PreventCommandDuringRecovery(CommandTag commandTag); /* in utils/misc/guc.c */ extern int trace_recovery_messages; diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index da0706add5..091693b696 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -22,6 +22,7 @@ #ifndef PARSENODES_H #define PARSENODES_H +#include "common/commandtag.h" #include "nodes/bitmapset.h" #include "nodes/lockoptions.h" #include "nodes/primnodes.h" diff --git a/src/include/tcop/dest.h b/src/include/tcop/dest.h index 35bce731a1..57d094cbad 100644 --- a/src/include/tcop/dest.h +++ b/src/include/tcop/dest.h @@ -67,6 +67,7 @@ #ifndef DEST_H #define DEST_H +#include "common/commandtag.h" #include "executor/tuptable.h" @@ -134,9 +135,9 @@ extern PGDLLIMPORT DestReceiver *None_Receiver; /* permanent receiver for /* 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 void EndCommand(const char *commandTag, CommandDest dest); +extern void EndCommand(const char *completionTag, CommandDest dest); /* Additional functions that go with destination management, more or less. */ diff --git a/src/include/tcop/utility.h b/src/include/tcop/utility.h index a551e08cb8..762556b159 100644 --- a/src/include/tcop/utility.h +++ b/src/include/tcop/utility.h @@ -92,7 +92,7 @@ extern TupleDesc UtilityTupleDescriptor(Node *parsetree); extern Query *UtilityContainsQuery(Node *parsetree); -extern const char *CreateCommandTag(Node *parsetree); +extern CommandTag CreateCommandTag(Node *parsetree); extern LogStmtLevel GetCommandLogLevel(Node *parsetree); diff --git a/src/include/utils/plancache.h b/src/include/utils/plancache.h index e48661ebec..04b02c083b 100644 --- a/src/include/utils/plancache.h +++ b/src/include/utils/plancache.h @@ -95,7 +95,7 @@ typedef struct CachedPlanSource int magic; /* should equal CACHEDPLANSOURCE_MAGIC */ struct RawStmt *raw_parse_tree; /* output of raw_parser(), or NULL */ const char *query_string; /* source text of query */ - const char *commandTag; /* command tag (a constant!), or NULL */ + CommandTag commandTag; Oid *param_types; /* array of parameter type OIDs, or NULL */ int num_params; /* length of param_types array */ ParserSetupHook parserSetup; /* alternative parameter spec method */ @@ -186,10 +186,10 @@ extern void ResetPlanCache(void); extern CachedPlanSource *CreateCachedPlan(struct RawStmt *raw_parse_tree, const char *query_string, - const char *commandTag); + CommandTag commandTag); extern CachedPlanSource *CreateOneShotCachedPlan(struct RawStmt *raw_parse_tree, const char *query_string, - const char *commandTag); + CommandTag commandTag); extern void CompleteCachedPlan(CachedPlanSource *plansource, List *querytree_list, MemoryContext querytree_context, diff --git a/src/include/utils/portal.h b/src/include/utils/portal.h index 0b69433722..a68fa3642b 100644 --- a/src/include/utils/portal.h +++ b/src/include/utils/portal.h @@ -46,6 +46,7 @@ #ifndef PORTAL_H #define PORTAL_H +#include "common/commandtag.h" #include "datatype/timestamp.h" #include "executor/execdesc.h" #include "utils/plancache.h" @@ -132,7 +133,9 @@ typedef struct PortalData /* The query or queries the portal will execute */ const char *sourceText; /* text of query (as of 8.4, never NULL) */ - const char *commandTag; /* command tag for original query */ + char completionTag[COMPLETION_TAG_BUFSIZE]; /* completion string for + * executed query */ + CommandTag commandTag; /* command tag for original query */ List *stmts; /* list of PlannedStmts */ CachedPlan *cplan; /* CachedPlan, if stmts are from one */ @@ -194,6 +197,12 @@ typedef struct PortalData bool visible; /* include this portal in pg_cursors? */ } PortalData; +static inline const char * +PortalGetCompletionTag(Portal portal) +{ + return (portal->completionTag[0] ? portal->completionTag : GetCommandTagName(portal->commandTag)); +} + /* * PortalIsValid * True iff portal is valid. @@ -227,7 +236,7 @@ extern Portal GetPortalByName(const char *name); extern void PortalDefineQuery(Portal portal, const char *prepStmtName, const char *sourceText, - const char *commandTag, + CommandTag commandTag, List *stmts, CachedPlan *cplan); extern PlannedStmt *PortalGetPrimaryStmt(Portal portal); diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c index 5acf604f63..8a0f31b4b8 100644 --- a/src/pl/plpgsql/src/pl_exec.c +++ b/src/pl/plpgsql/src/pl_exec.c @@ -4115,10 +4115,9 @@ exec_stmt_execsql(PLpgSQL_execstate *estate, * tree(s), since those are the result of rewriting and could have * been transmogrified into something else entirely. */ - if (plansource->commandTag && - (strcmp(plansource->commandTag, "INSERT") == 0 || - strcmp(plansource->commandTag, "UPDATE") == 0 || - strcmp(plansource->commandTag, "DELETE") == 0)) + if (plansource->commandTag == COMMANDTAG_INSERT || + plansource->commandTag == COMMANDTAG_UPDATE || + plansource->commandTag == COMMANDTAG_DELETE) { stmt->mod_stmt = true; break; diff --git a/src/test/modules/test_ddl_deparse/test_ddl_deparse.c b/src/test/modules/test_ddl_deparse/test_ddl_deparse.c index e1629ec618..d10c465a24 100644 --- a/src/test/modules/test_ddl_deparse/test_ddl_deparse.c +++ b/src/test/modules/test_ddl_deparse/test_ddl_deparse.c @@ -74,7 +74,7 @@ get_command_tag(PG_FUNCTION_ARGS) if (!cmd->parsetree) PG_RETURN_NULL(); - PG_RETURN_TEXT_P(cstring_to_text(CreateCommandTag(cmd->parsetree))); + PG_RETURN_TEXT_P(cstring_to_text(GetCommandTagName(CreateCommandTag(cmd->parsetree)))); } /* -- 2.21.1 (Apple Git-122.3)