OSDN Git Service

pg_class has a relnamespace column. You can create and access tables
[pg-rex/syncrep.git] / src / backend / tcop / utility.c
index 29b4fb5..84f3325 100644 (file)
@@ -5,11 +5,12 @@
  *       commands.  At one time acted as an interface between the Lisp and C
  *       systems.
  *
- * Copyright (c) 1994, Regents of the University of California
+ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.65 1999/09/18 19:07:44 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.140 2002/03/26 19:16:03 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 
 #include "access/heapam.h"
 #include "catalog/catalog.h"
-#include "catalog/pg_type.h"
+#include "catalog/namespace.h"
+#include "catalog/pg_shadow.h"
 #include "commands/async.h"
 #include "commands/cluster.h"
 #include "commands/command.h"
+#include "commands/comment.h"
 #include "commands/copy.h"
 #include "commands/creatinh.h"
 #include "commands/dbcommands.h"
 #include "commands/rename.h"
 #include "commands/sequence.h"
 #include "commands/trigger.h"
+#include "commands/user.h"
 #include "commands/vacuum.h"
 #include "commands/variable.h"
 #include "commands/view.h"
 #include "miscadmin.h"
+#include "parser/parse.h"
+#include "parser/parse_clause.h"
+#include "parser/parse_expr.h"
 #include "rewrite/rewriteDefine.h"
 #include "rewrite/rewriteRemove.h"
 #include "tcop/utility.h"
 #include "utils/acl.h"
-#include "utils/acl.h"
-#include "utils/ps_status.h"
 #include "utils/syscache.h"
+#include "utils/temprel.h"
+#include "access/xlog.h"
 
-#include "../backend/parser/parse.h"
+/*
+ * Error-checking support for DROP commands
+ */
 
-void           DefineUser(CreateUserStmt *stmt, CommandDest);
-void           AlterUser(AlterUserStmt *stmt, CommandDest);
-void           RemoveUser(char *username, CommandDest);
+struct kindstrings
+{
+       char            kind;
+       char       *indef_article;
+       char       *name;
+       char       *command;
+};
+
+static struct kindstrings kindstringarray[] = {
+       {RELKIND_RELATION, "a", "table", "TABLE"},
+       {RELKIND_SEQUENCE, "a", "sequence", "SEQUENCE"},
+       {RELKIND_VIEW, "a", "view", "VIEW"},
+       {RELKIND_INDEX, "an", "index", "INDEX"},
+       {'\0', "a", "???", "???"}
+};
+
+
+static void
+DropErrorMsg(char *relname, char wrongkind, char rightkind)
+{
+       struct kindstrings *rentry;
+       struct kindstrings *wentry;
 
-/* ----------------
- *             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, "(transaction aborted): %s", \
-                        "all queries ignored until end of transaction block"); \
-               commandTag = "*ABORT STATE*"; \
-               break; \
-       } \
-} else
-
-/* ----------------
+       for (rentry = kindstringarray; rentry->kind != '\0'; rentry++)
+               if (rentry->kind == rightkind)
+                       break;
+       Assert(rentry->kind != '\0');
+
+       for (wentry = kindstringarray; wentry->kind != '\0'; wentry++)
+               if (wentry->kind == wrongkind)
+                       break;
+       /* wrongkind could be something we don't have in our table... */
+       if (wentry->kind != '\0')
+               elog(ERROR, "\"%s\" is not %s %s. Use DROP %s to remove %s %s",
+                        relname, rentry->indef_article, rentry->name,
+                        wentry->command, wentry->indef_article, wentry->name);
+       else
+               elog(ERROR, "\"%s\" is not %s %s",
+                        relname, rentry->indef_article, rentry->name);
+}
+
+static void
+CheckDropPermissions(RangeVar *rel, char rightkind)
+{
+       struct kindstrings *rentry;
+       Oid                     relOid;
+       HeapTuple       tuple;
+       Form_pg_class classform;
+
+       for (rentry = kindstringarray; rentry->kind != '\0'; rentry++)
+               if (rentry->kind == rightkind)
+                       break;
+       Assert(rentry->kind != '\0');
+
+       relOid = RangeVarGetRelid(rel, true);
+       if (!OidIsValid(relOid))
+               elog(ERROR, "%s \"%s\" does not exist", rentry->name, rel->relname);
+       tuple = SearchSysCache(RELOID,
+                                                  ObjectIdGetDatum(relOid),
+                                                  0, 0, 0);
+       if (!HeapTupleIsValid(tuple))
+               elog(ERROR, "%s \"%s\" does not exist", rentry->name, rel->relname);
+
+       classform = (Form_pg_class) GETSTRUCT(tuple);
+
+       if (classform->relkind != rightkind)
+               DropErrorMsg(rel->relname, classform->relkind, rightkind);
+
+       if (!pg_class_ownercheck(relOid, GetUserId()))
+               elog(ERROR, "you do not own %s \"%s\"",
+                        rentry->name, rel->relname);
+
+       if (!allowSystemTableMods && IsSystemRelationName(rel->relname) &&
+               !is_temp_relname(rel->relname))
+               elog(ERROR, "%s \"%s\" is a system %s",
+                        rentry->name, rel->relname, rentry->name);
+
+       ReleaseSysCache(tuple);
+}
+
+static void
+CheckOwnership(RangeVar *rel, bool noCatalogs)
+{
+       Oid                     relOid;
+       HeapTuple       tuple;
+
+       relOid = RangeVarGetRelid(rel, false);
+       tuple = SearchSysCache(RELOID,
+                                                  ObjectIdGetDatum(relOid),
+                                                  0, 0, 0);
+       if (!HeapTupleIsValid(tuple))
+               elog(ERROR, "Relation \"%s\" does not exist", rel->relname);
+
+       if (!pg_class_ownercheck(relOid, GetUserId()))
+               elog(ERROR, "%s: %s", rel->relname,
+                        aclcheck_error_strings[ACLCHECK_NOT_OWNER]);
+
+       if (noCatalogs)
+       {
+               if (!allowSystemTableMods && IsSystemRelationName(rel->relname))
+                       elog(ERROR, "relation \"%s\" is a system catalog",
+                                rel->relname);
+       }
+
+       ReleaseSysCache(tuple);
+}
+
+
+/*
+ * ProcessUtility
  *             general utility function invoker
- * ----------------
+ *
+ *     parsetree: the parse tree for the utility statement
+ *     dest: where to send results
+ *     completionTag: points to a buffer of size COMPLETION_TAG_BUFSIZE
+ *             in which to store a command completion status string.
+ *
+ * completionTag is only set nonempty if we want to return a nondefault
+ * status (currently, only used for MOVE/FETCH).
+ *
+ * completionTag may be NULL if caller doesn't want a status string.
  */
 void
 ProcessUtility(Node *parsetree,
-                          CommandDest dest)
+                          CommandDest dest,
+                          char *completionTag)
 {
-       char       *commandTag = NULL;
        char       *relname;
-       char       *relationName;
-       char       *userName;
 
-       userName = GetPgUserName();
+       if (completionTag)
+               completionTag[0] = '\0';
 
        switch (nodeTag(parsetree))
        {
-
                        /*
                         * ******************************** transactions ********************************
                         *
@@ -95,18 +198,14 @@ ProcessUtility(Node *parsetree,
                                switch (stmt->command)
                                {
                                        case BEGIN_TRANS:
-                                               PS_SET_STATUS(commandTag = "BEGIN");
-                                               CHECK_IF_ABORTED();
                                                BeginTransactionBlock();
                                                break;
 
-                                       case END_TRANS:
-                                               PS_SET_STATUS(commandTag = "END");
+                                       case COMMIT:
                                                EndTransactionBlock();
                                                break;
 
-                                       case ABORT_TRANS:
-                                               PS_SET_STATUS(commandTag = "ABORT");
+                                       case ROLLBACK:
                                                UserAbortTransactionBlock();
                                                break;
                                }
@@ -121,9 +220,6 @@ ProcessUtility(Node *parsetree,
                        {
                                ClosePortalStmt *stmt = (ClosePortalStmt *) parsetree;
 
-                               PS_SET_STATUS(commandTag = "CLOSE");
-                               CHECK_IF_ABORTED();
-
                                PerformPortalClose(stmt->portalname, dest);
                        }
                        break;
@@ -135,8 +231,7 @@ ProcessUtility(Node *parsetree,
                                bool            forward;
                                int                     count;
 
-                               PS_SET_STATUS(commandTag = (stmt->ismove) ? "MOVE" : "FETCH");
-                               CHECK_IF_ABORTED();
+                               SetQuerySnapshot();
 
                                forward = (bool) (stmt->direction == FORWARD);
 
@@ -145,75 +240,124 @@ ProcessUtility(Node *parsetree,
                                 */
 
                                count = stmt->howMany;
-                               PerformPortalFetch(portalName, forward, count, commandTag,
-                                                                  (stmt->ismove) ? None : dest);               /* /dev/null for MOVE */
+                               PerformPortalFetch(portalName, forward, count,
+                                                                  (stmt->ismove) ? None : dest,
+                                                                  completionTag);
                        }
                        break;
 
                        /*
-                        * ******************************** relation and attribute
-                        * manipulation ********************************
-                        *
+                        * relation and attribute manipulation
                         */
+               case T_CreateSchemaStmt:
+                       {
+                               CreateSchemaStmt  *stmt = (CreateSchemaStmt *) parsetree;
+
+                               CreateSchemaCommand(stmt);
+                       }
+                       break;
+
                case T_CreateStmt:
-                       PS_SET_STATUS(commandTag = "CREATE");
-                       CHECK_IF_ABORTED();
+                       {
+                               Oid                     relOid;
+
+                               relOid = DefineRelation((CreateStmt *) parsetree,
+                                                                               RELKIND_RELATION);
 
-                       DefineRelation((CreateStmt *) parsetree, RELKIND_RELATION);
+                               /*
+                                * Let AlterTableCreateToastTable decide if this one needs a
+                                * secondary relation too.
+                                */
+                               CommandCounterIncrement();
+                               AlterTableCreateToastTable(relOid, true);
+                       }
                        break;
 
-               case T_DestroyStmt:
+               case T_DropStmt:
                        {
-                               DestroyStmt *stmt = (DestroyStmt *) parsetree;
-                               List       *args = stmt->relNames;
+                               DropStmt   *stmt = (DropStmt *) parsetree;
                                List       *arg;
 
-                               PS_SET_STATUS(commandTag = "DROP");
-                               CHECK_IF_ABORTED();
-
-                               /* check as much as we can before we start dropping ... */
-                               foreach(arg, args)
-                               {
-                                       Relation        rel;
-
-                                       relname = strVal(lfirst(arg));
-                                       if (!allowSystemTableMods && IsSystemRelationName(relname))
-                                               elog(ERROR, "class \"%s\" is a system catalog",
-                                                        relname);
-                                       rel = heap_openr(relname, AccessExclusiveLock);
-                                       if (stmt->sequence &&
-                                               rel->rd_rel->relkind != RELKIND_SEQUENCE)
-                                               elog(ERROR, "Use DROP TABLE to drop table '%s'",
-                                                        relname);
-                                       if (!(stmt->sequence) &&
-                                               rel->rd_rel->relkind == RELKIND_SEQUENCE)
-                                               elog(ERROR, "Use DROP SEQUENCE to drop sequence '%s'",
-                                                        relname);
-                                       /* close rel, but keep lock until end of xact */
-                                       heap_close(rel, NoLock);
-#ifndef NO_SECURITY
-                                       if (!pg_ownercheck(userName, relname, RELNAME))
-                                               elog(ERROR, "you do not own class \"%s\"",
-                                                        relname);
-#endif
-                               }
-                               /* OK, terminate 'em all */
-                               foreach(arg, args)
+                               foreach(arg, stmt->objects)
                                {
-                                       relname = strVal(lfirst(arg));
-                                       RemoveRelation(relname);
+                                       RangeVar   *rel = (RangeVar *) lfirst(arg);
+
+                                       relname = rel->relname;
+
+                                       switch (stmt->removeType)
+                                       {
+                                               case DROP_TABLE:
+                                                       CheckDropPermissions(rel, RELKIND_RELATION);
+                                                       RemoveRelation(relname);
+                                                       break;
+
+                                               case DROP_SEQUENCE:
+                                                       CheckDropPermissions(rel, RELKIND_SEQUENCE);
+                                                       RemoveRelation(relname);
+                                                       break;
+
+                                               case DROP_VIEW:
+                                                       CheckDropPermissions(rel, RELKIND_VIEW);
+                                                       RemoveView(relname);
+                                                       break;
+
+                                               case DROP_INDEX:
+                                                       CheckDropPermissions(rel, RELKIND_INDEX);
+                                                       RemoveIndex(rel);
+                                                       break;
+
+                                               case DROP_RULE:
+                                                       /* RemoveRewriteRule checks permissions */
+                                                       RemoveRewriteRule(relname);
+                                                       break;
+
+                                               case DROP_TYPE:
+                                                       /* RemoveType does its own permissions checks */
+                                                       RemoveType(relname);
+                                                       break;
+
+                                               case DROP_DOMAIN:
+                                                       /* RemoveDomain does its own permissions checks */
+                                                       RemoveDomain(relname, stmt->behavior);
+                                                       break;
+                                       }
+
+                                       /*
+                                        * Make sure subsequent loop iterations will see
+                                        * results of this one; needed if removing multiple
+                                        * rules for same table, for example.
+                                        */
+                                       CommandCounterIncrement();
                                }
                        }
                        break;
 
+               case T_TruncateStmt:
+                       {
+                               relname = ((TruncateStmt *) parsetree)->relation->relname;
+                               TruncateRelation(relname);
+                       }
+                       break;
+
+               case T_CommentStmt:
+                       {
+                               CommentStmt *stmt;
+
+                               stmt = ((CommentStmt *) parsetree);
+
+                               CommentObject(stmt->objtype, stmt->objschema, stmt->objname,
+                                                         stmt->objproperty, stmt->objlist, stmt->comment);
+                       }
+                       break;
+
                case T_CopyStmt:
                        {
                                CopyStmt   *stmt = (CopyStmt *) parsetree;
 
-                               PS_SET_STATUS(commandTag = "COPY");
-                               CHECK_IF_ABORTED();
+                               if (stmt->direction != FROM)
+                                       SetQuerySnapshot();
 
-                               DoCopy(stmt->relname,
+                               DoCopy(stmt->relation->relname,
                                           stmt->binary,
                                           stmt->oids,
                                           (bool) (stmt->direction == FROM),
@@ -224,25 +368,8 @@ ProcessUtility(Node *parsetree,
                                 * than to/from a file.
                                 */
                                           stmt->filename,
-                                          stmt->delimiter);
-                       }
-                       break;
-
-               case T_AddAttrStmt:
-                       {
-                               AddAttrStmt *stmt = (AddAttrStmt *) parsetree;
-
-                               PS_SET_STATUS(commandTag = "ADD");
-                               CHECK_IF_ABORTED();
-
-                               /*
-                                * owner checking done in PerformAddAttribute (now
-                                * recursive)
-                                */
-                               PerformAddAttribute(stmt->relname,
-                                                                       userName,
-                                                                       stmt->inh,
-                                                                       (ColumnDef *) stmt->colDef);
+                                          stmt->delimiter,
+                                          stmt->null_print);
                        }
                        break;
 
@@ -253,18 +380,8 @@ ProcessUtility(Node *parsetree,
                        {
                                RenameStmt *stmt = (RenameStmt *) parsetree;
 
-                               PS_SET_STATUS(commandTag = "RENAME");
-                               CHECK_IF_ABORTED();
-
-                               relname = stmt->relname;
-                               if (!allowSystemTableMods && IsSystemRelationName(relname))
-                                       elog(ERROR, "class \"%s\" is a system catalog",
-                                                relname);
-#ifndef NO_SECURITY
-                               if (!pg_ownercheck(userName, relname, RELNAME))
-                                       elog(ERROR, "you do not own class \"%s\"",
-                                                relname);
-#endif
+                               relname = stmt->relation->relname;
+                               CheckOwnership(stmt->relation, true);
 
                                /* ----------------
                                 *      XXX using len == 3 to tell the difference
@@ -277,61 +394,97 @@ ProcessUtility(Node *parsetree,
                                 */
                                if (stmt->column == NULL)
                                {
-                                       /* ----------------
-                                        *              rename relation
+                                       /*
+                                        * rename relation
                                         *
-                                        *              Note: we also rename the "type" tuple
-                                        *              corresponding to the relation.
-                                        * ----------------
+                                        * Note: we also rename the "type" tuple corresponding to
+                                        * the relation.
                                         */
-                                       renamerel(relname,      /* old name */
+                                       renamerel(stmt->relation,       /* old relation */
                                                          stmt->newname);       /* new name */
-                                       TypeRename(relname, /* old name */
-                                                          stmt->newname);      /* new name */
                                }
                                else
                                {
-                                       /* ----------------
-                                        *              rename attribute
-                                        * ----------------
+                                       /*
+                                        * rename attribute
                                         */
                                        renameatt(relname,      /* relname */
                                                          stmt->column,         /* old att name */
                                                          stmt->newname,        /* new att name */
-                                                         userName,
-                                                         stmt->inh);           /* recursive? */
+                                                         interpretInhOption(stmt->relation->inhOpt));          /* recursive? */
                                }
                        }
                        break;
 
-               case T_ChangeACLStmt:
-                       {
-                               ChangeACLStmt *stmt = (ChangeACLStmt *) parsetree;
-                               List       *i;
-                               AclItem    *aip;
-                               unsigned        modechg;
-
-                               PS_SET_STATUS(commandTag = "CHANGE");
-                               CHECK_IF_ABORTED();
+                       /* various Alter Table forms */
 
-                               aip = stmt->aclitem;
+               case T_AlterTableStmt:
+                       {
+                               AlterTableStmt *stmt = (AlterTableStmt *) parsetree;
 
-                               modechg = stmt->modechg;
-#ifndef NO_SECURITY
-                               foreach(i, stmt->relNames)
-                               {
-                                       relname = strVal(lfirst(i));
-                                       if (!pg_ownercheck(userName, relname, RELNAME))
-                                               elog(ERROR, "you do not own class \"%s\"",
-                                                        relname);
-                               }
-#endif
-                               foreach(i, stmt->relNames)
+                               /*
+                                * Some or all of these functions are recursive to cover
+                                * inherited things, so permission checks are done there.
+                                */
+                               switch (stmt->subtype)
                                {
-                                       relname = strVal(lfirst(i));
-                                       ChangeAcl(relname, aip, modechg);
+                                       case 'A':       /* ADD COLUMN */
+                                               AlterTableAddColumn(stmt->relation->relname,
+                                                                               interpretInhOption((stmt->relation)->inhOpt),
+                                                                                       (ColumnDef *) stmt->def);
+                                               break;
+                                       case 'T':       /* ALTER COLUMN DEFAULT */
+                                               AlterTableAlterColumnDefault(stmt->relation->relname,
+                                                                               interpretInhOption((stmt->relation)->inhOpt),
+                                                                                                        stmt->name,
+                                                                                                        stmt->def);
+                                               break;
+                                       case 'S':       /* ALTER COLUMN STATISTICS */
+                                       case 'M':   /* ALTER COLUMN STORAGE */
+                                               AlterTableAlterColumnFlags(stmt->relation->relname,
+                                                                               interpretInhOption(stmt->relation->inhOpt),
+                                                                                                               stmt->name,
+                                                                                                               stmt->def,
+                                                                                                       &(stmt->subtype));
+                                               break;
+                                       case 'D':       /* DROP COLUMN */
+                                               AlterTableDropColumn(stmt->relation->relname,
+                                                                               interpretInhOption(stmt->relation->inhOpt),
+                                                                                        stmt->name,
+                                                                                        stmt->behavior);
+                                               break;
+                                       case 'C':       /* ADD CONSTRAINT */
+                                               AlterTableAddConstraint(stmt->relation->relname,
+                                                                               interpretInhOption(stmt->relation->inhOpt),
+                                                                                               (List *) stmt->def);
+                                               break;
+                                       case 'X':       /* DROP CONSTRAINT */
+                                               AlterTableDropConstraint(stmt->relation->relname,
+                                                                               interpretInhOption(stmt->relation->inhOpt),
+                                                                                                stmt->name,
+                                                                                                stmt->behavior);
+                                               break;
+                                       case 'E':       /* CREATE TOAST TABLE */
+                                               AlterTableCreateToastTable(RangeVarGetRelid(stmt->relation, false),
+                                                                                                  false);
+                                               break;
+                                       case 'U':       /* ALTER OWNER */
+                                               AlterTableOwner(stmt->relation,
+                                                                               stmt->name);
+                                               break;
+                                       default:        /* oops */
+                                               elog(ERROR, "T_AlterTableStmt: unknown subtype");
+                                               break;
                                }
+                       }
+                       break;
+
 
+               case T_GrantStmt:
+                       {
+                               GrantStmt  *stmt = (GrantStmt *) parsetree;
+
+                               ExecuteGrantStmt(stmt);
                        }
                        break;
 
@@ -344,9 +497,6 @@ ProcessUtility(Node *parsetree,
                        {
                                DefineStmt *stmt = (DefineStmt *) parsetree;
 
-                               PS_SET_STATUS(commandTag = "CREATE");
-                               CHECK_IF_ABORTED();
-
                                switch (stmt->defType)
                                {
                                        case OPERATOR:
@@ -368,29 +518,24 @@ ProcessUtility(Node *parsetree,
                        {
                                ViewStmt   *stmt = (ViewStmt *) parsetree;
 
-                               PS_SET_STATUS(commandTag = "CREATE");
-                               CHECK_IF_ABORTED();
-                               DefineView(stmt->viewname, stmt->query);                /* retrieve parsetree */
+                               DefineView(stmt->view->relname, stmt->query);   /* retrieve parsetree */
                        }
                        break;
 
                case T_ProcedureStmt:   /* CREATE FUNCTION */
-                       PS_SET_STATUS(commandTag = "CREATE");
-                       CHECK_IF_ABORTED();
-                       CreateFunction((ProcedureStmt *) parsetree, dest);      /* everything */
+                       CreateFunction((ProcedureStmt *) parsetree);
                        break;
 
                case T_IndexStmt:               /* CREATE INDEX */
                        {
                                IndexStmt  *stmt = (IndexStmt *) parsetree;
 
-                               PS_SET_STATUS(commandTag = "CREATE");
-                               CHECK_IF_ABORTED();
-                               DefineIndex(stmt->relname,              /* relation name */
-                                                       stmt->idxname,          /* index name */
-                                                       stmt->accessMethod, /* am name */
-                                                       stmt->indexParams,      /* parameters */
-                                                       stmt->withClause,
+                               CheckOwnership(stmt->relation, true);
+
+                               DefineIndex(stmt->relation,                             /* relation */
+                                                       stmt->idxname,                          /* index name */
+                                                       stmt->accessMethod,             /* am name */
+                                                       stmt->indexParams,                      /* parameters */
                                                        stmt->unique,
                                                        stmt->primary,
                                                        (Expr *) stmt->whereClause,
@@ -399,111 +544,22 @@ ProcessUtility(Node *parsetree,
                        break;
 
                case T_RuleStmt:                /* CREATE RULE */
-                       {
-                               RuleStmt   *stmt = (RuleStmt *) parsetree;
-                               int                     aclcheck_result;
-
-#ifndef NO_SECURITY
-                               relname = stmt->object->relname;
-                               aclcheck_result = pg_aclcheck(relname, userName, ACL_RU);
-                               if (aclcheck_result != ACLCHECK_OK)
-                                       elog(ERROR, "%s: %s", relname, aclcheck_error_strings[aclcheck_result]);
-#endif
-                               PS_SET_STATUS(commandTag = "CREATE");
-                               CHECK_IF_ABORTED();
-                               DefineQueryRewrite(stmt);
-                       }
+                       DefineQueryRewrite((RuleStmt *) parsetree);
                        break;
 
                case T_CreateSeqStmt:
-                       PS_SET_STATUS(commandTag = "CREATE");
-                       CHECK_IF_ABORTED();
-
                        DefineSequence((CreateSeqStmt *) parsetree);
                        break;
 
-               case T_ExtendStmt:
-                       {
-                               ExtendStmt *stmt = (ExtendStmt *) parsetree;
-
-                               PS_SET_STATUS(commandTag = "EXTEND");
-                               CHECK_IF_ABORTED();
-
-                               ExtendIndex(stmt->idxname,              /* index name */
-                                                       (Expr *) stmt->whereClause, /* where */
-                                                       stmt->rangetable);
-                       }
-                       break;
-
-               case T_RemoveStmt:
-                       {
-                               RemoveStmt *stmt = (RemoveStmt *) parsetree;
-
-                               PS_SET_STATUS(commandTag = "DROP");
-                               CHECK_IF_ABORTED();
-
-                               switch (stmt->removeType)
-                               {
-                                       case INDEX:
-                                               relname = stmt->name;
-                                               if (!allowSystemTableMods && IsSystemRelationName(relname))
-                                                       elog(ERROR, "class \"%s\" is a system catalog index",
-                                                                relname);
-#ifndef NO_SECURITY
-                                               if (!pg_ownercheck(userName, relname, RELNAME))
-                                                       elog(ERROR, "%s: %s", relname, aclcheck_error_strings[ACLCHECK_NOT_OWNER]);
-#endif
-                                               RemoveIndex(relname);
-                                               break;
-                                       case RULE:
-                                               {
-                                                       char       *rulename = stmt->name;
-                                                       int                     aclcheck_result;
-
-#ifndef NO_SECURITY
-
-                                                       relationName = RewriteGetRuleEventRel(rulename);
-                                                       aclcheck_result = pg_aclcheck(relationName, userName, ACL_RU);
-                                                       if (aclcheck_result != ACLCHECK_OK)
-                                                               elog(ERROR, "%s: %s", relationName, aclcheck_error_strings[aclcheck_result]);
-#endif
-                                                       RemoveRewriteRule(rulename);
-                                               }
-                                               break;
-                                       case TYPE_P:
-#ifndef NO_SECURITY
-                                               /* XXX moved to remove.c */
-#endif
-                                               RemoveType(stmt->name);
-                                               break;
-                                       case VIEW:
-                                               {
-                                                       char       *viewName = stmt->name;
-                                                       char       *ruleName;
-
-#ifndef NO_SECURITY
-
-                                                       ruleName = MakeRetrieveViewRuleName(viewName);
-                                                       relationName = RewriteGetRuleEventRel(ruleName);
-                                                       if (!pg_ownercheck(userName, relationName, RELNAME))
-                                                               elog(ERROR, "%s: %s", relationName, aclcheck_error_strings[ACLCHECK_NOT_OWNER]);
-                                                       pfree(ruleName);
-#endif
-                                                       RemoveView(viewName);
-                                               }
-                                               break;
-                               }
-                               break;
-                       }
-                       break;
-
                case T_RemoveAggrStmt:
                        {
                                RemoveAggrStmt *stmt = (RemoveAggrStmt *) parsetree;
+                               char       *typename = (char *) NULL;
+
+                               if (stmt->aggtype != NULL)
+                                       typename = TypeNameToInternalName((TypeName *) stmt->aggtype);
 
-                               PS_SET_STATUS(commandTag = "DROP");
-                               CHECK_IF_ABORTED();
-                               RemoveAggregate(stmt->aggname, stmt->aggtype);
+                               RemoveAggregate(stmt->aggname, typename);
                        }
                        break;
 
@@ -511,52 +567,46 @@ ProcessUtility(Node *parsetree,
                        {
                                RemoveFuncStmt *stmt = (RemoveFuncStmt *) parsetree;
 
-                               PS_SET_STATUS(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;
 
-                               PS_SET_STATUS(commandTag = "DROP");
-                               CHECK_IF_ABORTED();
+                               if (typenode1 != NULL)
+                                       typename1 = TypeNameToInternalName(typenode1);
+                               if (typenode2 != NULL)
+                                       typename2 = TypeNameToInternalName(typenode2);
 
-                               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);
+                               RemoveOperator(stmt->opname, typename1, typename2);
                        }
                        break;
 
-               case T_VersionStmt:
-                       elog(ERROR, "CREATE VERSION is not currently implemented");
-                       break;
-
                case T_CreatedbStmt:
                        {
                                CreatedbStmt *stmt = (CreatedbStmt *) parsetree;
 
-                               PS_SET_STATUS(commandTag = "CREATEDB");
-                               CHECK_IF_ABORTED();
-                               createdb(stmt->dbname, stmt->dbpath, stmt->encoding, dest);
+                               createdb(stmt->dbname, stmt->dbowner,
+                                                stmt->dbpath, stmt->dbtemplate,
+                                                stmt->encoding);
                        }
                        break;
 
-               case T_DestroydbStmt:
+               case T_AlterDatabaseSetStmt:
+                       AlterDatabaseSet((AlterDatabaseSetStmt *)parsetree);
+                       break;
+
+               case T_DropdbStmt:
                        {
-                               DestroydbStmt *stmt = (DestroydbStmt *) parsetree;
+                               DropdbStmt *stmt = (DropdbStmt *) parsetree;
 
-                               PS_SET_STATUS(commandTag = "DESTROYDB");
-                               CHECK_IF_ABORTED();
-                               destroydb(stmt->dbname, dest);
+                               dropdb(stmt->dbname);
                        }
                        break;
 
@@ -565,10 +615,7 @@ ProcessUtility(Node *parsetree,
                        {
                                NotifyStmt *stmt = (NotifyStmt *) parsetree;
 
-                               PS_SET_STATUS(commandTag = "NOTIFY");
-                               CHECK_IF_ABORTED();
-
-                               Async_Notify(stmt->relname);
+                               Async_Notify(stmt->relation->relname);
                        }
                        break;
 
@@ -576,10 +623,7 @@ ProcessUtility(Node *parsetree,
                        {
                                ListenStmt *stmt = (ListenStmt *) parsetree;
 
-                               PS_SET_STATUS(commandTag = "LISTEN");
-                               CHECK_IF_ABORTED();
-
-                               Async_Listen(stmt->relname, MyProcPid);
+                               Async_Listen(stmt->relation->relname, MyProcPid);
                        }
                        break;
 
@@ -587,24 +631,14 @@ ProcessUtility(Node *parsetree,
                        {
                                UnlistenStmt *stmt = (UnlistenStmt *) parsetree;
 
-                               PS_SET_STATUS(commandTag = "UNLISTEN");
-                               CHECK_IF_ABORTED();
-
-                               Async_Unlisten(stmt->relname, MyProcPid);
+                               Async_Unlisten(stmt->relation->relname, MyProcPid);
                        }
                        break;
 
-                       /*
-                        * ******************************** dynamic loader ********************************
-                        *
-                        */
                case T_LoadStmt:
                        {
                                LoadStmt   *stmt = (LoadStmt *) parsetree;
 
-                               PS_SET_STATUS(commandTag = "LOAD");
-                               CHECK_IF_ABORTED();
-
                                closeAllVfds(); /* probably not necessary... */
                                load_file(stmt->filename);
                        }
@@ -614,58 +648,36 @@ ProcessUtility(Node *parsetree,
                        {
                                ClusterStmt *stmt = (ClusterStmt *) parsetree;
 
-                               PS_SET_STATUS(commandTag = "CLUSTER");
-                               CHECK_IF_ABORTED();
+                               CheckOwnership(stmt->relation, true);
 
-                               cluster(stmt->relname, stmt->indexname);
+                               cluster(stmt->relation, stmt->indexname);
                        }
                        break;
 
                case T_VacuumStmt:
-                       PS_SET_STATUS(commandTag = "VACUUM");
-                       CHECK_IF_ABORTED();
-                       vacuum(((VacuumStmt *) parsetree)->vacrel,
-                                  ((VacuumStmt *) parsetree)->verbose,
-                                  ((VacuumStmt *) parsetree)->analyze,
-                                  ((VacuumStmt *) parsetree)->va_spec);
+                       vacuum((VacuumStmt *) parsetree);
                        break;
 
                case T_ExplainStmt:
-                       {
-                               ExplainStmt *stmt = (ExplainStmt *) parsetree;
-
-                               PS_SET_STATUS(commandTag = "EXPLAIN");
-                               CHECK_IF_ABORTED();
-
-                               ExplainQuery(stmt->query, stmt->verbose, dest);
-                       }
+                       ExplainQuery((ExplainStmt *) parsetree, dest);
                        break;
 
 #ifdef NOT_USED
 
-                       /*
-                        * ******************************** Tioga-related statements *******************************
-                        */
                case T_RecipeStmt:
                        {
                                RecipeStmt *stmt = (RecipeStmt *) parsetree;
 
-                               PS_SET_STATUS(commandTag = "EXECUTE RECIPE");
-                               CHECK_IF_ABORTED();
                                beginRecipe(stmt);
                        }
                        break;
 #endif
 
-                       /*
-                        * ******************************** set variable statements *******************************
-                        */
                case T_VariableSetStmt:
                        {
                                VariableSetStmt *n = (VariableSetStmt *) parsetree;
 
-                               SetPGVariable(n->name, n->value);
-                               PS_SET_STATUS(commandTag = "SET VARIABLE");
+                               SetPGVariable(n->name, n->args);
                        }
                        break;
 
@@ -674,7 +686,6 @@ ProcessUtility(Node *parsetree,
                                VariableShowStmt *n = (VariableShowStmt *) parsetree;
 
                                GetPGVariable(n->name);
-                               PS_SET_STATUS(commandTag = "SHOW VARIABLE");
                        }
                        break;
 
@@ -683,90 +694,119 @@ ProcessUtility(Node *parsetree,
                                VariableResetStmt *n = (VariableResetStmt *) parsetree;
 
                                ResetPGVariable(n->name);
-                               PS_SET_STATUS(commandTag = "RESET VARIABLE");
                        }
                        break;
 
-                       /*
-                        * ******************************** TRIGGER statements *******************************
-                        */
                case T_CreateTrigStmt:
-                       PS_SET_STATUS(commandTag = "CREATE");
-                       CHECK_IF_ABORTED();
-
                        CreateTrigger((CreateTrigStmt *) parsetree);
                        break;
 
                case T_DropTrigStmt:
-                       PS_SET_STATUS(commandTag = "DROP");
-                       CHECK_IF_ABORTED();
-
                        DropTrigger((DropTrigStmt *) parsetree);
                        break;
 
-                       /*
-                        * ************* PROCEDURAL LANGUAGE statements *****************
-                        */
                case T_CreatePLangStmt:
-                       PS_SET_STATUS(commandTag = "CREATE");
-                       CHECK_IF_ABORTED();
-
                        CreateProceduralLanguage((CreatePLangStmt *) parsetree);
                        break;
 
                case T_DropPLangStmt:
-                       PS_SET_STATUS(commandTag = "DROP");
-                       CHECK_IF_ABORTED();
-
                        DropProceduralLanguage((DropPLangStmt *) parsetree);
                        break;
 
                        /*
+                        * ******************************** DOMAIN statements ****
+                        */
+               case T_CreateDomainStmt:
+                       DefineDomain((CreateDomainStmt *) parsetree);
+                       break;
+
+                       /*
                         * ******************************** USER statements ****
-                        *
                         */
                case T_CreateUserStmt:
-                       PS_SET_STATUS(commandTag = "CREATE USER");
-                       CHECK_IF_ABORTED();
-
-                       DefineUser((CreateUserStmt *) parsetree, dest);
+                       CreateUser((CreateUserStmt *) parsetree);
                        break;
 
                case T_AlterUserStmt:
-                       PS_SET_STATUS(commandTag = "ALTER USER");
-                       CHECK_IF_ABORTED();
+                       AlterUser((AlterUserStmt *) parsetree);
+                       break;
 
-                       AlterUser((AlterUserStmt *) parsetree, dest);
+               case T_AlterUserSetStmt:
+                       AlterUserSet((AlterUserSetStmt *) parsetree);
                        break;
 
                case T_DropUserStmt:
-                       PS_SET_STATUS(commandTag = "DROP USER");
-                       CHECK_IF_ABORTED();
-
-                       RemoveUser(((DropUserStmt *) parsetree)->user, dest);
+                       DropUser((DropUserStmt *) parsetree);
                        break;
 
                case T_LockStmt:
-                       PS_SET_STATUS(commandTag = "LOCK TABLE");
-                       CHECK_IF_ABORTED();
-
                        LockTableCommand((LockStmt *) parsetree);
                        break;
 
+               case T_ConstraintsSetStmt:
+                       DeferredTriggerSetState((ConstraintsSetStmt *) parsetree);
+                       break;
+
+               case T_CreateGroupStmt:
+                       CreateGroup((CreateGroupStmt *) parsetree);
+                       break;
+
+               case T_AlterGroupStmt:
+                       AlterGroup((AlterGroupStmt *) parsetree, "ALTER GROUP");
+                       break;
+
+               case T_DropGroupStmt:
+                       DropGroup((DropGroupStmt *) parsetree);
+                       break;
+
+               case T_CheckPointStmt:
+                       {
+                               if (!superuser())
+                                       elog(ERROR, "permission denied");
+                               CreateCheckPoint(false);
+                       }
+                       break;
+
+               case T_ReindexStmt:
+                       {
+                               ReindexStmt *stmt = (ReindexStmt *) parsetree;
+
+                               switch (stmt->reindexType)
+                               {
+                                       case INDEX:
+                                               relname = (char *) stmt->relation->relname;
+                                               if (IsSystemRelationName(relname))
+                                               {
+                                                       if (!allowSystemTableMods)
+                                                               elog(ERROR, "\"%s\" is a system index. call REINDEX under standalone postgres with -O -P options",
+                                                                        relname);
+                                                       if (!IsIgnoringSystemIndexes())
+                                                               elog(ERROR, "\"%s\" is a system index. call REINDEX under standalone postgres with -P -O options",
+                                                                        relname);
+                                               }
+                                               CheckOwnership(stmt->relation, false);
+                                               ReindexIndex(stmt->relation, stmt->force);
+                                               break;
+                                       case TABLE:
+                                               CheckOwnership(stmt->relation, false);
+                                               ReindexTable(stmt->relation, stmt->force);
+                                               break;
+                                       case DATABASE:
+                                               relname = (char *) stmt->name;
+                                               if (!allowSystemTableMods)
+                                                       elog(ERROR, "must be called under standalone postgres with -O -P options");
+                                               if (!IsIgnoringSystemIndexes())
+                                                       elog(ERROR, "must be called under standalone postgres with -P -O options");
+                                               ReindexDatabase(relname, stmt->force, false);
+                                               break;
+                               }
+                               break;
+                       }
+                       break;
 
-                       /*
-                        * ******************************** default ********************************
-                        *
-                        */
                default:
                        elog(ERROR, "ProcessUtility: command #%d unsupported",
                                 nodeTag(parsetree));
                        break;
        }
-
-       /* ----------------
-        *      tell fe/be or whatever that we're done.
-        * ----------------
-        */
-       EndCommand(commandTag, dest);
 }