diff options
Diffstat (limited to 'src/backend/tcop')
-rw-r--r-- | src/backend/tcop/postgres.c | 491 | ||||
-rw-r--r-- | src/backend/tcop/utility.c | 132 |
2 files changed, 367 insertions, 256 deletions
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index bddad9e4f6e..3eaa3a1562d 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.177 2000/10/03 03:11:19 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.178 2000/10/07 00:58:18 tgl Exp $ * * NOTES * this is the "main" module of the postgres backend and @@ -47,6 +47,8 @@ #include "nodes/print.h" #include "optimizer/cost.h" #include "optimizer/planner.h" +#include "parser/analyze.h" +#include "parser/parse.h" #include "parser/parser.h" #include "rewrite/rewriteHandler.h" #include "tcop/fastpath.h" @@ -90,8 +92,6 @@ extern char ControlFilePath[]; static bool dontExecute = false; -static bool IsEmptyQuery = false; - /* note: these declarations had better match tcopprot.h */ DLLIMPORT sigjmp_buf Warn_restart; @@ -129,6 +129,10 @@ int XfuncMode = 0; static int InteractiveBackend(StringInfo inBuf); static int SocketBackend(StringInfo inBuf); static int ReadCommand(StringInfo inBuf); +static List *pg_parse_query(char *query_string, Oid *typev, int nargs); +static List *pg_analyze_and_rewrite(Node *parsetree); +static void start_xact_command(void); +static void finish_xact_command(void); static void SigHupHandler(SIGNAL_ARGS); static void FloatExceptionHandler(SIGNAL_ARGS); static void quickdie(SIGNAL_ARGS); @@ -341,46 +345,120 @@ ReadCommand(StringInfo inBuf) * * A list of Query nodes is returned, since the string might contain * multiple queries and/or the rewriter might expand one query to several. + * + * NOTE: this routine is no longer used for processing interactive queries, + * but it is still needed for parsing of SQL function bodies. */ List * pg_parse_and_rewrite(char *query_string, /* string to execute */ Oid *typev, /* parameter types */ int nargs) /* number of parameters */ { + List *raw_parsetree_list; List *querytree_list; - List *querytree_list_item; - Query *querytree; - List *new_list; + List *list_item; + + /* ---------------- + * (1) parse the request string into a list of raw parse trees. + * ---------------- + */ + raw_parsetree_list = pg_parse_query(query_string, typev, nargs); + + /* ---------------- + * (2) Do parse analysis and rule rewrite. + * ---------------- + */ + querytree_list = NIL; + foreach(list_item, raw_parsetree_list) + { + Node *parsetree = (Node *) lfirst(list_item); + + querytree_list = nconc(querytree_list, + pg_analyze_and_rewrite(parsetree)); + } + + return querytree_list; +} + +/* + * Do raw parsing (only). + * + * A list of parsetrees is returned, since there might be multiple + * commands in the given string. + * + * NOTE: for interactive queries, it is important to keep this routine + * separate from the analysis & rewrite stages. Analysis and rewriting + * cannot be done in an aborted transaction, since they require access to + * database tables. So, we rely on the raw parser to determine whether + * we've seen a COMMIT or ABORT command; when we are in abort state, other + * commands are not processed any further than the raw parse stage. + */ +static List * +pg_parse_query(char *query_string, Oid *typev, int nargs) +{ + List *raw_parsetree_list; if (Debug_print_query) elog(DEBUG, "query: %s", query_string); + if (Show_parser_stats) + ResetUsage(); + + raw_parsetree_list = parser(query_string, typev, nargs); + + if (Show_parser_stats) + { + fprintf(StatFp, "PARSER STATISTICS\n"); + ShowUsage(); + } + + return raw_parsetree_list; +} + +/* + * Given a raw parsetree (gram.y output), perform parse analysis and + * rule rewriting. + * + * A list of Query nodes is returned, since either the analyzer or the + * rewriter might expand one query to several. + * + * NOTE: for reasons mentioned above, this must be separate from raw parsing. + */ +static List * +pg_analyze_and_rewrite(Node *parsetree) +{ + List *querytree_list; + List *list_item; + Query *querytree; + List *new_list; + /* ---------------- - * (1) parse the request string into a list of parse trees + * (1) Perform parse analysis. * ---------------- */ if (Show_parser_stats) ResetUsage(); - querytree_list = parser(query_string, typev, nargs); + querytree_list = parse_analyze(parsetree, NULL); if (Show_parser_stats) { - fprintf(StatFp, "PARSER STATISTICS\n"); + fprintf(StatFp, "PARSE ANALYSIS STATISTICS\n"); ShowUsage(); + ResetUsage(); } /* ---------------- - * (2) rewrite the queries, as necessary + * (2) Rewrite the queries, as necessary * * rewritten queries are collected in new_list. Note there may be * more or fewer than in the original list. * ---------------- */ new_list = NIL; - foreach(querytree_list_item, querytree_list) + foreach(list_item, querytree_list) { - querytree = (Query *) lfirst(querytree_list_item); + querytree = (Query *) lfirst(list_item); if (Debug_print_parse) { @@ -409,19 +487,18 @@ pg_parse_and_rewrite(char *query_string, /* string to execute */ querytree_list = new_list; + if (Show_parser_stats) + { + fprintf(StatFp, "REWRITER STATISTICS\n"); + ShowUsage(); + } + #ifdef COPY_PARSE_PLAN_TREES - /* Optional debugging check: pass parsetree output through copyObject() */ - /* - * Note: we run this test after rewrite, not before, because copyObject() - * does not handle most kinds of nodes that are used only in raw parse - * trees. The present (bizarre) implementation of UNION/INTERSECT/EXCEPT - * doesn't run analysis of the second and later subqueries until rewrite, - * so we'd get false failures on these queries if we did it beforehand. - */ + /* Optional debugging check: pass querytree output through copyObject() */ new_list = (List *) copyObject(querytree_list); /* This checks both copyObject() and the equal() routines... */ if (! equal(new_list, querytree_list)) - elog(NOTICE, "pg_parse_and_rewrite: copyObject failed on parse tree"); + elog(NOTICE, "pg_analyze_and_rewrite: copyObject failed on parse tree"); else querytree_list = new_list; #endif @@ -431,9 +508,9 @@ pg_parse_and_rewrite(char *query_string, /* string to execute */ if (Debug_pretty_print) { elog(DEBUG, "rewritten parse tree:"); - foreach(querytree_list_item, querytree_list) + foreach(list_item, querytree_list) { - querytree = (Query *) lfirst(querytree_list_item); + querytree = (Query *) lfirst(list_item); nodeDisplay(querytree); printf("\n"); } @@ -441,10 +518,9 @@ pg_parse_and_rewrite(char *query_string, /* string to execute */ else { elog(DEBUG, "rewritten parse tree:"); - - foreach(querytree_list_item, querytree_list) + foreach(list_item, querytree_list) { - querytree = (Query *) lfirst(querytree_list_item); + querytree = (Query *) lfirst(list_item); elog(DEBUG, "%s", nodeToString(querytree)); } } @@ -514,7 +590,7 @@ pg_plan_query(Query *querytree) /* ---------------------------------------------------------------- - * pg_exec_query_dest() + * pg_exec_query_string() * * Takes a querystring, runs the parser/utilities or * parser/planner/executor over it as necessary. @@ -545,21 +621,31 @@ pg_plan_query(Query *querytree) */ void -pg_exec_query_dest(char *query_string, /* string to execute */ - CommandDest dest, /* where results should go */ - MemoryContext parse_context) /* context for parsetrees */ +pg_exec_query_string(char *query_string, /* string to execute */ + CommandDest dest, /* where results should go */ + MemoryContext parse_context) /* context for parsetrees */ { + bool xact_started; MemoryContext oldcontext; - List *querytree_list, - *querytree_item; + List *parsetree_list, + *parsetree_item; /* - * If you called this routine with parse_context = CurrentMemoryContext, - * you blew it. They *must* be different, else the context reset - * at the bottom of the loop will destroy the querytree 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.) + * 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 execution 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); @@ -569,48 +655,57 @@ pg_exec_query_dest(char *query_string, /* string to execute */ oldcontext = MemoryContextSwitchTo(parse_context); /* - * Parse and rewrite the query or queries. + * Do basic parsing of the query or queries (this should be safe + * even if we are in aborted transaction state!) */ - querytree_list = pg_parse_and_rewrite(query_string, NULL, 0); + parsetree_list = pg_parse_query(query_string, NULL, 0); /* - * Switch back to execution context for planning and execution. + * Switch back to execution context to enter the loop. */ MemoryContextSwitchTo(oldcontext); /* - * Run through the query or queries and execute each one. + * Run through the parsetree(s) and process each one. */ - foreach(querytree_item, querytree_list) + foreach(parsetree_item, parsetree_list) { - Query *querytree = (Query *) lfirst(querytree_item); + Node *parsetree = (Node *) lfirst(parsetree_item); + bool isTransactionStmt; + List *querytree_list, + *querytree_item; - /* if we got a cancel signal in parsing or prior command, quit */ - if (QueryCancel) - CancelQuery(); + /* Transaction control statements need some special handling */ + isTransactionStmt = IsA(parsetree, TransactionStmt); - if (querytree->commandType == CMD_UTILITY) + /* + * If we are in an aborted transaction, ignore 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 state. + * (It might be safe to allow some additional utility commands in + * this state, but not many...) + */ + if (IsAbortedTransactionBlockState()) { - /* ---------------- - * process utility functions (create, destroy, etc..) - * - * Note: we do not check for the transaction aborted state - * because that is done in ProcessUtility. - * ---------------- - */ - if (Debug_print_query) - elog(DEBUG, "ProcessUtility: %s", query_string); - else if (DebugLvl > 1) - elog(DEBUG, "ProcessUtility"); + bool allowit = false; - ProcessUtility(querytree->utilityStmt, dest); - } - else - { - Plan *plan; + if (isTransactionStmt) + { + TransactionStmt *stmt = (TransactionStmt *) parsetree; + + switch (stmt->command) + { + case COMMIT: + case ROLLBACK: + allowit = true; + break; + default: + break; + } + } - /* If aborted transaction, skip planning and execution */ - if (IsAbortedTransactionBlockState()) + if (! allowit) { /* ---------------- * the EndCommand() stuff is to tell the frontend @@ -631,58 +726,180 @@ pg_exec_query_dest(char *query_string, /* string to execute */ */ continue; } + } - plan = pg_plan_query(querytree); + /* Make sure we are in a transaction command */ + if (! xact_started) + { + start_xact_command(); + xact_started = true; + } - /* if we got a cancel signal whilst planning, quit */ - if (QueryCancel) - CancelQuery(); + /* If we got a cancel signal in parsing or prior command, quit */ + if (QueryCancel) + CancelQuery(); + + /* + * OK to analyze and rewrite this query. + * + * Switch to appropriate context for constructing querytrees + * (again, these must outlive the execution context). + */ + oldcontext = MemoryContextSwitchTo(parse_context); - /* Initialize snapshot state for query */ - SetQuerySnapshot(); + querytree_list = pg_analyze_and_rewrite(parsetree); - /* - * execute the plan - */ - if (Show_executor_stats) - ResetUsage(); + /* + * Switch back to execution context for planning and execution. + */ + MemoryContextSwitchTo(oldcontext); + + /* + * Inner loop handles the individual queries generated from a + * single parsetree by analysis and rewrite. + */ + foreach(querytree_item, querytree_list) + { + Query *querytree = (Query *) lfirst(querytree_item); - if (dontExecute) + /* Make sure we are in a transaction command */ + if (! xact_started) { - /* don't execute it, just show the query plan */ - print_plan(plan, querytree); + start_xact_command(); + xact_started = true; + } + + /* If we got a cancel signal in analysis or prior command, quit */ + if (QueryCancel) + CancelQuery(); + + if (querytree->commandType == CMD_UTILITY) + { + /* ---------------- + * process utility functions (create, destroy, etc..) + * ---------------- + */ + if (Debug_print_query) + elog(DEBUG, "ProcessUtility: %s", query_string); + else if (DebugLvl > 1) + elog(DEBUG, "ProcessUtility"); + + ProcessUtility(querytree->utilityStmt, dest); } else { - if (DebugLvl > 1) - elog(DEBUG, "ProcessQuery"); - ProcessQuery(querytree, plan, dest); + /* ---------------- + * process a plannable query. + * ---------------- + */ + Plan *plan; + + plan = pg_plan_query(querytree); + + /* if we got a cancel signal whilst planning, quit */ + if (QueryCancel) + CancelQuery(); + + /* Initialize snapshot state for query */ + SetQuerySnapshot(); + + /* + * execute the plan + */ + if (Show_executor_stats) + ResetUsage(); + + if (dontExecute) + { + /* don't execute it, just show the query plan */ + print_plan(plan, querytree); + } + else + { + if (DebugLvl > 1) + elog(DEBUG, "ProcessQuery"); + ProcessQuery(querytree, plan, dest); + } + + if (Show_executor_stats) + { + fprintf(stderr, "EXECUTOR STATISTICS\n"); + ShowUsage(); + } } - if (Show_executor_stats) + /* + * 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 (!isTransactionStmt) + CommandCounterIncrement(); + + /* + * Invoke IMMEDIATE constraint triggers + */ + DeferredTriggerEndQuery(); + + /* + * 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); + + MemoryContextResetAndDeleteChildren(CurrentMemoryContext); + + /* + * If this was a transaction control statement, commit it + * and arrange to start a new xact command for the next + * command (if any). + */ + if (isTransactionStmt) { - fprintf(stderr, "EXECUTOR STATISTICS\n"); - ShowUsage(); + finish_xact_command(); + xact_started = false; } - } - /* - * 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. - */ - CommandCounterIncrement(); - /* - * Also, 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". - */ - MemoryContextResetAndDeleteChildren(CurrentMemoryContext); - } + } /* end loop over queries generated from a parsetree */ + } /* end loop over parsetrees */ + + /* + * Close down transaction statement, if one is open. + */ + if (xact_started) + finish_xact_command(); } +/* + * Convenience routines for starting/committing a single command. + */ +static void +start_xact_command(void) +{ + if (DebugLvl >= 1) + elog(DEBUG, "StartTransactionCommand"); + StartTransactionCommand(); +} + +static void +finish_xact_command(void) +{ + if (DebugLvl >= 1) + elog(DEBUG, "CommitTransactionCommand"); + set_ps_display("commit"); /* XXX probably the wrong place to do this */ + CommitTransactionCommand(); +#ifdef SHOW_MEMORY_STATS + /* print mem stats at each commit for leak tracking */ + if (ShowStats) + MemoryContextStats(TopMemoryContext); +#endif +} + + /* -------------------------------- * signal handler routines used in PostgresMain() * @@ -1397,7 +1614,7 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[], const cha if (!IsUnderPostmaster) { puts("\nPOSTGRES backend interactive interface "); - puts("$Revision: 1.177 $ $Date: 2000/10/03 03:11:19 $\n"); + puts("$Revision: 1.178 $ $Date: 2000/10/07 00:58:18 $\n"); } /* @@ -1524,22 +1741,20 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[], const cha { /* ---------------- * 'F' indicates a fastpath call. - * XXX HandleFunctionRequest * ---------------- */ case 'F': - IsEmptyQuery = false; - /* start an xact for this function invocation */ - if (DebugLvl >= 1) - elog(DEBUG, "StartTransactionCommand"); - StartTransactionCommand(); + start_xact_command(); if (HandleFunctionRequest() == EOF) { /* lost frontend connection during F message input */ goto normalexit; } + + /* commit the function-invocation transaction */ + finish_xact_command(); break; /* ---------------- @@ -1551,35 +1766,28 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[], const cha { /* ---------------- * if there is nothing in the input buffer, don't bother - * trying to parse and execute anything.. + * trying to parse and execute anything; just send + * back a quick NullCommand response. * ---------------- */ - IsEmptyQuery = true; + if (IsUnderPostmaster) + NullCommand(Remote); } else { /* ---------------- * otherwise, process the input string. + * + * Note: transaction command start/end is now done + * within pg_exec_query_string(), not here. * ---------------- */ - IsEmptyQuery = false; if (Show_query_stats) ResetUsage(); - /* start an xact for this query */ - if (DebugLvl >= 1) - elog(DEBUG, "StartTransactionCommand"); - StartTransactionCommand(); - - pg_exec_query_dest(parser_input->data, - whereToSendOutput, - QueryContext); - - /* - * Invoke IMMEDIATE constraint triggers - * - */ - DeferredTriggerEndQuery(); + pg_exec_query_string(parser_input->data, + whereToSendOutput, + QueryContext); if (Show_query_stats) { @@ -1603,39 +1811,14 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[], const cha elog(ERROR, "unknown frontend message was received"); } - /* ---------------- - * (6) commit the current transaction - * - * Note: if we had an empty input buffer, then we didn't - * call pg_exec_query_dest, so we don't bother to commit - * this transaction. - * ---------------- - */ - if (!IsEmptyQuery) - { - if (DebugLvl >= 1) - elog(DEBUG, "CommitTransactionCommand"); - set_ps_display("commit"); - CommitTransactionCommand(); -#ifdef SHOW_MEMORY_STATS - /* print global-context stats at each commit for leak tracking */ - if (ShowStats) - MemoryContextStats(TopMemoryContext); -#endif - } - else - { - if (IsUnderPostmaster) - NullCommand(Remote); - } - #ifdef MEMORY_CONTEXT_CHECKING /* - * Check all memory after each backend loop + * Check all memory after each backend loop. This is a rather + * weird place to do it, perhaps. */ MemoryContextCheck(TopMemoryContext); #endif - } /* end of main loop */ + } /* end of input-reading loop */ normalexit: ExitAfterAbort = true; /* ensure we will exit if elog during abort */ diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c index 9edb092e62d..9b52e9b66cd 100644 --- a/src/backend/tcop/utility.c +++ b/src/backend/tcop/utility.c @@ -10,7 +10,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.94 2000/09/12 05:09:45 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.95 2000/10/07 00:58:18 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -37,6 +37,7 @@ #include "commands/view.h" #include "miscadmin.h" #include "parser/parse.h" +#include "parser/parse_expr.h" #include "rewrite/rewriteDefine.h" #include "rewrite/rewriteRemove.h" #include "tcop/utility.h" @@ -46,24 +47,6 @@ /* ---------------- - * CHECK_IF_ABORTED() is used to avoid doing unnecessary - * processing within an aborted transaction block. - * ---------------- - */ - /* we have to use IF because of the 'break' */ -#define CHECK_IF_ABORTED() \ -if (1) \ -{ \ - if (IsAbortedTransactionBlockState()) \ - { \ - elog(NOTICE, "current transaction is aborted, " \ - "queries ignored until end of transaction block"); \ - commandTag = "*ABORT STATE*"; \ - break; \ - } \ -} else - -/* ---------------- * general utility function invoker * ---------------- */ @@ -90,7 +73,6 @@ ProcessUtility(Node *parsetree, { case BEGIN_TRANS: set_ps_display(commandTag = "BEGIN"); - CHECK_IF_ABORTED(); BeginTransactionBlock(); break; @@ -116,7 +98,6 @@ ProcessUtility(Node *parsetree, ClosePortalStmt *stmt = (ClosePortalStmt *) parsetree; set_ps_display(commandTag = "CLOSE"); - CHECK_IF_ABORTED(); PerformPortalClose(stmt->portalname, dest); } @@ -130,7 +111,6 @@ ProcessUtility(Node *parsetree, int count; set_ps_display(commandTag = (stmt->ismove) ? "MOVE" : "FETCH"); - CHECK_IF_ABORTED(); SetQuerySnapshot(); @@ -153,7 +133,6 @@ ProcessUtility(Node *parsetree, */ case T_CreateStmt: set_ps_display(commandTag = "CREATE"); - CHECK_IF_ABORTED(); DefineRelation((CreateStmt *) parsetree, RELKIND_RELATION); @@ -174,7 +153,6 @@ ProcessUtility(Node *parsetree, List *arg; set_ps_display(commandTag = "DROP"); - CHECK_IF_ABORTED(); /* check as much as we can before we start dropping ... */ foreach(arg, args) @@ -216,7 +194,6 @@ ProcessUtility(Node *parsetree, Relation rel; set_ps_display(commandTag = "TRUNCATE"); - CHECK_IF_ABORTED(); relname = ((TruncateStmt *) parsetree)->relName; if (!allowSystemTableMods && IsSystemRelationName(relname)) @@ -243,27 +220,23 @@ ProcessUtility(Node *parsetree, case T_CommentStmt: { - CommentStmt *statement; statement = ((CommentStmt *) parsetree); set_ps_display(commandTag = "COMMENT"); - CHECK_IF_ABORTED(); + CommentObject(statement->objtype, statement->objname, statement->objproperty, statement->objlist, statement->comment); } break; - - case T_CopyStmt: { CopyStmt *stmt = (CopyStmt *) parsetree; set_ps_display(commandTag = "COPY"); - CHECK_IF_ABORTED(); if (stmt->direction != FROM) SetQuerySnapshot(); @@ -292,7 +265,6 @@ ProcessUtility(Node *parsetree, RenameStmt *stmt = (RenameStmt *) parsetree; set_ps_display(commandTag = "ALTER"); - CHECK_IF_ABORTED(); relname = stmt->relname; if (!allowSystemTableMods && IsSystemRelationName(relname)) @@ -345,7 +317,6 @@ ProcessUtility(Node *parsetree, AlterTableStmt *stmt = (AlterTableStmt *) parsetree; set_ps_display(commandTag = "ALTER"); - CHECK_IF_ABORTED(); /* * Some or all of these functions are recursive to cover @@ -385,34 +356,10 @@ ProcessUtility(Node *parsetree, case T_ChangeACLStmt: { ChangeACLStmt *stmt = (ChangeACLStmt *) parsetree; - List *i; - AclItem *aip; - unsigned modechg; set_ps_display(commandTag = "CHANGE"); - CHECK_IF_ABORTED(); - - aip = stmt->aclitem; - modechg = stmt->modechg; - foreach(i, stmt->relNames) - { - Relation rel; - - relname = strVal(lfirst(i)); - rel = heap_openr(relname, AccessExclusiveLock); - if (rel && rel->rd_rel->relkind == RELKIND_INDEX) - elog(ERROR, "\"%s\" is an index relation", - relname); - /* close rel, but keep lock until end of xact */ - heap_close(rel, NoLock); -#ifndef NO_SECURITY - if (!pg_ownercheck(GetUserId(), relname, RELNAME)) - elog(ERROR, "you do not own class \"%s\"", - relname); -#endif - ChangeAcl(relname, aip, modechg); - } + ExecuteChangeACLStmt(stmt); } break; @@ -426,7 +373,6 @@ ProcessUtility(Node *parsetree, DefineStmt *stmt = (DefineStmt *) parsetree; set_ps_display(commandTag = "CREATE"); - CHECK_IF_ABORTED(); switch (stmt->defType) { @@ -450,14 +396,14 @@ ProcessUtility(Node *parsetree, ViewStmt *stmt = (ViewStmt *) parsetree; set_ps_display(commandTag = "CREATE"); - CHECK_IF_ABORTED(); + DefineView(stmt->viewname, stmt->query); /* retrieve parsetree */ } break; case T_ProcedureStmt: /* CREATE FUNCTION */ set_ps_display(commandTag = "CREATE"); - CHECK_IF_ABORTED(); + CreateFunction((ProcedureStmt *) parsetree, dest); /* everything */ break; @@ -466,7 +412,7 @@ ProcessUtility(Node *parsetree, IndexStmt *stmt = (IndexStmt *) parsetree; set_ps_display(commandTag = "CREATE"); - CHECK_IF_ABORTED(); + DefineIndex(stmt->relname, /* relation name */ stmt->idxname, /* index name */ stmt->accessMethod, /* am name */ @@ -491,14 +437,13 @@ ProcessUtility(Node *parsetree, elog(ERROR, "%s: %s", relname, aclcheck_error_strings[aclcheck_result]); #endif set_ps_display(commandTag = "CREATE"); - CHECK_IF_ABORTED(); + DefineQueryRewrite(stmt); } break; case T_CreateSeqStmt: set_ps_display(commandTag = "CREATE"); - CHECK_IF_ABORTED(); DefineSequence((CreateSeqStmt *) parsetree); break; @@ -508,7 +453,6 @@ ProcessUtility(Node *parsetree, ExtendStmt *stmt = (ExtendStmt *) parsetree; set_ps_display(commandTag = "EXTEND"); - CHECK_IF_ABORTED(); ExtendIndex(stmt->idxname, /* index name */ (Expr *) stmt->whereClause, /* where */ @@ -521,7 +465,6 @@ ProcessUtility(Node *parsetree, RemoveStmt *stmt = (RemoveStmt *) parsetree; set_ps_display(commandTag = "DROP"); - CHECK_IF_ABORTED(); switch (stmt->removeType) { @@ -581,10 +524,14 @@ ProcessUtility(Node *parsetree, case T_RemoveAggrStmt: { RemoveAggrStmt *stmt = (RemoveAggrStmt *) parsetree; + char *typename = (char *) NULL; set_ps_display(commandTag = "DROP"); - CHECK_IF_ABORTED(); - RemoveAggregate(stmt->aggname, stmt->aggtype); + + if (stmt->aggtype != NULL) + typename = TypeNameToInternalName((TypeName *) stmt->aggtype); + + RemoveAggregate(stmt->aggname, typename); } break; @@ -593,27 +540,27 @@ ProcessUtility(Node *parsetree, RemoveFuncStmt *stmt = (RemoveFuncStmt *) parsetree; set_ps_display(commandTag = "DROP"); - CHECK_IF_ABORTED(); - RemoveFunction(stmt->funcname, - length(stmt->args), - stmt->args); + + RemoveFunction(stmt->funcname, stmt->args); } break; case T_RemoveOperStmt: { RemoveOperStmt *stmt = (RemoveOperStmt *) parsetree; - char *type1 = (char *) NULL; - char *type2 = (char *) NULL; + TypeName *typenode1 = (TypeName *) lfirst(stmt->args); + TypeName *typenode2 = (TypeName *) lsecond(stmt->args); + char *typename1 = (char *) NULL; + char *typename2 = (char *) NULL; set_ps_display(commandTag = "DROP"); - CHECK_IF_ABORTED(); - if (lfirst(stmt->args) != NULL) - type1 = strVal(lfirst(stmt->args)); - if (lsecond(stmt->args) != NULL) - type2 = strVal(lsecond(stmt->args)); - RemoveOperator(stmt->opname, type1, type2); + if (typenode1 != NULL) + typename1 = TypeNameToInternalName(typenode1); + if (typenode2 != NULL) + typename2 = TypeNameToInternalName(typenode2); + + RemoveOperator(stmt->opname, typename1, typename2); } break; @@ -626,7 +573,7 @@ ProcessUtility(Node *parsetree, CreatedbStmt *stmt = (CreatedbStmt *) parsetree; set_ps_display(commandTag = "CREATE DATABASE"); - CHECK_IF_ABORTED(); + createdb(stmt->dbname, stmt->dbpath, stmt->encoding); } break; @@ -636,7 +583,7 @@ ProcessUtility(Node *parsetree, DropdbStmt *stmt = (DropdbStmt *) parsetree; set_ps_display(commandTag = "DROP DATABASE"); - CHECK_IF_ABORTED(); + dropdb(stmt->dbname); } break; @@ -647,7 +594,6 @@ ProcessUtility(Node *parsetree, NotifyStmt *stmt = (NotifyStmt *) parsetree; set_ps_display(commandTag = "NOTIFY"); - CHECK_IF_ABORTED(); Async_Notify(stmt->relname); } @@ -658,7 +604,6 @@ ProcessUtility(Node *parsetree, ListenStmt *stmt = (ListenStmt *) parsetree; set_ps_display(commandTag = "LISTEN"); - CHECK_IF_ABORTED(); Async_Listen(stmt->relname, MyProcPid); } @@ -669,7 +614,6 @@ ProcessUtility(Node *parsetree, UnlistenStmt *stmt = (UnlistenStmt *) parsetree; set_ps_display(commandTag = "UNLISTEN"); - CHECK_IF_ABORTED(); Async_Unlisten(stmt->relname, MyProcPid); } @@ -684,7 +628,6 @@ ProcessUtility(Node *parsetree, LoadStmt *stmt = (LoadStmt *) parsetree; set_ps_display(commandTag = "LOAD"); - CHECK_IF_ABORTED(); closeAllVfds(); /* probably not necessary... */ load_file(stmt->filename); @@ -696,7 +639,6 @@ ProcessUtility(Node *parsetree, ClusterStmt *stmt = (ClusterStmt *) parsetree; set_ps_display(commandTag = "CLUSTER"); - CHECK_IF_ABORTED(); cluster(stmt->relname, stmt->indexname); } @@ -704,7 +646,7 @@ ProcessUtility(Node *parsetree, case T_VacuumStmt: set_ps_display(commandTag = "VACUUM"); - CHECK_IF_ABORTED(); + vacuum(((VacuumStmt *) parsetree)->vacrel, ((VacuumStmt *) parsetree)->verbose, ((VacuumStmt *) parsetree)->analyze, @@ -716,7 +658,6 @@ ProcessUtility(Node *parsetree, ExplainStmt *stmt = (ExplainStmt *) parsetree; set_ps_display(commandTag = "EXPLAIN"); - CHECK_IF_ABORTED(); ExplainQuery(stmt->query, stmt->verbose, dest); } @@ -732,7 +673,7 @@ ProcessUtility(Node *parsetree, RecipeStmt *stmt = (RecipeStmt *) parsetree; set_ps_display(commandTag = "EXECUTE RECIPE"); - CHECK_IF_ABORTED(); + beginRecipe(stmt); } break; @@ -773,14 +714,12 @@ ProcessUtility(Node *parsetree, */ case T_CreateTrigStmt: set_ps_display(commandTag = "CREATE"); - CHECK_IF_ABORTED(); CreateTrigger((CreateTrigStmt *) parsetree); break; case T_DropTrigStmt: set_ps_display(commandTag = "DROP"); - CHECK_IF_ABORTED(); DropTrigger((DropTrigStmt *) parsetree); break; @@ -790,14 +729,12 @@ ProcessUtility(Node *parsetree, */ case T_CreatePLangStmt: set_ps_display(commandTag = "CREATE"); - CHECK_IF_ABORTED(); CreateProceduralLanguage((CreatePLangStmt *) parsetree); break; case T_DropPLangStmt: set_ps_display(commandTag = "DROP"); - CHECK_IF_ABORTED(); DropProceduralLanguage((DropPLangStmt *) parsetree); break; @@ -808,56 +745,48 @@ ProcessUtility(Node *parsetree, */ case T_CreateUserStmt: set_ps_display(commandTag = "CREATE USER"); - CHECK_IF_ABORTED(); CreateUser((CreateUserStmt *) parsetree); break; case T_AlterUserStmt: set_ps_display(commandTag = "ALTER USER"); - CHECK_IF_ABORTED(); AlterUser((AlterUserStmt *) parsetree); break; case T_DropUserStmt: set_ps_display(commandTag = "DROP USER"); - CHECK_IF_ABORTED(); DropUser((DropUserStmt *) parsetree); break; case T_LockStmt: set_ps_display(commandTag = "LOCK TABLE"); - CHECK_IF_ABORTED(); LockTableCommand((LockStmt *) parsetree); break; case T_ConstraintsSetStmt: set_ps_display(commandTag = "SET CONSTRAINTS"); - CHECK_IF_ABORTED(); DeferredTriggerSetState((ConstraintsSetStmt *) parsetree); break; case T_CreateGroupStmt: set_ps_display(commandTag = "CREATE GROUP"); - CHECK_IF_ABORTED(); CreateGroup((CreateGroupStmt *) parsetree); break; case T_AlterGroupStmt: set_ps_display(commandTag = "ALTER GROUP"); - CHECK_IF_ABORTED(); AlterGroup((AlterGroupStmt *) parsetree, "ALTER GROUP"); break; case T_DropGroupStmt: set_ps_display(commandTag = "DROP GROUP"); - CHECK_IF_ABORTED(); DropGroup((DropGroupStmt *) parsetree); break; @@ -867,7 +796,6 @@ ProcessUtility(Node *parsetree, ReindexStmt *stmt = (ReindexStmt *) parsetree; set_ps_display(commandTag = "REINDEX"); - CHECK_IF_ABORTED(); switch (stmt->reindexType) { |