summaryrefslogtreecommitdiff
path: root/src/backend/tcop/postgres.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2003-05-02 20:54:36 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2003-05-02 20:54:36 +0000
commitde28dc9a04c4df5d711815b7a518501b43535a26 (patch)
tree1b93363ece14ded804195ff4a1c754a9b4a32306 /src/backend/tcop/postgres.c
parent1940434f1ef8475c8b59bb8ff03e3f3a10cac6ae (diff)
Portal and memory management infrastructure for extended query protocol.
Both plannable queries and utility commands are now always executed within Portals, which have been revamped so that they can handle the load (they used to be good only for single SELECT queries). Restructure code to push command-completion-tag selection logic out of postgres.c, so that it won't have to be duplicated between simple and extended queries. initdb forced due to addition of a field to Query nodes.
Diffstat (limited to 'src/backend/tcop/postgres.c')
-rw-r--r--src/backend/tcop/postgres.c834
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;
-}