diff options
Diffstat (limited to 'src/backend/tcop/postgres.c')
-rw-r--r-- | src/backend/tcop/postgres.c | 834 |
1 files changed, 143 insertions, 691 deletions
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index bc98d1d91ec..6c2e456ccc1 100644 --- a/src/backend/tcop/postgres.c +++ b/src/backend/tcop/postgres.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.326 2003/04/29 22:13:11 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.327 2003/05/02 20:54:35 tgl Exp $ * * NOTES * this is the "main" module of the postgres backend and @@ -74,8 +74,6 @@ const char *debug_query_string; /* for pgmonitor and /* Note: whereToSendOutput is initialized for the bootstrap/standalone case */ CommandDest whereToSendOutput = Debug; -static bool dontExecute = false; - /* note: these declarations had better match tcopprot.h */ sigjmp_buf Warn_restart; @@ -122,7 +120,6 @@ static void start_xact_command(void); static void finish_xact_command(bool forceCommit); static void SigHupHandler(SIGNAL_ARGS); static void FloatExceptionHandler(SIGNAL_ARGS); -static const char *CreateCommandTag(Node *parsetree); /* ---------------------------------------------------------------- @@ -310,9 +307,9 @@ SocketBackend(StringInfo inBuf) /* ---------------- * ReadCommand reads a command from either the frontend or - * standard input, places it in inBuf, and returns a char - * representing whether the string is a 'Q'uery or a 'F'astpath - * call. EOF is returned if end of file. + * standard input, places it in inBuf, and returns the + * message type code (first byte of the message). + * EOF is returned if end of file. * ---------------- */ static int @@ -487,7 +484,7 @@ pg_analyze_and_rewrite(Node *parsetree, Oid *paramTypes, int numParams) } -/* Generate a plan for a single query. */ +/* Generate a plan for a single already-rewritten query. */ Plan * pg_plan_query(Query *querytree) { @@ -534,41 +531,58 @@ pg_plan_query(Query *querytree) return plan; } - -/* ---------------------------------------------------------------- - * pg_exec_query_string() - * - * Takes a querystring, runs the parser/utilities or - * parser/planner/executor over it as necessary. - * - * Assumptions: - * - * At call, we are not inside a transaction command. - * - * The CurrentMemoryContext after starting a transaction command must be - * appropriate for execution of individual queries (typically this will be - * TransactionCommandContext). Note that this routine resets that context - * after each individual query, so don't store anything there that - * must outlive the call! - * - * parse_context references a context suitable for holding the - * parse/rewrite trees (typically this will be QueryContext). - * This context *must* be longer-lived than the transaction context! - * In fact, if the query string might contain BEGIN/COMMIT commands, - * parse_context had better outlive TopTransactionContext! +/* + * Generate plans for a list of already-rewritten queries. * - * We could have hard-wired knowledge about QueryContext and - * TransactionCommandContext into this routine, but it seems better - * not to, in case callers from outside this module need to use some - * other contexts. + * If needSnapshot is TRUE, we haven't yet set a snapshot for the current + * query. A snapshot must be set before invoking the planner, since it + * might try to evaluate user-defined functions. But we must not set a + * snapshot if the list contains only utility statements, because some + * utility statements depend on not having frozen the snapshot yet. + * (We assume that such statements cannot appear together with plannable + * statements in the rewriter's output.) + */ +List * +pg_plan_queries(List *querytrees, bool needSnapshot) +{ + List *plan_list = NIL; + List *query_list; + + foreach(query_list, querytrees) + { + Query *query = (Query *) lfirst(query_list); + Plan *plan; + + if (query->commandType == CMD_UTILITY) + { + /* Utility commands have no plans. */ + plan = NULL; + } + else + { + if (needSnapshot) + { + SetQuerySnapshot(); + needSnapshot = false; + } + plan = pg_plan_query(query); + } + + plan_list = lappend(plan_list, plan); + } + + return plan_list; +} + + +/* + * exec_simple_query() * - * ---------------------------------------------------------------- + * Execute a "simple Query" protocol message. */ static void -pg_exec_query_string(const char *query_string, /* string to execute */ - CommandDest dest, /* where results should go */ - MemoryContext parse_context) /* context for - * parsetrees */ +exec_simple_query(const char *query_string, /* string to execute */ + CommandDest dest) /* where results should go */ { bool xact_started; MemoryContext oldcontext; @@ -577,39 +591,40 @@ pg_exec_query_string(const char *query_string, /* string to execute */ struct timeval start_t, stop_t; bool save_log_duration = log_duration; + bool save_log_statement_stats = log_statement_stats; + /* + * Report query to various monitoring facilities. + */ debug_query_string = query_string; + pgstat_report_activity(query_string); + /* * We use save_log_duration so "SET log_duration = true" doesn't * report incorrect time because gettimeofday() wasn't called. + * Similarly, log_statement_stats has to be captured once. */ if (save_log_duration) gettimeofday(&start_t, NULL); + if (save_log_statement_stats) + ResetUsage(); + /* * Start up a transaction command. All queries generated by the * query_string will be in this same command block, *unless* we find a * BEGIN/COMMIT/ABORT statement; we have to force a new xact command * after one of those, else bad things will happen in xact.c. (Note - * that this will possibly change current memory context.) + * that this will normally change current memory context.) */ start_xact_command(); xact_started = true; /* - * parse_context *must* be different from the execution memory - * context, else the context reset at the bottom of the loop will - * destroy the parsetree list. (We really ought to check that - * parse_context isn't a child of CurrentMemoryContext either, but - * that would take more cycles than it's likely to be worth.) - */ - Assert(parse_context != CurrentMemoryContext); - - /* * Switch to appropriate context for constructing parsetrees. */ - oldcontext = MemoryContextSwitchTo(parse_context); + oldcontext = MemoryContextSwitchTo(MessageContext); /* * Do basic parsing of the query or queries (this should be safe even @@ -618,57 +633,36 @@ pg_exec_query_string(const char *query_string, /* string to execute */ parsetree_list = pg_parse_query(query_string); /* - * Switch back to execution context to enter the loop. + * Switch back to transaction context to enter the loop. */ MemoryContextSwitchTo(oldcontext); /* - * Run through the parsetree(s) and process each one. + * Run through the raw parsetree(s) and process each one. */ foreach(parsetree_item, parsetree_list) { Node *parsetree = (Node *) lfirst(parsetree_item); const char *commandTag; char completionTag[COMPLETION_TAG_BUFSIZE]; - CmdType origCmdType; - bool foundOriginalQuery = false; List *querytree_list, - *querytree_item; + *plantree_list; + Portal portal; /* - * First we set the command-completion tag to the main query (as - * opposed to each of the others that may be generated by analyze - * and rewrite). Also set ps_status and do any special - * start-of-SQL-command processing needed by the destination. + * Get the command name for use in status display (it also becomes the + * default completion tag, down inside PortalRun). Set ps_status and + * do any special start-of-SQL-command processing needed by the + * destination. */ commandTag = CreateCommandTag(parsetree); - switch (nodeTag(parsetree)) - { - case T_InsertStmt: - origCmdType = CMD_INSERT; - break; - case T_DeleteStmt: - origCmdType = CMD_DELETE; - break; - case T_UpdateStmt: - origCmdType = CMD_UPDATE; - break; - case T_SelectStmt: - origCmdType = CMD_SELECT; - break; - default: - /* Otherwise, never match commandType */ - origCmdType = CMD_UNKNOWN; - break; - } - set_ps_display(commandTag); BeginCommand(commandTag, dest); /* - * If we are in an aborted transaction, ignore all commands except + * If we are in an aborted transaction, reject all commands except * COMMIT/ABORT. It is important that this test occur before we * try to do parse analysis, rewrite, or planning, since all those * phases try to do database accesses, which may fail in abort @@ -704,203 +698,61 @@ pg_exec_query_string(const char *query_string, /* string to execute */ CHECK_FOR_INTERRUPTS(); /* - * OK to analyze and rewrite this query. + * OK to analyze, rewrite, and plan this query. * * Switch to appropriate context for constructing querytrees (again, * these must outlive the execution context). */ - oldcontext = MemoryContextSwitchTo(parse_context); + oldcontext = MemoryContextSwitchTo(MessageContext); querytree_list = pg_analyze_and_rewrite(parsetree, NULL, 0); + plantree_list = pg_plan_queries(querytree_list, true); + + /* If we got a cancel signal in analysis or planning, quit */ + CHECK_FOR_INTERRUPTS(); + /* - * Switch back to execution context for planning and execution. + * Switch back to transaction context for execution. */ MemoryContextSwitchTo(oldcontext); /* - * Inner loop handles the individual queries generated from a - * single parsetree by analysis and rewrite. + * Create unnamed portal to run the query or queries in. + * If there already is one, silently drop it. */ - foreach(querytree_item, querytree_list) - { - Query *querytree = (Query *) lfirst(querytree_item); - bool endTransactionBlock = false; - bool canSetTag; - - /* Make sure we are in a transaction command */ - if (!xact_started) - { - start_xact_command(); - xact_started = true; - } - - /* - * If we got a cancel signal in analysis or prior command, - * quit - */ - CHECK_FOR_INTERRUPTS(); - - /* - * This query can set the completion tag if it is the original - * query, or if it is an INSTEAD query of the same kind as the - * original and we haven't yet seen the original query. - */ - if (querytree->querySource == QSRC_ORIGINAL) - { - canSetTag = true; - foundOriginalQuery = true; - } - else if (!foundOriginalQuery && - querytree->commandType == origCmdType && - (querytree->querySource == QSRC_INSTEAD_RULE || - querytree->querySource == QSRC_QUAL_INSTEAD_RULE)) - canSetTag = true; - else - canSetTag = false; - - if (querytree->commandType == CMD_UTILITY) - { - /* - * process utility functions (create, destroy, etc..) - */ - Node *utilityStmt = querytree->utilityStmt; - - elog(DEBUG2, "ProcessUtility"); - - /* - * Set snapshot if utility stmt needs one. Most reliable - * way to do this seems to be to enumerate those that do not - * need one; this is a short list. Transaction control, - * LOCK, and SET must *not* set a snapshot since they need - * to be executable at the start of a serializable transaction - * without freezing a snapshot. By extension we allow SHOW - * not to set a snapshot. The other stmts listed are just - * efficiency hacks. Beware of listing anything that can - * modify the database --- if, say, it has to update a - * functional index, then it had better have a snapshot. - */ - if (! (IsA(utilityStmt, TransactionStmt) || - IsA(utilityStmt, LockStmt) || - IsA(utilityStmt, VariableSetStmt) || - IsA(utilityStmt, VariableShowStmt) || - IsA(utilityStmt, VariableResetStmt) || - IsA(utilityStmt, ConstraintsSetStmt) || - /* efficiency hacks from here down */ - IsA(utilityStmt, FetchStmt) || - IsA(utilityStmt, ListenStmt) || - IsA(utilityStmt, NotifyStmt) || - IsA(utilityStmt, UnlistenStmt) || - IsA(utilityStmt, CheckPointStmt))) - SetQuerySnapshot(); - - /* end transaction block if transaction or variable stmt */ - if (IsA(utilityStmt, TransactionStmt) || - IsA(utilityStmt, VariableSetStmt) || - IsA(utilityStmt, VariableShowStmt) || - IsA(utilityStmt, VariableResetStmt)) - endTransactionBlock = true; - - if (canSetTag) - { - /* utility statement can override default tag string */ - ProcessUtility(utilityStmt, dest, completionTag); - if (completionTag[0]) - commandTag = completionTag; - } - else - { - /* utility added by rewrite cannot override tag */ - ProcessUtility(utilityStmt, dest, NULL); - } - } - else - { - /* - * process a plannable query. - */ - Plan *plan; - - /* - * Initialize snapshot state for query. This has to - * be done before running the planner, because it might - * try to evaluate immutable or stable functions, which - * in turn might run queries. - */ - SetQuerySnapshot(); - - /* Make the plan */ - plan = pg_plan_query(querytree); + portal = CreatePortal("", true, true); - /* if we got a cancel signal whilst planning, quit */ - CHECK_FOR_INTERRUPTS(); - - /* - * execute the plan - */ - if (log_executor_stats) - ResetUsage(); - - if (dontExecute) - { - /* don't execute it, just show the query plan */ - print_plan(plan, querytree); - } - else - { - elog(DEBUG2, "ProcessQuery"); - - if (canSetTag) - { - /* statement can override default tag string */ - ProcessQuery(querytree, plan, dest, completionTag); - commandTag = completionTag; - } - else - { - /* stmt added by rewrite cannot override tag */ - ProcessQuery(querytree, plan, dest, NULL); - } - } + PortalDefineQuery(portal, + query_string, + commandTag, + querytree_list, + plantree_list, + MessageContext); - if (log_executor_stats) - ShowUsage("EXECUTOR STATISTICS"); - } - - /* - * In a query block, we want to increment the command counter - * between queries so that the effects of early queries are - * visible to subsequent ones. In particular we'd better do - * so before checking constraints. - */ - if (!endTransactionBlock) - CommandCounterIncrement(); - - /* - * Clear the execution context to recover temporary memory - * used by the query. NOTE: if query string contains - * BEGIN/COMMIT transaction commands, execution context may - * now be different from what we were originally passed; so be - * careful to clear current context not "oldcontext". - */ - Assert(parse_context != CurrentMemoryContext); + /* + * Run the portal to completion, and then drop it. + */ + PortalStart(portal, NULL); - MemoryContextResetAndDeleteChildren(CurrentMemoryContext); + (void) PortalRun(portal, FETCH_ALL, dest, dest, completionTag); - /* - * If this was a transaction control statement or a variable - * set/show/reset statement, commit it and arrange to start a - * new xact command for the next command (if any). - */ - if (endTransactionBlock) - { - finish_xact_command(true); - xact_started = false; - } - } /* end loop over queries generated from a - * parsetree */ + PortalDrop(portal, false); /* + * If this was a transaction control statement or a variable + * set/show/reset statement, commit it and arrange to start a + * new xact command for the next command (if any). + */ + if (IsA(parsetree, TransactionStmt) || + IsA(parsetree, VariableSetStmt) || + IsA(parsetree, VariableShowStmt) || + IsA(parsetree, VariableResetStmt)) + { + finish_xact_command(true); + xact_started = false; + } + /* * If this is the last parsetree of the query string, close down * transaction statement before reporting command-complete. This * is so that any end-of-transaction errors are reported before @@ -910,28 +762,18 @@ pg_exec_query_string(const char *query_string, /* string to execute */ * historical Postgres behavior, we do not force a transaction * boundary between queries appearing in a single query string. */ - if ((lnext(parsetree_item) == NIL || !autocommit) && xact_started) + else if (lnext(parsetree_item) == NIL || !autocommit) { finish_xact_command(false); xact_started = false; } - - /* - * It is possible that the original query was removed due to a DO - * INSTEAD rewrite rule. If so, and if we found no INSTEAD query - * matching the command type, we will still have the default - * completion tag. This is fine for most purposes, but it - * may confuse clients if it's INSERT/UPDATE/DELETE. Clients - * expect those tags to have counts after them (cf. ProcessQuery). - */ - if (!foundOriginalQuery) + else { - if (strcmp(commandTag, "INSERT") == 0) - commandTag = "INSERT 0 0"; - else if (strcmp(commandTag, "UPDATE") == 0) - commandTag = "UPDATE 0"; - else if (strcmp(commandTag, "DELETE") == 0) - commandTag = "DELETE 0"; + /* + * We need a CommandCounterIncrement after every query, + * except those that start or end a transaction block. + */ + CommandCounterIncrement(); } /* @@ -941,20 +783,24 @@ pg_exec_query_string(const char *query_string, /* string to execute */ * (But a command aborted by error will not send an EndCommand * report at all.) */ - EndCommand(commandTag, dest); + EndCommand(completionTag, dest); } /* end loop over parsetrees */ - /* No parsetree - return empty result */ + /* + * If there were no parsetrees, return EmptyQueryResponse message. + */ if (!parsetree_list) NullCommand(dest); /* - * Close down transaction statement, if one is open. (Note that this - * will only happen if the querystring was empty.) + * Close down transaction statement, if one is open. */ if (xact_started) finish_xact_command(false); + /* + * Finish up monitoring. + */ if (save_log_duration) { gettimeofday(&stop_t, NULL); @@ -968,6 +814,9 @@ pg_exec_query_string(const char *query_string, /* string to execute */ (long) (stop_t.tv_usec - start_t.tv_usec)); } + if (save_log_statement_stats) + ShowUsage("QUERY STATISTICS"); + debug_query_string = NULL; } @@ -1431,10 +1280,6 @@ PostgresMain(int argc, char *argv[], const char *username) SetConfigOption(tmp, "false", ctx, gucsource); break; - case 'i': - dontExecute = true; - break; - case 'N': /* @@ -1827,22 +1672,20 @@ PostgresMain(int argc, char *argv[], const char *username) if (!IsUnderPostmaster) { puts("\nPOSTGRES backend interactive interface "); - puts("$Revision: 1.326 $ $Date: 2003/04/29 22:13:11 $\n"); + puts("$Revision: 1.327 $ $Date: 2003/05/02 20:54:35 $\n"); } /* * Create the memory context we will use in the main loop. * - * QueryContext is reset once per iteration of the main loop, ie, upon - * completion of processing of each supplied query string. It can - * therefore be used for any data that should live just as long as the - * query string --- parse trees, for example. + * MessageContext is reset once per iteration of the main loop, ie, upon + * completion of processing of each command message from the client. */ - QueryContext = AllocSetContextCreate(TopMemoryContext, - "QueryContext", - ALLOCSET_DEFAULT_MINSIZE, - ALLOCSET_DEFAULT_INITSIZE, - ALLOCSET_DEFAULT_MAXSIZE); + MessageContext = AllocSetContextCreate(TopMemoryContext, + "MessageContext", + ALLOCSET_DEFAULT_MINSIZE, + ALLOCSET_DEFAULT_INITSIZE, + ALLOCSET_DEFAULT_MAXSIZE); /* ---------- * Tell the statistics collector that we're alive and @@ -1897,6 +1740,9 @@ PostgresMain(int argc, char *argv[], const char *username) */ MemoryContextSwitchTo(TopMemoryContext); MemoryContextResetAndDeleteChildren(ErrorContext); + CurrentPortal = NULL; + PortalContext = NULL; + QueryContext = NULL; /* * Clear flag to indicate that we got out of error recovery mode @@ -1924,10 +1770,10 @@ PostgresMain(int argc, char *argv[], const char *username) { /* * Release storage left over from prior query cycle, and create a - * new query input buffer in the cleared QueryContext. + * new query input buffer in the cleared MessageContext. */ - MemoryContextSwitchTo(QueryContext); - MemoryContextResetAndDeleteChildren(QueryContext); + MemoryContextSwitchTo(MessageContext); + MemoryContextResetAndDeleteChildren(MessageContext); input_message = makeStringInfo(); @@ -2006,25 +1852,9 @@ PostgresMain(int argc, char *argv[], const char *username) { case 'Q': /* simple query */ { - /* - * Process the query string. - * - * Note: transaction command start/end is now done within - * pg_exec_query_string(), not here. - */ const char *query_string = pq_getmsgstring(input_message); - if (log_statement_stats) - ResetUsage(); - - pgstat_report_activity(query_string); - - pg_exec_query_string(query_string, - whereToSendOutput, - QueryContext); - - if (log_statement_stats) - ShowUsage("QUERY STATISTICS"); + exec_simple_query(query_string, whereToSendOutput); send_rfq = true; } @@ -2225,381 +2055,3 @@ ShowUsage(const char *title) pfree(str.data); } - -/* ---------------------------------------------------------------- - * CreateCommandTag - * - * utility to get a string representation of the - * command operation. - * ---------------------------------------------------------------- - */ -static const char * -CreateCommandTag(Node *parsetree) -{ - const char *tag; - - switch (nodeTag(parsetree)) - { - case T_InsertStmt: - tag = "INSERT"; - break; - - case T_DeleteStmt: - tag = "DELETE"; - break; - - case T_UpdateStmt: - tag = "UPDATE"; - break; - - case T_SelectStmt: - tag = "SELECT"; - break; - - case T_TransactionStmt: - { - TransactionStmt *stmt = (TransactionStmt *) parsetree; - - switch (stmt->kind) - { - case TRANS_STMT_BEGIN: - tag = "BEGIN"; - break; - - case TRANS_STMT_START: - tag = "START TRANSACTION"; - break; - - case TRANS_STMT_COMMIT: - tag = "COMMIT"; - break; - - case TRANS_STMT_ROLLBACK: - tag = "ROLLBACK"; - break; - - default: - tag = "???"; - break; - } - } - break; - - case T_DeclareCursorStmt: - tag = "DECLARE CURSOR"; - break; - - case T_ClosePortalStmt: - tag = "CLOSE CURSOR"; - break; - - case T_FetchStmt: - { - FetchStmt *stmt = (FetchStmt *) parsetree; - - tag = (stmt->ismove) ? "MOVE" : "FETCH"; - } - break; - - case T_CreateDomainStmt: - tag = "CREATE DOMAIN"; - break; - - case T_CreateSchemaStmt: - tag = "CREATE SCHEMA"; - break; - - case T_CreateStmt: - tag = "CREATE TABLE"; - break; - - case T_DropStmt: - switch (((DropStmt *) parsetree)->removeType) - { - case DROP_TABLE: - tag = "DROP TABLE"; - break; - case DROP_SEQUENCE: - tag = "DROP SEQUENCE"; - break; - case DROP_VIEW: - tag = "DROP VIEW"; - break; - case DROP_INDEX: - tag = "DROP INDEX"; - break; - case DROP_TYPE: - tag = "DROP TYPE"; - break; - case DROP_DOMAIN: - tag = "DROP DOMAIN"; - break; - case DROP_CONVERSION: - tag = "DROP CONVERSION"; - break; - case DROP_SCHEMA: - tag = "DROP SCHEMA"; - break; - default: - tag = "???"; - } - break; - - case T_TruncateStmt: - tag = "TRUNCATE TABLE"; - break; - - case T_CommentStmt: - tag = "COMMENT"; - break; - - case T_CopyStmt: - tag = "COPY"; - break; - - case T_RenameStmt: - if (((RenameStmt *) parsetree)->renameType == RENAME_TRIGGER) - tag = "ALTER TRIGGER"; - else - tag = "ALTER TABLE"; - break; - - case T_AlterTableStmt: - tag = "ALTER TABLE"; - break; - - case T_AlterDomainStmt: - tag = "ALTER DOMAIN"; - break; - - case T_GrantStmt: - { - GrantStmt *stmt = (GrantStmt *) parsetree; - - tag = (stmt->is_grant) ? "GRANT" : "REVOKE"; - } - break; - - case T_DefineStmt: - switch (((DefineStmt *) parsetree)->kind) - { - case DEFINE_STMT_AGGREGATE: - tag = "CREATE AGGREGATE"; - break; - case DEFINE_STMT_OPERATOR: - tag = "CREATE OPERATOR"; - break; - case DEFINE_STMT_TYPE: - tag = "CREATE TYPE"; - break; - default: - tag = "???"; - } - break; - - case T_CompositeTypeStmt: - tag = "CREATE TYPE"; - break; - - case T_ViewStmt: - tag = "CREATE VIEW"; - break; - - case T_CreateFunctionStmt: - tag = "CREATE FUNCTION"; - break; - - case T_IndexStmt: - tag = "CREATE INDEX"; - break; - - case T_RuleStmt: - tag = "CREATE RULE"; - break; - - case T_CreateSeqStmt: - tag = "CREATE SEQUENCE"; - break; - - case T_AlterSeqStmt: - tag = "ALTER SEQUENCE"; - break; - - case T_RemoveAggrStmt: - tag = "DROP AGGREGATE"; - break; - - case T_RemoveFuncStmt: - tag = "DROP FUNCTION"; - break; - - case T_RemoveOperStmt: - tag = "DROP OPERATOR"; - break; - - case T_CreatedbStmt: - tag = "CREATE DATABASE"; - break; - - case T_AlterDatabaseSetStmt: - tag = "ALTER DATABASE"; - break; - - case T_DropdbStmt: - tag = "DROP DATABASE"; - break; - - case T_NotifyStmt: - tag = "NOTIFY"; - break; - - case T_ListenStmt: - tag = "LISTEN"; - break; - - case T_UnlistenStmt: - tag = "UNLISTEN"; - break; - - case T_LoadStmt: - tag = "LOAD"; - break; - - case T_ClusterStmt: - tag = "CLUSTER"; - break; - - case T_VacuumStmt: - if (((VacuumStmt *) parsetree)->vacuum) - tag = "VACUUM"; - else - tag = "ANALYZE"; - break; - - case T_ExplainStmt: - tag = "EXPLAIN"; - break; - - case T_VariableSetStmt: - tag = "SET"; - break; - - case T_VariableShowStmt: - tag = "SHOW"; - break; - - case T_VariableResetStmt: - tag = "RESET"; - break; - - case T_CreateTrigStmt: - tag = "CREATE TRIGGER"; - break; - - case T_DropPropertyStmt: - switch (((DropPropertyStmt *) parsetree)->removeType) - { - case DROP_TRIGGER: - tag = "DROP TRIGGER"; - break; - case DROP_RULE: - tag = "DROP RULE"; - break; - default: - tag = "???"; - } - break; - - case T_CreatePLangStmt: - tag = "CREATE LANGUAGE"; - break; - - case T_DropPLangStmt: - tag = "DROP LANGUAGE"; - break; - - case T_CreateUserStmt: - tag = "CREATE USER"; - break; - - case T_AlterUserStmt: - tag = "ALTER USER"; - break; - - case T_AlterUserSetStmt: - tag = "ALTER USER"; - break; - - case T_DropUserStmt: - tag = "DROP USER"; - break; - - case T_LockStmt: - tag = "LOCK TABLE"; - break; - - case T_ConstraintsSetStmt: - tag = "SET CONSTRAINTS"; - break; - - case T_CreateGroupStmt: - tag = "CREATE GROUP"; - break; - - case T_AlterGroupStmt: - tag = "ALTER GROUP"; - break; - - case T_DropGroupStmt: - tag = "DROP GROUP"; - break; - - case T_CheckPointStmt: - tag = "CHECKPOINT"; - break; - - case T_ReindexStmt: - tag = "REINDEX"; - break; - - case T_CreateConversionStmt: - tag = "CREATE CONVERSION"; - break; - - case T_CreateCastStmt: - tag = "CREATE CAST"; - break; - - case T_DropCastStmt: - tag = "DROP CAST"; - break; - - case T_CreateOpClassStmt: - tag = "CREATE OPERATOR CLASS"; - break; - - case T_RemoveOpClassStmt: - tag = "DROP OPERATOR CLASS"; - break; - - case T_PrepareStmt: - tag = "PREPARE"; - break; - - case T_ExecuteStmt: - tag = "EXECUTE"; - break; - - case T_DeallocateStmt: - tag = "DEALLOCATE"; - break; - - default: - elog(LOG, "CreateCommandTag: unknown parse node type %d", - nodeTag(parsetree)); - tag = "???"; - break; - } - - return tag; -} |